* Convert metadata tables to camelCase * datasourcemetadataid to datasourceid * refactor metadata folders * fix command * move commands out of metadata * fix seed * rename objectId and fieldId in objectMetadataId and fieldMetadataId in FE * fix field-metadata * Fix * Fix * remove logs --------- Co-authored-by: Charles Bochet <charles@twenty.com>
234 lines
5.8 KiB
TypeScript
234 lines
5.8 KiB
TypeScript
import { GraphQLResolveInfo } from 'graphql';
|
|
|
|
import { FieldMetadataTargetColumnMap } from 'src/tenant/schema-builder/interfaces/field-metadata-target-column-map.interface';
|
|
|
|
import {
|
|
PGGraphQLQueryBuilder,
|
|
PGGraphQLQueryBuilderOptions,
|
|
} from 'src/tenant/resolver-builder/pg-graphql/pg-graphql-query-builder';
|
|
import { FieldMetadataEntity } from 'src/database/typeorm/metadata/entities/field-metadata.entity';
|
|
|
|
const testUUID = '123e4567-e89b-12d3-a456-426614174001';
|
|
|
|
const normalizeWhitespace = (str) => str.replace(/\s+/g, '');
|
|
|
|
// Mocking dependencies
|
|
jest.mock('uuid', () => ({
|
|
v4: jest.fn(() => testUUID),
|
|
}));
|
|
|
|
jest.mock('graphql-fields', () =>
|
|
jest.fn(() => ({
|
|
name: true,
|
|
age: true,
|
|
complexField: {
|
|
subField1: true,
|
|
subField2: true,
|
|
},
|
|
})),
|
|
);
|
|
|
|
describe('PGGraphQLQueryBuilder', () => {
|
|
let queryBuilder;
|
|
let mockOptions: PGGraphQLQueryBuilderOptions;
|
|
|
|
beforeEach(() => {
|
|
const fieldMetadataCollection = [
|
|
{
|
|
name: 'name',
|
|
targetColumnMap: {
|
|
value: 'column_name',
|
|
} as FieldMetadataTargetColumnMap,
|
|
},
|
|
{
|
|
name: 'age',
|
|
targetColumnMap: {
|
|
value: 'column_age',
|
|
} as FieldMetadataTargetColumnMap,
|
|
},
|
|
{
|
|
name: 'complexField',
|
|
targetColumnMap: {
|
|
subField1: 'column_subField1',
|
|
subField2: 'column_subField2',
|
|
} as FieldMetadataTargetColumnMap,
|
|
},
|
|
] as FieldMetadataEntity[];
|
|
|
|
mockOptions = {
|
|
targetTableName: 'TestTable',
|
|
info: {} as GraphQLResolveInfo,
|
|
fieldMetadataCollection,
|
|
};
|
|
|
|
queryBuilder = new PGGraphQLQueryBuilder(mockOptions);
|
|
});
|
|
|
|
test('findMany generates correct query with no arguments', () => {
|
|
const query = queryBuilder.findMany();
|
|
|
|
expect(normalizeWhitespace(query)).toBe(
|
|
normalizeWhitespace(`
|
|
query {
|
|
TestTableCollection {
|
|
name: column_name
|
|
age: column_age
|
|
___complexField_subField1: column_subField1
|
|
___complexField_subField2: column_subField2
|
|
}
|
|
}
|
|
`),
|
|
);
|
|
});
|
|
|
|
test('findMany generates correct query with filter parameters', () => {
|
|
const args = {
|
|
filter: {
|
|
name: { eq: 'Alice' },
|
|
age: { gt: 20 },
|
|
},
|
|
};
|
|
const query = queryBuilder.findMany(args);
|
|
|
|
expect(normalizeWhitespace(query)).toBe(
|
|
normalizeWhitespace(`
|
|
query {
|
|
TestTableCollection(filter: { column_name: { eq: "Alice" }, column_age: { gt: 20 } }) {
|
|
name: column_name
|
|
age: column_age
|
|
___complexField_subField1: column_subField1
|
|
___complexField_subField2: column_subField2
|
|
}
|
|
}
|
|
`),
|
|
);
|
|
});
|
|
|
|
test('findMany generates correct query with combined pagination parameters', () => {
|
|
const args = {
|
|
first: 5,
|
|
after: 'someCursor',
|
|
before: 'anotherCursor',
|
|
last: 3,
|
|
};
|
|
const query = queryBuilder.findMany(args);
|
|
|
|
expect(normalizeWhitespace(query)).toBe(
|
|
normalizeWhitespace(`
|
|
query {
|
|
TestTableCollection(
|
|
first: 5,
|
|
after: "someCursor",
|
|
before: "anotherCursor",
|
|
last: 3
|
|
) {
|
|
name: column_name
|
|
age: column_age
|
|
___complexField_subField1: column_subField1
|
|
___complexField_subField2: column_subField2
|
|
}
|
|
}
|
|
`),
|
|
);
|
|
});
|
|
|
|
test('findOne generates correct query with ID filter', () => {
|
|
const args = { filter: { id: { eq: testUUID } } };
|
|
const query = queryBuilder.findOne(args);
|
|
|
|
expect(normalizeWhitespace(query)).toBe(
|
|
normalizeWhitespace(`
|
|
query {
|
|
TestTableCollection(filter: { id: { eq: "${testUUID}" } }) {
|
|
edges {
|
|
node {
|
|
name: column_name
|
|
age: column_age
|
|
___complexField_subField1: column_subField1
|
|
___complexField_subField2: column_subField2
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`),
|
|
);
|
|
});
|
|
|
|
test('createMany generates correct mutation with complex and nested fields', () => {
|
|
const args = {
|
|
data: [
|
|
{
|
|
name: 'Alice',
|
|
age: 30,
|
|
complexField: {
|
|
subField1: 'data1',
|
|
subField2: 'data2',
|
|
},
|
|
},
|
|
],
|
|
};
|
|
const query = queryBuilder.createMany(args);
|
|
|
|
expect(normalizeWhitespace(query)).toBe(
|
|
normalizeWhitespace(`
|
|
mutation {
|
|
insertIntoTestTableCollection(objects: [{
|
|
id: "${testUUID}",
|
|
column_name: "Alice",
|
|
column_age: 30,
|
|
column_subField1: "data1",
|
|
column_subField2: "data2"
|
|
}]) {
|
|
affectedCount
|
|
records {
|
|
name: column_name
|
|
age: column_age
|
|
___complexField_subField1: column_subField1
|
|
___complexField_subField2: column_subField2
|
|
}
|
|
}
|
|
}
|
|
`),
|
|
);
|
|
});
|
|
|
|
test('updateOne generates correct mutation with complex and nested fields', () => {
|
|
const args = {
|
|
id: '1',
|
|
data: {
|
|
name: 'Bob',
|
|
age: 40,
|
|
complexField: {
|
|
subField1: 'newData1',
|
|
subField2: 'newData2',
|
|
},
|
|
},
|
|
};
|
|
const query = queryBuilder.updateOne(args);
|
|
|
|
expect(normalizeWhitespace(query)).toBe(
|
|
normalizeWhitespace(`
|
|
mutation {
|
|
updateTestTableCollection(
|
|
set: {
|
|
column_name: "Bob",
|
|
column_age: 40,
|
|
column_subField1: "newData1",
|
|
column_subField2: "newData2"
|
|
},
|
|
filter: { id: { eq: "1" } }
|
|
) {
|
|
affectedCount
|
|
records {
|
|
name: column_name
|
|
age: column_age
|
|
___complexField_subField1: column_subField1
|
|
___complexField_subField2: column_subField2
|
|
}
|
|
}
|
|
}
|
|
`),
|
|
);
|
|
});
|
|
});
|