diff options
Diffstat (limited to 'spec/frontend/code_review/signals_spec.js')
-rw-r--r-- | spec/frontend/code_review/signals_spec.js | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/spec/frontend/code_review/signals_spec.js b/spec/frontend/code_review/signals_spec.js new file mode 100644 index 00000000000..03c3580860e --- /dev/null +++ b/spec/frontend/code_review/signals_spec.js @@ -0,0 +1,145 @@ +import { start } from '~/code_review/signals'; + +import diffsEventHub from '~/diffs/event_hub'; +import { EVT_MR_PREPARED } from '~/diffs/constants'; +import { getDerivedMergeRequestInformation } from '~/diffs/utils/merge_request'; + +jest.mock('~/diffs/utils/merge_request'); + +describe('~/code_review', () => { + const io = diffsEventHub; + + beforeAll(() => { + getDerivedMergeRequestInformation.mockImplementation(() => ({ + namespace: 'x', + project: 'y', + id: '1', + })); + }); + + describe('start', () => { + it.each` + description | argument + ${'no event hub is provided'} | ${{}} + ${'no parameters are provided'} | ${undefined} + `('throws an error if $description', async ({ argument }) => { + await expect(() => start(argument)).rejects.toThrow('signalBus is a required argument'); + }); + + describe('observeMergeRequestFinishingPreparation', () => { + const callArgs = {}; + const apollo = {}; + let querySpy; + let apolloSubscribeSpy; + let subscribeSpy; + let nextSpy; + let unsubscribeSpy; + let observable; + + beforeEach(() => { + querySpy = jest.fn(); + apolloSubscribeSpy = jest.fn(); + subscribeSpy = jest.fn(); + unsubscribeSpy = jest.fn(); + nextSpy = jest.fn(); + observable = { + next: nextSpy, + subscribe: subscribeSpy.mockReturnValue({ + unsubscribe: unsubscribeSpy, + }), + }; + + querySpy.mockResolvedValue({ + data: { project: { mergeRequest: { id: 'gql:id:1', preparedAt: 'x' } } }, + }); + apolloSubscribeSpy.mockReturnValue(observable); + + apollo.query = querySpy; + apollo.subscribe = apolloSubscribeSpy; + + callArgs.signalBus = io; + callArgs.apolloClient = apollo; + }); + + it('does not query at all if the page does not seem like a merge request', async () => { + getDerivedMergeRequestInformation.mockImplementationOnce(() => ({})); + + await start(callArgs); + + expect(querySpy).not.toHaveBeenCalled(); + expect(apolloSubscribeSpy).not.toHaveBeenCalled(); + }); + + describe('on a merge request page', () => { + it('requests the preparedAt (and id) for the current merge request', async () => { + await start(callArgs); + + expect(querySpy).toHaveBeenCalledWith( + expect.objectContaining({ + variables: { + projectPath: 'x/y', + iid: '1', + }, + }), + ); + }); + + it('does not subscribe to any updates if the preparedAt value is already populated', async () => { + await start(callArgs); + + expect(apolloSubscribeSpy).not.toHaveBeenCalled(); + }); + + describe('if the merge request is still asynchronously preparing', () => { + beforeEach(() => { + querySpy.mockResolvedValue({ + data: { project: { mergeRequest: { id: 'gql:id:1', preparedAt: null } } }, + }); + }); + + it('subscribes to updates', async () => { + await start(callArgs); + + expect(apolloSubscribeSpy).toHaveBeenCalledWith( + expect.objectContaining({ variables: { issuableId: 'gql:id:1' } }), + ); + expect(observable.subscribe).toHaveBeenCalled(); + }); + + describe('when the MR has been updated', () => { + let emitSpy; + let behavior; + + beforeEach(() => { + emitSpy = jest.spyOn(diffsEventHub, '$emit'); + nextSpy.mockImplementation((data) => behavior?.(data)); + subscribeSpy.mockImplementation((handler) => { + behavior = handler; + + return { unsubscribe: unsubscribeSpy }; + }); + }); + + it('does nothing if the MR has not yet finished preparing', async () => { + await start(callArgs); + + observable.next({ data: { mergeRequestMergeStatusUpdated: { preparedAt: null } } }); + + expect(unsubscribeSpy).not.toHaveBeenCalled(); + expect(emitSpy).not.toHaveBeenCalled(); + }); + + it('emits an event and unsubscribes when the MR is prepared', async () => { + await start(callArgs); + + observable.next({ data: { mergeRequestMergeStatusUpdated: { preparedAt: 'x' } } }); + + expect(unsubscribeSpy).toHaveBeenCalled(); + expect(emitSpy).toHaveBeenCalledWith(EVT_MR_PREPARED); + }); + }); + }); + }); + }); + }); +}); |