diff options
Diffstat (limited to 'polygerrit-ui/app/models/change/change-model_test.ts')
-rw-r--r-- | polygerrit-ui/app/models/change/change-model_test.ts | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/polygerrit-ui/app/models/change/change-model_test.ts b/polygerrit-ui/app/models/change/change-model_test.ts new file mode 100644 index 0000000000..ceb87cca89 --- /dev/null +++ b/polygerrit-ui/app/models/change/change-model_test.ts @@ -0,0 +1,292 @@ +/** + * @license + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Subject} from 'rxjs'; +import {ChangeStatus} from '../../constants/constants'; +import '../../test/common-test-setup-karma'; +import { + createChange, + createChangeMessageInfo, + createEditInfo, + createParsedChange, + createRevision, +} from '../../test/test-data-generators'; +import { + mockPromise, + stubRestApi, + waitUntilObserved, +} from '../../test/test-utils'; +import { + CommitId, + EditPatchSetNum, + NumericChangeId, + PatchSetNum, +} from '../../types/common'; +import {ParsedChangeInfo} from '../../types/types'; +import {getAppContext} from '../../services/app-context'; +import {GerritView} from '../../services/router/router-model'; +import {ChangeState, LoadingStatus, updateChangeWithEdit} from './change-model'; +import {ChangeModel} from './change-model'; + +suite('updateChangeWithEdit() tests', () => { + test('undefined change', async () => { + assert.isUndefined(updateChangeWithEdit()); + }); + + test('undefined edit', async () => { + const change = createParsedChange(); + assert.equal(updateChangeWithEdit(change), change); + }); + + test('set edit rev and current rev', async () => { + let change: ParsedChangeInfo | undefined = createParsedChange(); + const edit = createEditInfo(); + change = updateChangeWithEdit(change, edit); + const editRev = change?.revisions[`${edit.commit.commit}`]; + assert.isDefined(editRev); + assert.equal(editRev?._number, EditPatchSetNum); + assert.equal(editRev?.basePatchNum, edit.base_patch_set_number); + assert.equal(change?.current_revision, edit.commit.commit); + }); + + test('do not set current rev when patchNum already set', async () => { + let change: ParsedChangeInfo | undefined = createParsedChange(); + const edit = createEditInfo(); + change = updateChangeWithEdit(change, edit, 1 as PatchSetNum); + const editRev = change?.revisions[`${edit.commit.commit}`]; + assert.isDefined(editRev); + assert.equal(change?.current_revision, 'abc' as CommitId); + }); +}); + +suite('change service tests', () => { + let changeModel: ChangeModel; + let knownChange: ParsedChangeInfo; + const testCompleted = new Subject<void>(); + + async function waitForLoadingStatus( + loadingStatus: LoadingStatus + ): Promise<ChangeState> { + return await waitUntilObserved( + changeModel.state$, + state => state.loadingStatus === loadingStatus, + `LoadingStatus was never ${loadingStatus}` + ); + } + + setup(() => { + changeModel = new ChangeModel( + getAppContext().routerModel, + getAppContext().restApiService, + getAppContext().userModel + ); + knownChange = { + ...createChange(), + revisions: { + sha1: { + ...createRevision(1), + description: 'patch 1', + _number: 1 as PatchSetNum, + }, + sha2: { + ...createRevision(2), + description: 'patch 2', + _number: 2 as PatchSetNum, + }, + }, + status: ChangeStatus.NEW, + current_revision: 'abc' as CommitId, + messages: [], + }; + }); + + teardown(() => { + testCompleted.next(); + changeModel.finalize(); + }); + + test('load a change', async () => { + const promise = mockPromise<ParsedChangeInfo | undefined>(); + const stub = stubRestApi('getChangeDetail').callsFake(() => promise); + let state: ChangeState; + + state = await waitForLoadingStatus(LoadingStatus.NOT_LOADED); + assert.equal(stub.callCount, 0); + assert.isUndefined(state?.change); + + changeModel.routerModel.setState({ + view: GerritView.CHANGE, + changeNum: knownChange._number, + }); + state = await waitForLoadingStatus(LoadingStatus.LOADING); + assert.equal(stub.callCount, 1); + assert.isUndefined(state?.change); + + promise.resolve(knownChange); + state = await waitForLoadingStatus(LoadingStatus.LOADED); + assert.equal(stub.callCount, 1); + assert.equal(state?.change, knownChange); + }); + + test('reload a change', async () => { + // setting up a loaded change + const promise = mockPromise<ParsedChangeInfo | undefined>(); + const stub = stubRestApi('getChangeDetail').callsFake(() => promise); + let state: ChangeState; + changeModel.routerModel.setState({ + view: GerritView.CHANGE, + changeNum: knownChange._number, + }); + promise.resolve(knownChange); + state = await waitForLoadingStatus(LoadingStatus.LOADED); + + // Reloading same change + document.dispatchEvent(new CustomEvent('reload')); + state = await waitForLoadingStatus(LoadingStatus.RELOADING); + assert.equal(stub.callCount, 2); + assert.equal(state?.change, knownChange); + + promise.resolve(knownChange); + state = await waitForLoadingStatus(LoadingStatus.LOADED); + assert.equal(stub.callCount, 2); + assert.equal(state?.change, knownChange); + }); + + test('navigating to another change', async () => { + // setting up a loaded change + let promise = mockPromise<ParsedChangeInfo | undefined>(); + const stub = stubRestApi('getChangeDetail').callsFake(() => promise); + let state: ChangeState; + changeModel.routerModel.setState({ + view: GerritView.CHANGE, + changeNum: knownChange._number, + }); + promise.resolve(knownChange); + state = await waitForLoadingStatus(LoadingStatus.LOADED); + + // Navigating to other change + + const otherChange: ParsedChangeInfo = { + ...knownChange, + _number: 123 as NumericChangeId, + }; + promise = mockPromise<ParsedChangeInfo | undefined>(); + changeModel.routerModel.setState({ + view: GerritView.CHANGE, + changeNum: otherChange._number, + }); + state = await waitForLoadingStatus(LoadingStatus.LOADING); + assert.equal(stub.callCount, 2); + assert.isUndefined(state?.change); + + promise.resolve(otherChange); + state = await waitForLoadingStatus(LoadingStatus.LOADED); + assert.equal(stub.callCount, 2); + assert.equal(state?.change, otherChange); + }); + + test('navigating to dashboard', async () => { + // setting up a loaded change + let promise = mockPromise<ParsedChangeInfo | undefined>(); + const stub = stubRestApi('getChangeDetail').callsFake(() => promise); + let state: ChangeState; + changeModel.routerModel.setState({ + view: GerritView.CHANGE, + changeNum: knownChange._number, + }); + promise.resolve(knownChange); + state = await waitForLoadingStatus(LoadingStatus.LOADED); + + // Navigating to dashboard + + promise = mockPromise<ParsedChangeInfo | undefined>(); + promise.resolve(undefined); + changeModel.routerModel.setState({ + view: GerritView.CHANGE, + changeNum: undefined, + }); + state = await waitForLoadingStatus(LoadingStatus.NOT_LOADED); + assert.equal(stub.callCount, 2); + assert.isUndefined(state?.change); + + // Navigating back from dashboard to change page + + promise = mockPromise<ParsedChangeInfo | undefined>(); + promise.resolve(knownChange); + changeModel.routerModel.setState({ + view: GerritView.CHANGE, + changeNum: knownChange._number, + }); + state = await waitForLoadingStatus(LoadingStatus.LOADED); + assert.equal(stub.callCount, 3); + assert.equal(state?.change, knownChange); + }); + + test('changeModel.fetchChangeUpdates on latest', async () => { + stubRestApi('getChangeDetail').returns(Promise.resolve(knownChange)); + const result = await changeModel.fetchChangeUpdates(knownChange); + assert.isTrue(result.isLatest); + assert.isNotOk(result.newStatus); + assert.isNotOk(result.newMessages); + }); + + test('changeModel.fetchChangeUpdates not on latest', async () => { + const actualChange = { + ...knownChange, + revisions: { + ...knownChange.revisions, + sha3: { + ...createRevision(3), + description: 'patch 3', + _number: 3 as PatchSetNum, + }, + }, + }; + stubRestApi('getChangeDetail').returns(Promise.resolve(actualChange)); + const result = await changeModel.fetchChangeUpdates(knownChange); + assert.isFalse(result.isLatest); + assert.isNotOk(result.newStatus); + assert.isNotOk(result.newMessages); + }); + + test('changeModel.fetchChangeUpdates new status', async () => { + const actualChange = { + ...knownChange, + status: ChangeStatus.MERGED, + }; + stubRestApi('getChangeDetail').returns(Promise.resolve(actualChange)); + const result = await changeModel.fetchChangeUpdates(knownChange); + assert.isTrue(result.isLatest); + assert.equal(result.newStatus, ChangeStatus.MERGED); + assert.isNotOk(result.newMessages); + }); + + test('changeModel.fetchChangeUpdates new messages', async () => { + const actualChange = { + ...knownChange, + messages: [{...createChangeMessageInfo(), message: 'blah blah'}], + }; + stubRestApi('getChangeDetail').returns(Promise.resolve(actualChange)); + const result = await changeModel.fetchChangeUpdates(knownChange); + assert.isTrue(result.isLatest); + assert.isNotOk(result.newStatus); + assert.deepEqual(result.newMessages, { + ...createChangeMessageInfo(), + message: 'blah blah', + }); + }); +}); |