import { Change } from "../../src/dataunit/Changes"; import DataUnit from "../../src/dataunit/DataUnit"; import { DUActionInterceptor } from "../../src/dataunit/interfaces/dataUnit"; import { Action, DataUnitAction } from "../../src/dataunit/state/action/DataUnitAction"; import ErrorException from "../../src/exceptions/ErrorException"; import ServiceCanceledException from "../../src/exceptions/ServiceCanceledException"; import SilentException from "../../src/exceptions/SilentException"; import WaitingChangeException from "../../src/exceptions/WaitingChangeException"; import { createDataUnitMock } from "./loader/utils/createDataUnitMock"; import { recordsTest } from "./resources/records"; describe('Saving data', () => { let dataUnit: DataUnit; beforeEach(() => { jest.clearAllMocks(); window.requestAnimationFrame = (functionCallback: Function) => functionCallback(); ({ dataUnit } = createDataUnitMock()); }); describe('saveData', () => { it('should call saveLoader with a new record', async () => { const saveLoaderMock = jest.fn().mockResolvedValue(recordsTest); dataUnit.saveLoader = saveLoaderMock; await dataUnit.addRecord(); await dataUnit.setFieldValue('column_name_1', 'new_value'); await dataUnit.saveData(); expect(saveLoaderMock).toHaveBeenCalledWith( dataUnit, expect.arrayContaining([ expect.objectContaining({ record: { "__record__id__": "NEW_0" }, updatingFields: { "column_name_1": "new_value" }, }) ]) ); }); it('should not call saveLoader when not has any data to saved', async () => { const saveLoaderMock = jest.fn().mockResolvedValue(recordsTest); dataUnit.saveLoader = saveLoaderMock; await dataUnit.saveData(); expect(saveLoaderMock).not.toHaveBeenCalled(); }); it('should call interceptor dataSaved', async () => { const saveLoaderMock = jest.fn().mockResolvedValue(recordsTest); dataUnit.saveLoader = saveLoaderMock; const dataSaved = jest.fn(); const interceptors: DUActionInterceptor = { interceptAction: (action) => { if (action.type === Action.DATA_SAVED) { dataSaved(); } return action; } } dataUnit.addInterceptor(interceptors); await dataUnit.addRecord(); await dataUnit.saveData(); expect(dataSaved).toHaveBeenCalled(); }); it('should throw error waiting change when has a blocking promise', async () => { const saveLoaderMock = jest.fn().mockResolvedValue(recordsTest); dataUnit.saveLoader = saveLoaderMock; await dataUnit.addRecord(); let resolvePromise: Function; dataUnit.startChange("column_name_1", { blocking: true, waitmessage: 'Waiting column change', promise: new Promise((resolve) => { resolvePromise = resolve; }) }); const saveData = () => dataUnit.saveData(); await expect(saveData).rejects.toBeInstanceOf(WaitingChangeException); }); it('should waiting change when not has blocking promises', async () => { const saveLoaderMock = jest.fn().mockResolvedValue(recordsTest); dataUnit.saveLoader = saveLoaderMock; let resolvePromise: () => void = () => { }; await dataUnit.addRecord(); dataUnit.startChange("column_name_1", { blocking: false, waitmessage: 'Waiting column change', promise: new Promise((resolve) => { resolvePromise = resolve; }), }); const promise = dataUnit.saveData(); expect(saveLoaderMock).not.toHaveBeenCalled(); resolvePromise(); await promise; expect(saveLoaderMock).toHaveBeenCalled(); }); it('should just resolve promises when not has a saveLoader', async () => { dataUnit.saveLoader = undefined; await dataUnit.addRecord(); dataUnit.startChange("column_name_1", { blocking: false, waitmessage: 'Waiting column change', promise: new Promise((resolve) => { resolve(); }), }); const dataSaved = jest.fn(); const interceptors: DUActionInterceptor = { interceptAction: (action) => { if (action.type === Action.DATA_SAVED) { dataSaved(); } return action; } } dataUnit.addInterceptor(interceptors); await dataUnit.saveData(); expect(dataSaved).not.toHaveBeenCalled(); }); it('should handle error saveLoader', async () => { const saveLoaderMock = jest.fn().mockRejectedValue("Error"); dataUnit.saveLoader = saveLoaderMock; const dataSaved = jest.fn(); const savingError = jest.fn(); const interceptors: DUActionInterceptor = { interceptAction: (action) => { switch (action.type) { case Action.DATA_SAVED: dataSaved(); break; case Action.SAVING_ERROR: savingError(); break; } return action; } } dataUnit.addInterceptor(interceptors); await dataUnit.addRecord(); const saveData = () => dataUnit.saveData(); await expect(saveData).rejects.toBeInstanceOf(ErrorException); expect(dataSaved).not.toHaveBeenCalled(); }); it('should handle error ServiceCanceledException saveLoader', async () => { const saveLoaderMock = jest.fn().mockRejectedValue(new ServiceCanceledException("Caceled", "Test canceled")); dataUnit.saveLoader = saveLoaderMock; await dataUnit.addRecord(); const response = await dataUnit.saveData(); expect(response).toBeUndefined(); }); it('should handle error SilentException saveLoader', async () => { const saveLoaderMock = jest.fn().mockRejectedValue(new SilentException("Silent", "Test silent")); dataUnit.saveLoader = saveLoaderMock; await dataUnit.addRecord(); const saveData = () => dataUnit.saveData(); await expect(saveData).rejects.toBeInstanceOf(SilentException); }); it('should dispatch action on child dataUnits', async () => { const dataUnitChild = dataUnit.getChildDataunit('test'); dataUnitChild.addRecord(); const savingData = jest.fn(); const observer = (action: DataUnitAction) => { if (action.type === Action.SAVING_DATA) { savingData(); } } dataUnitChild.subscribe(observer); await dataUnit.addRecord(); dataUnit.saveData(); expect(savingData).toHaveBeenCalled(); }); }); describe('buildChangesToSaveFromChild', () => { it('should return changes on dataUnit childs', async () => { const parentDataUnit = new DataUnit(); const childDataUnit = parentDataUnit.getChildDataunit('test'); const changes: Change[] = []; childDataUnit.addRecord(); await childDataUnit.setFieldValue('column_name_1', 'new_value'); parentDataUnit.buildChangesToSaveFromChild(changes, parentDataUnit); expect(changes).toStrictEqual( expect.arrayContaining([ expect.objectContaining({ record: { "__record__id__": "NEW_0" }, updatingFields: { "column_name_1": "new_value" }, }) ]) ); }); it('should return empty when no has any change', async () => { const parentDataUnit = new DataUnit(); parentDataUnit.getChildDataunit('test'); const changes: Change[] = []; parentDataUnit.buildChangesToSaveFromChild(changes, parentDataUnit); expect(changes).toStrictEqual([]); }); }); });