UNPKG

forest-express

Version:

Official package for all Forest Express Lianas

330 lines (305 loc) 9.88 kB
const { init, inject } = require('@forestadmin/context'); const SchemaFileUpdater = require('../../src/services/schema-file-updater'); const SchemaSerializer = require('../../src/serializers/schema'); describe('services > schema-file-updater', () => { init((context) => context .addInstance('fs', { writeFileSync: jest.fn() }) .addInstance('logger', { warn: jest.fn() }) .addUsingClass('schemaFileUpdater', () => SchemaFileUpdater)); const meta = { liana: 'some-liana', liana_version: 'some-liana-version', stack: { database_type: 'some-db-type', engine: 'some-engine', engine_version: 'some-engine-version', orm_version: 'some-orm-version', }, }; const schemaSerializer = new SchemaSerializer(); const { options: serializerOptions } = schemaSerializer; const { schemaFileUpdater } = inject(); const buildSchema = (collection, metas = meta) => schemaFileUpdater.update('test.json', collection, metas, serializerOptions); // NOTICE: Expecting `fs.writeFileSync` second parameter to be valid JSON. it('should call fs.writeFileSync with a valid JSON as data', () => { const { fs } = inject(); buildSchema([], {}); expect(fs.writeFileSync).toHaveBeenCalledTimes(1); const jsonStringSchema = fs.writeFileSync.mock.calls[0][1]; expect(() => JSON.parse(jsonStringSchema)).not.toThrow(); }); it('should format a collection', () => { const schema = buildSchema([{ name: 'collectionName' }], meta); expect(schema.collections[0]).toStrictEqual({ name: 'collectionName', nameOld: 'collectionName', icon: null, integration: null, isReadOnly: false, isSearchable: true, isVirtual: false, onlyForRelationships: false, paginationType: 'page', fields: [], segments: [], actions: [], }); }); it('should format field', () => { const schema = buildSchema([{ name: 'collectionName', fields: [{ field: 'fieldA', defaultValue: 5, }, { field: 'fieldB', validations: [{ type: 'is', value: 42, }], }], }]); expect(schema.collections[0].fields[0]).toStrictEqual({ field: 'fieldA', type: 'String', defaultValue: 5, enums: null, integration: null, isFilterable: true, isReadOnly: false, isRequired: false, isPrimaryKey: false, isSortable: true, isVirtual: false, reference: null, inverseOf: null, validations: [], }); expect(schema.collections[0].fields[1].validations[0]).toMatchObject({ message: null, type: 'is', value: 42, }); }); it('should set field\'s properties', () => { const schema = buildSchema([{ name: 'collectionName', fields: [{ field: 'fieldA', defaultValue: 5, isRequired: true, isReadOnly: true, isFilterable: false, isPrimaryKey: true, isSortable: false, }], }]); expect(schema.collections[0].fields[0]).toStrictEqual({ field: 'fieldA', type: 'String', defaultValue: 5, enums: null, integration: null, isFilterable: false, isReadOnly: true, isRequired: true, isPrimaryKey: true, isSortable: false, isVirtual: false, reference: null, inverseOf: null, validations: [], }); }); it('should format action', () => { const schema = buildSchema([{ name: 'collectionName', actions: [ { name: 'actionName', type: 'notAnExistingType' }, { name: 'secondActionName', fields: [{ field: 'someOtherField', description: 'This action will \r\n do something', enums: ['yes', 'no'], }], }, { name: 'thirdActionName', fields: [{ field: 'someOtherField', description: 'This action will \r\n do something', isReadOnly: true, }], }, ], }]); expect(schema.collections[0].actions[0]).toStrictEqual({ name: 'actionName', type: null, baseUrl: null, endpoint: '/forest/actions/actionname', httpMethod: 'POST', redirect: null, download: false, fields: [], hooks: { load: false, change: [] }, }); expect(schema.collections[0].actions[1].fields[0]).toStrictEqual({ field: 'someOtherField', type: 'String', defaultValue: null, enums: ['yes', 'no'], isRequired: false, reference: null, description: 'This action will \r\n do something', position: 0, widget: null, }); expect(schema.collections[0].actions[2].fields[0]).toStrictEqual({ field: 'someOtherField', type: 'String', defaultValue: null, isRequired: false, reference: null, description: 'This action will \r\n do something', position: 0, widget: null, enums: null, isReadOnly: true, }); }); it('should format action hooks', () => { const INVALID_HOOKS = 'Action With Invalid Hooks'; const INVALID_LOAD_HOOK = 'Action With Invalid Load Hook'; const INVALID_CHANGE_HOOK = 'Action With Invalid Change Hook'; const VALID_HOOKS = 'Action With Valid Hooks'; const VALID_ONLY_LOAD_HOOK = 'Action With Only a Load Hook'; const VALID_ONLY_CHANGE_HOOK = 'Action With Only a Change Hook'; const schema = buildSchema([{ name: 'collectionName', actions: [ { name: INVALID_HOOKS, type: 'single', hooks: { load: 'oops', change: null }, }, { name: INVALID_LOAD_HOOK, type: 'single', hooks: { load: 'oops', change: { foo: () => { } } }, }, { name: INVALID_CHANGE_HOOK, type: 'single', hooks: { load: () => { }, change: null }, }, { name: VALID_HOOKS, type: 'single', hooks: { load: () => { }, change: { foo: () => { }, bar: () => { }, }, }, }, { name: VALID_ONLY_LOAD_HOOK, type: 'single', hooks: { load: () => { } }, }, { name: VALID_ONLY_CHANGE_HOOK, type: 'single', hooks: { change: { foo: () => { }, bar: () => { }, }, }, }, ], }]); const { actions } = schema.collections[0]; const findAction = (name) => actions.find((action) => action.name === name); expect(findAction(INVALID_HOOKS)) .toMatchObject({ hooks: { load: false, change: [] } }); expect(findAction(INVALID_LOAD_HOOK)) .toMatchObject({ hooks: { load: false, change: ['foo'] } }); expect(findAction(INVALID_CHANGE_HOOK)) .toMatchObject({ hooks: { load: true, change: [] } }); expect(findAction(VALID_HOOKS)) .toMatchObject({ hooks: { load: true, change: ['foo', 'bar'] } }); expect(findAction(VALID_ONLY_LOAD_HOOK)) .toMatchObject({ hooks: { load: true, change: [] } }); expect(findAction(VALID_ONLY_CHANGE_HOOK)) .toMatchObject({ hooks: { load: false, change: ['foo', 'bar'] } }); }); it('should format segments', () => { const schema = buildSchema([{ name: 'collectionName', segments: [{ name: 'segmentName' }], }]); expect(schema.collections[0].segments[0]).toStrictEqual({ name: 'segmentName' }); }); it('should not override existing properties', () => { const schema = buildSchema([{ name: 'collectionName', isVirtual: true }]); expect(schema.collections[0]).toMatchObject({ isVirtual: true, }); }); it('should contains meta', () => { const schema = buildSchema([], meta); expect(schema.meta).toStrictEqual(meta); }); it('should sort collections by name', () => { const schema = buildSchema([{ name: 'collectionZ' }, { name: 'collectionA' }]); expect(schema.collections[0].name).toBe('collectionA'); expect(schema.collections[1].name).toBe('collectionZ'); }); it('should sort fields by field and type', () => { const schema = buildSchema([{ name: 'collectionName', fields: [{ field: 'fieldZ' }, { field: 'fieldA', type: 'Z' }, { field: 'fieldA', type: 'A' }], }]); expect(schema.collections[0].fields[0]).toMatchObject({ field: 'fieldA', type: 'A' }); expect(schema.collections[0].fields[1]).toMatchObject({ field: 'fieldA', type: 'Z' }); expect(schema.collections[0].fields[2]).toMatchObject({ field: 'fieldZ' }); }); it('should sort actions by name', () => { const schema = buildSchema([{ name: 'collectionName', actions: [{ name: 'actionZ' }, { name: 'actionA' }], }]); expect(schema.collections[0].actions[0].name).toBe('actionA'); expect(schema.collections[0].actions[1].name).toBe('actionZ'); }); it('should set to null invalid action type', () => { const { logger } = inject(); const schema = buildSchema([{ name: 'collectionName', actions: [ { name: 'actionName', type: 'notAnExistingType' }, ], }]); expect(schema.collections[0].actions[0].type).toBeNull(); expect(logger.warn).toHaveBeenCalledWith( expect.stringMatching('Please set a valid Smart Action type'), ); }); it('should log if action.global=true is still used', () => { const { logger } = inject(); buildSchema([{ name: 'collectionName', actions: [ { name: 'actionName', global: true }, ], }]); expect(logger.warn).toHaveBeenCalledWith( expect.stringMatching('REMOVED OPTION: The support for Smart Action "global" option is now removed'), ); }); });