summaryrefslogtreecommitdiff
path: root/spec/frontend/code_review/signals_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/code_review/signals_spec.js')
-rw-r--r--spec/frontend/code_review/signals_spec.js145
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);
+ });
+ });
+ });
+ });
+ });
+ });
+});