import { MiddlewareDependencies, StoreState } from 'app/common/store/store.types'; import { DeepPartial } from 'redux'; import { ActionsObservable, StateObservable } from 'redux-observable'; import { enteredBunkerAdjustmentMonthlyPage, enteredTechnicalManagementBunkerAdjustmentMonthlyPage, enteredTechnicalManagementBunkerAdjustmentTrendsPage, enteredVesselBunkerAdjustmentPage, enteredVesselBunkerAdjustmentTrendsPage, redirectTo, } from 'app/common/store/router/router.actions'; import { vesselDetailsFetchGeneralInfoRequest } from 'app/modules/vesselDetails/root/store/vesselDetails.actions'; import { bunkerAdjustmentFetchAvailabilityFailure, bunkerAdjustmentFetchAvailabilityRequest, bunkerAdjustmentFetchAvailabilitySuccess, bunkerAdjustmentFetchFiguresFailure, bunkerAdjustmentFetchFiguresRequest, bunkerAdjustmentFetchFiguresSuccess, bunkerAdjustmentFetchTrendsFailure, bunkerAdjustmentFetchTrendsRequest, bunkerAdjustmentFetchTrendsSuccess, bunkerAdjustmentReset, bunkerAdjustmentSetCurrentPeriod, } from './bunkerAdjustment.actions'; import { enteredBunkerAdjustmentMonthlyPageEpic, enteredBunkerAdjustmentPageEpic, enteredBunkerAdjustmentTrendsPageEpic, fetchAvailabilityEpic, fetchAvailabilitySuccessEpic, fetchBunkerAdjustmentMonthlyDataEpic, fetchFiguresEpic, fetchTrendsEpic, redirectOnCurrentPeriodSetEpic, } from './bunkerAdjustment.epic'; import { of, Subject, throwError } from 'rxjs'; import { ROUTER, technicalManagementPoolVesselBunkerAdjustmentMonthlyRoute, vesselDetailsBunkerAdjustmentMonthlyRoute, vesselDetailsBunkerAdjustmentRoute } from 'app/common/routes'; describe('Bunker Adjustment epic tests', () => { let dependencies: MiddlewareDependencies; const paramsMock = { pool: 3, vesselCode: 'ABC', partnerAxCode: 'MT', }; const availibilityMock = [ { date: '2022-03-01T00:00:00', isActive: false, }, { date: '2022-02-01T00:00:00', isActive: true, }, ]; const periodParamsMock = { ...paramsMock, date: availibilityMock[1].date, }; const dataMock = { consumption: null, summary: null, keyFigures: { consumptionActual: null, consumptionDifference: null, bunkerCompliant: null, bunkerNonCompliant: null, bunkerAdjustment: null, scrubberBonus: null, }, }; const trendsMock = [ { year: 2022, month: 2, onHireDays: 13, bunkerPriceCompliant: 14, bunkerPriceNonCompliant: 15, consumptionSimulated: 16, consumptionActual: 17, }, ]; beforeEach(() => { dependencies = ({ bunkerAdjustment: { getAvailability: jest.fn(() => of(availibilityMock)), getFigures: jest.fn(() => of(dataMock)), getTrends: jest.fn(() => of(trendsMock)), }, }) as DeepPartial as MiddlewareDependencies; }); it('returns fetch and reset actions on entered page action', done => { const stateMock = { vesselDetails: { generalInfo: {}, }, }; const action$ = ActionsObservable.of(enteredVesselBunkerAdjustmentPage(paramsMock)); const state$ = new StateObservable(new Subject(), stateMock as DeepPartial as StoreState); const expectedOutputActions = [ vesselDetailsFetchGeneralInfoRequest(paramsMock, stateMock), bunkerAdjustmentReset(), bunkerAdjustmentFetchAvailabilityRequest(paramsMock), ]; enteredBunkerAdjustmentPageEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('fetches availibility on fetch availiblity action', done => { const action$ = ActionsObservable.of(bunkerAdjustmentFetchAvailabilityRequest(paramsMock)); const state$ = {} as StateObservable; const expectedOutputActions = bunkerAdjustmentFetchAvailabilitySuccess(availibilityMock); fetchAvailabilityEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('returns fetch availibility error action on availibility fetch failure', done => { dependencies.bunkerAdjustment.getAvailability = jest.fn(() => { return throwError(''); }); const action$ = ActionsObservable.of(bunkerAdjustmentFetchAvailabilityRequest(paramsMock)); const state$ = {} as StateObservable; const expectedOutputActions = bunkerAdjustmentFetchAvailabilityFailure(); fetchAvailabilityEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('sets first active period on fetch availability success', done => { const action$ = ActionsObservable.of(bunkerAdjustmentFetchAvailabilitySuccess(availibilityMock)); const state$ = new StateObservable(new Subject(), { bunkerAdjustment: {}, router: { location: { pathname: vesselDetailsBunkerAdjustmentRoute } }, } as DeepPartial as StoreState); const expectedOutputActions = bunkerAdjustmentSetCurrentPeriod(availibilityMock[1].date); fetchAvailabilitySuccessEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('sets current period based on route option on fetch availibility success', done => { const action$ = ActionsObservable.of(bunkerAdjustmentFetchAvailabilitySuccess(availibilityMock)); const state$ = new StateObservable(new Subject(), { bunkerAdjustment: {}, router: { location: { pathname: ROUTER.generate(vesselDetailsBunkerAdjustmentMonthlyRoute, { ...paramsMock, year: '2022', month: '03', }) } }, } as DeepPartial as StoreState); const expectedOutputActions = bunkerAdjustmentSetCurrentPeriod(availibilityMock[0].date); fetchAvailabilitySuccessEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('does not set current period if route options does not match any availibility period', done => { const action$ = ActionsObservable.of(bunkerAdjustmentFetchAvailabilitySuccess(availibilityMock)); const state$ = new StateObservable(new Subject(), { bunkerAdjustment: {}, router: { location: { pathname: ROUTER.generate(vesselDetailsBunkerAdjustmentMonthlyRoute, { ...paramsMock, pool: paramsMock.pool.toString(), year: '2022', month: '04', }) } }, } as DeepPartial as StoreState); const expectedOutputActions = []; fetchAvailabilitySuccessEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('does not set current period if there is no active period', done => { const availabilityNoActivePeriodMock = [ { date: '2022-03-01T00:00:00', isActive: false, }, { date: '2022-02-01T00:00:00', isActive: false, }, ]; availabilityNoActivePeriodMock[1].isActive = false; const action$ = ActionsObservable.of(bunkerAdjustmentFetchAvailabilitySuccess(availabilityNoActivePeriodMock)); const state$ = new StateObservable(new Subject(), { bunkerAdjustment: {}, router: { location: { pathname: vesselDetailsBunkerAdjustmentRoute } }, } as DeepPartial as StoreState); const expectedOutputActions = []; fetchAvailabilitySuccessEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('does not set current period if it is set already', done => { const action$ = ActionsObservable.of(bunkerAdjustmentFetchAvailabilitySuccess(availibilityMock)); const state$ = new StateObservable(new Subject(), { bunkerAdjustment: { currentPeriod: availibilityMock[0].date }, router: { location: { pathname: vesselDetailsBunkerAdjustmentRoute } }, } as DeepPartial as StoreState); const expectedOutputActions = []; fetchAvailabilitySuccessEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('redirects on setting current period', done => { const action$ = ActionsObservable.of(bunkerAdjustmentSetCurrentPeriod(availibilityMock[1].date)); const state$ = new StateObservable(new Subject(), { bunkerAdjustment: { periods: availibilityMock }, router: { location: { pathname: ROUTER.generate(vesselDetailsBunkerAdjustmentMonthlyRoute, { ...paramsMock, year: '2022', month: '02', }) } }, } as DeepPartial as StoreState); const expectedOutputActions = redirectTo({ routeName: vesselDetailsBunkerAdjustmentMonthlyRoute, options: { ...paramsMock, pool: paramsMock.pool.toString(), year: '2022', month: '02', }, replace: true, }); redirectOnCurrentPeriodSetEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('redirects to technical manager route on setting current period if that is current router context', done => { const action$ = ActionsObservable.of(bunkerAdjustmentSetCurrentPeriod(availibilityMock[1].date)); const state$ = new StateObservable(new Subject(), { bunkerAdjustment: { periods: availibilityMock }, router: { location: { pathname: ROUTER.generate(technicalManagementPoolVesselBunkerAdjustmentMonthlyRoute, { ...paramsMock, year: '2022', month: '02', }) } }, } as DeepPartial as StoreState); const expectedOutputActions = redirectTo({ routeName: technicalManagementPoolVesselBunkerAdjustmentMonthlyRoute, options: { ...paramsMock, pool: paramsMock.pool.toString(), year: '2022', month: '02', }, replace: true, }); redirectOnCurrentPeriodSetEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('does not redirect on setting current period if that period is not active', done => { const action$ = ActionsObservable.of(bunkerAdjustmentSetCurrentPeriod(availibilityMock[0].date)); const state$ = new StateObservable(new Subject(), { bunkerAdjustment: { periods: availibilityMock }, router: { location: { pathname: ROUTER.generate(vesselDetailsBunkerAdjustmentMonthlyRoute, { ...paramsMock, year: '2022', month: '03', }) } }, } as DeepPartial as StoreState); const expectedOutputActions = []; redirectOnCurrentPeriodSetEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('returns fetch actions on entered monthly page action', done => { const stateMock = { vesselDetails: { generalInfo: {}, }, }; const action$ = ActionsObservable.of(enteredBunkerAdjustmentMonthlyPage(periodParamsMock)); const state$ = new StateObservable(new Subject(), stateMock as DeepPartial as StoreState); const expectedOutputActions = [ bunkerAdjustmentFetchAvailabilityRequest(paramsMock), vesselDetailsFetchGeneralInfoRequest(paramsMock, stateMock), ]; enteredBunkerAdjustmentMonthlyPageEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('returns fetch actions on entered technical manager page action', done => { const stateMock = { vesselDetails: { generalInfo: {}, }, }; const action$ = ActionsObservable.of(enteredTechnicalManagementBunkerAdjustmentMonthlyPage(periodParamsMock)); const state$ = new StateObservable(new Subject(), stateMock as DeepPartial as StoreState); const expectedOutputActions = [ bunkerAdjustmentFetchAvailabilityRequest(paramsMock), vesselDetailsFetchGeneralInfoRequest(paramsMock, stateMock), ]; enteredBunkerAdjustmentMonthlyPageEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('returns fetch data action on fetch availibility success action', done => { const action$ = ActionsObservable.of(bunkerAdjustmentFetchAvailabilitySuccess(availibilityMock)); const state$ = new StateObservable(new Subject(), { bunkerAdjustment: { currentPeriod: availibilityMock[1].date }, router: { location: { pathname: ROUTER.generate(vesselDetailsBunkerAdjustmentMonthlyRoute, { ...paramsMock, year: '2022', month: '02', }) } }, } as DeepPartial as StoreState); const expectedOutputActions = [ bunkerAdjustmentFetchFiguresRequest({ ...periodParamsMock, // @ts-ignore pool: periodParamsMock.pool.toString(), }), ]; fetchBunkerAdjustmentMonthlyDataEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('does not return fetch data action on fetch availibility success action if period is not active', done => { const action$ = ActionsObservable.of(bunkerAdjustmentFetchAvailabilitySuccess(availibilityMock)); const state$ = new StateObservable(new Subject(), { bunkerAdjustment: { currentPeriod: availibilityMock[0].date }, router: { location: { pathname: ROUTER.generate(vesselDetailsBunkerAdjustmentMonthlyRoute, { ...paramsMock, year: '2022', month: '03', }) } }, } as DeepPartial as StoreState); const expectedOutputActions = []; fetchBunkerAdjustmentMonthlyDataEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('fetches data on fetch data request action', done => { const action$ = ActionsObservable.of(bunkerAdjustmentFetchFiguresRequest(periodParamsMock)); const state$ = {} as StateObservable; const expectedOutputActions = bunkerAdjustmentFetchFiguresSuccess(dataMock); fetchFiguresEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('returns error action on fetch data request failure', done => { dependencies.bunkerAdjustment.getFigures = jest.fn(() => { return throwError(''); }); const action$ = ActionsObservable.of(bunkerAdjustmentFetchFiguresRequest(periodParamsMock)); const state$ = {} as StateObservable; const expectedOutputActions = bunkerAdjustmentFetchFiguresFailure(); fetchFiguresEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('returns fetch actions on entered trends page action', done => { const stateMock = { vesselDetails: { generalInfo: {}, }, }; const action$ = ActionsObservable.of(enteredVesselBunkerAdjustmentTrendsPage(paramsMock)); const state$ = new StateObservable(new Subject(), stateMock as DeepPartial as StoreState); const expectedOutputActions = [ vesselDetailsFetchGeneralInfoRequest(paramsMock, stateMock), bunkerAdjustmentFetchTrendsRequest(paramsMock), ]; enteredBunkerAdjustmentTrendsPageEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('returns fetch actions on entered technical manager trends page action', done => { const stateMock = { vesselDetails: { generalInfo: {}, }, }; const action$ = ActionsObservable.of(enteredTechnicalManagementBunkerAdjustmentTrendsPage(paramsMock)); const state$ = new StateObservable(new Subject(), stateMock as DeepPartial as StoreState); const expectedOutputActions = [ vesselDetailsFetchGeneralInfoRequest(paramsMock, stateMock), bunkerAdjustmentFetchTrendsRequest(paramsMock), ]; enteredBunkerAdjustmentTrendsPageEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('fetches trends on fetch trends request action', done => { const action$ = ActionsObservable.of(bunkerAdjustmentFetchTrendsRequest(periodParamsMock)); const state$ = {} as StateObservable; const expectedOutputActions = bunkerAdjustmentFetchTrendsSuccess(trendsMock); fetchTrendsEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); it('returns error action on fetch trends request failure', done => { dependencies.bunkerAdjustment.getTrends = jest.fn(() => { return throwError(''); }); const action$ = ActionsObservable.of(bunkerAdjustmentFetchTrendsRequest(periodParamsMock)); const state$ = {} as StateObservable; const expectedOutputActions = bunkerAdjustmentFetchTrendsFailure(); fetchTrendsEpic(action$, state$, dependencies).subscribe( (actualOutputAction) => { expect(actualOutputAction).toEqual(expectedOutputActions); done(); }, () => { done('epic is in error state'); } ); }); });