Add rest api (#2757)

* Add a wildcard get route

* Call api from api

* Add a query formatter

* Use headers to authenticate

* Handle findMany query

* Add limit, orderBy and lastCursor parameters

* Add filter parameters

* Remove singular object name from valid requests

* Update order_by format

* Add depth parameter

* Make /api/objects/ID requests work

* Fix filter

* Add INTERNAL_SERVER_URL env variable

* Remove useless comment

* Change bath api url to 'rest'

* Fix limit parser

* Handle full filter version

* Improve handle full filter version

* Continue rest api

* Add and(...) default behaviour on filters

* Add tests

* Handle 'not' conjunction for filters

* Check filter query

* Format values with field metadata item type

* Handle nested filtering

* Update parsing method

* Check nested fields

* Add delete query

* Add create query

* Rename methods

* Add update query

* Update get one object request

* Fix error handling

* Code review returns
This commit is contained in:
martmull
2023-12-01 16:26:39 +01:00
committed by GitHub
parent f405b77cea
commit 97f154ef2c
9 changed files with 872 additions and 1 deletions

View File

@ -0,0 +1,148 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ApiRestService } from 'src/core/api-rest/api-rest.service';
import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service';
import { EnvironmentService } from 'src/integrations/environment/environment.service';
describe('ApiRestService', () => {
let service: ApiRestService;
const objectMetadataItem = { fields: [{ name: 'field', type: 'NUMBER' }] };
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
ApiRestService,
{
provide: ObjectMetadataService,
useValue: {},
},
{
provide: EnvironmentService,
useValue: {},
},
],
}).compile();
service = module.get<ApiRestService>(ApiRestService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
describe('checkFilterQuery', () => {
it('should check filter query', () => {
expect(() => service.checkFilterQuery('(')).toThrow();
expect(() => service.checkFilterQuery(')')).toThrow();
expect(() => service.checkFilterQuery('(()')).toThrow();
expect(() => service.checkFilterQuery('())')).toThrow();
expect(() =>
service.checkFilterQuery(
'and(or(field[eq]:1,field[eq]:2)),field[eq]:3)',
),
).toThrow();
expect(() =>
service.checkFilterQuery(
'and(or(field[eq]:1,field[eq]:2),field[eq]:3)',
),
).not.toThrow();
});
});
describe('formatFieldValue', () => {
it('should format field value', () => {
expect(service.formatFieldValue('1', 'NUMBER')).toEqual(1);
expect(service.formatFieldValue(1, 'NUMBER')).toEqual(1);
expect(service.formatFieldValue('a', 'NUMBER')).toEqual(NaN);
expect(service.formatFieldValue('true', 'BOOLEAN')).toEqual(true);
expect(service.formatFieldValue('True', 'BOOLEAN')).toEqual(true);
expect(service.formatFieldValue('false', 'BOOLEAN')).toEqual(false);
expect(service.formatFieldValue('1', 'TEXT')).toEqual('1');
});
});
describe('parseFilterQueryContent', () => {
it('should parse query filter test 1', () => {
expect(service.parseFilterQueryContent('and(field[eq]:1)')).toEqual([
'field[eq]:1',
]);
});
it('should parse query filter test 2', () => {
expect(
service.parseFilterQueryContent('and(field[eq]:1,field[eq]:2)'),
).toEqual(['field[eq]:1', 'field[eq]:2']);
});
it('should parse query filter test 3', () => {
expect(
service.parseFilterQueryContent(
'and(field[eq]:1,or(field[eq]:2,field[eq]:3))',
),
).toEqual(['field[eq]:1', 'or(field[eq]:2,field[eq]:3)']);
});
it('should parse query filter test 4', () => {
expect(
service.parseFilterQueryContent(
'and(field[eq]:1,or(field[eq]:2,not(field[eq]:3)),field[eq]:4,not(field[eq]:5))',
),
).toEqual([
'field[eq]:1',
'or(field[eq]:2,not(field[eq]:3))',
'field[eq]:4',
'not(field[eq]:5)',
]);
});
});
describe('parseStringFilter', () => {
it('should parse string filter test 1', () => {
expect(
service.parseStringFilter(
'and(field[eq]:1,field[eq]:2)',
objectMetadataItem,
),
).toEqual({ and: [{ field: { eq: 1 } }, { field: { eq: 2 } }] });
});
it('should parse string filter test 2', () => {
expect(
service.parseStringFilter(
'and(field[eq]:1,or(field[eq]:2,field[eq]:3))',
objectMetadataItem,
),
).toEqual({
and: [
{ field: { eq: 1 } },
{ or: [{ field: { eq: 2 } }, { field: { eq: 3 } }] },
],
});
});
it('should parse string filter test 3', () => {
expect(
service.parseStringFilter(
'and(field[eq]:1,or(field[eq]:2,field[eq]:3,and(field[eq]:6,field[eq]:7)),or(field[eq]:4,field[eq]:5))',
objectMetadataItem,
),
).toEqual({
and: [
{ field: { eq: 1 } },
{
or: [
{ field: { eq: 2 } },
{ field: { eq: 3 } },
{ and: [{ field: { eq: 6 } }, { field: { eq: 7 } }] },
],
},
{ or: [{ field: { eq: 4 } }, { field: { eq: 5 } }] },
],
});
});
it('should handler not', () => {
expect(
service.parseStringFilter(
'and(field[eq]:1,not(field[eq]:2))',
objectMetadataItem,
),
).toEqual({
and: [
{ field: { eq: 1 } },
{
not: { field: { eq: 2 } },
},
],
});
});
});
});