Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding some tests #31

Merged
merged 5 commits into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions plugins/open-feedback-backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@backstage/backend-common": "^0.21.7",
"@backstage/backend-defaults": "^0.2.17",
"@backstage/backend-plugin-api": "^0.6.17",
"@backstage/backend-test-utils": "^0.3.8",
"@backstage/config": "^1.2.0",
"@parsifal-m/backstage-plugin-open-feedback-common": "0.3.0",
"@types/express": "*",
Expand Down
77 changes: 77 additions & 0 deletions plugins/open-feedback-backend/src/database/DatabaseHandler.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { TestDatabases } from '@backstage/backend-test-utils';
import { Knex } from 'knex';
import { OpenFeedbackDatabaseHandler } from './DatabaseHandler';

const databases = TestDatabases.create();

describe('OpenFeedbackDatabaseHandler', () => {
let db: Knex;
let handler: OpenFeedbackDatabaseHandler;

beforeAll(async () => {
db = await databases.init('SQLITE_3');

const mockDatabaseManager = {
getClient: jest.fn().mockResolvedValue(db),
};

handler = await OpenFeedbackDatabaseHandler.create(mockDatabaseManager);
});

beforeEach(async () => {
await db('open_feedback').del();
});

afterAll(async () => {
await db.destroy();
});

it('should add feedback', async () => {
const feedback = {
userRef: 'test',
rating: 5,
comment: 'test comment',
};

await handler.addFeedback(feedback);

const result = await db('open_feedback').select();
expect(result).toHaveLength(1);
expect({
...result[0],
rating: parseFloat(result[0].rating),
}).toMatchObject(feedback);
});

it('should get feedback', async () => {
const feedback = {
userRef: 'test',
rating: 5,
comment: 'test comment',
};

await handler.addFeedback(feedback);

const result = await handler.getFeedback();
expect(result).not.toBeNull();
expect(result).not.toBeUndefined();
});

it('should remove feedback', async () => {
const feedback = {
userRef: 'test',
rating: 5,
comment: 'test comment',
};

await handler.addFeedback(feedback);

let result = await handler.getFeedback();
expect(result).toHaveLength(1);

await handler.removeFeedback(result[0].id);

result = await handler.getFeedback();
expect(result).toHaveLength(0);
});
});
34 changes: 17 additions & 17 deletions plugins/open-feedback-backend/src/database/DatabaseHandler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { resolvePackagePath } from '@backstage/backend-common';
import {
resolvePackagePath,
PluginDatabaseManager,
} from '@backstage/backend-common';
import { Knex } from 'knex';
import {
AppFeedback,
Expand All @@ -10,33 +13,30 @@ const migrationsDir = resolvePackagePath(
'migrations',
);

type Options = {
database: Knex;
};

export class DatabaseHandler {
static async create(options: Options): Promise<DatabaseHandler> {
const { database } = options;
export class OpenFeedbackDatabaseHandler {
private readonly client: Knex;
static async create(
database: PluginDatabaseManager,
): Promise<OpenFeedbackDatabaseHandler> {
const client = await database.getClient();

await database.migrate.latest({
await client.migrate.latest({
directory: migrationsDir,
});

return new DatabaseHandler(options);
return new OpenFeedbackDatabaseHandler(client);
}

private readonly database: Knex;

private constructor(options: Options) {
this.database = options.database;
private constructor(client: Knex) {
this.client = client;
}

async addFeedback(feedback: SubmitFeedback): Promise<void> {
await this.database('open_feedback').insert(feedback);
await this.client('open_feedback').insert(feedback);
}

async getFeedback(): Promise<AppFeedback[]> {
return this.database('open_feedback').select(
return this.client('open_feedback').select(
'id',
'userRef',
'rating',
Expand All @@ -46,6 +46,6 @@ export class DatabaseHandler {
}

async removeFeedback(id: number): Promise<void> {
return this.database('open_feedback').where('id', id).delete();
return this.client('open_feedback').where('id', id).delete();
}
}
6 changes: 5 additions & 1 deletion plugins/open-feedback-backend/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
createBackendPlugin,
} from '@backstage/backend-plugin-api';
import { createRouter } from './service/router';
import { OpenFeedbackDatabaseHandler } from './database/DatabaseHandler';

/**
* openFeedbackPlugin backend plugin
Expand All @@ -22,9 +23,12 @@ export const openFeedbackPlugin = createBackendPlugin({
httpAuth: coreServices.httpAuth,
},
async init({ database, discovery, logger, httpRouter, auth, httpAuth }) {
const databaseHandler = await OpenFeedbackDatabaseHandler.create(
database,
);
httpRouter.use(
await createRouter({
database,
databaseHandler,
discovery,
logger,
auth,
Expand Down
61 changes: 59 additions & 2 deletions plugins/open-feedback-backend/src/service/router.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import { getVoidLogger } from '@backstage/backend-common';
import express from 'express';
import request from 'supertest';

import { createRouter } from './router';
import { OpenFeedbackDatabaseHandler } from '../database/DatabaseHandler';

const mockDatabaseHandler = {
addFeedback: jest.fn(),
getFeedback: jest.fn(),
removeFeedback: jest.fn(),
} as unknown as OpenFeedbackDatabaseHandler;

describe('createRouter', () => {
let app: express.Express;

beforeAll(async () => {
const router = await createRouter({
logger: getVoidLogger(),
database: { getClient: jest.fn() },
databaseHandler: mockDatabaseHandler,
discovery: {
getBaseUrl: jest.fn(),
// eslint-disable-next-line func-names
Expand All @@ -34,4 +40,55 @@ describe('createRouter', () => {
expect(response.body).toEqual({ status: 'ok' });
});
});

describe('POST /feedback/submit', () => {
it('returns ok when feedback is added', async () => {
const feedback = { rating: 5, comment: 'Great!', userRef: 'user1' };

const response = await request(app)
.post('/feedback/submit')
.send(feedback);

expect(response.status).toEqual(201);
expect(response.body).toEqual({
status: 'ok',
message: 'Feedback added',
});
expect(mockDatabaseHandler.addFeedback).toHaveBeenCalledWith(feedback);
});
});
describe('GET /feedback', () => {
it('returns feedback list', async () => {
const feedbackList = [{ rating: 5, comment: 'Great!', userRef: 'user1' }];
mockDatabaseHandler.getFeedback = jest
.fn()
.mockResolvedValue(feedbackList);

const response = await request(app).get('/feedback');

expect(response.status).toEqual(200);
expect(response.body).toEqual(feedbackList);
expect(mockDatabaseHandler.getFeedback).toHaveBeenCalled();
});
});

describe('DELETE /feedback/:id', () => {
it('returns ok when feedback is removed', async () => {
const feedbackId = 1;
mockDatabaseHandler.removeFeedback = jest
.fn()
.mockResolvedValue(feedbackId);

const response = await request(app).delete(`/feedback/${feedbackId}`);

expect(response.status).toEqual(200);
expect(response.body).toEqual({
status: 'ok',
message: 'Feedback removed',
});
expect(mockDatabaseHandler.removeFeedback).toHaveBeenCalledWith(
feedbackId,
);
});
});
});
15 changes: 6 additions & 9 deletions plugins/open-feedback-backend/src/service/router.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
errorHandler,
PluginDatabaseManager,
PluginEndpointDiscovery,
} from '@backstage/backend-common';
import {
Expand All @@ -11,11 +10,11 @@ import {
import express, { Request, Response } from 'express';
import Router from 'express-promise-router';
import { body } from 'express-validator';
import { DatabaseHandler } from '../database/DatabaseHandler';
import { OpenFeedbackDatabaseHandler } from '../database/DatabaseHandler';
import { SubmitFeedback } from '@parsifal-m/backstage-plugin-open-feedback-common';

export interface RouterOptions {
database: PluginDatabaseManager;
databaseHandler: OpenFeedbackDatabaseHandler;
discovery: PluginEndpointDiscovery;
logger: LoggerService;
auth?: AuthService;
Expand All @@ -31,9 +30,7 @@ const feedbackValidator = [
export async function createRouter(
options: RouterOptions,
): Promise<express.Router> {
const { logger, database } = options;
const db = await database.getClient();
const dbHandler = await DatabaseHandler.create({ database: db });
const { logger, databaseHandler } = options;

const router = Router();
router.use(express.json());
Expand All @@ -52,7 +49,7 @@ export async function createRouter(
const feedback: SubmitFeedback = { userRef, rating, comment };

try {
await dbHandler.addFeedback(feedback);
await databaseHandler.addFeedback(feedback);
logger.info(`Received feedback from ${userRef} with rating ${rating}`);
res.status(201).json({ status: 'ok', message: 'Feedback added' });
} catch (error) {
Expand All @@ -66,7 +63,7 @@ export async function createRouter(

router.get('/feedback', async (_, res: Response) => {
try {
const feedback = await dbHandler.getFeedback();
const feedback = await databaseHandler.getFeedback();
res.status(200).json(feedback);
} catch (error) {
logger.error(`Failed to get feedback: ${error}`);
Expand All @@ -80,7 +77,7 @@ export async function createRouter(
const { id } = req.params;

try {
await dbHandler.removeFeedback(Number(id));
await databaseHandler.removeFeedback(Number(id));
res.status(200).json({ status: 'ok', message: 'Feedback removed' });
} catch (error) {
logger.error(`Failed to remove feedback: ${error}`);
Expand Down
Loading
Loading