entityManager.test.ts 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. import { describe, test, it, expect } from 'vitest'
  2. import EntityManager from "~/services/data/entityManager";
  3. import ApiResource from "~/models/ApiResource";
  4. import ApiModel from "~/models/ApiModel";
  5. import ApiRequestService from "~/services/data/apiRequestService";
  6. import {Element, Repository} from "pinia-orm";
  7. // TODO: vérifier si les classes Testable sont bien nécessaires, sinon les supprimer
  8. class TestableEntityManager extends EntityManager {
  9. public cast(model: typeof ApiResource, entity: ApiResource): ApiResource { return super.cast(model, entity) }
  10. public async saveResponseAsEntity(model: typeof ApiModel, response: Response) { return super.saveResponseAsEntity(model, response) }
  11. public saveInitialState(model: typeof ApiResource, entity: ApiResource) { return super.saveInitialState(model, entity) }
  12. public getInitialStateOf(model: typeof ApiResource, id: string | number): ApiResource | null { return super.getInitialStateOf(model, id) }
  13. public removeTempAfterPersist(model: typeof ApiResource, tempEntityId: number | string) { return super.removeTempAfterPersist(model, tempEntityId) }
  14. }
  15. class DummyApiResource extends ApiResource {
  16. static entity = 'dummyResource'
  17. }
  18. class DummyApiModel extends ApiModel {
  19. static entity = 'dummyModel'
  20. }
  21. let apiRequestService: ApiRequestService
  22. let entityManager: TestableEntityManager
  23. beforeEach(() => {
  24. // @ts-ignore
  25. apiRequestService = vi.fn() as ApiRequestService
  26. entityManager = new TestableEntityManager(apiRequestService)
  27. // TODO: s'assurer que les mocks globaux sont bien réinitialisés après les tests, en particulier les fonctions de console
  28. })
  29. describe('getRepository', () => {
  30. // TODO: à revoir
  31. })
  32. describe('cast', () => {
  33. test('simple cast', () => {
  34. // @ts-ignore
  35. const result = entityManager.cast(DummyApiResource, { id: 1 })
  36. expect(result instanceof DummyApiResource).toEqual(true)
  37. })
  38. })
  39. describe('getModelFor', () => {
  40. // TODO: à revoir
  41. })
  42. describe('getModelFromIri', () => {
  43. test('simple call', () => {
  44. // @ts-ignore
  45. entityManager.getModelFor = vi.fn((entityName: string) => entityName === 'dummy' ? DummyApiResource : null)
  46. // @ts-ignore
  47. const result = entityManager.getModelFromIri('/api/dummy/123')
  48. expect(result).toEqual(DummyApiResource)
  49. })
  50. test('invalide Iri', () => {
  51. expect(() => entityManager.getModelFromIri('/invalid')).toThrowError('cannot parse the IRI')
  52. })
  53. })
  54. describe('newInstance', () => {
  55. test('simple call', () => {
  56. const properties = { 'id': 1 }
  57. // @ts-ignore TODO: voir à factoriser
  58. const repo = vi.fn() as Repository<ApiResource>
  59. // @ts-ignore
  60. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  61. return model === DummyApiResource ? repo : null
  62. })
  63. entityManager.saveInitialState = vi.fn((model: typeof ApiResource, entity: ApiResource) => null)
  64. // @ts-ignore
  65. const entity = new DummyApiResource(properties)
  66. entity.setModel = vi.fn((model: typeof ApiResource) => null)
  67. // @ts-ignore
  68. repo.make = vi.fn((properties: object) => {
  69. // @ts-ignore
  70. entity.id = properties.id
  71. return entity
  72. })
  73. // @ts-ignore
  74. repo.save = vi.fn((record: Element) => entity)
  75. const result = entityManager.newInstance(DummyApiResource, properties)
  76. expect(repo.make).toHaveBeenCalledWith(properties)
  77. expect(entity.setModel).toHaveBeenCalledWith(DummyApiResource)
  78. expect(repo.save).toHaveBeenCalledWith(entity)
  79. expect(entityManager.saveInitialState).toHaveBeenCalledWith(DummyApiResource, entity)
  80. expect(result.id).toEqual(properties.id)
  81. })
  82. test('with no id provided', () => {
  83. const properties = { 'name': 'bob' }
  84. // @ts-ignore
  85. const repo = vi.fn() as Repository<ApiResource>
  86. // @ts-ignore
  87. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  88. return model === DummyApiResource ? repo : null
  89. })
  90. entityManager.saveInitialState = vi.fn((model: typeof ApiResource, entity: ApiResource) => null)
  91. // @ts-ignore
  92. const entity = new DummyApiResource(properties)
  93. entity.setModel = vi.fn((model: typeof ApiResource) => null)
  94. // @ts-ignore
  95. repo.make = vi.fn((properties: object) => {
  96. // @ts-ignore
  97. entity.name = properties.name
  98. return entity
  99. })
  100. // @ts-ignore
  101. repo.save = vi.fn((record: Element) => entity)
  102. const result = entityManager.newInstance(DummyApiResource, properties)
  103. expect(
  104. result.id,
  105. 'id is \'tmp\' followed by a valid uuid-V4'
  106. ).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}/)
  107. expect(result.name).toEqual(properties.name)
  108. })
  109. })
  110. describe('save', () => {
  111. test('simple call', () => {
  112. // @ts-ignore
  113. const repo = vi.fn() as Repository<ApiResource>
  114. // @ts-ignore
  115. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  116. return model === DummyApiResource ? repo : null
  117. })
  118. // @ts-ignore
  119. repo.save = vi.fn((record: Element) => entity)
  120. const entity = new DummyApiResource()
  121. entityManager.save(DummyApiResource, entity)
  122. expect(repo.save).toHaveBeenCalledWith(entity)
  123. })
  124. })
  125. describe('find', () => {
  126. test('simple call', () => {
  127. // @ts-ignore
  128. const repo = vi.fn() as Repository<ApiResource>
  129. // @ts-ignore
  130. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  131. return model === DummyApiResource ? repo : null
  132. })
  133. const entity = new DummyApiResource({ id: 1 })
  134. // @ts-ignore
  135. repo.find = vi.fn((id: string | number) => entity)
  136. entityManager.find(DummyApiResource, 1)
  137. expect(entityManager.getRepository).toHaveBeenCalledWith(DummyApiResource)
  138. expect(repo.find).toHaveBeenCalledWith(1)
  139. })
  140. })
  141. describe('fetch', () => {
  142. test('not in store, no force refresh', async () => {
  143. const properties = { id: 1 }
  144. const entity = new DummyApiResource({ id: 1 })
  145. // @ts-ignore
  146. entityManager.find = vi.fn((model: typeof ApiResource, id: number) => undefined)
  147. // @ts-ignore
  148. apiRequestService.get = vi.fn(async (url: string) => properties)
  149. // @ts-ignore
  150. entityManager.newInstance = vi.fn((model: typeof ApiResource, props: object) => entity)
  151. const result = await entityManager.fetch(DummyApiResource, 1)
  152. expect(entityManager.find).toHaveBeenCalledWith(DummyApiResource, 1)
  153. expect(apiRequestService.get).toHaveBeenCalledWith('api/dummyResource/1')
  154. expect(entityManager.newInstance).toHaveBeenCalledWith(DummyApiResource, properties)
  155. expect(result).toEqual(entity)
  156. })
  157. test('in store, no force refresh', async () => {
  158. const properties = { id: 1 }
  159. const entity = new DummyApiResource({ id: 1 })
  160. // @ts-ignore
  161. entityManager.find = vi.fn((model: typeof ApiResource, id: number) => entity)
  162. const result = await entityManager.fetch(DummyApiResource, 1)
  163. expect(entityManager.find).toHaveBeenCalledWith(DummyApiResource, 1)
  164. expect(result).toEqual(entity)
  165. })
  166. test('in store, but with force refresh', async () => {
  167. const properties = { id: 1 }
  168. const entity = new DummyApiResource({ id: 1 })
  169. // @ts-ignore
  170. entityManager.find = vi.fn((model: typeof ApiResource, id: number) => undefined)
  171. // @ts-ignore
  172. apiRequestService.get = vi.fn(async (url: string) => properties)
  173. // @ts-ignore
  174. entityManager.newInstance = vi.fn((model: typeof ApiResource, props: object) => entity)
  175. const result = await entityManager.fetch(DummyApiResource, 1, true)
  176. expect(entityManager.find).toHaveBeenCalledTimes(0)
  177. expect(apiRequestService.get).toHaveBeenCalledWith('api/dummyResource/1')
  178. expect(entityManager.newInstance).toHaveBeenCalledWith(DummyApiResource, properties)
  179. expect(result).toEqual(entity)
  180. })
  181. })
  182. describe('fetchCollection', () => {
  183. test('simple call', async () => {
  184. const collection = {
  185. '@type': 'hydra:Collection',
  186. 'hydra:totalItems': 3,
  187. 'hydra:member': [
  188. {id: 1},
  189. {id: 2},
  190. {id: 3},
  191. ]
  192. }
  193. // @ts-ignore
  194. apiRequestService.get = vi.fn(async (url: string) => collection)
  195. // @ts-ignore
  196. entityManager.newInstance = vi.fn((model: typeof ApiResource, props: object) => {
  197. return new DummyApiResource(props)
  198. })
  199. const result = await entityManager.fetchCollection(DummyApiResource, null)
  200. expect(apiRequestService.get).toHaveBeenCalledWith('api/dummyResource', [])
  201. expect(entityManager.newInstance).toHaveBeenCalledTimes(3)
  202. expect(entityManager.newInstance).toHaveBeenCalledWith(DummyApiResource, {id: 1})
  203. expect(entityManager.newInstance).toHaveBeenCalledWith(DummyApiResource, {id: 2})
  204. expect(entityManager.newInstance).toHaveBeenCalledWith(DummyApiResource, {id: 3})
  205. expect(result.items).toEqual([
  206. new DummyApiResource({id: 1}),
  207. new DummyApiResource({id: 2}),
  208. new DummyApiResource({id: 3})
  209. ])
  210. expect(result.pagination, 'default pagination').toEqual({
  211. first: 1,
  212. last: 1,
  213. next: undefined,
  214. previous: undefined
  215. })
  216. })
  217. test('with a parent', async () => {
  218. const collection = {
  219. '@type': 'hydra:Collection',
  220. 'hydra:totalItems': 3,
  221. 'hydra:member': [
  222. {id: 1},
  223. {id: 2},
  224. {id: 3},
  225. ]
  226. }
  227. // @ts-ignore
  228. apiRequestService.get = vi.fn(async (url: string) => collection)
  229. // @ts-ignore
  230. entityManager.newInstance = vi.fn((model: typeof ApiResource, props: object) => {
  231. return new DummyApiResource(props)
  232. })
  233. const parent = new DummyApiModel()
  234. parent.id = 100
  235. parent.entity = 'dummyModel' // TODO: je ne comprend pas pqoi cette ligne est nécessaire...
  236. await entityManager.fetchCollection(DummyApiResource, parent)
  237. expect(apiRequestService.get).toHaveBeenCalledWith('api/dummyModel/100/dummyResource', [])
  238. })
  239. test('with a query', async () => {
  240. const collection = {
  241. '@type': 'hydra:Collection',
  242. 'hydra:totalItems': 3,
  243. 'hydra:member': [
  244. {id: 1},
  245. {id: 2},
  246. {id: 3},
  247. ]
  248. }
  249. // @ts-ignore
  250. apiRequestService.get = vi.fn(async (url: string) => collection)
  251. // @ts-ignore
  252. entityManager.newInstance = vi.fn((model: typeof ApiResource, props: object) => {
  253. return new DummyApiResource(props)
  254. })
  255. await entityManager.fetchCollection(DummyApiResource, null, { page: 10 })
  256. expect(apiRequestService.get).toHaveBeenCalledWith('api/dummyResource', { page: 10 })
  257. })
  258. test('with pagination', async () => {
  259. const collection = {
  260. '@type': 'hydra:Collection',
  261. 'hydra:totalItems': 1000,
  262. 'hydra:member': [],
  263. 'hydra:view': {
  264. "@id": "/api/subdomains?organization=498&page=50",
  265. 'hydra:first': '/api/subdomains?organization=498&page=1',
  266. 'hydra:last': '/api/subdomains?organization=498&page=100',
  267. 'hydra:next': '/api/subdomains?organization=498&page=51',
  268. 'hydra:previous': '/api/subdomains?organization=498&page=49'
  269. }
  270. }
  271. // @ts-ignore
  272. apiRequestService.get = vi.fn(async (url: string) => collection)
  273. const result = await entityManager.fetchCollection(DummyApiResource, null)
  274. expect(result.totalItems).toEqual(1000)
  275. expect(result.pagination.first).toEqual(1)
  276. expect(result.pagination.last).toEqual(100)
  277. expect(result.pagination.previous).toEqual(49)
  278. expect(result.pagination.next).toEqual(51)
  279. })
  280. })
  281. describe('saveResponseAsEntity', () => {
  282. test('simple call', async () => {
  283. const entity = new DummyApiModel({id: 1})
  284. // @ts-ignore
  285. const repo = vi.fn() as Repository<ApiResource>
  286. // @ts-ignore
  287. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  288. return model === DummyApiModel ? repo : null
  289. })
  290. // @ts-ignore
  291. const response = {id: 1} as Response
  292. entityManager.newInstance = vi.fn((model: typeof ApiResource, properties: object) => {
  293. return entity
  294. })
  295. entityManager.saveInitialState = vi.fn((model: typeof ApiResource, entity: ApiResource) => null)
  296. // @ts-ignore
  297. repo.save = vi.fn((data: any) => null)
  298. const result = await entityManager.saveResponseAsEntity(DummyApiModel, response)
  299. expect(entityManager.getRepository).toHaveBeenCalledWith(DummyApiModel)
  300. expect(entityManager.newInstance).toHaveBeenCalledWith(DummyApiModel, {id: 1})
  301. expect(entityManager.saveInitialState).toHaveBeenCalledWith(DummyApiModel, entity)
  302. expect(repo.save).toHaveBeenCalledWith(entity)
  303. expect(result).toEqual(entity)
  304. })
  305. })
  306. describe('persist', () => {
  307. test('new entity (POST)', async () => {
  308. const entity = new DummyApiModel({id: 'tmp1', name: 'bob'})
  309. entity.isNew = vi.fn(() => true)
  310. // @ts-ignore
  311. entity.$toJson = vi.fn(() => {
  312. return {id: 'tmp1', name: 'bob'}
  313. })
  314. entityManager.cast = vi.fn((model: typeof ApiResource, entity: ApiResource): ApiResource => entity)
  315. const response = { id: 1, name: 'bob' }
  316. // @ts-ignore
  317. apiRequestService.post = vi.fn((url, data) => response)
  318. // @ts-ignore
  319. entityManager.saveResponseAsEntity = vi.fn((model, response) => {
  320. const newEntity = new DummyApiModel(response)
  321. // @ts-ignore
  322. newEntity.id = response.id
  323. // @ts-ignore
  324. newEntity.name = response.name
  325. return newEntity
  326. })
  327. entityManager.removeTempAfterPersist = vi.fn()
  328. const result = await entityManager.persist(DummyApiModel, entity)
  329. // temp id should have been purged from the posted data
  330. expect(apiRequestService.post).toHaveBeenCalledWith('api/dummyModel', {name: 'bob'})
  331. expect(entityManager.saveResponseAsEntity).toHaveBeenCalledWith(DummyApiModel, response)
  332. expect(entityManager.removeTempAfterPersist).toHaveBeenCalledWith(DummyApiModel, entity.id)
  333. expect(result.id).toEqual(1)
  334. expect(result.name).toEqual('bob')
  335. })
  336. test('existing entity (PUT)', async () => {
  337. const props = {id: 1, name: 'bob'}
  338. const entity = new DummyApiModel(props)
  339. entity.id = 1
  340. entity.isNew = vi.fn(() => false)
  341. // @ts-ignore
  342. entity.$toJson = vi.fn(() => props)
  343. entityManager.cast = vi.fn((model: typeof ApiResource, entity: ApiResource): ApiResource => entity)
  344. // @ts-ignore
  345. apiRequestService.put = vi.fn((url, data) => props)
  346. // @ts-ignore
  347. entityManager.saveResponseAsEntity = vi.fn((model, response) => {
  348. const newEntity = new DummyApiModel(response)
  349. // @ts-ignore
  350. newEntity.id = response.id
  351. // @ts-ignore
  352. newEntity.name = response.name
  353. return newEntity
  354. })
  355. entityManager.removeTempAfterPersist = vi.fn()
  356. const result = await entityManager.persist(DummyApiModel, entity)
  357. expect(apiRequestService.put).toHaveBeenCalledWith('api/dummyModel/1', {id: 1, name: 'bob'})
  358. expect(entityManager.saveResponseAsEntity).toHaveBeenCalledWith(DummyApiModel, props)
  359. expect(entityManager.removeTempAfterPersist).toHaveBeenCalledTimes(0)
  360. expect(result.id).toEqual(1)
  361. expect(result.name).toEqual('bob')
  362. })
  363. })
  364. describe('patch', () => {
  365. test('simple call', async () => {
  366. const props = {id: 1, name: 'bobby'}
  367. // @ts-ignore
  368. apiRequestService.put = vi.fn((url, data) => props)
  369. // @ts-ignore
  370. entityManager.saveResponseAsEntity = vi.fn((model, response) => {
  371. const newEntity = new DummyApiModel(response)
  372. // @ts-ignore
  373. newEntity.id = response.id
  374. // @ts-ignore
  375. newEntity.name = response.name
  376. return newEntity
  377. })
  378. const result = await entityManager.patch(DummyApiModel, 1, {name: 'bobby'})
  379. expect(apiRequestService.put).toHaveBeenCalledWith('api/dummyModel/1', '{"name":"bobby"}')
  380. expect(entityManager.saveResponseAsEntity).toHaveBeenCalledWith(DummyApiModel, {id: 1, name: 'bobby'})
  381. expect(result.id).toEqual(1)
  382. expect(result.name).toEqual('bobby')
  383. })
  384. })
  385. describe('delete', () => {
  386. test('delete non persisted entity', () => {
  387. const entity = new DummyApiModel()
  388. entity.isNew = vi.fn(() => true)
  389. entity.id = 'tmp123'
  390. // @ts-ignore
  391. const repo = vi.fn() as Repository<ApiResource>
  392. // @ts-ignore
  393. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  394. return model === DummyApiModel ? repo : null
  395. })
  396. apiRequestService.delete = vi.fn()
  397. // @ts-ignore
  398. repo.destroy = vi.fn((id: number) => null)
  399. entityManager.delete(DummyApiModel, entity)
  400. expect(entityManager.getRepository).toHaveBeenCalledWith(DummyApiModel)
  401. expect(apiRequestService.delete).toHaveBeenCalledTimes(0)
  402. expect(repo.destroy).toHaveBeenCalledWith('tmp123')
  403. })
  404. test('delete persisted entity', async () => {
  405. const entity = new DummyApiModel()
  406. entity.isNew = vi.fn(() => false)
  407. entity.id = 1
  408. // @ts-ignore
  409. const repo = vi.fn() as Repository<ApiResource>
  410. // @ts-ignore
  411. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  412. return model === DummyApiModel ? repo : null
  413. })
  414. // @ts-ignore
  415. apiRequestService.delete = vi.fn((id: number) => null)
  416. // @ts-ignore
  417. repo.destroy = vi.fn((id: number) => null)
  418. await entityManager.delete(DummyApiModel, entity)
  419. expect(entityManager.getRepository).toHaveBeenCalledWith(DummyApiModel)
  420. expect(apiRequestService.delete).toHaveBeenCalledWith('api/dummyModel/1')
  421. expect(repo.destroy).toHaveBeenCalledWith(1)
  422. })
  423. })
  424. describe('reset', () => {
  425. test('simple call', () => {
  426. const entity = new DummyApiModel()
  427. entity.id = 1
  428. entity.name = 'paul'
  429. const initialEntity = new DummyApiModel()
  430. initialEntity.id = 1
  431. initialEntity.name = 'serges'
  432. entityManager.getInitialStateOf = vi.fn((model: typeof ApiResource, id: string | number) => initialEntity)
  433. // @ts-ignore
  434. const repo = vi.fn() as Repository<ApiResource>
  435. // @ts-ignore
  436. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  437. return model === DummyApiModel ? repo : null
  438. })
  439. // @ts-ignore
  440. repo.save = vi.fn((data: any) => null)
  441. const result = entityManager.reset(DummyApiModel, entity)
  442. expect(entityManager.getInitialStateOf).toHaveBeenCalledWith(DummyApiModel, 1)
  443. expect(repo.save).toHaveBeenCalledWith(initialEntity)
  444. expect(result).toEqual(initialEntity)
  445. })
  446. test('no initial state stored', () => {
  447. const entity = new DummyApiModel()
  448. entity.id = 1
  449. entityManager.getInitialStateOf = vi.fn((model: typeof ApiResource, id: string | number) => null)
  450. expect(() => entityManager.reset(DummyApiModel, entity)).toThrowError(
  451. 'no initial state recorded for this object - abort [dummyModel/1]'
  452. )
  453. })
  454. })
  455. describe('flush', () => {
  456. test('simple call', () => {
  457. // @ts-ignore
  458. const repo = vi.fn() as Repository<ApiResource>
  459. // @ts-ignore
  460. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  461. return model === DummyApiModel ? repo : null
  462. })
  463. repo.flush = vi.fn()
  464. entityManager.flush(DummyApiModel)
  465. expect(repo.flush).toHaveBeenCalled()
  466. })
  467. })
  468. describe('isNewEntity', () => {
  469. test('with new entity', () => {
  470. const entity = new DummyApiModel()
  471. entity.isNew = vi.fn(() => true)
  472. // @ts-ignore
  473. const repo = vi.fn() as Repository<ApiResource>
  474. // @ts-ignore
  475. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  476. return model === DummyApiModel ? repo : null
  477. })
  478. // @ts-ignore
  479. repo.find = vi.fn((id: number) => entity)
  480. const result = entityManager.isNewEntity(DummyApiModel, 1)
  481. expect(result).toBeTruthy()
  482. })
  483. test('with existing entity', () => {
  484. const entity = new DummyApiModel()
  485. entity.isNew = vi.fn(() => false)
  486. // @ts-ignore
  487. const repo = vi.fn() as Repository<ApiResource>
  488. // @ts-ignore
  489. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  490. return model === DummyApiModel ? repo : null
  491. })
  492. // @ts-ignore
  493. repo.find = vi.fn((id: number) => entity)
  494. const result = entityManager.isNewEntity(DummyApiModel, 1)
  495. expect(result).toBeFalsy()
  496. })
  497. test('non-existing entity', () => {
  498. // @ts-ignore
  499. const repo = vi.fn() as Repository<ApiResource>
  500. // @ts-ignore
  501. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  502. return model === DummyApiModel ? repo : null
  503. })
  504. // @ts-ignore
  505. repo.find = vi.fn((id: number) => null)
  506. console.error = vi.fn()
  507. const result = entityManager.isNewEntity(DummyApiModel, 1)
  508. expect(result).toBeFalsy()
  509. expect(console.error).toHaveBeenCalledWith('dummyModel/1 does not exist!')
  510. })
  511. })
  512. describe('saveInitialState', () => {
  513. test('simple call', () => {
  514. // @ts-ignore
  515. const entity = { id: 1, name: 'bob' } as DummyApiResource
  516. // @ts-ignore
  517. const repo = vi.fn() as Repository<ApiResource>
  518. // @ts-ignore
  519. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  520. return model === DummyApiResource ? repo : null
  521. })
  522. // @ts-ignore
  523. repo.save = vi.fn((record: Element) => null)
  524. entityManager.saveInitialState(DummyApiResource, entity)
  525. expect(repo.save).toHaveBeenCalledWith({ id: '_clone_1', name: 'bob' })
  526. expect(entity.id).toEqual(1)
  527. })
  528. })
  529. describe('getInitialStateOf', () => {
  530. test('with initial state', () => {
  531. // @ts-ignore
  532. const entity = { id: 1, name: 'bob' } as DummyApiResource
  533. // @ts-ignore
  534. const repo = vi.fn() as Repository<ApiResource>
  535. // @ts-ignore
  536. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  537. return model === DummyApiResource ? repo : null
  538. })
  539. // @ts-ignore
  540. repo.find = vi.fn((id: number | string) => {
  541. // @ts-ignore
  542. return { id: 1, name: 'robert' } as DummyApiResource
  543. })
  544. const result = entityManager.getInitialStateOf(DummyApiResource, 1) as DummyApiResource
  545. expect(repo.find).toHaveBeenCalledWith('_clone_1')
  546. expect(result.id).toEqual(1)
  547. expect(result.name).toEqual('robert')
  548. })
  549. test('without initial state', () => {
  550. // @ts-ignore
  551. const repo = vi.fn() as Repository<ApiResource>
  552. // @ts-ignore
  553. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  554. return model === DummyApiResource ? repo : null
  555. })
  556. // @ts-ignore
  557. repo.find = vi.fn((id: number | string) => null)
  558. const result = entityManager.getInitialStateOf(DummyApiResource, 1) as DummyApiResource
  559. expect(repo.find).toHaveBeenCalledWith('_clone_1')
  560. expect(result).toEqual(null)
  561. })
  562. })
  563. describe('removeTempAfterPersist', () => {
  564. test('simple call', () => {
  565. // @ts-ignore
  566. const entity = new DummyApiResource()
  567. entity.id = 'tmp123'
  568. entity.isNew = vi.fn(() => true)
  569. // @ts-ignore
  570. const repo = vi.fn() as Repository<ApiResource>
  571. // @ts-ignore
  572. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  573. return model === DummyApiResource ? repo : null
  574. })
  575. // @ts-ignore
  576. repo.find = vi.fn((id: number | string) => entity)
  577. // @ts-ignore
  578. repo.destroy = vi.fn()
  579. entityManager.removeTempAfterPersist(DummyApiResource, 'tmp123')
  580. expect(repo.destroy).toHaveBeenCalledWith('tmp123')
  581. expect(repo.destroy).toHaveBeenCalledWith('_clone_tmp123')
  582. })
  583. test('entity is not temporary', () => {
  584. // @ts-ignore
  585. const entity = new DummyApiResource()
  586. entity.id = 1
  587. entity.isNew = vi.fn(() => false)
  588. // @ts-ignore
  589. const repo = vi.fn() as Repository<ApiResource>
  590. // @ts-ignore
  591. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  592. return model === DummyApiResource ? repo : null
  593. })
  594. // @ts-ignore
  595. repo.find = vi.fn((id: number | string) => entity)
  596. // @ts-ignore
  597. repo.destroy = vi.fn()
  598. expect(() => entityManager.removeTempAfterPersist(DummyApiResource, 'tmp123')).toThrowError(
  599. 'Error: Can not remove a non-temporary entity'
  600. )
  601. expect(repo.destroy).toHaveBeenCalledTimes(0)
  602. })
  603. test('entity does not exist', () => {
  604. // @ts-ignore
  605. const repo = vi.fn() as Repository<ApiResource>
  606. // @ts-ignore
  607. entityManager.getRepository = vi.fn((model: typeof ApiResource) => {
  608. return model === DummyApiResource ? repo : null
  609. })
  610. // @ts-ignore
  611. repo.find = vi.fn((id: number | string) => null)
  612. // @ts-ignore
  613. repo.destroy = vi.fn()
  614. console.error = vi.fn()
  615. entityManager.removeTempAfterPersist(DummyApiResource, 'tmp123')
  616. expect(repo.destroy).toHaveBeenCalledTimes(0)
  617. expect(console.error).toHaveBeenCalledWith('dummyResource/tmp123 does not exist!')
  618. })
  619. })