| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 |
- import { vi, describe, test, it, expect, afterEach } from 'vitest'
- import { Str, Uid, Attr } from 'pinia-orm/dist/decorators'
- import type { AnyJson } from '~/types/data'
- import HydraNormalizer from '~/services/data/normalizer/hydraNormalizer'
- import { METADATA_TYPE } from '~/types/enum/data'
- import ApiModel from '~/models/ApiModel'
- import { IriEncoded } from '~/models/decorators'
- import UrlUtils from '~/services/utils/urlUtils'
- import ApiResource from '~/models/ApiResource'
- class DummyApiChild extends ApiModel {
- static entity = 'dummyChild'
- @Uid()
- declare id: number | string
- }
- class DummyApiModel extends ApiModel {
- static entity = 'dummyModel'
- @Uid()
- declare id: number | string
- @Attr(null)
- @IriEncoded(DummyApiChild)
- declare oneToOneRelation: number | null
- @Attr([])
- @IriEncoded(DummyApiChild)
- declare oneToManyRelation: []
- @Str(null)
- declare name: null
- }
- afterEach(() => {
- vi.clearAllMocks()
- vi.resetAllMocks()
- })
- describe('normalize', () => {
- const initialMakeUriMethod = UrlUtils.makeIRI
- afterEach(() => {
- UrlUtils.makeIRI = initialMakeUriMethod
- })
- test('should normalize an entity into a JSON Object', () => {
- const entity: DummyApiModel = new DummyApiModel({
- id: 7351,
- oneToOneRelation: 99,
- oneToManyRelation: [123, 124, 125],
- })
- // @ts-ignore
- UrlUtils.makeIRI = vi.fn((targetEntity, id) => {
- return {
- 99: '/api/dummyChild/99',
- 123: '/api/dummyChild/123',
- 124: '/api/dummyChild/124',
- 125: '/api/dummyChild/125',
- }[id]
- })
- const result = HydraNormalizer.normalizeEntity(entity)
- const expected = {
- id: 7351,
- name: null,
- oneToOneRelation: '/api/dummyChild/99',
- oneToManyRelation: [
- '/api/dummyChild/123',
- '/api/dummyChild/124',
- '/api/dummyChild/125',
- ],
- }
- expect(result).toStrictEqual(expected)
- })
- })
- describe('denormalize', () => {
- // @ts-ignore
- const initialGetDataMethod = HydraNormalizer.getData
- // @ts-ignore
- const initialGetMetadataMethod = HydraNormalizer.getMetadata
- afterEach(() => {
- // @ts-ignore
- HydraNormalizer.getData = initialGetDataMethod
- // @ts-ignore
- HydraNormalizer.getMetadata = initialGetMetadataMethod
- })
- test('should parse a API Item response and return a JSON Object', () => {
- const data: AnyJson = { id: 1, name: 'foo' }
- // @ts-ignore
- HydraNormalizer.getData = vi.fn((data, model) => {
- return data
- })
- // @ts-ignore
- HydraNormalizer.getMetadata = vi.fn((data, model) => {
- return { type: METADATA_TYPE.ITEM }
- })
- const result = HydraNormalizer.denormalize(data, DummyApiModel)
- const expected = {
- data: {
- id: 1,
- name: 'foo',
- },
- metadata: {
- type: METADATA_TYPE.ITEM,
- },
- }
- expect(result).toEqual(expected)
- })
- })
- describe('getData', () => {
- test('With collection', () => {
- const data = {
- '@context': '/api/contexts/Foo',
- '@id': '/api/foo',
- '@type': 'Collection',
- member: ['foo'],
- }
- // @ts-ignore
- expect(HydraNormalizer.getData(data)).toEqual(['foo'])
- })
- test('With item', () => {
- const data = {
- '@context': '/api/contexts/Foo',
- '@id': '/api/foo',
- '@type': 'Foo',
- param1: 'a',
- }
- // @ts-ignore
- expect(HydraNormalizer.getData(data)).toEqual(data)
- })
- })
- describe('getMetadata', () => {
- test('With valid collection metadata', () => {
- const data = {
- '@context': '/api/contexts/Foo',
- '@id': '/api/foo',
- '@type': 'Collection',
- member: ['foo'],
- totalItems: 10,
- view: {
- '@id': '/api/foo?page=3',
- '@type': 'PartialCollectionView',
- first: '/api/foo?page=1',
- last: '/api/foo?page=5',
- next: '/api/foo?page=4',
- previous: '/api/foo?page=2',
- },
- }
- // @ts-ignore
- const metadata = HydraNormalizer.getMetadata(data)
- expect(metadata.totalItems).toEqual(10)
- expect(metadata.first).toEqual(1)
- expect(metadata.last).toEqual(5)
- expect(metadata.next).toEqual(4)
- expect(metadata.previous).toEqual(2)
- expect(metadata.type).toEqual(METADATA_TYPE.COLLECTION)
- })
- test('With partial collection metadata', () => {
- const data = {
- '@context': '/api/contexts/Foo',
- '@id': '/api/foo',
- '@type': 'Collection',
- member: ['foo'],
- totalItems: 10,
- view: {
- '@id': '/api/foo?page=3',
- '@type': 'PartialCollectionView',
- first: '/api/foo?page=1',
- },
- }
- // @ts-ignore
- const metadata = HydraNormalizer.getMetadata(data)
- expect(metadata.totalItems).toEqual(10)
- expect(metadata.first).toEqual(1)
- expect(metadata.last).toEqual(1)
- expect(metadata.next).toEqual(undefined)
- expect(metadata.previous).toEqual(undefined)
- })
- test('With item metadata', () => {
- // @ts-ignore
- const metadata = HydraNormalizer.getMetadata({})
- expect(metadata.type).toEqual(METADATA_TYPE.ITEM)
- })
- })
- describe('denormalizeItem', () => {
- // @ts-ignore
- const initialDenormalizeEntity = HydraNormalizer.denormalizeEntity
- // @ts-ignore
- const initialDenormalizeEnum = HydraNormalizer.denormalizeEnum
- // @ts-ignore
- const initialParseEntityIRI = HydraNormalizer.parseEntityIRI
- const initialConsoleError = console.error
- afterEach(() => {
- // @ts-ignore
- HydraNormalizer.denormalizeEntity = initialDenormalizeEntity
- // @ts-ignore
- HydraNormalizer.denormalizeEnum = initialDenormalizeEnum
- // @ts-ignore
- HydraNormalizer.parseEntityIRI = initialParseEntityIRI
- console.error = initialConsoleError
- })
- test('With provided model', () => {
- const item = {
- '@id': '/api/dummyModel/1',
- id: 1,
- name: 'foo',
- }
- const model = DummyApiModel
- const expected = new DummyApiModel(item)
- // @ts-ignore
- HydraNormalizer.denormalizeEntity = vi.fn((model, item) => {
- return expected
- })
- // @ts-ignore
- const result = HydraNormalizer.denormalizeItem(item, model)
- expect(result).toEqual(expected)
- // @ts-ignore
- expect(HydraNormalizer.denormalizeEntity).toHaveBeenCalledWith(model, item)
- })
- test('with no @id prop', () => {
- const item = {
- id: 1,
- name: 'foo',
- }
- console.error = vi.fn((msg) => {})
- // @ts-ignore
- const result = HydraNormalizer.denormalizeItem(item)
- expect(result).toEqual(item)
- expect(console.error).toHaveBeenCalledWith(
- 'De-normalization error : the item is not hydra formatted',
- item,
- )
- })
- test('with enum', () => {
- const item = {
- '@id': '/api/enum/abc',
- A: 1,
- B: 2,
- C: 3,
- }
- // @ts-ignore
- HydraNormalizer.denormalizeEnum = vi.fn((item) => {
- return item
- })
- // @ts-ignore
- const result = HydraNormalizer.denormalizeItem(item)
- expect(result).toEqual(item)
- // @ts-ignore
- expect(HydraNormalizer.denormalizeEnum).toHaveBeenCalledWith(item)
- })
- test('with unparsable iri', () => {
- const item = {
- '@id': 'some_invalid_iri',
- id: 1,
- name: 'foo',
- }
- // @ts-ignore
- HydraNormalizer.parseEntityIRI = vi.fn((iri) => {
- throw new Error('parsing error')
- })
- console.error = vi.fn((msg) => {})
- // @ts-ignore
- const result = HydraNormalizer.denormalizeItem(item)
- expect(result).toEqual(item)
- // @ts-ignore
- expect(console.error).toHaveBeenCalledWith(
- 'De-normalization error : could not parse the IRI',
- item,
- )
- })
- test('With valid iri and existing model', () => {
- HydraNormalizer.models = {
- dummyModel: DummyApiModel,
- }
- const item = {
- '@id': '/api/dummyModel/1',
- id: 1,
- name: 'foo',
- }
- // @ts-ignore
- HydraNormalizer.parseEntityIRI = vi.fn((iri) => {
- return { entity: 'dummyModel' }
- })
- const expected = new DummyApiModel(item)
- // @ts-ignore
- HydraNormalizer.denormalizeEntity = vi.fn((model, item) => {
- return expected
- })
- // @ts-ignore
- const result = HydraNormalizer.denormalizeItem(item)
- expect(result).toEqual(expected)
- // @ts-ignore
- expect(HydraNormalizer.denormalizeEntity).toHaveBeenCalledWith(
- DummyApiModel,
- item,
- )
- })
- test('With valid iri and un-existing model', () => {
- HydraNormalizer.models = {
- dummyModel: DummyApiModel,
- }
- const item = {
- '@id': '/api/unknownModel/1',
- id: 1,
- name: 'foo',
- }
- // @ts-ignore
- HydraNormalizer.parseEntityIRI = vi.fn((iri) => {
- return 'unknownModel'
- })
- expect(
- // @ts-ignore
- () => HydraNormalizer.denormalizeItem(item),
- ).toThrowError()
- })
- })
- describe('denormalizeEntity', () => {
- // @ts-ignore
- const initialGetIdFromEntityIriMethod = HydraNormalizer.getIdFromEntityIri
- afterEach(() => {
- // @ts-ignore
- HydraNormalizer.getIdFromEntityIri = initialGetIdFromEntityIriMethod
- })
- test('should denormalize a Json object into an entity', () => {
- const data = {
- id: 7351,
- name: null,
- oneToOneRelation: '/api/dummyChild/99',
- oneToManyRelation: [
- '/api/dummyChild/123',
- '/api/dummyChild/124',
- '/api/dummyChild/125',
- ],
- }
- // @ts-ignore
- HydraNormalizer.getIdFromEntityIri = vi.fn((iri) => {
- return {
- '/api/dummyChild/99': 99,
- '/api/dummyChild/123': 123,
- '/api/dummyChild/124': 124,
- '/api/dummyChild/125': 125,
- }[iri]
- })
- // @ts-ignore
- const result = HydraNormalizer.denormalizeEntity(DummyApiModel, data)
- expect(result).toStrictEqual(
- new DummyApiModel({
- id: 7351,
- name: null,
- oneToOneRelation: 99,
- oneToManyRelation: [123, 124, 125],
- }),
- )
- })
- test('should ignore relations fields when missing in the incoming data', () => {
- const data = {
- id: 7351,
- name: 'Bob',
- oneToManyRelation: [
- '/api/dummyChild/123',
- '/api/dummyChild/124',
- '/api/dummyChild/125',
- ],
- }
- // @ts-ignore
- HydraNormalizer.getIdFromEntityIri = vi.fn((iri) => {
- return {
- '/api/dummyChild/123': 123,
- '/api/dummyChild/124': 124,
- '/api/dummyChild/125': 125,
- }[iri]
- })
- // @ts-ignore
- const result = HydraNormalizer.denormalizeEntity(DummyApiModel, data)
- expect(result).toStrictEqual(
- new DummyApiModel({
- id: 7351,
- name: 'Bob',
- oneToOneRelation: null,
- oneToManyRelation: [123, 124, 125],
- }),
- )
- })
- test('should handle relations with empty values', () => {
- const data = {
- id: 7351,
- name: null,
- oneToOneRelation: null,
- oneToManyRelation: [],
- }
- // @ts-ignore
- HydraNormalizer.getIriEncodedFields = vi.fn((entity) => {
- return {
- oneToOneRelation: DummyApiChild,
- oneToManyRelation: DummyApiChild,
- }
- })
- // @ts-ignore
- const result = HydraNormalizer.denormalizeEntity(DummyApiModel, data)
- expect(result).toStrictEqual(
- new DummyApiModel({
- id: 7351,
- name: null,
- oneToOneRelation: null,
- oneToManyRelation: [],
- }),
- )
- })
- })
- describe('denormalizeEnum', () => {
- test('does nothing', () => {
- const item = {
- '@id': '/api/enum/abc',
- A: 1,
- B: 2,
- C: 3,
- }
- // @ts-ignore
- expect(HydraNormalizer.denormalizeEnum(item)).toStrictEqual(item)
- })
- })
- describe('parseEntityIRI', () => {
- test('valid iri', () => {
- const iri = '/api/someEntity/456'
- const expected = {
- entity: 'someEntity',
- id: 456,
- }
- // @ts-ignore
- expect(HydraNormalizer.parseEntityIRI(iri)).toStrictEqual(expected)
- })
- test('invalid iri', () => {
- const iri = 'some_invalid_iri'
- // @ts-ignore
- expect(() => HydraNormalizer.parseEntityIRI(iri)).toThrowError(
- 'could not parse the IRI : "some_invalid_iri"',
- )
- })
- })
- describe('getIdFromEntityIri', () => {
- // @ts-ignore
- const initialParseEntityIRI = HydraNormalizer.parseEntityIRI
- afterEach(() => {
- // @ts-ignore
- HydraNormalizer.parseEntityIRI = initialParseEntityIRI
- })
- test('valid iri', () => {
- const iri = '/api/someEntity/456'
- // @ts-ignore
- const result = HydraNormalizer.getIdFromEntityIri(iri, 'someEntity')
- expect(result).toEqual(456)
- })
- test('entity not matching', () => {
- const iri = '/api/someEntity/456'
- // @ts-ignore
- expect(
- // @ts-ignore
- () => HydraNormalizer.getIdFromEntityIri(iri, 'otherEntity'),
- ).toThrowError(
- "IRI entity does not match the field's target entity (someEntity != otherEntity)",
- )
- })
- })
|