Skip to content

Commit

Permalink
Use prepared statements + add tests for record position (#4451)
Browse files Browse the repository at this point in the history
Use prepared statements + add tests

Co-authored-by: Thomas Trompette <thomast@twenty.com>
  • Loading branch information
thomtrp and Thomas Trompette authored Mar 13, 2024
1 parent 8c0680b commit a02e11f
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,73 @@ describe('RecordPositionQueryFactory', () => {
});

describe('create', () => {
it('should return a string with the position when positionValue is first', async () => {
const positionValue = 'first';
describe('createForGet', () => {
it('should return a string with the position when positionValue is first', async () => {
const positionValue = 'first';

const result = await factory.create(
RecordPositionQueryType.GET,
positionValue,
objectMetadataItem,
dataSourceSchema,
);
const result = await factory.create(
RecordPositionQueryType.GET,
positionValue,
objectMetadataItem,
dataSourceSchema,
);

expect(result).toEqual(
`SELECT position FROM workspace_test."company"
expect(result).toEqual(
`SELECT position FROM workspace_test."company"
WHERE "position" IS NOT NULL ORDER BY "position" ASC LIMIT 1`,
);
);
});

it('should return a string with the position when positionValue is last', async () => {
const positionValue = 'last';

const result = await factory.create(
RecordPositionQueryType.GET,
positionValue,
objectMetadataItem,
dataSourceSchema,
);

expect(result).toEqual(
`SELECT position FROM workspace_test."company"
WHERE "position" IS NOT NULL ORDER BY "position" DESC LIMIT 1`,
);
});
});

it('should return a string with the position when positionValue is a number', async () => {
const positionValue = 1;

try {
await factory.create(
RecordPositionQueryType.GET,
positionValue,
objectMetadataItem,
dataSourceSchema,
);
} catch (error) {
expect(error.message).toEqual(
'RecordPositionQueryType.GET requires positionValue to be a number',
);
}
});
});

it('should return a string with the position when positionValue is last', async () => {
const positionValue = 'last';
describe('createForUpdate', () => {
it('should return a string when RecordPositionQueryType is UPDATE', async () => {
const positionValue = 1;

const result = await factory.create(
RecordPositionQueryType.GET,
RecordPositionQueryType.UPDATE,
positionValue,
objectMetadataItem,
dataSourceSchema,
);

expect(result).toEqual(
`SELECT position FROM workspace_test."company"
WHERE "position" IS NOT NULL ORDER BY "position" DESC LIMIT 1`,
`UPDATE workspace_test."company"
SET "position" = $1
WHERE "id" = $2`,
);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export class RecordPositionQueryFactory {
positionValue: 'first' | 'last' | number,
objectMetadata: { isCustom: boolean; nameSingular: string },
dataSourceSchema: string,
recordId?: string,
): Promise<string> {
const name =
(objectMetadata.isCustom ? '_' : '') + objectMetadata.nameSingular;
Expand All @@ -27,24 +26,7 @@ export class RecordPositionQueryFactory {

return this.createForGet(positionValue, name, dataSourceSchema);
case RecordPositionQueryType.UPDATE:
if (typeof positionValue !== 'number') {
throw new Error(
'RecordPositionQueryType.UPDATE requires positionValue to be a number',
);
}

if (!recordId) {
throw new Error(
'RecordPositionQueryType.UPDATE requires recordId to be defined',
);
}

return this.createForUpdate(
positionValue,
name,
dataSourceSchema,
recordId,
);
return this.createForUpdate(name, dataSourceSchema);
default:
throw new Error('Invalid RecordPositionQueryType');
}
Expand All @@ -62,13 +44,11 @@ export class RecordPositionQueryFactory {
}

private async createForUpdate(
positionValue: number,
name: string,
dataSourceSchema: string,
recordId: string,
): Promise<string> {
return `UPDATE ${dataSourceSchema}."${name}"
SET "position" = ${positionValue}
WHERE "id" = '${recordId}'`;
SET "position" = $1
WHERE "id" = $2`;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { TestingModule, Test } from '@nestjs/testing';

import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service';
import { RecordPositionQueryFactory } from 'src/workspace/workspace-query-builder/factories/record-position-query.factory';
import { RecordPositionFactory } from 'src/workspace/workspace-query-runner/factories/record-position.factory';

describe('RecordPositionFactory', () => {
const recordPositionQueryFactory = {
create: jest.fn().mockResolvedValue('query'),
};

const workspaceDataSourceService = {
getSchemaName: jest.fn().mockReturnValue('schemaName'),
executeRawQuery: jest.fn().mockResolvedValue([{ position: 1 }]),
};

let factory: RecordPositionFactory;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
RecordPositionFactory,
{
provide: RecordPositionQueryFactory,
useValue: recordPositionQueryFactory,
},
{
provide: WorkspaceDataSourceService,
useValue: workspaceDataSourceService,
},
],
}).compile();

factory = module.get<RecordPositionFactory>(RecordPositionFactory);
});

it('should be defined', () => {
expect(factory).toBeDefined();
});

describe('create', () => {
const objectMetadata = { isCustom: false, nameSingular: 'company' };
const workspaceId = 'workspaceId';

it('should return the value when value is a number', async () => {
const value = 1;
const result = await factory.create(value, objectMetadata, workspaceId);

expect(result).toEqual(value);
});
it('should return the existing position / 2 when value is first', async () => {
const value = 'first';
const result = await factory.create(value, objectMetadata, workspaceId);

expect(result).toEqual(0.5);
});
it('should return the existing position + 1 when value is last', async () => {
const value = 'last';
const result = await factory.create(value, objectMetadata, workspaceId);

expect(result).toEqual(2);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,11 @@ export class RecordPositionBackfillService {
position,
objectMetadata as ObjectMetadataInterface,
dataSourceSchema,
recordId,
);

this.workspaceDataSourceService.executeRawQuery(
query,
[],
[position, recordId],
workspaceId,
undefined,
);
Expand Down

0 comments on commit a02e11f

Please sign in to comment.