UNPKG

@rest-api/react-models

Version:

[![npm version](https://img.shields.io/npm/v/@rest-api/react-models)](https://www.npmjs.com/package/@rest-api/react-models) [![codecov](https://codecov.io/gh/hector7/rest-api-react-models/branch/master/graph/badge.svg)](https://codecov.io/gh/hector7/rest-

1,025 lines (1,024 loc) 59.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const __1 = require("../../../../"); require("jest-expect-message"); const fake_xml_http_request_1 = __importDefault(require("fake-xml-http-request")); const redux_1 = require("redux"); const ReducerStorage_1 = __importDefault(require("../../ReducerStorage")); const redux_thunk_1 = __importDefault(require("redux-thunk")); describe('IT', () => { it('fetch get the correct data from a identifier', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { this.respond(200, {}, JSON.stringify({ id: 1 })); } }; const s = __1.Schema({ id: { required: true, type: Number } }); const ss = new __1.Model(s, 'id', '/api/rest'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(ss._actions.fetchByIdIfNeeded(1)); const obj = ss._reducer.getById(root.getState(), 1); expect(obj).not.toBe(null); if (obj !== null) { expect(obj.hasOwnProperty('id')).toBeTruthy(); expect(obj.id).toBe(1); let called = false; global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { called = true; } }; root.dispatch(ss._actions.fetchByIdIfNeeded(1)); expect(called, 'this not will be called').toBe(false); } }); it('validate fails', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { this.respond(200, {}, JSON.stringify({ id: 1, date: '' })); } }; const s = __1.Schema({ id: { required: true, type: Number }, date: { required: true, type: Number } }).updateField('date', date => new Date(date)); const ss = new __1.Model(s, 'id', '/api/rest'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(ss._actions.fetchByIdIfNeeded(1)); const obj = ss._reducer.getById(root.getState(), 1); expect(obj).toBe(null); expect(ss._reducer.getIdError(root.getState(), 1)).not.toBe(null); }); it('Invalidate by id works', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { this.respond(200, {}, JSON.stringify({ id: 1, date: 1 })); } }; const s = __1.Schema({ id: { required: true, type: Number }, date: { required: true, type: Number } }).updateField('date', date => new Date(date)); const ss = new __1.Model(s, 'id', '/api/rest'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); expect(ss._reducer.isIdInvalidated(root.getState(), 1)).toBeTruthy(); root.dispatch(ss._actions.fetchByIdIfNeeded(1)); expect(ss._reducer.isIdInvalidated(root.getState(), 1)).toBeFalsy(); root.dispatch(ss._actions.invalidateById(1)); expect(ss._reducer.isIdInvalidated(root.getState(), 1)).toBeTruthy(); }); it('post works', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { constructor() { super(...arguments); this.method = 'GET'; } open(...args) { super.open(...args); this.method = args[0]; } send() { switch (this.method) { case 'GET': return this.respond(200, {}, JSON.stringify([{ id: 1, date: 2 }])); case 'POST': return this.respond(200, {}, JSON.stringify({ id: 2, date: 2 })); } } }; const s = __1.Schema({ id: { required: true, type: Number }, date: { required: true, type: Number } }).updateField('date', date => new Date(date)); const ss = new __1.Model(s, 'id', '/api/rest'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(ss._actions.fetchIfNeeded()); expect(ss._reducer.isInvalidated(root.getState())).toBeFalsy(); root.dispatch(ss._actions.post({ date: new Date() }, () => { })); expect(ss._reducer.getById(root.getState(), 2)).not.toBe(null); expect(ss._reducer.isInvalidated(root.getState())).toBeTruthy(); }); it('put works', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { constructor() { super(...arguments); this.method = 'GET'; } open(...args) { super.open(...args); this.method = args[0]; } send() { switch (this.method) { case 'GET': return this.respond(200, {}, JSON.stringify([{ id: 1, date: 2 }])); case 'PUT': return this.respond(200, {}, JSON.stringify({ id: 1, date: 2 })); } } }; const s = __1.Schema({ id: { required: true, type: Number }, date: { required: true, type: Number } }).updateField('date', date => new Date(date)); const ss = new __1.Model(s, 'id', '/api/rest'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(ss._actions.fetchIfNeeded()); expect(ss._reducer.isInvalidated(root.getState())).toBeFalsy(); expect(ss._reducer.getById(root.getState(), 1)).not.toBe(null); root.dispatch(ss._actions.put(1, { id: 1, date: new Date() }, () => { })); expect(ss._reducer.getById(root.getState(), 1)).not.toBe(null); expect(ss._reducer.isInvalidated(root.getState())).toBeTruthy(); }); it('patch works', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { constructor() { super(...arguments); this.method = 'GET'; } open(...args) { super.open(...args); this.method = args[0]; } send() { switch (this.method) { case 'GET': return this.respond(200, {}, JSON.stringify([{ id: 1, date: 2 }])); case 'PATCH': return this.respond(200, {}, JSON.stringify({ id: 1, date: 2 })); } } }; const s = __1.Schema({ id: { required: true, type: Number }, date: { required: true, type: Number } }).updateField('date', date => new Date(date)); const ss = new __1.Model(s, 'id', '/api/rest'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(ss._actions.fetchIfNeeded()); expect(ss._reducer.isInvalidated(root.getState())).toBeFalsy(); expect(ss._reducer.getById(root.getState(), 1)).not.toBe(null); root.dispatch(ss._actions.patch(1, { id: 1, date: new Date() }, () => { })); expect(ss._reducer.getById(root.getState(), 1)).not.toBe(null); expect(ss._reducer.isInvalidated(root.getState())).toBeTruthy(); }); it('delete works', (d) => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { constructor() { super(...arguments); this.method = 'GET'; } open(...args) { super.open(...args); this.method = args[0]; } send() { switch (this.method) { case 'GET': return this.respond(200, {}, JSON.stringify([{ id: 1, date: 2 }])); case 'DELETE': return this.respond(200, {}, JSON.stringify({ id: 1, date: 2 })); } } }; const s = __1.Schema({ id: { required: true, type: Number }, date: { required: true, type: Number } }).updateField('date', date => new Date(date)); const ss = new __1.Model(s, 'id', '/api/rest'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(ss._actions.fetchIfNeeded()); expect(ss._reducer.isInvalidated(root.getState())).toBeFalsy(); expect(ss._reducer.getById(root.getState(), 1)).not.toBe(null); root.dispatch(ss._actions.delete({ id: 1, date: new Date() }, (err) => { if (err) d(err); expect(ss._reducer.getById(root.getState(), 1)).toBe(null); expect(ss._reducer.isInvalidated(root.getState())).toBeTruthy(); d(); })); }); it('fetch get the correct data from a identifier with updateSteps', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { this.respond(200, {}, JSON.stringify({ id: 1, date: new Date().getTime() })); } }; const s = __1.Schema({ id: { required: true, type: Number }, date: { required: true, type: Number } }).updateField('date', date => new Date(date)); const ss = new __1.Model(s, 'id', '/api/rest'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(ss._actions.fetchByIdIfNeeded(1)); const obj = ss._reducer.getById(root.getState(), 1); expect(obj).not.toBe(null); if (obj !== null) { expect(obj.hasOwnProperty('id')).toBeTruthy(); expect(obj.hasOwnProperty('date')).toBeTruthy(); expect(obj.date.constructor).toBe(Date); expect(obj.id).toBe(1); let called = false; global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { called = true; } }; root.dispatch(ss._actions.fetchByIdIfNeeded(1)); expect(called, 'this not will be called').toBe(false); } }); it('fetch fails', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { this.respond(500, {}, 'here the error'); } }; const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], date: { type: String, required: true }, objectType: { type: __1.Schema({ hola: Number }), required: true }, object: __1.Schema({ hola: { required: true, type: Number, } }), type: { type: String, required: true }, r: [{ type: __1.Schema({ jeje: Number }), required: true }] }).updateField('date', date => new Date(date)); const ss = new __1.Model(s, 'id', '/api/rest'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(ss._actions.fetchIfNeeded()); const obj = ss._reducer.getError(root.getState()); expect(obj).not.toBe(null); if (obj !== null) { expect(obj.codeNumber).toBe(500); expect(obj.message).toBe('here the error'); } }); it('fetch by id fails', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { this.respond(500, {}, 'here the error'); } }; const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], date: { type: String, required: true }, objectType: { type: __1.Schema({ hola: Number }), required: true }, object: __1.Schema({ hola: { required: true, type: Number, } }), type: { type: String, required: true }, r: [{ type: __1.Schema({ jeje: Number }), required: true }] }).updateField('date', date => new Date(date)); const ss = new __1.Model(s, 'id', '/api/rest'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(ss._actions.fetchByIdIfNeeded(1)); const obj = ss._reducer.getIdError(root.getState(), 1); expect(obj).not.toBe(null); if (obj !== null) { expect(obj.codeNumber).toBe(500); expect(obj.message).toBe('here the error'); } }); it('invalidate works', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { this.respond(200, {}, JSON.stringify([ { id: 1, name: ['jose'] }, { id: 2, name: ['hector'] }, { id: 3, name: ['pepito'] }, { id: 4, name: ['albert'] } ])); } }; const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }); const ss = new __1.Model(s, 'id', '/api/rest'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(ss._actions.fetchIfNeeded()); const obj = ss._reducer.get(root.getState()); expect(obj).not.toBe(null); if (obj !== null) { expect(Array.isArray(obj), 'response is an array').toBe(true); expect(obj.length).toBe(4); expect(obj[0].id).toBe(1); expect(Array.isArray(obj[0].name), 'name is an array').toBe(true); expect(obj[0].name.length).toBe(1); expect(obj[0].name[0]).toBe('jose'); let called = false; global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { called = true; } }; root.dispatch(ss._actions.fetchIfNeeded()); expect(called, 'this not will be called').toBe(false); expect(ss._reducer.isInvalidated(root.getState())).toBeFalsy(); root.dispatch(ss._actions.invalidate()); expect(ss._reducer.isInvalidated(root.getState())).toBeTruthy(); } }); it('fetch get the correct data from all objects', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { this.respond(200, {}, JSON.stringify([ { id: 1, name: ['jose'] }, { id: 2, name: ['hector'] }, { id: 3, name: ['pepito'] }, { id: 4, name: ['albert'] } ])); } }; const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }); const ss = new __1.Model(s, 'id', '/api/rest'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(ss._actions.fetchIfNeeded()); const obj = ss._reducer.get(root.getState()); expect(obj).not.toBe(null); if (obj !== null) { expect(Array.isArray(obj), 'response is an array').toBe(true); expect(obj.length).toBe(4); expect(obj[0].id).toBe(1); expect(Array.isArray(obj[0].name), 'name is an array').toBe(true); expect(obj[0].name.length).toBe(1); expect(obj[0].name[0]).toBe('jose'); let called = false; global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { called = true; } }; root.dispatch(ss._actions.fetchIfNeeded()); expect(called, 'this not will be called').toBe(false); } }); it('simple fetch populate is working', () => { let called_global = false; let called_populated = false; global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/generalResponse': called_global = true; return this.respond(200, {}, JSON.stringify([ { id: 1, model: 1 } ])); case '/populatedResponse/1': called_populated = true; return this.respond(200, {}, JSON.stringify({ id: 1, name: ['jose'] })); } } }; const ss = new __1.Model(__1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }), 'id', '/populatedResponse'); const cc = new __1.Model(__1.Schema({ id: { required: true, type: Number }, model: { type: ss, idOnly: true } }), 'id', '/generalResponse'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(cc._actions.fetchPopulatedIfNeeded()); const obj = ss._reducer.get(root.getState()); expect(obj).not.toBe(null); if (obj !== null) { expect(called_global).toBeTruthy(); expect(called_populated).toBeTruthy(); } }); it('simple fetch with schema populate is working', () => { let called_populated = false; global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/generalResponse': return this.respond(200, {}, JSON.stringify([ { id: 1, model: { model: 1 } } ])); case '/populatedResponse/1': called_populated = true; return this.respond(200, {}, JSON.stringify({ id: 1, name: ['jose'] })); } } }; const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }); const ss = new __1.Model(s, 'id', '/populatedResponse'); const cc = new __1.Model(__1.Schema({ id: { required: true, type: Number }, model: __1.Schema({ model: { type: ss, idOnly: true } }) }), 'id', '/generalResponse'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(cc._actions.fetchPopulatedIfNeeded()); const obj = ss._reducer.get(root.getState()); expect(obj).not.toBe(null); if (obj !== null) { expect(called_populated, 'populate calls by id inside a schema').toBe(true); } }); it('populate of populate is working', () => { let called_populated = false; global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/generalResponse': return this.respond(200, {}, JSON.stringify([ { id: 1, model: [1] } ])); case '/populatedResponse/1': return this.respond(200, {}, JSON.stringify({ id: 1, model: 2 })); case '/populatedResponse2/2': called_populated = true; return this.respond(200, {}, JSON.stringify({ id: 2, name: ['jose'] })); } } }; const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }); const tt = new __1.Model(s, 'id', '/populatedResponse2'); const ss = new __1.Model(__1.Schema({ id: { required: true, type: Number }, model: { type: tt, idOnly: true } }), 'id', '/populatedResponse'); const cc = new __1.Model(__1.Schema({ id: { required: true, type: Number }, model: [{ type: ss, required: true, idOnly: true }] }), 'id', '/generalResponse'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(cc._actions.fetchPopulatedIfNeeded()); const obj1 = ss._reducer.getPopulated(root.getState()); expect(ss._reducer.isPopulated(root.getState())).toBeTruthy(); //first time is not in redux, so is not fetched. root.dispatch(cc._actions.fetchPopulatedIfNeeded()); const obj = ss._reducer.get(root.getState()); expect(obj).not.toBe(null); if (obj !== null) { expect(called_populated, 'populate call model of model is not working').toBe(true); } }); it('populated in progress is working', () => { let called_populated = false; global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/generalResponse': return this.respond(200, {}, JSON.stringify([ { id: 1, model: [1, 2] } ])); case '/populatedResponse/1': return this.respond(200, {}, JSON.stringify({ id: 1, model: 2 })); } } }; const s = __1.Schema({ id: { required: true, type: Number }, name: [{ type: String, required: true }], }); const tt = new __1.Model(s, 'id', '/populatedResponse2'); s.updateSchema({ d: { type: s, } }); const ss = new __1.Model(__1.Schema({ id: { required: true, type: Number }, model: { type: tt, idOnly: true } }), 'id', '/populatedResponse'); const cc = new __1.Model(__1.Schema({ id: { required: true, type: Number }, model: [{ type: ss, required: true, idOnly: true }] }), 'id', '/generalResponse'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(cc._actions.fetchPopulatedIfNeeded()); const obj1 = cc._reducer.getPopulated(root.getState()); expect(cc._reducer.isPopulated(root.getState())).toBeFalsy(); //first time is not in redux, so is not fetched. root.dispatch(cc._actions.fetchPopulatedIfNeeded()); const obj = cc._reducer.getPopulated(root.getState()); expect(cc._reducer.isPopulated(root.getState())).toBeFalsy(); expect(obj).not.toBe(null); if (obj !== null) { expect(obj[0].model[0].model.id, 'id is not equal to id').toBe(2); expect(obj[0].model[0].model.name, 'this should be undefined as not a fetched object').toBe(undefined); } }); it('getItems is working', () => { let called_populated = false; global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/generalResponse/': called_populated = true; return this.respond(200, {}, JSON.stringify({ count: 100, results: [{ id: 1 }, { id: 2 }] })); } } }; const s = __1.Schema({ id: { required: true, type: Number }, name: [{ type: String, required: true }], }); const tt = new __1.Model(s, 'id', '/generalResponse', __1.Schema({ count: Number, results: [{ type: s, required: __1.required }] }), (el) => el.results, (el) => el.count, { trailingSlash: true }); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(tt._actions.fetchIfNeeded()); expect(called_populated).toBeTruthy(); const obj = tt._reducer.get(root.getState()); const metadata = tt._reducer.getMetadata(root.getState()); expect(obj.length).toBe(2); expect(metadata).toBe(100); }); it('simple get populate is working', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/generalResponse': return this.respond(200, {}, JSON.stringify([ { id: 1, model: 1 } ])); case '/populatedResponse/1': return this.respond(200, {}, JSON.stringify({ id: 1, name: ['jose'] })); } } }; const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }); const ss = new __1.Model(s, 'id', '/populatedResponse'); const cc = new __1.Model(__1.Schema({ id: { required: true, type: Number }, model: { type: ss, idOnly: true } }), 'id', '/generalResponse'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(cc._actions.fetchPopulatedIfNeeded()); //second call root.dispatch(cc._actions.fetchPopulatedIfNeeded()); const obj = cc._reducer.getPopulated(root.getState()); expect(cc._reducer.isPopulated(root.getState())).toBeTruthy(); expect(obj).not.toBe(null); if (obj !== null) { expect(obj.length).toBe(1); const first = obj[0]; expect(first.id).toBe(1); expect(first.model, 'model is undefined?').not.toBe(undefined); expect(first.model.id, 'expecting populate id').toBe(1); expect(Array.isArray(first.model.name)).toBeTruthy(); } }); it('simple get populate is working with trailing slash', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/generalResponse/': return this.respond(200, {}, JSON.stringify([ { id: 1, model: 1 } ])); case '/populatedResponse/1': return this.respond(200, {}, JSON.stringify({ id: 1, name: ['jose'] })); } } }; const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }); const ss = new __1.Model(s, 'id', '/populatedResponse'); const cc = new __1.Model(__1.Schema({ id: { required: true, type: Number }, model: { type: ss, idOnly: true } }), 'id', '/generalResponse', { trailingSlash: true }); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(cc._actions.fetchPopulatedIfNeeded()); //second call root.dispatch(cc._actions.fetchPopulatedIfNeeded()); const obj = cc._reducer.getPopulated(root.getState()); expect(cc._reducer.isPopulated(root.getState())).toBeTruthy(); expect(obj).not.toBe(null); if (obj !== null) { expect(obj.length).toBe(1); const first = obj[0]; expect(first.id).toBe(1); expect(first.model, 'model is undefined?').not.toBe(undefined); expect(first.model.id, 'expecting populate id').toBe(1); expect(Array.isArray(first.model.name)).toBeTruthy(); } }); it('simple get with schema populate is working', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/generalResponse': return this.respond(200, {}, JSON.stringify([ { id: 1, model: { model: 1 } } ])); case '/populatedResponse/1': return this.respond(200, {}, JSON.stringify({ id: 1, name: ['jose'] })); } } }; const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }); const ss = new __1.Model(s, 'id', '/populatedResponse'); const cc = new __1.Model(__1.Schema({ id: { required: true, type: Number }, model: __1.Schema({ model: { type: ss, idOnly: true } }) }), 'id', '/generalResponse'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(cc._actions.fetchPopulatedIfNeeded()); const obj = cc._reducer.getPopulated(root.getState()); expect(cc._reducer.isPopulated(root.getState())).toBeTruthy(); expect(obj).not.toBe(null); if (obj !== null) { expect(obj.length).toBe(1); const first = obj[0]; expect(first.id).toBe(1); expect(first.model, 'model is undefined?').not.toBe(undefined); expect(first.model.model, 'model is undefined?').not.toBe(undefined); expect(first.model.model.id, 'expecting populate id').toBe(1); expect(Array.isArray(first.model.model.name)).toBeTruthy(); } }); it('get populate of populate is working', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/generalResponse': return this.respond(200, {}, JSON.stringify([ { id: 1, subType: { model: 1 } } ])); case '/populatedResponse/1': return this.respond(200, {}, JSON.stringify({ id: 1, model: 2 })); case '/populatedResponse2/2': return this.respond(200, {}, JSON.stringify({ id: 2, name: ['jose'] })); } } }; const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }); const tt = new __1.Model(s, 'id', '/populatedResponse2'); const ss = new __1.Model(__1.Schema({ id: { required: true, type: Number }, model: { type: tt, idOnly: true } }), 'id', '/populatedResponse'); const cc = new __1.Model(__1.Schema({ id: { required: true, type: Number }, subType: { type: __1.Schema({ model: { type: ss, idOnly: true } }), required: __1.required } }), 'id', '/generalResponse'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(cc._actions.fetchPopulatedIfNeeded()); //first time is not in redux, so is not fetched. root.dispatch(cc._actions.fetchPopulatedIfNeeded()); const obj = cc._reducer.getPopulated(root.getState()); expect(cc._reducer.isPopulated(root.getState())).toBeTruthy(); expect(obj).not.toBe(null); if (obj !== null) { expect(obj.length).toBe(1); const first = obj[0]; expect(first.id).toBe(1); expect(first.subType.model, 'model is undefined?').not.toBe(undefined); expect(first.subType.model.model, 'model is undefined?').not.toBe(undefined); expect(first.subType.model.model.id, 'expecting populate id').toBe(2); expect(Array.isArray(first.subType.model.model.name)).toBeTruthy(); } }); it('get populate of populate is working on real case', (d) => { let called_faculty = false; let called_level = false; global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/api/user_has_level/': return this.respond(200, {}, JSON.stringify([ { id: 1, name: 'test', levels: [{ faculty: 1, level: 1 }] } ])); case '/api/faculty/1/': return setTimeout(() => { called_faculty = true; this.respond(200, {}, JSON.stringify({ id: 1, name: 'e' })); }, 20); case '/api/level/1/': return setTimeout(() => { called_level = true; this.respond(200, {}, JSON.stringify({ id: 1, name: 'e' })); }, 20); } } }; const FacultySchema = __1.Schema({ id: { type: Number, required: __1.required }, name: { type: String, required: __1.required } }); const levelSchema = __1.Schema({ id: { type: Number, required: __1.required }, name: { type: String, required: __1.required } }); const Level = new __1.Model(levelSchema, 'id', '/api/level', { trailingSlash: true }); const Faculty = new __1.Model(FacultySchema, 'id', '/api/faculty', { trailingSlash: true }); const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }); const subUserHasLevelSchema = __1.Schema({ faculty: { type: Faculty, required: true, idOnly: true }, faculty_name: String, level: { type: Level, required: true, idOnly: true }, level_name: String }); const UserHasLevelSchema = __1.Schema({ id: { type: Number, required: __1.required }, name: { type: String }, levels: [{ type: subUserHasLevelSchema, required: __1.required }] }); const UserHasLevel = new __1.Model(UserHasLevelSchema, 'id', '/api/user_has_level', { trailingSlash: true }); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(UserHasLevel._actions.fetchPopulatedIfNeeded()); expect(UserHasLevel._reducer.isPopulated(root.getState())).toBeFalsy(); root.dispatch(UserHasLevel._actions.fetchPopulatedIfNeeded()); setTimeout(() => { expect(UserHasLevel._reducer.isPopulated(root.getState())).toBeTruthy(); const obj = UserHasLevel._reducer.getPopulated(root.getState()); expect(obj).not.toBe(null); if (obj !== null) { expect(obj.length).toBe(1); const first = obj[0]; expect(first.id).toBe(1); expect(Array.isArray(first.levels)).toBeTruthy(); d(); } }, 30); }); it('get populate of populate is working on real case', (d) => { let called_faculty = false; let called_level = false; global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/api/user_has_level/': return this.respond(200, {}, JSON.stringify([ { id: 1, name: 'test', level: { faculty: 1, level: 1 } } ])); case '/api/faculty/1/': return setTimeout(() => { called_faculty = true; this.respond(200, {}, JSON.stringify({ id: 1, name: 'e' })); }, 20); case '/api/level/1/': return setTimeout(() => { called_level = true; this.respond(200, {}, JSON.stringify({ id: 1, name: 'e' })); }, 20); } } }; const FacultySchema = __1.Schema({ id: { type: Number, required: __1.required }, name: { type: String, required: __1.required } }); const levelSchema = __1.Schema({ id: { type: Number, required: __1.required }, name: { type: String, required: __1.required } }); const Level = new __1.Model(levelSchema, 'id', '/api/level', { trailingSlash: true }); const Faculty = new __1.Model(FacultySchema, 'id', '/api/faculty', { trailingSlash: true }); const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }); const subUserHasLevelSchema = __1.Schema({ faculty: { type: Faculty, required: true, idOnly: true }, faculty_name: String, level: { type: Level, required: true, idOnly: true }, level_name: String }); const UserHasLevelSchema = __1.Schema({ id: { type: Number, required: __1.required }, name: { type: String }, level: { type: subUserHasLevelSchema, required: __1.required } }); const UserHasLevel = new __1.Model(UserHasLevelSchema, 'id', '/api/user_has_level', { trailingSlash: true }); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(UserHasLevel._actions.fetchPopulatedIfNeeded()); expect(UserHasLevel._reducer.isPopulated(root.getState())).toBeFalsy(); root.dispatch(UserHasLevel._actions.fetchPopulatedIfNeeded()); setTimeout(() => { expect(UserHasLevel._reducer.isPopulated(root.getState())).toBeTruthy(); const obj = UserHasLevel._reducer.getPopulated(root.getState()); expect(obj).not.toBe(null); if (obj !== null) { expect(obj.length).toBe(1); const first = obj[0]; expect(first.id).toBe(1); d(); } }, 30); }); it('get populate of populate is working on real case (autopopulated)', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/api/user_has_level/': return this.respond(200, {}, JSON.stringify([ { id: 1, name: 'test', levels: [{ faculty: { id: 1, name: 'e' }, level: { id: 1, name: 'e' } }] } ])); case '/api/faculty/1/': return this.respond(500, {}, JSON.stringify({ id: 1, name: 'e' })); case '/api/level/1/': return this.respond(500, {}, JSON.stringify({ id: 1, name: 'e' })); } } }; const FacultySchema = __1.Schema({ id: { type: Number, required: __1.required }, name: { type: String, required: __1.required } }); const levelSchema = __1.Schema({ id: { type: Number, required: __1.required }, name: { type: String, required: __1.required } }); const Level = new __1.Model(levelSchema, 'id', '/api/level', { trailingSlash: true }); const Faculty = new __1.Model(FacultySchema, 'id', '/api/faculty', { trailingSlash: true }); const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }); const subUserHasLevelSchema = __1.Schema({ faculty: { type: Faculty, required: true, }, faculty_name: String, level: { type: Level, required: true, }, level_name: String }); const UserHasLevelSchema = __1.Schema({ id: { type: Number, required: __1.required }, name: { type: String }, levels: [{ type: subUserHasLevelSchema, required: __1.required }] }); const UserHasLevel = new __1.Model(UserHasLevelSchema, 'id', '/api/user_has_level', { trailingSlash: true }); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(UserHasLevel._actions.fetchPopulatedIfNeeded()); expect(UserHasLevel._reducer.isPopulated(root.getState())).toBeTruthy(); const obj = UserHasLevel._reducer.getPopulated(root.getState()); expect(obj).not.toBe(null); if (obj !== null) { expect(obj.length).toBe(1); const first = obj[0]; expect(first.id).toBe(1); expect(Array.isArray(first.levels)).toBeTruthy(); } }); it('invalidate is working', () => { let called = 0; global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/generalResponse': called++; return this.respond(200, {}, JSON.stringify([ { id: 1, model: 1 } ])); } } }; const s = __1.Schema({ id: { required: true, type: Number, }, name: [{ type: String, required: true }], }); const cc = new __1.Model(__1.Schema({ id: { required: true, type: Number } }), 'id', '/generalResponse'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(cc._actions.fetchIfNeeded()); root.dispatch(cc._actions.invalidateAll()); root.dispatch(cc._actions.fetchIfNeeded()); expect(called).toBe(2); }); it('getItem without metadata and routeopts works', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/api/example': return this.respond(200, {}, JSON.stringify({ items: [ { id: 1, name: 'Book 1' } ] })); } } }; const bookSchema = __1.Schema({ id: { type: Number, required: true }, name: String, }); const model = new __1.Model(bookSchema, 'id', '/api/example', __1.Schema({ items: [{ type: bookSchema, required: true }] }), d => d.items); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(model._actions.fetchIfNeeded()); expect(model._reducer.get(root.getState())[0].id).toBe(1); expect(model._reducer.getMetadata(root.getState())).toBe(null); }); it('getItem without metadata but with routeopts works', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/api/example/': return this.respond(200, {}, JSON.stringify({ items: [ { id: 1, name: 'Book 1' } ] })); } } }; const bookSchema = __1.Schema({ id: { type: Number, required: true }, name: String, }); const model = new __1.Model(bookSchema, 'id', '/api/example', __1.Schema({ items: [{ type: bookSchema, required: true }] }), d => d.items, { trailingSlash: true }); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(model._actions.fetchIfNeeded()); expect(model._reducer.get(root.getState())[0].id).toBe(1); expect(model._reducer.getMetadata(root.getState())).toBe(null); }); it('getItem with metadata and without routeopts works', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/api/example': return this.respond(200, {}, JSON.stringify({ items: [ { id: 1, name: 'Book 1' } ] })); } } }; const bookSchema = __1.Schema({ id: { type: Number, required: true }, name: String, }); const model = new __1.Model(bookSchema, 'id', '/api/example', __1.Schema({ items: [{ type: bookSchema, required: true }] }), d => d.items, d => d.items.length); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(model._actions.fetchIfNeeded()); expect(model._reducer.get(root.getState())[0].id).toBe(1); expect(model._reducer.getMetadata(root.getState())).toBe(1); }); it('getItem with metadata but with routeopts works', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/api/example/': return this.respond(200, {}, JSON.stringify({ items: [ { id: 1, name: 'Book 1' } ] })); } } }; const bookSchema = __1.Schema({ id: { type: Number, required: true }, name: String, }); const model = new __1.Model(bookSchema, 'id', '/api/example', __1.Schema({ items: [{ type: bookSchema, required: true }] }), d => d.items, d => d.items.length, { trailingSlash: true }); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(model._actions.fetchIfNeeded()); expect(model._reducer.get(root.getState())[0].id).toBe(1); expect(model._reducer.getMetadata(root.getState())).toBe(1); }); it('getSubModel with key works', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default { send() { switch (this.responseURL) { case '/api/example/Book 1': return this.respond(200, {}, JSON.stringify({ id: 1, name: 'Book 1' })); } } }; const bookSchema = __1.Schema({ id: { type: Number, required: true }, name: { type: String, required: true }, }); const model = new __1.Model(bookSchema, 'id', '/api/example').getSubModelWithKey('name'); const root = redux_1.createStore(ReducerStorage_1.default.generalReducer, {}, redux_1.applyMiddleware(redux_thunk_1.default)); root.dispatch(model._actions.fetchByIdIfNeeded('Book 1')); expect(model._reducer.getById(root.getState(), 'Book 1').id).toBe(1); }); it('getSubModel root with key works', () => { global.XMLHttpRequest = class XMLHttpRequest extends fake_xml_http_request_1.default {