UNPKG

@data-client/endpoint

Version:

Declarative Network Interface Definitions

407 lines (379 loc) 10.3 kB
// eslint-env jest import { normalize } from '@data-client/normalizr'; import { IDEntity } from '__tests__/new'; import { fromJS } from 'immutable'; import SimpleMemoCache from './denormalize'; import { schema } from '../../'; import { INVALID } from '../../special'; import Entity from '../Entity'; let dateSpy; beforeAll(() => { dateSpy = jest .spyOn(global.Date, 'now') .mockImplementation(() => new Date('2019-05-14T11:01:58.135Z').valueOf()); }); afterAll(() => { dateSpy.mockRestore(); }); class Cat extends IDEntity { type = ''; } class Dog extends IDEntity { type = ''; } describe(`${schema.Values.name} normalization`, () => { let warnSpy; afterEach(() => { warnSpy.mockRestore(); }); beforeEach(() => (warnSpy = jest.spyOn(console, 'warn')).mockImplementation(() => {}), ); test('normalizes without schemaAttribute', () => { class MyEntity extends IDEntity { name = ''; } const valuesSchema = new schema.Values(MyEntity); expect( normalize(valuesSchema, { first: { id: '1', name: 'first thing', }, second: { id: '2', name: 'second thing', }, }), ).toMatchSnapshot(); }); test('normalizes the values of an object with the given schema', () => { const valuesSchema = new schema.Values( { dogs: Dog, cats: Cat, }, entity => entity.type, ); expect( normalize(valuesSchema, { fido: { id: '1', type: 'dogs' }, fluffy: { id: '1', type: 'cats' }, }), ).toMatchSnapshot(); }); test('can use a function to determine the schema when normalizing', () => { const valuesSchema = new schema.Values( { dogs: Dog, cats: Cat, }, entity => `${entity.type}s`, ); expect( normalize(valuesSchema, { fido: { id: '1', type: 'dog' }, fluffy: { id: '1', type: 'cat' }, jim: { id: '2', type: 'lizard' }, }), ).toMatchSnapshot(); expect(warnSpy.mock.calls).toMatchSnapshot(); }); test('filters out null and undefined values', () => { const valuesSchema = new schema.Values( { dogs: Dog, cats: Cat, }, entity => entity.type, ); expect( normalize(valuesSchema, { fido: undefined, milo: null, fluffy: { id: '1', type: 'cats' }, }), ).toMatchSnapshot(); }); test('works on complex object', () => { class Estimate extends Entity { pk() { return this.fee.currency; } } const response = { data: { estimates: { BTC: { confirmation_duration: 900, exchange: { rate: '6820.07', local: 'USD', crypto: 'BTC', }, fee_per_kb: { amount: '0.00016566', currency: 'BTC', }, fee: { amount: '0.00002270', currency: 'BTC', }, priority: 'fast', recipient_value: { amount: '0.00054147', currency: 'BTC', }, exchange_to_proceeds: { rate: '6820.07', local: 'EUR', crypto: 'BTC', }, min_order_size: { amount: '0.001', currency: 'BTC', }, coinbase_fees: { amount: '0.00002270', currency: 'BTC', }, }, ETH: { confirmation_duration: 900, exchange: { rate: '197.07', local: 'USD', crypto: 'ETH', }, fee_per_kb: { amount: '0.00086', currency: 'ETH', }, fee: { amount: '0.03795', currency: 'ETH', }, priority: 'fast', recipient_value: { amount: '2.53', currency: 'ETH', }, exchange_to_proceeds: { rate: '6820.07', local: 'EUR', crypto: 'BTC', }, min_order_size: { amount: '0.001', currency: 'BTC', }, coinbase_fees: { amount: '0.00002270', currency: 'BTC', }, }, }, }, }; expect( normalize({ data: { estimates: new schema.Values(Estimate) } }, response), ).toMatchSnapshot(); }); }); describe.each([ ['direct', data => data], ['immutable', fromJS], ])(`input (%s)`, (_, createInput) => { describe.each([['current', new SimpleMemoCache().denormalize]])( `${schema.Values.name} denormalization (%s)`, (_, denormalize) => { test('denormalizes without schemaAttribute', () => { class MyEntity extends IDEntity { name = ''; } const valuesSchema = new schema.Values(MyEntity); const entities = { MyEntity: { 1: { id: '1', name: 'first thing', }, 2: { id: '2', name: 'second thing', }, }, }; expect( denormalize( valuesSchema, { first: '1', second: '2', }, createInput(entities), ), ).toMatchSnapshot(); }); test('denormalizes the values of an object with the given schema', () => { const valuesSchema = new schema.Values( { dogs: Dog, cats: Cat, }, entity => entity.type, ); const entities = { Cat: { 1: { id: '1', type: 'cats' } }, Dog: { 1: { id: '1', type: 'dogs' } }, }; expect( denormalize( valuesSchema, { fido: { id: '1', schema: 'dogs' }, fluffy: { id: '1', schema: 'cats' }, }, createInput(entities), ), ).toMatchSnapshot(); }); test('denormalizes with missing entity should have false second value', () => { const valuesSchema = new schema.Values( { dogs: Dog, cats: Cat, }, entity => entity.type, ); const entities = { Cat: { 1: { id: '1', type: 'cats' } }, Dog: { 1: { id: '1', type: 'dogs' } }, }; expect( denormalize( valuesSchema, { fido: { id: '1', schema: 'dogs' }, fluffy: { id: '1', schema: 'cats' }, prancy: { id: '5', schema: 'cats' }, }, createInput(entities), ), ).toMatchSnapshot(); }); test('denormalizes with deleted entity should just remove them', () => { const valuesSchema = new schema.Values( { dogs: Dog, cats: Cat, }, entity => entity.type, ); const entities = { Cat: { 1: { id: '1', type: 'cats' }, 5: INVALID }, Dog: { 1: { id: '1', type: 'dogs' } }, }; expect( denormalize( valuesSchema, { fido: { id: '1', schema: 'dogs' }, fluffy: { id: '1', schema: 'cats' }, prancy: { id: '5', schema: 'cats' }, }, createInput(entities), ), ).toMatchSnapshot(); }); test('works on complex object', () => { class Estimate extends Entity { pk() { return this.fee.currency; } } const response = { data: { estimates: { BTC: { confirmation_duration: 900, exchange: { rate: '6820.07', local: 'USD', crypto: 'BTC', }, fee_per_kb: { amount: '0.00016566', currency: 'BTC', }, fee: { amount: '0.00002270', currency: 'BTC', }, priority: 'fast', recipient_value: { amount: '0.00054147', currency: 'BTC', }, exchange_to_proceeds: { rate: '6820.07', local: 'EUR', crypto: 'BTC', }, min_order_size: { amount: '0.001', currency: 'BTC', }, coinbase_fees: { amount: '0.00002270', currency: 'BTC', }, }, ETH: { confirmation_duration: 900, exchange: { rate: '197.07', local: 'USD', crypto: 'ETH', }, fee_per_kb: { amount: '0.00086', currency: 'ETH', }, fee: { amount: '0.03795', currency: 'ETH', }, priority: 'fast', recipient_value: { amount: '2.53', currency: 'ETH', }, exchange_to_proceeds: { rate: '6820.07', local: 'EUR', crypto: 'BTC', }, min_order_size: { amount: '0.001', currency: 'BTC', }, coinbase_fees: { amount: '0.00002270', currency: 'BTC', }, }, }, }, }; const shape = new schema.Object({ data: new schema.Object({ estimates: new schema.Values(Estimate) }), }); const { result, entities } = normalize(shape, response); expect( denormalize(shape, result, createInput(entities)), ).toMatchSnapshot(); }); }, ); });