Skip to content

Commit

Permalink
Merge pull request #188 from codex-team/feat/update-add-tool-response
Browse files Browse the repository at this point in the history
feat: updated add user tool response
  • Loading branch information
slaveeks authored Feb 24, 2024
2 parents e86833a + a98026d commit 1a86ef8
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 20 deletions.
9 changes: 9 additions & 0 deletions src/domain/service/editorTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ export default class EditorToolsService implements EditorToolsServiceSharedMetho
return await this.repository.getToolsByIds(editorToolIds);
}

/**
* Get tool by it's identifier
*
* @param editorToolId - unique tool identifier
*/
public async getToolById(editorToolId: EditorTool['id']): Promise<EditorTool | null> {
return await this.repository.getToolById(editorToolId);
}

/**
* Return tools that are available at Editor by default
*/
Expand Down
7 changes: 7 additions & 0 deletions src/domain/service/shared/editorTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@ export default interface EditorToolsServiceSharedMethods {
* @param ids - tool ids to resolve
*/
getToolsByIds(ids: EditorTool['id'][]): Promise<EditorTool[]>;

/**
* Get tool by it's identifier
*
* @param id - unique tool identifier
*/
getToolById(id: EditorTool['id']): Promise<EditorTool | null>;
}
12 changes: 10 additions & 2 deletions src/domain/service/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,19 @@ export default class UserService {
}: {
userId: User['id'],
toolId: EditorTool['id'],
}): Promise<void> {
return await this.repository.addUserEditorTool({
}): Promise<EditorTool> {
const toolToAdd = await this.shared.editorTools.getToolById(toolId);

if (toolToAdd === null) {
throw new DomainError('Editor tool not found');
}

await this.repository.addUserEditorTool({
userId,
toolId,
});

return toolToAdd;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/presentation/http/router/noteList.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { describe, test, expect, beforeAll } from 'vitest';
*/
let accessToken = '';

describe('NoteList API', () => {
describe('Note list API', () => {
beforeAll(() => {
/**
* userId for authorization
Expand Down
54 changes: 53 additions & 1 deletion src/presentation/http/router/user.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,56 @@ describe('User API', () => {
expect(body.message).toBe('You must be authenticated to access this resource');
});
});
});
describe('POST /user/editor-tools', () => {
test('Returns added tool with status code 200 if tool added to user extensions', async () => {
await global.db.truncateTables();

/**
* Create user and get accessToken
*/
const createdUser = await global.db.insertUser({
email: '[email protected]',
name: 'Test',
});
const accessToken = global.auth(createdUser.id);

const addedToolId = await global.db.insertEditorTool({
name: 'code',
title: 'Code Tool',
exportName: 'Code',
isDefault: false,
source: {
cdn: 'https://cdn.jsdelivr.net/npm/@editorjs/code@latest',
},
});

const response = await global.api?.fakeRequest({
method: 'POST',
headers: {
authorization: `Bearer ${accessToken}`,
},
url: '/user/editor-tools',
body: {
'toolId': addedToolId,
},
});

expect(response?.statusCode).toBe(200);

const body = response?.json();

expect(body).toStrictEqual({
addedTool :{
id: addedToolId,
name: 'code',
title: 'Code Tool',
exportName: 'Code',
isDefault: false,
source: {
cdn: 'https://cdn.jsdelivr.net/npm/@editorjs/code@latest',
},
},
});
});
});
});
18 changes: 16 additions & 2 deletions src/presentation/http/router/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,32 @@ const UserRouter: FastifyPluginCallback<UserRouterOptions> = (fastify, opts, don
description: 'Unique editor tool id',
},
},
response: {
'2xx': {
description: 'Added editor tool id',
content: {
'application/json': {
schema: {
addedTool: {
$ref: 'EditorToolSchema',
},
},
},
},
},
}
},
}, async (request, reply) => {
const toolId = request.body.toolId;
const userId = request.userId as number;

await userService.addUserEditorTool({
const addedTool = await userService.addUserEditorTool({
userId,
toolId,
});

return reply.send({
data: toolId,
addedTool,
});
});

Expand Down
9 changes: 9 additions & 0 deletions src/repository/editorTools.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ export default class EditorToolsRepository {
return createdEditorTool;
}

/**
* Get tool by it's identifier
*
* @param editorToolId - unique tool identifier
*/
public async getToolById(editorToolId: EditorTool['id']): Promise<EditorTool | null> {
return await this.storage.getToolById(editorToolId);
}

/**
* Get bunch of tools by their ids
*
Expand Down
9 changes: 9 additions & 0 deletions src/repository/storage/postgres/orm/sequelize/editorTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,15 @@ export default class UserSequelizeStorage {
});
}

/**
* Get tool by it's identifier
*
* @param editorToolId - unique tool identifier
*/
public async getToolById(editorToolId: EditorTool['id']): Promise<EditorTool | null> {
return await this.model.findByPk(editorToolId);
}

/**
* Get all default tools
*/
Expand Down
2 changes: 1 addition & 1 deletion src/repository/storage/postgres/orm/sequelize/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export default class UserSequelizeStorage {
type: DataTypes.STRING,
},
editorTools: {
type: DataTypes.ARRAY(DataTypes.STRING),
type: DataTypes.JSONB,
},
}, {
tableName: this.tableName,
Expand Down
31 changes: 18 additions & 13 deletions src/tests/utils/database-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ export default class DatabaseHelpers {
const content = note.content ?? '{}';

// eslint-disable-next-line
const [results, metadata] = await this.orm.connection.query(`INSERT INTO public.notes ("content", "creator_id", "created_at", "updated_at", "public_id")
VALUES ('${content}', ${note.creatorId}, CURRENT_DATE, CURRENT_DATE, '${note.publicId}')
const [results, metadata] = await this.orm.connection.query(`INSERT INTO public.notes ("content", "creator_id", "created_at", "updated_at", "public_id")
VALUES ('${content}', ${note.creatorId}, CURRENT_DATE, CURRENT_DATE, '${note.publicId}')
RETURNING "id", "content", "creator_id" AS "creatorId", "public_id" AS "publicId", "created_at" AS "createdAt", "updated_at" AS "updatedAt"`,
{
type: QueryTypes.INSERT,
Expand All @@ -121,8 +121,8 @@ export default class DatabaseHelpers {
const editorTools = user.editorTools ?? '[]';

// eslint-disable-next-line
const [results, metadata] = await this.orm.connection.query(`INSERT INTO public.users ("email", "name", "created_at", "editor_tools")
VALUES ('${user.email}', '${user.name}', CURRENT_DATE, array${editorTools}::text[])
const [results, metadata] = await this.orm.connection.query(`INSERT INTO public.users ("email", "name", "created_at", "editor_tools")
VALUES ('${user.email}', '${user.name}', CURRENT_DATE, '${editorTools}'::jsonb)
RETURNING "id", "email", "name", "editor_tools" AS "editorTools", "created_at" AS "createdAt", "photo"`,
{
type: QueryTypes.INSERT,
Expand Down Expand Up @@ -197,38 +197,43 @@ export default class DatabaseHelpers {
*
* if no isDefault passed, then is_default would be false in database
*/
public async insertEditorTool(editorTool: EditorToolMockCreationAttributes): Promise<EditorToolMockCreationAttributes> {
const isDefault = editorTool.isDefault ?? null;
public async insertEditorTool(editorTool: EditorToolMockCreationAttributes): Promise<EditorTool['id']> {
const isDefault = editorTool.isDefault ?? false;

await this.orm.connection.query(`INSERT INTO public.editor_tools ("name", "title", "export_name", "source", "is_default") VALUES ('${editorTool.name}', '${editorTool.title}', '${editorTool.exportName}', '${editorTool.exportName}', ${isDefault}')`);
// eslint-disable-next-line
const [result, _] = await this.orm.connection.query(`INSERT INTO public.editor_tools ("name", "title", "export_name", "source", "is_default")
VALUES ('${editorTool.name}', '${editorTool.title}', '${editorTool.exportName}', '${JSON.stringify(editorTool.source)}', ${isDefault})
RETURNING "id"`);

const addedToolData = result[0];

return editorTool;
return String(addedToolData.id);
}

/**
* Truncates all tables and restarts all autoincrement sequences
*/
public async truncateTables(): Promise<unknown> {
return await this.orm.connection.query(`DO $$
DECLARE
DECLARE
-- table iterator
tbl RECORD;
-- sequence iterator
seq RECORD;
BEGIN
-- truncate all tables (except migrations) in database
FOR tbl IN
FOR tbl IN
SELECT * FROM information_schema.tables
WHERE table_name!= 'migrations'
AND table_schema= 'public'
AND table_type= 'BASE TABLE'
LOOP
EXECUTE format('TRUNCATE public.%s CASCADE', tbl.table_name);
END LOOP;
-- restart all sequences
-- restart all sequences
-- (autoincrement should start with 1 when test-data is truncated)
FOR seq IN
FOR seq IN
SELECT * FROM information_schema.sequences
WHERE sequence_schema= 'public'
LOOP
Expand Down

0 comments on commit 1a86ef8

Please sign in to comment.