|
|
@@ -0,0 +1,842 @@
|
|
|
+import { describe, test, it, expect } from 'vitest'
|
|
|
+import EntityManager from "~/services/data/entityManager";
|
|
|
+import ApiResource from "~/models/ApiResource";
|
|
|
+import ApiModel from "~/models/ApiModel";
|
|
|
+import ApiRequestService from "~/services/data/apiRequestService";
|
|
|
+import {Element, Repository} from "pinia-orm";
|
|
|
+import {ApiResponse} from "~/types/data";
|
|
|
+import HydraDenormalizer from "~/services/data/normalizer/hydraDenormalizer";
|
|
|
+
|
|
|
+class TestableEntityManager extends EntityManager {
|
|
|
+ public cast(model: typeof ApiResource, entity: ApiResource): ApiResource { return super.cast(model, entity) }
|
|
|
+ public async saveResponseAsEntity(model: typeof ApiModel, response: Response) { return super.saveResponseAsEntity(model, response) }
|
|
|
+ public saveInitialState(model: typeof ApiResource, entity: ApiResource) { return super.saveInitialState(model, entity) }
|
|
|
+ public getInitialStateOf(model: typeof ApiResource, id: string | number): ApiResource | null { return super.getInitialStateOf(model, id) }
|
|
|
+ public removeTempAfterPersist(model: typeof ApiResource, tempEntityId: number | string) { return super.removeTempAfterPersist(model, tempEntityId) }
|
|
|
+}
|
|
|
+
|
|
|
+class DummyApiResource extends ApiResource {
|
|
|
+ static entity = 'dummyResource'
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+class DummyApiModel extends ApiModel {
|
|
|
+ static entity = 'dummyModel'
|
|
|
+}
|
|
|
+
|
|
|
+let apiRequestService: ApiRequestService
|
|
|
+let entityManager: TestableEntityManager
|
|
|
+
|
|
|
+beforeEach(() => {
|
|
|
+ // @ts-ignore
|
|
|
+ apiRequestService = vi.fn() as ApiRequestService
|
|
|
+
|
|
|
+ entityManager = new TestableEntityManager(apiRequestService)
|
|
|
+
|
|
|
+ // TODO: s'assurer que les mocks globaux sont bien réinitialisés après les tests, en particulier les fonctions de console
|
|
|
+})
|
|
|
+
|
|
|
+describe('getRepository', () => {
|
|
|
+ // TODO: à revoir
|
|
|
+})
|
|
|
+
|
|
|
+describe('cast', () => {
|
|
|
+ test('simple cast', () => {
|
|
|
+ // @ts-ignore
|
|
|
+ const result = entityManager.cast(DummyApiResource, { id: 1 })
|
|
|
+
|
|
|
+ expect(result instanceof DummyApiResource).toEqual(true)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('getModelFor', () => {
|
|
|
+ // TODO: à revoir
|
|
|
+})
|
|
|
+
|
|
|
+describe('getModelFromIri', () => {
|
|
|
+ test('simple call', () => {
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getModelFor = vi.fn((entityName: string) => entityName === 'dummy' ? DummyApiResource : null)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const result = entityManager.getModelFromIri('/api/dummy/123')
|
|
|
+
|
|
|
+ expect(result).toEqual(DummyApiResource)
|
|
|
+ })
|
|
|
+ test('invalide Iri', () => {
|
|
|
+ expect(() => entityManager.getModelFromIri('/invalid')).toThrowError('cannot parse the IRI')
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('newInstance', () => {
|
|
|
+
|
|
|
+ test('simple call', () => {
|
|
|
+ const properties = { 'id': 1 }
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiResource ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ entityManager.saveInitialState = vi.fn((model: typeof ApiResource, entity: ApiResource) => null)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const entity = new DummyApiResource(properties)
|
|
|
+ entity.setModel = vi.fn((model: typeof ApiResource) => null)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.make = vi.fn((properties: object) => {
|
|
|
+ // @ts-ignore
|
|
|
+ entity.id = properties.id
|
|
|
+ return entity
|
|
|
+ })
|
|
|
+ // @ts-ignore
|
|
|
+ repo.save = vi.fn((record: Element) => entity)
|
|
|
+
|
|
|
+ const result = entityManager.newInstance(DummyApiResource, properties)
|
|
|
+
|
|
|
+ expect(repo.make).toHaveBeenCalledWith(properties)
|
|
|
+ expect(entity.setModel).toHaveBeenCalledWith(DummyApiResource)
|
|
|
+ expect(repo.save).toHaveBeenCalledWith(entity)
|
|
|
+ expect(entityManager.saveInitialState).toHaveBeenCalledWith(DummyApiResource, entity)
|
|
|
+
|
|
|
+ expect(result.id).toEqual(properties.id)
|
|
|
+ })
|
|
|
+
|
|
|
+ test('with no id provided', () => {
|
|
|
+ const properties = { 'name': 'bob' }
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiResource ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ entityManager.saveInitialState = vi.fn((model: typeof ApiResource, entity: ApiResource) => null)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const entity = new DummyApiResource(properties)
|
|
|
+ entity.setModel = vi.fn((model: typeof ApiResource) => null)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.make = vi.fn((properties: object) => {
|
|
|
+ // @ts-ignore
|
|
|
+ entity.name = properties.name
|
|
|
+ return entity
|
|
|
+ })
|
|
|
+ // @ts-ignore
|
|
|
+ repo.save = vi.fn((record: Element) => entity)
|
|
|
+
|
|
|
+ const result = entityManager.newInstance(DummyApiResource, properties)
|
|
|
+
|
|
|
+ expect(
|
|
|
+ result.id,
|
|
|
+ 'id is \'tmp\' followed by a valid uuid-V4'
|
|
|
+ ).toMatch(/tmp[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}/)
|
|
|
+
|
|
|
+ expect(result.name).toEqual(properties.name)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('save', () => {
|
|
|
+ test('simple call', () => {
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiResource ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.save = vi.fn((record: Element) => entity)
|
|
|
+
|
|
|
+ const entity = new DummyApiResource()
|
|
|
+ entityManager.save(DummyApiResource, entity)
|
|
|
+
|
|
|
+ expect(repo.save).toHaveBeenCalledWith(entity)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('find', () => {
|
|
|
+ test('simple call', () => {
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiResource ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ const entity = new DummyApiResource({ id: 1 })
|
|
|
+ // @ts-ignore
|
|
|
+ repo.find = vi.fn((id: string | number) => entity)
|
|
|
+
|
|
|
+ entityManager.find(DummyApiResource, 1)
|
|
|
+
|
|
|
+ expect(entityManager.getRepository).toHaveBeenCalledWith(DummyApiResource)
|
|
|
+ expect(repo.find).toHaveBeenCalledWith(1)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('fetch', () => {
|
|
|
+ test('not in store, no force refresh', async () => {
|
|
|
+
|
|
|
+ const properties = { id: 1 }
|
|
|
+
|
|
|
+ const entity = new DummyApiResource({ id: 1 })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.find = vi.fn((model: typeof ApiResource, id: number) => undefined)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ apiRequestService.get = vi.fn(async (url: string) => properties)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.newInstance = vi.fn((model: typeof ApiResource, props: object) => entity)
|
|
|
+
|
|
|
+ const result = await entityManager.fetch(DummyApiResource, 1)
|
|
|
+
|
|
|
+ expect(entityManager.find).toHaveBeenCalledWith(DummyApiResource, 1)
|
|
|
+ expect(apiRequestService.get).toHaveBeenCalledWith('api/dummyResource/1')
|
|
|
+ expect(entityManager.newInstance).toHaveBeenCalledWith(DummyApiResource, properties)
|
|
|
+
|
|
|
+ expect(result).toEqual(entity)
|
|
|
+ })
|
|
|
+
|
|
|
+ test('in store, no force refresh', async () => {
|
|
|
+
|
|
|
+ const properties = { id: 1 }
|
|
|
+
|
|
|
+ const entity = new DummyApiResource({ id: 1 })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.find = vi.fn((model: typeof ApiResource, id: number) => entity)
|
|
|
+
|
|
|
+ const result = await entityManager.fetch(DummyApiResource, 1)
|
|
|
+
|
|
|
+ expect(entityManager.find).toHaveBeenCalledWith(DummyApiResource, 1)
|
|
|
+ expect(result).toEqual(entity)
|
|
|
+ })
|
|
|
+
|
|
|
+ test('in store, but with force refresh', async () => {
|
|
|
+
|
|
|
+ const properties = { id: 1 }
|
|
|
+
|
|
|
+ const entity = new DummyApiResource({ id: 1 })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.find = vi.fn((model: typeof ApiResource, id: number) => undefined)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ apiRequestService.get = vi.fn(async (url: string) => properties)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.newInstance = vi.fn((model: typeof ApiResource, props: object) => entity)
|
|
|
+
|
|
|
+ const result = await entityManager.fetch(DummyApiResource, 1, true)
|
|
|
+
|
|
|
+ expect(entityManager.find).toHaveBeenCalledTimes(0)
|
|
|
+ expect(apiRequestService.get).toHaveBeenCalledWith('api/dummyResource/1')
|
|
|
+ expect(entityManager.newInstance).toHaveBeenCalledWith(DummyApiResource, properties)
|
|
|
+
|
|
|
+ expect(result).toEqual(entity)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('fetchCollection', () => {
|
|
|
+ test('simple call', async () => {
|
|
|
+
|
|
|
+ const collection = {
|
|
|
+ '@type': 'hydra:Collection',
|
|
|
+ 'hydra:totalItems': 3,
|
|
|
+ 'hydra:member': [
|
|
|
+ {id: 1},
|
|
|
+ {id: 2},
|
|
|
+ {id: 3},
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ apiRequestService.get = vi.fn(async (url: string) => collection)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.newInstance = vi.fn((model: typeof ApiResource, props: object) => {
|
|
|
+ return new DummyApiResource(props)
|
|
|
+ })
|
|
|
+
|
|
|
+ const result = await entityManager.fetchCollection(DummyApiResource, null)
|
|
|
+
|
|
|
+ expect(apiRequestService.get).toHaveBeenCalledWith('api/dummyResource', [])
|
|
|
+ expect(entityManager.newInstance).toHaveBeenCalledTimes(3)
|
|
|
+ expect(entityManager.newInstance).toHaveBeenCalledWith(DummyApiResource, {id: 1})
|
|
|
+ expect(entityManager.newInstance).toHaveBeenCalledWith(DummyApiResource, {id: 2})
|
|
|
+ expect(entityManager.newInstance).toHaveBeenCalledWith(DummyApiResource, {id: 3})
|
|
|
+
|
|
|
+ expect(result.items).toEqual([
|
|
|
+ new DummyApiResource({id: 1}),
|
|
|
+ new DummyApiResource({id: 2}),
|
|
|
+ new DummyApiResource({id: 3})
|
|
|
+ ])
|
|
|
+
|
|
|
+ expect(result.pagination, 'default pagination').toEqual({
|
|
|
+ first: 1,
|
|
|
+ last: 1,
|
|
|
+ next: undefined,
|
|
|
+ previous: undefined
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ test('with a parent', async () => {
|
|
|
+
|
|
|
+ const collection = {
|
|
|
+ '@type': 'hydra:Collection',
|
|
|
+ 'hydra:totalItems': 3,
|
|
|
+ 'hydra:member': [
|
|
|
+ {id: 1},
|
|
|
+ {id: 2},
|
|
|
+ {id: 3},
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ apiRequestService.get = vi.fn(async (url: string) => collection)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.newInstance = vi.fn((model: typeof ApiResource, props: object) => {
|
|
|
+ return new DummyApiResource(props)
|
|
|
+ })
|
|
|
+
|
|
|
+ const parent = new DummyApiModel()
|
|
|
+ parent.id = 100
|
|
|
+ parent.entity = 'dummyModel' // TODO: je ne comprend pas pqoi cette ligne est nécessaire...
|
|
|
+
|
|
|
+ await entityManager.fetchCollection(DummyApiResource, parent)
|
|
|
+
|
|
|
+ expect(apiRequestService.get).toHaveBeenCalledWith('api/dummyModel/100/dummyResource', [])
|
|
|
+ })
|
|
|
+
|
|
|
+ test('with a query', async () => {
|
|
|
+
|
|
|
+ const collection = {
|
|
|
+ '@type': 'hydra:Collection',
|
|
|
+ 'hydra:totalItems': 3,
|
|
|
+ 'hydra:member': [
|
|
|
+ {id: 1},
|
|
|
+ {id: 2},
|
|
|
+ {id: 3},
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ apiRequestService.get = vi.fn(async (url: string) => collection)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.newInstance = vi.fn((model: typeof ApiResource, props: object) => {
|
|
|
+ return new DummyApiResource(props)
|
|
|
+ })
|
|
|
+
|
|
|
+ await entityManager.fetchCollection(DummyApiResource, null, { page: 10 })
|
|
|
+
|
|
|
+ expect(apiRequestService.get).toHaveBeenCalledWith('api/dummyResource', { page: 10 })
|
|
|
+ })
|
|
|
+
|
|
|
+ test('with pagination', async () => {
|
|
|
+
|
|
|
+ const collection = {
|
|
|
+ '@type': 'hydra:Collection',
|
|
|
+ 'hydra:totalItems': 1000,
|
|
|
+ 'hydra:member': [],
|
|
|
+ 'hydra:view': {
|
|
|
+ "@id": "/api/subdomains?organization=498&page=50",
|
|
|
+ 'hydra:first': '/api/subdomains?organization=498&page=1',
|
|
|
+ 'hydra:last': '/api/subdomains?organization=498&page=100',
|
|
|
+ 'hydra:next': '/api/subdomains?organization=498&page=51',
|
|
|
+ 'hydra:previous': '/api/subdomains?organization=498&page=49'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ apiRequestService.get = vi.fn(async (url: string) => collection)
|
|
|
+
|
|
|
+ const result = await entityManager.fetchCollection(DummyApiResource, null)
|
|
|
+
|
|
|
+ expect(result.totalItems).toEqual(1000)
|
|
|
+ expect(result.pagination.first).toEqual(1)
|
|
|
+ expect(result.pagination.last).toEqual(100)
|
|
|
+ expect(result.pagination.previous).toEqual(49)
|
|
|
+ expect(result.pagination.next).toEqual(51)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('saveResponseAsEntity', () => {
|
|
|
+ test('simple call', async () => {
|
|
|
+
|
|
|
+ const entity = new DummyApiModel({id: 1})
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiModel ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const response = {id: 1} as Response
|
|
|
+
|
|
|
+ entityManager.newInstance = vi.fn((model: typeof ApiResource, properties: object) => {
|
|
|
+ return entity
|
|
|
+ })
|
|
|
+
|
|
|
+ entityManager.saveInitialState = vi.fn((model: typeof ApiResource, entity: ApiResource) => null)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.save = vi.fn((data: any) => null)
|
|
|
+
|
|
|
+ const result = await entityManager.saveResponseAsEntity(DummyApiModel, response)
|
|
|
+
|
|
|
+ expect(entityManager.getRepository).toHaveBeenCalledWith(DummyApiModel)
|
|
|
+ expect(entityManager.newInstance).toHaveBeenCalledWith(DummyApiModel, {id: 1})
|
|
|
+ expect(entityManager.saveInitialState).toHaveBeenCalledWith(DummyApiModel, entity)
|
|
|
+ expect(repo.save).toHaveBeenCalledWith(entity)
|
|
|
+
|
|
|
+ expect(result).toEqual(entity)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+describe('persist', () => {
|
|
|
+ test('new entity (POST)', async () => {
|
|
|
+ const entity = new DummyApiModel({id: 'tmp1', name: 'bob'})
|
|
|
+ entity.isNew = vi.fn(() => true)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entity.$toJson = vi.fn(() => {
|
|
|
+ return {id: 'tmp1', name: 'bob'}
|
|
|
+ })
|
|
|
+
|
|
|
+ entityManager.cast = vi.fn((model: typeof ApiResource, entity: ApiResource): ApiResource => entity)
|
|
|
+
|
|
|
+ const response = { id: 1, name: 'bob' }
|
|
|
+ // @ts-ignore
|
|
|
+ apiRequestService.post = vi.fn((url, data) => response)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.saveResponseAsEntity = vi.fn((model, response) => {
|
|
|
+ const newEntity = new DummyApiModel(response)
|
|
|
+ // @ts-ignore
|
|
|
+ newEntity.id = response.id
|
|
|
+ // @ts-ignore
|
|
|
+ newEntity.name = response.name
|
|
|
+
|
|
|
+ return newEntity
|
|
|
+ })
|
|
|
+
|
|
|
+ entityManager.removeTempAfterPersist = vi.fn()
|
|
|
+
|
|
|
+ const result = await entityManager.persist(DummyApiModel, entity)
|
|
|
+
|
|
|
+ // temp id should have been purged from the posted data
|
|
|
+ expect(apiRequestService.post).toHaveBeenCalledWith('api/dummyModel', {name: 'bob'})
|
|
|
+ expect(entityManager.saveResponseAsEntity).toHaveBeenCalledWith(DummyApiModel, response)
|
|
|
+ expect(entityManager.removeTempAfterPersist).toHaveBeenCalledWith(DummyApiModel, entity.id)
|
|
|
+
|
|
|
+ expect(result.id).toEqual(1)
|
|
|
+ expect(result.name).toEqual('bob')
|
|
|
+ })
|
|
|
+
|
|
|
+ test('existing entity (PUT)', async () => {
|
|
|
+ const props = {id: 1, name: 'bob'}
|
|
|
+ const entity = new DummyApiModel(props)
|
|
|
+ entity.id = 1
|
|
|
+ entity.isNew = vi.fn(() => false)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entity.$toJson = vi.fn(() => props)
|
|
|
+
|
|
|
+ entityManager.cast = vi.fn((model: typeof ApiResource, entity: ApiResource): ApiResource => entity)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ apiRequestService.put = vi.fn((url, data) => props)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.saveResponseAsEntity = vi.fn((model, response) => {
|
|
|
+ const newEntity = new DummyApiModel(response)
|
|
|
+ // @ts-ignore
|
|
|
+ newEntity.id = response.id
|
|
|
+ // @ts-ignore
|
|
|
+ newEntity.name = response.name
|
|
|
+
|
|
|
+ return newEntity
|
|
|
+ })
|
|
|
+
|
|
|
+ entityManager.removeTempAfterPersist = vi.fn()
|
|
|
+
|
|
|
+ const result = await entityManager.persist(DummyApiModel, entity)
|
|
|
+
|
|
|
+ expect(apiRequestService.put).toHaveBeenCalledWith('api/dummyModel/1', {id: 1, name: 'bob'})
|
|
|
+ expect(entityManager.saveResponseAsEntity).toHaveBeenCalledWith(DummyApiModel, props)
|
|
|
+ expect(entityManager.removeTempAfterPersist).toHaveBeenCalledTimes(0)
|
|
|
+
|
|
|
+ expect(result.id).toEqual(1)
|
|
|
+ expect(result.name).toEqual('bob')
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+describe('patch', () => {
|
|
|
+ test('simple call', async () => {
|
|
|
+ const props = {id: 1, name: 'bobby'}
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ apiRequestService.put = vi.fn((url, data) => props)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.saveResponseAsEntity = vi.fn((model, response) => {
|
|
|
+ const newEntity = new DummyApiModel(response)
|
|
|
+ // @ts-ignore
|
|
|
+ newEntity.id = response.id
|
|
|
+ // @ts-ignore
|
|
|
+ newEntity.name = response.name
|
|
|
+
|
|
|
+ return newEntity
|
|
|
+ })
|
|
|
+
|
|
|
+ const result = await entityManager.patch(DummyApiModel, 1, {name: 'bobby'})
|
|
|
+
|
|
|
+ expect(apiRequestService.put).toHaveBeenCalledWith('api/dummyModel/1', '{"name":"bobby"}')
|
|
|
+ expect(entityManager.saveResponseAsEntity).toHaveBeenCalledWith(DummyApiModel, {id: 1, name: 'bobby'})
|
|
|
+
|
|
|
+ expect(result.id).toEqual(1)
|
|
|
+ expect(result.name).toEqual('bobby')
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+describe('delete', () => {
|
|
|
+ test('delete non persisted entity', () => {
|
|
|
+ const entity = new DummyApiModel()
|
|
|
+ entity.isNew = vi.fn(() => true)
|
|
|
+ entity.id = 'tmp123'
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiModel ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ apiRequestService.delete = vi.fn()
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.destroy = vi.fn((id: number) => null)
|
|
|
+
|
|
|
+ entityManager.delete(DummyApiModel, entity)
|
|
|
+
|
|
|
+ expect(entityManager.getRepository).toHaveBeenCalledWith(DummyApiModel)
|
|
|
+ expect(apiRequestService.delete).toHaveBeenCalledTimes(0)
|
|
|
+ expect(repo.destroy).toHaveBeenCalledWith('tmp123')
|
|
|
+ })
|
|
|
+
|
|
|
+ test('delete persisted entity', async () => {
|
|
|
+ const entity = new DummyApiModel()
|
|
|
+ entity.isNew = vi.fn(() => false)
|
|
|
+ entity.id = 1
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiModel ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ apiRequestService.delete = vi.fn((id: number) => null)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.destroy = vi.fn((id: number) => null)
|
|
|
+
|
|
|
+ await entityManager.delete(DummyApiModel, entity)
|
|
|
+
|
|
|
+ expect(entityManager.getRepository).toHaveBeenCalledWith(DummyApiModel)
|
|
|
+ expect(apiRequestService.delete).toHaveBeenCalledWith('api/dummyModel/1')
|
|
|
+ expect(repo.destroy).toHaveBeenCalledWith(1)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('reset', () => {
|
|
|
+ test('simple call', () => {
|
|
|
+ const entity = new DummyApiModel()
|
|
|
+ entity.id = 1
|
|
|
+ entity.name = 'paul'
|
|
|
+
|
|
|
+ const initialEntity = new DummyApiModel()
|
|
|
+ initialEntity.id = 1
|
|
|
+ initialEntity.name = 'serges'
|
|
|
+
|
|
|
+ entityManager.getInitialStateOf = vi.fn((model: typeof ApiResource, id: string | number) => initialEntity)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiModel ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.save = vi.fn((data: any) => null)
|
|
|
+
|
|
|
+ const result = entityManager.reset(DummyApiModel, entity)
|
|
|
+
|
|
|
+ expect(entityManager.getInitialStateOf).toHaveBeenCalledWith(DummyApiModel, 1)
|
|
|
+ expect(repo.save).toHaveBeenCalledWith(initialEntity)
|
|
|
+ expect(result).toEqual(initialEntity)
|
|
|
+ })
|
|
|
+
|
|
|
+ test('no initial state stored', () => {
|
|
|
+ const entity = new DummyApiModel()
|
|
|
+ entity.id = 1
|
|
|
+
|
|
|
+ entityManager.getInitialStateOf = vi.fn((model: typeof ApiResource, id: string | number) => null)
|
|
|
+
|
|
|
+ expect(() => entityManager.reset(DummyApiModel, entity)).toThrowError(
|
|
|
+ 'no initial state recorded for this object - abort [dummyModel/1]'
|
|
|
+ )
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('flush', () => {
|
|
|
+ test('simple call', () => {
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiModel ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ repo.flush = vi.fn()
|
|
|
+
|
|
|
+ entityManager.flush(DummyApiModel)
|
|
|
+
|
|
|
+ expect(repo.flush).toHaveBeenCalled()
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('isNewEntity', () => {
|
|
|
+ test('with new entity', () => {
|
|
|
+ const entity = new DummyApiModel()
|
|
|
+ entity.isNew = vi.fn(() => true)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiModel ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.find = vi.fn((id: number) => entity)
|
|
|
+
|
|
|
+ const result = entityManager.isNewEntity(DummyApiModel, 1)
|
|
|
+
|
|
|
+ expect(result).toBeTruthy()
|
|
|
+ })
|
|
|
+
|
|
|
+ test('with existing entity', () => {
|
|
|
+ const entity = new DummyApiModel()
|
|
|
+ entity.isNew = vi.fn(() => false)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiModel ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.find = vi.fn((id: number) => entity)
|
|
|
+
|
|
|
+ const result = entityManager.isNewEntity(DummyApiModel, 1)
|
|
|
+
|
|
|
+ expect(result).toBeFalsy()
|
|
|
+ })
|
|
|
+
|
|
|
+ test('non-existing entity', () => {
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiModel ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.find = vi.fn((id: number) => null)
|
|
|
+
|
|
|
+ console.error = vi.fn()
|
|
|
+
|
|
|
+ const result = entityManager.isNewEntity(DummyApiModel, 1)
|
|
|
+
|
|
|
+ expect(result).toBeFalsy()
|
|
|
+
|
|
|
+ expect(console.error).toHaveBeenCalledWith('dummyModel/1 does not exist!')
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('saveInitialState', () => {
|
|
|
+ test('simple call', () => {
|
|
|
+ // @ts-ignore
|
|
|
+ const entity = { id: 1, name: 'bob' } as DummyApiResource
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiResource ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.save = vi.fn((record: Element) => null)
|
|
|
+
|
|
|
+ entityManager.saveInitialState(DummyApiResource, entity)
|
|
|
+
|
|
|
+ expect(repo.save).toHaveBeenCalledWith({ id: '_clone_1', name: 'bob' })
|
|
|
+ expect(entity.id).toEqual(1)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('getInitialStateOf', () => {
|
|
|
+ test('with initial state', () => {
|
|
|
+ // @ts-ignore
|
|
|
+ const entity = { id: 1, name: 'bob' } as DummyApiResource
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiResource ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.find = vi.fn((id: number | string) => {
|
|
|
+ // @ts-ignore
|
|
|
+ return { id: 1, name: 'robert' } as DummyApiResource
|
|
|
+ })
|
|
|
+
|
|
|
+ const result = entityManager.getInitialStateOf(DummyApiResource, 1) as DummyApiResource
|
|
|
+
|
|
|
+ expect(repo.find).toHaveBeenCalledWith('_clone_1')
|
|
|
+ expect(result.id).toEqual(1)
|
|
|
+ expect(result.name).toEqual('robert')
|
|
|
+ })
|
|
|
+
|
|
|
+ test('without initial state', () => {
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiResource ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.find = vi.fn((id: number | string) => null)
|
|
|
+
|
|
|
+ const result = entityManager.getInitialStateOf(DummyApiResource, 1) as DummyApiResource
|
|
|
+
|
|
|
+ expect(repo.find).toHaveBeenCalledWith('_clone_1')
|
|
|
+ expect(result).toEqual(null)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('removeTempAfterPersist', () => {
|
|
|
+ test('simple call', () => {
|
|
|
+ // @ts-ignore
|
|
|
+ const entity = new DummyApiResource()
|
|
|
+ entity.id = 'tmp123'
|
|
|
+ entity.isNew = vi.fn(() => true)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiResource ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.find = vi.fn((id: number | string) => entity)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.destroy = vi.fn()
|
|
|
+
|
|
|
+ entityManager.removeTempAfterPersist(DummyApiResource, 'tmp123')
|
|
|
+
|
|
|
+ expect(repo.destroy).toHaveBeenCalledWith('tmp123')
|
|
|
+ expect(repo.destroy).toHaveBeenCalledWith('_clone_tmp123')
|
|
|
+ })
|
|
|
+
|
|
|
+ test('entity is not temporary', () => {
|
|
|
+ // @ts-ignore
|
|
|
+ const entity = new DummyApiResource()
|
|
|
+ entity.id = 1
|
|
|
+ entity.isNew = vi.fn(() => false)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiResource ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.find = vi.fn((id: number | string) => entity)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.destroy = vi.fn()
|
|
|
+
|
|
|
+ expect(() => entityManager.removeTempAfterPersist(DummyApiResource, 'tmp123')).toThrowError(
|
|
|
+ 'Error: Can not remove a non-temporary entity'
|
|
|
+ )
|
|
|
+
|
|
|
+ expect(repo.destroy).toHaveBeenCalledTimes(0)
|
|
|
+ })
|
|
|
+
|
|
|
+ test('entity does not exist', () => {
|
|
|
+ // @ts-ignore
|
|
|
+ const repo = vi.fn() as Repository<ApiResource>
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
|
|
|
+ return model === DummyApiResource ? repo : null
|
|
|
+ })
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.find = vi.fn((id: number | string) => null)
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ repo.destroy = vi.fn()
|
|
|
+
|
|
|
+ console.error = vi.fn()
|
|
|
+
|
|
|
+ entityManager.removeTempAfterPersist(DummyApiResource, 'tmp123')
|
|
|
+
|
|
|
+ expect(repo.destroy).toHaveBeenCalledTimes(0)
|
|
|
+ expect(console.error).toHaveBeenCalledWith('dummyResource/tmp123 does not exist!')
|
|
|
+ })
|
|
|
+})
|