Move loading of related changes into a new model
Release-Notes: skip
Google-Bug-Id: b/247042673
Change-Id: Ib46587cb011dac9905f375f77fe9aa2302f815d9
diff --git a/polygerrit-ui/app/models/change/related-changes-model_test.ts b/polygerrit-ui/app/models/change/related-changes-model_test.ts
new file mode 100644
index 0000000..31c0026
--- /dev/null
+++ b/polygerrit-ui/app/models/change/related-changes-model_test.ts
@@ -0,0 +1,238 @@
+/**
+ * @license
+ * Copyright 2023 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+import '../../test/common-test-setup';
+import {getAppContext} from '../../services/app-context';
+import {ChangeModel, changeModelToken} from '../change/change-model';
+import {assert} from '@open-wc/testing';
+import {testResolver} from '../../test/common-test-setup';
+import {RelatedChangesModel} from './related-changes-model';
+import {configModelToken} from '../config/config-model';
+import {SinonStub} from 'sinon';
+import {
+ ChangeInfo,
+ RelatedChangesInfo,
+ SubmittedTogetherInfo,
+} from '../../types/common';
+import {stubRestApi, waitUntilObserved} from '../../test/test-utils';
+import {
+ createParsedChange,
+ createRelatedChangesInfo,
+ createRelatedChangeAndCommitInfo,
+ createChange,
+} from '../../test/test-data-generators';
+import {ChangeStatus, TopicName} from '../../api/rest-api';
+
+suite('related-changes-model tests', () => {
+ let model: RelatedChangesModel;
+ let changeModel: ChangeModel;
+
+ setup(async () => {
+ changeModel = testResolver(changeModelToken);
+ model = new RelatedChangesModel(
+ changeModel,
+ testResolver(configModelToken),
+ getAppContext().restApiService
+ );
+ await waitUntilObserved(changeModel.change$, c => c === undefined);
+ });
+
+ teardown(() => {
+ model.finalize();
+ });
+
+ test('register and fetch', async () => {
+ assert.equal('', '');
+ });
+
+ suite('related changes and hasParent', async () => {
+ let getRelatedChangesStub: SinonStub;
+ let getRelatedChangesResponse: RelatedChangesInfo;
+ let hasParent: boolean | undefined;
+
+ setup(() => {
+ getRelatedChangesStub = stubRestApi('getRelatedChanges').callsFake(() =>
+ Promise.resolve(getRelatedChangesResponse)
+ );
+ model.hasParent$.subscribe(x => (hasParent = x));
+ });
+
+ test('relatedChanges initially undefined', async () => {
+ await waitUntilObserved(
+ model.relatedChanges$,
+ relatedChanges => relatedChanges === undefined
+ );
+ assert.isFalse(getRelatedChangesStub.called);
+ assert.isUndefined(hasParent);
+ });
+
+ test('relatedChanges loading empty', async () => {
+ changeModel.updateStateChange({...createParsedChange()});
+
+ await waitUntilObserved(
+ model.relatedChanges$,
+ relatedChanges => relatedChanges?.length === 0
+ );
+ assert.isTrue(getRelatedChangesStub.calledOnce);
+ assert.isFalse(hasParent);
+ });
+
+ test('relatedChanges loading one change', async () => {
+ getRelatedChangesResponse = {
+ ...createRelatedChangesInfo(),
+ changes: [createRelatedChangeAndCommitInfo()],
+ };
+ changeModel.updateStateChange({...createParsedChange()});
+
+ await waitUntilObserved(
+ model.relatedChanges$,
+ relatedChanges => relatedChanges?.length === 1
+ );
+ assert.isTrue(getRelatedChangesStub.calledOnce);
+ assert.isTrue(hasParent);
+ });
+ });
+
+ suite('loadSubmittedTogether', async () => {
+ let getChangesSubmittedTogetherStub: SinonStub;
+ let getChangesSubmittedTogetherResponse: SubmittedTogetherInfo;
+
+ setup(() => {
+ getChangesSubmittedTogetherStub = stubRestApi(
+ 'getChangesSubmittedTogether'
+ ).callsFake(() => Promise.resolve(getChangesSubmittedTogetherResponse));
+ });
+
+ test('submittedTogether initially undefined', async () => {
+ await waitUntilObserved(
+ model.submittedTogether$,
+ submittedTogether => submittedTogether === undefined
+ );
+ assert.isFalse(getChangesSubmittedTogetherStub.called);
+ });
+
+ test('submittedTogether emits', async () => {
+ getChangesSubmittedTogetherResponse = {
+ changes: [createChange()],
+ non_visible_changes: 0,
+ };
+ changeModel.updateStateChange({...createParsedChange()});
+
+ await waitUntilObserved(
+ model.submittedTogether$,
+ submittedTogether => submittedTogether?.changes?.length === 1
+ );
+ assert.isTrue(getChangesSubmittedTogetherStub.calledOnce);
+ });
+ });
+
+ suite('loadCherryPicks', async () => {
+ let getChangeCherryPicksStub: SinonStub;
+ let getChangeCherryPicksResponse: ChangeInfo[];
+
+ setup(() => {
+ getChangeCherryPicksStub = stubRestApi('getChangeCherryPicks').callsFake(
+ () => Promise.resolve(getChangeCherryPicksResponse)
+ );
+ });
+
+ test('cherryPicks initially undefined', async () => {
+ await waitUntilObserved(
+ model.cherryPicks$,
+ cherryPicks => cherryPicks === undefined
+ );
+ assert.isFalse(getChangeCherryPicksStub.called);
+ });
+
+ test('cherryPicks emits', async () => {
+ getChangeCherryPicksResponse = [createChange()];
+ changeModel.updateStateChange({...createParsedChange()});
+
+ await waitUntilObserved(
+ model.cherryPicks$,
+ cherryPicks => cherryPicks?.length === 1
+ );
+ assert.isTrue(getChangeCherryPicksStub.calledOnce);
+ });
+ });
+
+ suite('loadConflictingChanges', async () => {
+ let getChangeConflictsStub: SinonStub;
+ let getChangeConflictsResponse: ChangeInfo[];
+
+ setup(() => {
+ getChangeConflictsStub = stubRestApi('getChangeConflicts').callsFake(() =>
+ Promise.resolve(getChangeConflictsResponse)
+ );
+ });
+
+ test('conflictingChanges initially undefined', async () => {
+ await waitUntilObserved(
+ model.conflictingChanges$,
+ conflictingChanges => conflictingChanges === undefined
+ );
+ assert.isFalse(getChangeConflictsStub.called);
+ });
+
+ test('conflictingChanges not loaded for merged changes', async () => {
+ getChangeConflictsResponse = [createChange()];
+ changeModel.updateStateChange({
+ ...createParsedChange(),
+ mergeable: true,
+ status: ChangeStatus.MERGED,
+ });
+
+ await waitUntilObserved(
+ model.conflictingChanges$,
+ conflictingChanges => conflictingChanges === undefined
+ );
+ assert.isFalse(getChangeConflictsStub.called);
+ });
+
+ test('conflictingChanges emits', async () => {
+ getChangeConflictsResponse = [createChange()];
+ changeModel.updateStateChange({...createParsedChange(), mergeable: true});
+
+ await waitUntilObserved(
+ model.conflictingChanges$,
+ conflictingChanges => conflictingChanges?.length === 1
+ );
+ assert.isTrue(getChangeConflictsStub.calledOnce);
+ });
+ });
+
+ suite('loadSameTopicChanges', async () => {
+ let getChangesWithSameTopicStub: SinonStub;
+ let getChangesWithSameTopicResponse: ChangeInfo[];
+
+ setup(() => {
+ getChangesWithSameTopicStub = stubRestApi(
+ 'getChangesWithSameTopic'
+ ).callsFake(() => Promise.resolve(getChangesWithSameTopicResponse));
+ });
+
+ test('sameTopicChanges initially undefined', async () => {
+ await waitUntilObserved(
+ model.sameTopicChanges$,
+ sameTopicChanges => sameTopicChanges === undefined
+ );
+ assert.isFalse(getChangesWithSameTopicStub.called);
+ });
+
+ test('sameTopicChanges emits', async () => {
+ getChangesWithSameTopicResponse = [createChange()];
+ changeModel.updateStateChange({
+ ...createParsedChange(),
+ topic: 'test-topic' as TopicName,
+ });
+
+ await waitUntilObserved(
+ model.sameTopicChanges$,
+ sameTopicChanges => sameTopicChanges?.length === 1
+ );
+ assert.isTrue(getChangesWithSameTopicStub.calledOnce);
+ });
+ });
+});