Code Testing and Reviewing

This section provides an overview of testing and reviewing the migrated code.

Code Testing

selectors.ts

Already explained in detail in the Updating the Selectors section.

listeners.test.ts

This code contains sample tests from listeners.test.ts file.

// sample test of how we tested the listeners

describe('getDeviceFulfilled listener', () => {
    let unsubscribe: UnsubscribeListener;

    beforeAll(() => {
        unsubscribe = listeners.getDeviceFulfilled();
    });

    afterAll(() => {
        unsubscribe();
    });

    it('should dispatch setAtomicId, setDevicePayload and initiate getTariffWithHardware', () => {
        // Mock selectors
        jest.spyOn(deviceSelectors, 'selectAtomicId').mockReturnValue('atomic123');
        jest.spyOn(appSelectors, 'selectSalesChannel').mockReturnValue(SALESCHANNEL_CONSUMER);
        jest.spyOn(appSelectors, 'selectIsTradeIn').mockReturnValue(false);

        const mockDevicePayload: HardwareDetailGroupResponse = {
            data: {
                modelName: 'Test Phone',
                virtualItemId: 'test-id',
                legacyGroupId: 'legacy-id',
                promotionAttribute: { cellular: Cellular.FiveG },
                url: { hubpage: { href: 'test-url' }, galleryImage: { href: 'test-image' } },
                colors: [],
                capacities: [],
                atomics: [],
                attributeGroups: [],
            },
        };

        const dispatchMock = jest.fn();
        const getStateMock = jest.fn();
        const mockState = {};

        listener.middleware({
            dispatch: dispatchMock,
            getState: getStateMock.mockReturnValue(mockState),
        })(() => (action: any) => action)({
            type: `${gladosApi.reducerPath}/executeQuery/fulfilled`,
            payload: mockDevicePayload,
            meta: {
                arg: {
                    endpointName: getHardwareDetailGroup.name,
                },
            },
        });

        expect(dispatchMock).toHaveBeenCalledWith(setAtomicId({ atomicId: 'atomic123' }));
        expect(dispatchMock).toHaveBeenCalledWith(setDevicePayload(mockDevicePayload));
        expect(dispatchMock).toHaveBeenCalledWith(expect.any(Function));
    });

    it('should handle different salesChannel and tradeIn values', () => {
        // Mock selectors with different values
        jest.spyOn(deviceSelectors, 'selectAtomicId').mockReturnValue('atomic456');
        jest.spyOn(appSelectors, 'selectSalesChannel').mockReturnValue(SALESCHANNEL_YOUNG);
        jest.spyOn(appSelectors, 'selectIsTradeIn').mockReturnValue(true);

        const mockDevicePayload: HardwareDetailGroupResponse = {
            data: {
                modelName: 'Test Phone2',
                virtualItemId: 'test-id',
                legacyGroupId: 'legacy-id',
                promotionAttribute: { cellular: Cellular.FiveG },
                url: { hubpage: { href: 'test-url' }, galleryImage: { href: 'test-image' } },
                colors: [],
                capacities: [],
                atomics: [],
                attributeGroups: [],
            },
        };

        const dispatchMock = jest.fn();
        const getStateMock = jest.fn();
        const mockState = {};

        listener.middleware({
            dispatch: dispatchMock,
            getState: getStateMock.mockReturnValue(mockState),
        })(() => (action: any) => action)({
            type: `${gladosApi.reducerPath}/executeQuery/fulfilled`,
            payload: mockDevicePayload,
            meta: {
                arg: {
                    endpointName: getHardwareDetailGroup.name,
                },
            },
        });

        expect(dispatchMock).toHaveBeenCalledWith(setAtomicId({ atomicId: 'atomic456' }));
        expect(dispatchMock).toHaveBeenCalledWith(setDevicePayload(mockDevicePayload));
        expect(dispatchMock).toHaveBeenCalledWith(expect.any(Function));
    });
});

slice.test.ts

This code contains sample tests from slice.test.ts file.

// sample test of how we tested the slices

// Divided into 2 main tests (Actions, Reducers)
describe('VVL Device Details Options Slice', () => {
    describe('Actions', () => {
        describe('setDefaultState', () => {
            it('should return the correct type', () => {
                const fixture = '123';
                const expected = {
                    type: expect.any(String),
                    payload: fixture,
                };

                expect(setDefaultState(fixture)).toEqual(expected);
            });
        });
    });

    describe('Reducer', () => {
        it('should handle the setDefaultState action correctly', () => {
            const atomicId = '1234';

            const expected = produce(optionsSlice.getInitialState(), draft => {
                draft.atomicId = atomicId;
            });
            expect(optionsSlice.reducer(optionsSlice.getInitialState(), setDefaultState(atomicId))).toEqual(expected);
        });
    });
});

Summary

These three files (listeners.test.ts, slice.test.ts, and selectors.test.ts) represent the primary test cases for the application alongside the helpers test files, ensuring functionality is covered across core features and functionalities.

Code Reviewing

Strategy and Schedule

  • The review process was organized into daily sessions.
  • Each team member reviewed their assigned part of the migration code.
  • Daily Routine:
    • 10:00 a.m. to 2:00 p.m.: Reviewing code.
    • 2:00 p.m. to 6:00 p.m.: Addressing comments and refining code.
  • PR Workflow:
    • Initially, all team members contributed to a single, large pull request (PR) after ensuring their respective migrations were fully tested and functional.
    • Any new errors or failed test cases discovered during the review were resolved by creating separate PRs. These fixes were tested, reviewed, and merged back into the main branch.

Visual Representation

Include a schedule or table summarizing the parts of the migration each team member reviewed and worked on daily during the reviewing period.

TaskDay 1Day 2Day 3
App SliceMayada/SayedMonaOsama
Option SliceNourOsamaMayada/Sayed
TradeinAhmedNourMona
TariffOsamaMayada/SayedAhmed
OverlayMonaAhmedNour
GladosMonaOsama

Thank You

Thank you for reading till the end 🙏

Additional Resources

  1. Redux Toolkit KT
  2. Redux Toolkit in Action

For a deeper understanding of Redux Toolkit and its implementation, we recommend these resources as they provide valuable insights and practical examples to help you master Redux Toolkit. Created with love by Kilo team ❤️.