Move to Dependency injection for UserModel Make model getters private on elements. They can be easily fetched with `testResolver(fooToken)` in tests. In addition, get rid of shortcutsService on appContext as it was not being used anywhere and shortcutsService is already DI. Release-Notes: skip Change-Id: I2f565127a3cdb7e79206500550e4313c23a7fb09
diff --git a/polygerrit-ui/FE_Style_Guide.md b/polygerrit-ui/FE_Style_Guide.md index 6673cdf..56b5aee 100644 --- a/polygerrit-ui/FE_Style_Guide.md +++ b/polygerrit-ui/FE_Style_Guide.md
@@ -167,83 +167,3 @@ the element's class constructor. Do not use appContext anywhere except the constructor of the class. - -**Note for legacy elements:** If a polymer element extends a LegacyElementMixin and overrides the `created()` method, -move all code from this method to a constructor right after the call to a `super()` -([example](#assign-dependencies-legacy-element-example)). The `created()` -method is [deprecated](https://polymer-library.polymer-project.org/2.0/docs/about_20#lifecycle-changes) and is called -when a super (i.e. base) class constructor is called. If you are unsure about moving the code from the `created` method -to the class constructor, consult with the source code: -[`LegacyElementMixin._initializeProperties`](https://github.com/Polymer/polymer/blob/v3.4.0/lib/legacy/legacy-element-mixin.js#L318) -and -[`PropertiesChanged.constructor`](https://github.com/Polymer/polymer/blob/v3.4.0/lib/mixins/properties-changed.js#L177) - - - -**Good:** -```Javascript -import {appContext} from `.../services/app-context.js`; - -export class MyCustomElement extends ...{ - constructor() { - super(); //This is mandatory to call parent constructor - this._userModel = appContext.userModel; - } - //... - _getUserName() { - return this._userModel.activeUserName(); - } -} -``` - -**Bad:** -```Javascript -import {appContext} from `.../services/app-context.js`; - -export class MyCustomElement extends ...{ - created() { - // Incorrect: assign all dependencies in the constructor - this._userModel = appContext.userModel; - } - //... - _getUserName() { - // Incorrect: use appContext outside of a constructor - return appContext.userModel.activeUserName(); - } -} -``` - -<a name="assign-dependencies-legacy-element-example"></a> -**Legacy element:** - -Before: -```Javascript -export class MyCustomElement extends ...LegacyElementMixin(...) { - constructor() { - super(); - someAction(); - } - created() { - super(); - createdAction1(); - createdAction2(); - } -} -``` - -After: -```Javascript -export class MyCustomElement extends ...LegacyElementMixin(...) { - constructor() { - super(); - // Assign services here - this._userModel = appContext.userModel; - // Code from the created method - put it before existing actions in constructor - createdAction1(); - createdAction2(); - // Original constructor code - someAction(); - } - // created method is removed -} -```
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.ts b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.ts index 01d452a..9d2711b 100644 --- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.ts +++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.ts
@@ -40,6 +40,8 @@ import {customElement, property, state} from 'lit/decorators.js'; import {subscribe} from '../../lit/subscription-controller'; import {createSearchUrl} from '../../../models/views/search'; +import {userModelToken} from '../../../models/user/user-model'; +import {resolve} from '../../../models/dependency'; const STATES = { active: {value: ProjectState.ACTIVE, label: 'Active'}, @@ -110,7 +112,7 @@ @state() private pluginConfigChanged = false; - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly restApiService = getAppContext().restApiService; @@ -118,7 +120,7 @@ super(); subscribe( this, - () => this.userModel.preferences$, + () => this.getUserModel().preferences$, prefs => { if (prefs?.download_scheme) { // Note (issue 5180): normalize the download scheme with lower-case.
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-bulk-vote-flow/gr-change-list-bulk-vote-flow.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-bulk-vote-flow/gr-change-list-bulk-vote-flow.ts index 5728529..714b588 100644 --- a/polygerrit-ui/app/elements/change-list/gr-change-list-bulk-vote-flow/gr-change-list-bulk-vote-flow.ts +++ b/polygerrit-ui/app/elements/change-list/gr-change-list-bulk-vote-flow/gr-change-list-bulk-vote-flow.ts
@@ -39,12 +39,13 @@ import {GrDialog} from '../../shared/gr-dialog/gr-dialog'; import {Interaction} from '../../../constants/reporting'; import {createChangeUrl} from '../../../models/views/change'; +import {userModelToken} from '../../../models/user/user-model'; @customElement('gr-change-list-bulk-vote-flow') export class GrChangeListBulkVoteFlow extends LitElement { private readonly getBulkActionsModel = resolve(this, bulkActionsModelToken); - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly reportingService = getAppContext().reportingService; @@ -141,7 +142,7 @@ ); subscribe( this, - () => this.userModel.account$, + () => this.getUserModel().account$, account => (this.account = account) ); }
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-reviewer-flow/gr-change-list-reviewer-flow.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-reviewer-flow/gr-change-list-reviewer-flow.ts index 436e435..cb6dd7d 100644 --- a/polygerrit-ui/app/elements/change-list/gr-change-list-reviewer-flow/gr-change-list-reviewer-flow.ts +++ b/polygerrit-ui/app/elements/change-list/gr-change-list-reviewer-flow/gr-change-list-reviewer-flow.ts
@@ -44,6 +44,7 @@ import {fireAlert, fireReload} from '../../../utils/event-util'; import {GrDialog} from '../../shared/gr-dialog/gr-dialog'; import {Interaction} from '../../../constants/reporting'; +import {userModelToken} from '../../../models/user/user-model'; @customElement('gr-change-list-reviewer-flow') export class GrChangeListReviewerFlow extends LitElement { @@ -95,9 +96,11 @@ private readonly reportingService = getAppContext().reportingService; - private getBulkActionsModel = resolve(this, bulkActionsModelToken); + private readonly getBulkActionsModel = resolve(this, bulkActionsModelToken); - private getConfigModel = resolve(this, configModelToken); + private readonly getConfigModel = resolve(this, configModelToken); + + private readonly getUserModel = resolve(this, userModelToken); private restApiService = getAppContext().restApiService; @@ -169,12 +172,12 @@ ); subscribe( this, - () => getAppContext().userModel.loggedIn$, + () => this.getUserModel().loggedIn$, isLoggedIn => (this.isLoggedIn = isLoggedIn) ); subscribe( this, - () => getAppContext().userModel.account$, + () => this.getUserModel().account$, account => (this.account = account) ); }
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts index 8000c22..cd5cb96 100644 --- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts +++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
@@ -27,6 +27,7 @@ } from '../../../models/views/search'; import {resolve} from '../../../models/dependency'; import {subscribe} from '../../lit/subscription-controller'; +import {userModelToken} from '../../../models/user/user-model'; const LIMIT_OPERATOR_PATTERN = /\blimit:(\d+)/i; @@ -76,7 +77,7 @@ private reporting = getAppContext().reportingService; - private userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly getViewModel = resolve(this, searchViewModelToken); @@ -117,22 +118,22 @@ ); subscribe( this, - () => this.userModel.account$, + () => this.getUserModel().account$, x => (this.account = x) ); subscribe( this, - () => this.userModel.loggedIn$, + () => this.getUserModel().loggedIn$, x => (this.loggedIn = x) ); subscribe( this, - () => this.userModel.preferenceChangesPerPage$, + () => this.getUserModel().preferenceChangesPerPage$, x => (this.changesPerPage = x) ); subscribe( this, - () => this.userModel.preferences$, + () => this.getUserModel().preferences$, x => (this.preferences = x) ); }
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts index d178880..f37dce3 100644 --- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts +++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
@@ -57,6 +57,7 @@ UserDashboard, YOUR_TURN, } from '../../../utils/dashboard-util'; +import {userModelToken} from '../../../models/user/user-model'; const PROJECT_PLACEHOLDER_PATTERN = /\${project}/g; @@ -107,7 +108,7 @@ private readonly restApiService = getAppContext().restApiService; - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly getViewModel = resolve(this, dashboardViewModelToken); @@ -119,7 +120,7 @@ super(); subscribe( this, - () => this.userModel.account$, + () => this.getUserModel().account$, x => (this.account = x) ); subscribe(
diff --git a/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary.ts b/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary.ts index ed1f46d..84bdffb 100644 --- a/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary.ts +++ b/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary.ts
@@ -57,6 +57,7 @@ import {when} from 'lit/directives/when.js'; import {KnownExperimentId} from '../../../services/flags/flags'; import {combineLatest} from 'rxjs'; +import {userModelToken} from '../../../models/user/user-model'; function handleSpaceOrEnter(e: KeyboardEvent, handler: () => void) { if (modifierPressed(e)) return; @@ -109,11 +110,9 @@ private readonly showAllChips = new Map<RunStatus | Category, boolean>(); - // private but used in tests - readonly getCommentsModel = resolve(this, commentsModelToken); + private readonly getCommentsModel = resolve(this, commentsModelToken); - // private but used in tests - readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly getChecksModel = resolve(this, checksModelToken); @@ -172,7 +171,7 @@ ); subscribe( this, - () => this.userModel.account$, + () => this.getUserModel().account$, x => (this.selfAccount = x) ); if (this.flagsService.isEnabled(KnownExperimentId.MENTION_USERS)) { @@ -180,7 +179,7 @@ this, () => combineLatest([ - this.userModel.account$, + this.getUserModel().account$, this.getCommentsModel().threads$, ]), ([selfAccount, threads]) => {
diff --git a/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary_test.ts b/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary_test.ts index 9584637..05036ab 100644 --- a/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary_test.ts +++ b/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary_test.ts
@@ -16,11 +16,22 @@ } from '../../../test/test-data-generators'; import {stubFlags} from '../../../test/test-utils'; import {Timestamp} from '../../../api/rest-api'; +import {testResolver} from '../../../test/common-test-setup'; +import {UserModel, userModelToken} from '../../../models/user/user-model'; +import { + CommentsModel, + commentsModelToken, +} from '../../../models/comments/comments-model'; suite('gr-change-summary test', () => { let element: GrChangeSummary; + let commentsModel: CommentsModel; + let userModel: UserModel; + setup(async () => { element = await fixture(html`<gr-change-summary></gr-change-summary>`); + commentsModel = testResolver(commentsModelToken); + userModel = testResolver(userModelToken); }); test('is defined', () => { @@ -29,7 +40,7 @@ }); test('renders', async () => { - element.getCommentsModel().setState({ + commentsModel.setState({ drafts: { a: [createDraft(), createDraft(), createDraft()], }, @@ -112,7 +123,7 @@ element = await fixture(html`<gr-change-summary></gr-change-summary>`); await element.updateComplete; - element.getCommentsModel().setState({ + commentsModel.setState({ drafts: { a: [ { @@ -139,7 +150,7 @@ }, discardedDrafts: [], }); - element.userModel.setAccount({ + userModel.setAccount({ ...createAccountWithEmail('abc@def.com'), registered_on: '2015-03-12 18:32:08.000000000' as Timestamp, });
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts index d6e1958..98b0b23 100644 --- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts +++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -181,6 +181,7 @@ } from '../../../models/views/change'; import {rootUrl} from '../../../utils/url-util'; import {createEditUrl} from '../../../models/views/edit'; +import {userModelToken} from '../../../models/user/user-model'; const MIN_LINES_FOR_COMMIT_COLLAPSE = 18; @@ -535,16 +536,13 @@ private readonly flagsService = getAppContext().flagsService; - // Private but used in tests. - readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); - // Private but used in tests. - readonly getChangeModel = resolve(this, changeModelToken); + private readonly getChangeModel = resolve(this, changeModelToken); private readonly routerModel = getAppContext().routerModel; - // Private but used in tests. - readonly getCommentsModel = resolve(this, commentsModelToken); + private readonly getCommentsModel = resolve(this, commentsModelToken); private readonly getConfigModel = resolve(this, configModelToken); @@ -738,7 +736,7 @@ ); subscribe( this, - () => this.userModel.preferenceDiffViewMode$, + () => this.getUserModel().preferenceDiffViewMode$, diffViewMode => { this.diffViewMode = diffViewMode; } @@ -768,14 +766,14 @@ ); subscribe( this, - () => this.userModel.account$, + () => this.getUserModel().account$, account => { this.account = account; } ); subscribe( this, - () => this.userModel.loggedIn$, + () => this.getUserModel().loggedIn$, loggedIn => { this.loggedIn = loggedIn; } @@ -1726,9 +1724,9 @@ // Private but used in tests. handleToggleDiffMode() { if (this.diffViewMode === DiffViewMode.SIDE_BY_SIDE) { - this.userModel.updatePreferences({diff_view: DiffViewMode.UNIFIED}); + this.getUserModel().updatePreferences({diff_view: DiffViewMode.UNIFIED}); } else { - this.userModel.updatePreferences({ + this.getUserModel().updatePreferences({ diff_view: DiffViewMode.SIDE_BY_SIDE, }); }
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts index f3017f8..095e942 100644 --- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts +++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
@@ -28,7 +28,6 @@ queryAndAssert, stubFlags, stubRestApi, - stubUsers, waitEventLoop, waitQueryAndAssert, waitUntil, @@ -86,7 +85,11 @@ import {ParsedChangeInfo} from '../../../types/types'; import {GrRelatedChangesList} from '../gr-related-changes-list/gr-related-changes-list'; import {ChangeStates} from '../../shared/gr-change-status/gr-change-status'; -import {LoadingStatus} from '../../../models/change/change-model'; +import { + ChangeModel, + changeModelToken, + LoadingStatus, +} from '../../../models/change/change-model'; import {FocusTarget, GrReplyDialog} from '../gr-reply-dialog/gr-reply-dialog'; import {GrOverlay} from '../../shared/gr-overlay/gr-overlay'; import {GrChangeStar} from '../../shared/gr-change-star/gr-change-star'; @@ -101,10 +104,18 @@ import {ChangeViewState} from '../../../models/views/change'; import {rootUrl} from '../../../utils/url-util'; import {testResolver} from '../../../test/common-test-setup'; +import {UserModel, userModelToken} from '../../../models/user/user-model'; +import { + CommentsModel, + commentsModelToken, +} from '../../../models/comments/comments-model'; suite('gr-change-view tests', () => { let element: GrChangeView; let setUrlStub: sinon.SinonStub; + let userModel: UserModel; + let changeModel: ChangeModel; + let commentsModel: CommentsModel; const ROBOT_COMMENTS_LIMIT = 10; @@ -374,6 +385,9 @@ assertIsDefined(element.actions); sinon.stub(element.actions, 'reload').returns(Promise.resolve()); }); + userModel = testResolver(userModelToken); + commentsModel = testResolver(commentsModelToken); + changeModel = testResolver(changeModelToken); }); teardown(async () => { @@ -805,7 +819,7 @@ }); test('A fires an error event when not logged in', async () => { - element.userModel.setAccount(undefined); + userModel.setAccount(undefined); const loggedInErrorSpy = sinon.spy(); element.addEventListener('show-auth-required', loggedInErrorSpy); pressKey(element, 'a'); @@ -978,14 +992,14 @@ }); test('m should toggle diff mode', async () => { - const updatePreferencesStub = stubUsers('updatePreferences'); + const updatePreferencesStub = sinon.stub(userModel, 'updatePreferences'); await element.updateComplete; const prefs = { ...createDefaultPreferences(), diff_view: DiffViewMode.SIDE_BY_SIDE, }; - element.userModel.setPreferences(prefs); + userModel.setPreferences(prefs); element.handleToggleDiffMode(); assert.isTrue( updatePreferencesStub.calledWith({diff_view: DiffViewMode.UNIFIED}) @@ -995,7 +1009,7 @@ ...createDefaultPreferences(), diff_view: DiffViewMode.UNIFIED, }; - element.userModel.setPreferences(newPrefs); + userModel.setPreferences(newPrefs); await element.updateComplete; element.handleToggleDiffMode(); assert.isTrue( @@ -1586,11 +1600,11 @@ sinon.stub(element, 'loadAndSetCommitInfo'); await element.updateComplete; const reloadPortedCommentsStub = sinon.stub( - element.getCommentsModel(), + commentsModel, 'reloadPortedComments' ); const reloadPortedDraftsStub = sinon.stub( - element.getCommentsModel(), + commentsModel, 'reloadPortedDrafts' ); sinon.stub(element.fileList, 'collapseAllDiffs'); @@ -1683,7 +1697,7 @@ ); element.viewState = createChangeViewState(); - element.getChangeModel().setState({ + changeModel.setState({ loadingStatus: LoadingStatus.LOADED, change: { ...createChangeViewChange(), @@ -1776,7 +1790,7 @@ test('topic is coalesced to null', async () => { sinon.stub(element, 'changeChanged'); - element.getChangeModel().setState({ + changeModel.setState({ loadingStatus: LoadingStatus.LOADED, change: { ...createChangeViewChange(), @@ -1791,7 +1805,7 @@ }); test('commit sha is populated from getChangeDetail', async () => { - element.getChangeModel().setState({ + changeModel.setState({ loadingStatus: LoadingStatus.LOADED, change: { ...createChangeViewChange(), @@ -2161,7 +2175,7 @@ test('selectedRevision updates when patchNum is changed', async () => { const revision1: RevisionInfo = createRevision(1); const revision2: RevisionInfo = createRevision(2); - element.getChangeModel().setState({ + changeModel.setState({ loadingStatus: LoadingStatus.LOADED, change: { ...createChangeViewChange(), @@ -2174,7 +2188,7 @@ current_revision: 'bbb' as CommitId, }, }); - element.userModel.setPreferences(createPreferences()); + userModel.setPreferences(createPreferences()); element.patchRange = {patchNum: 2 as RevisionPatchSetNum}; await element.performPostChangeLoadTasks(); @@ -2189,7 +2203,7 @@ const revision1 = createRevision(1); const revision2 = createRevision(2); const revision3 = createEditRevision(); - element.getChangeModel().setState({ + changeModel.setState({ loadingStatus: LoadingStatus.LOADED, change: { ...createChangeViewChange(), @@ -2463,7 +2477,7 @@ changeNum: TEST_NUMERIC_CHANGE_ID, project: TEST_PROJECT_NAME, }; - element.getChangeModel().setState({ + changeModel.setState({ loadingStatus: LoadingStatus.LOADED, change: { ...createChangeViewChange(),
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts index 832738b..9bac7c2 100644 --- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts +++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
@@ -38,10 +38,10 @@ shortcutsServiceToken, } from '../../../services/shortcuts/shortcuts-service'; import {resolve} from '../../../models/dependency'; -import {getAppContext} from '../../../services/app-context'; import {subscribe} from '../../lit/subscription-controller'; import {configModelToken} from '../../../models/config/config-model'; import {createChangeUrl} from '../../../models/views/change'; +import {userModelToken} from '../../../models/user/user-model'; @customElement('gr-file-list-header') export class GrFileListHeader extends LitElement { @@ -123,7 +123,7 @@ // 'hide diffs' buttons still be functional. private readonly maxFilesForBulkActions = 225; - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly getNavigation = resolve(this, navigationToken); @@ -131,7 +131,7 @@ super(); subscribe( this, - () => this.userModel.diffPreferences$, + () => this.getUserModel().diffPreferences$, diffPreferences => { if (!diffPreferences) return; this.diffPrefs = diffPreferences;
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts index 3e8530c..c40d018 100644 --- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts +++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.ts
@@ -76,6 +76,7 @@ import {createDiffUrl} from '../../../models/views/diff'; import {createEditUrl} from '../../../models/views/edit'; import {createChangeUrl} from '../../../models/views/change'; +import {userModelToken} from '../../../models/user/user-model'; export const DEFAULT_NUM_FILES_SHOWN = 200; @@ -285,7 +286,7 @@ private readonly restApiService = getAppContext().restApiService; - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly getChangeModel = resolve(this, changeModelToken); @@ -766,7 +767,7 @@ ); subscribe( this, - () => this.userModel.diffPreferences$, + () => this.getUserModel().diffPreferences$, diffPreferences => { this.diffPrefs = diffPreferences; } @@ -775,7 +776,7 @@ this, () => select( - this.userModel.preferences$, + this.getUserModel().preferences$, prefs => !!prefs?.size_bar_in_change_table ), sizeBarInChangeTable => { @@ -784,7 +785,7 @@ ); subscribe( this, - () => this.userModel.loggedIn$, + () => this.getUserModel().loggedIn$, loggedIn => { this.loggedIn = loggedIn; } @@ -2595,7 +2596,7 @@ } private handleReloadingDiffPreference() { - this.userModel.getDiffPreferences(); + this.getUserModel().getDiffPreferences(); } private getOldPath(file: NormalizedFileInfo) {
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.ts b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.ts index 5417127..e7a54fb 100644 --- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.ts +++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.ts
@@ -322,8 +322,7 @@ @state() private combinedMessages: CombinedMessage[] = []; - // Private but used in tests. - readonly getCommentsModel = resolve(this, commentsModelToken); + private readonly getCommentsModel = resolve(this, commentsModelToken); private readonly changeModel = resolve(this, changeModelToken);
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.ts b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.ts index 2e62718..158ad8d 100644 --- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.ts +++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.ts
@@ -32,6 +32,8 @@ import {fixture, assert} from '@open-wc/testing'; import {GrButton} from '../../shared/gr-button/gr-button'; import {PaperToggleButtonElement} from '@polymer/paper-toggle-button'; +import {testResolver} from '../../../test/common-test-setup'; +import {commentsModelToken} from '../../../models/comments/comments-model'; const author = { _account_id: 42 as AccountId, @@ -136,7 +138,9 @@ element = await fixture<GrMessagesList>( html`<gr-messages-list></gr-messages-list>` ); - await element.getCommentsModel().reloadComments(0 as NumericChangeId); + await testResolver(commentsModelToken).reloadComments( + 0 as NumericChangeId + ); element.messages = messages; await element.updateComplete; });
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts index 26b9a63..ba3e62f 100644 --- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts +++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
@@ -131,6 +131,7 @@ import {ShortcutController} from '../../lit/shortcut-controller'; import {Key, Modifier, whenVisible} from '../../../utils/dom-util'; import {GrThreadList} from '../gr-thread-list/gr-thread-list'; +import {userModelToken} from '../../../models/user/user-model'; export enum FocusTarget { ANY = 'any', @@ -216,8 +217,7 @@ private readonly getChangeModel = resolve(this, changeModelToken); - // Private but used in tests. - readonly getCommentsModel = resolve(this, commentsModelToken); + private readonly getCommentsModel = resolve(this, commentsModelToken); // TODO: update type to only ParsedChangeInfo @property({type: Object}) @@ -397,6 +397,8 @@ private readonly accountsModel = getAppContext().accountsModel; + private readonly getUserModel = resolve(this, userModelToken); + private latestPatchNum?: PatchSetNumber; storeTask?: DelayedTask; @@ -631,7 +633,7 @@ subscribe( this, - () => getAppContext().userModel.loggedIn$, + () => this.getUserModel().loggedIn$, isLoggedIn => (this.isLoggedIn = isLoggedIn) ); subscribe(
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts index 8185139..ef781ba 100644 --- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts +++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
@@ -63,6 +63,11 @@ import {KnownExperimentId} from '../../../services/flags/flags'; import {Key, Modifier} from '../../../utils/dom-util'; import {GrComment} from '../../shared/gr-comment/gr-comment'; +import {testResolver} from '../../../test/common-test-setup'; +import { + CommentsModel, + commentsModelToken, +} from '../../../models/comments/comments-model'; function cloneableResponse(status: number, text: string) { return { @@ -88,6 +93,7 @@ let element: GrReplyDialog; let changeNum: NumericChangeId; let patchNum: PatchSetNum; + let commentsModel: CommentsModel; let lastId = 1; const makeAccount = function () { @@ -148,6 +154,7 @@ element.draftCommentThreads = []; await element.updateComplete; + commentsModel = testResolver(commentsModelToken); }); function stubSaveReview( @@ -2378,7 +2385,7 @@ test('replies to patchset level comments are not filtered out', async () => { const draft = {...createDraft(), in_reply_to: '1' as UrlEncodedCommentId}; - element.getCommentsModel().setState({ + commentsModel.setState({ drafts: { 'abc.txt': [draft], }, @@ -2414,7 +2421,7 @@ ...createDraft(), message: 'hey @abcd@def take a look at this', }; - element.getCommentsModel().setState({ + commentsModel.setState({ comments: {}, robotComments: {}, drafts: { @@ -2449,7 +2456,7 @@ message: 'hey @abcd@def.com take a look at this', unresolved: true, }; - element.getCommentsModel().setState({ + commentsModel.setState({ comments: {}, robotComments: {}, drafts: { @@ -2489,7 +2496,7 @@ message: 'hey @abcd@def.com take a look at this', unresolved: true, }; - element.getCommentsModel().setState({ + commentsModel.setState({ comments: {}, robotComments: {}, drafts: { @@ -2542,7 +2549,7 @@ }; stubRestApi('getAccountDetails').returns(Promise.resolve(account)); - element.getCommentsModel().setState({ + commentsModel.setState({ comments: {}, robotComments: {}, drafts: { @@ -2579,7 +2586,7 @@ registered_on: '2015-03-12 18:32:08.000000000' as Timestamp, }; stubRestApi('getAccountDetails').returns(Promise.resolve(account)); - element.getCommentsModel().setState({ + commentsModel.setState({ comments: {}, robotComments: {}, drafts: {
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.ts b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.ts index 27b5097..414fed9 100644 --- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.ts +++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.ts
@@ -44,6 +44,7 @@ import {Interaction} from '../../../constants/reporting'; import {KnownExperimentId} from '../../../services/flags/flags'; import {HtmlPatched} from '../../../utils/lit-util'; +import {userModelToken} from '../../../models/user/user-model'; enum SortDropdownState { TIMESTAMP = 'Latest timestamp', @@ -205,7 +206,7 @@ private readonly flagsService = getAppContext().flagsService; - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly patched = new HtmlPatched(key => { this.reporting.reportInteraction(Interaction.AUTOCLOSE_HTML_PATCHED, { @@ -228,7 +229,7 @@ ); subscribe( this, - () => this.userModel.account$, + () => this.getUserModel().account$, x => (this.account = x) ); // for COMMENTS_AUTOCLOSE logging purposes only
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts index dcc9a99..6c6d6a0 100644 --- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts +++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts
@@ -29,6 +29,7 @@ import {fireEvent} from '../../../utils/event-util'; import {resolve} from '../../../models/dependency'; import {configModelToken} from '../../../models/config/config-model'; +import {userModelToken} from '../../../models/user/user-model'; type MainHeaderLink = RequireProperties<DropdownLink, 'url' | 'name'>; @@ -142,9 +143,9 @@ private readonly jsAPI = getAppContext().jsApiService; - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); - private readonly configModel = resolve(this, configModelToken); + private readonly getConfigModel = resolve(this, configModelToken); private subscriptions: Subscription[] = []; @@ -153,8 +154,8 @@ this.loadAccount(); this.subscriptions.push( - this.userModel.preferences$ - .pipe( + this.getUserModel() + .preferences$.pipe( map(preferences => preferences?.my ?? []), distinctUntilChanged() ) @@ -163,7 +164,7 @@ }) ); this.subscriptions.push( - this.configModel().serverConfig$.subscribe(config => { + this.getConfigModel().serverConfig$.subscribe(config => { if (!config) return; this.serverConfig = config; this.retrieveFeedbackURL(config);
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts index 17d7516..8e77f96 100644 --- a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts +++ b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
@@ -34,6 +34,7 @@ import {resolve} from '../../../models/dependency'; import {createChangeUrl} from '../../../models/views/change'; import {GrDialog} from '../../shared/gr-dialog/gr-dialog'; +import {userModelToken} from '../../../models/user/user-model'; interface FilePreview { filepath: string; @@ -89,7 +90,7 @@ private readonly restApiService = getAppContext().restApiService; - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly getNavigation = resolve(this, navigationToken); @@ -97,7 +98,7 @@ super(); subscribe( this, - () => this.userModel.preferences$, + () => this.getUserModel().preferences$, preferences => { if (!preferences?.disable_token_highlighting) { this.layers = [new TokenHighlightLayer(this)]; @@ -106,7 +107,7 @@ ); subscribe( this, - () => this.userModel.diffPreferences$, + () => this.getUserModel().diffPreferences$, diffPreferences => { if (!diffPreferences) return; this.diffPrefs = diffPreferences;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts index baf89c0..35eebd0 100644 --- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts +++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
@@ -95,6 +95,7 @@ } from '../../../utils/async-util'; import {subscribe} from '../../lit/subscription-controller'; import {GeneratedWebLink} from '../../../utils/weblink-util'; +import {userModelToken} from '../../../models/user/user-model'; const EMPTY_BLAME = 'No blame information for this diff.'; @@ -330,7 +331,7 @@ private readonly restApiService = getAppContext().restApiService; // visible for testing - readonly userModel = getAppContext().userModel; + readonly getUserModel = resolve(this, userModelToken); // visible for testing readonly jsAPI = getAppContext().jsApiService; @@ -372,7 +373,7 @@ ); subscribe( this, - () => this.userModel.loggedIn$, + () => this.getUserModel().loggedIn$, loggedIn => (this.loggedIn = loggedIn) ); subscribe( @@ -384,7 +385,7 @@ ); subscribe( this, - () => this.userModel.diffPreferences$, + () => this.getUserModel().diffPreferences$, diffPreferences => { this.prefs = diffPreferences; }
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.ts b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.ts index 598819b..4163989 100644 --- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.ts +++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.ts
@@ -53,11 +53,14 @@ import {GrAnnotationActionsInterface} from '../../shared/gr-js-api-interface/gr-annotation-actions-js-api'; import {fixture, html, assert} from '@open-wc/testing'; import {EventType} from '../../../types/events'; +import {testResolver} from '../../../test/common-test-setup'; +import {userModelToken, UserModel} from '../../../models/user/user-model'; suite('gr-diff-host tests', () => { let element: GrDiffHost; let account = createAccountDetailWithId(1); let getDiffRestApiStub: SinonStub; + let userModel: UserModel; setup(async () => { stubRestApi('getAccount').callsFake(() => Promise.resolve(account)); @@ -70,6 +73,7 @@ // Fall back in case a test forgets to set one up getDiffRestApiStub.returns(Promise.resolve(createDiff())); await element.updateComplete; + userModel = testResolver(userModelToken); }); suite('plugin layers', () => { @@ -591,7 +595,7 @@ }); test('cannot create comments when not logged in', () => { - element.userModel.setAccount(undefined); + userModel.setAccount(undefined); element.patchRange = createPatchRange(); const showAuthRequireSpy = sinon.spy(); element.addEventListener('show-auth-required', showAuthRequireSpy);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts index 6ad8e2f..9a8a9ab 100644 --- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts +++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
@@ -100,7 +100,6 @@ import {LoadingStatus} from '../../../models/change/change-model'; import {DisplayLine} from '../../../api/diff'; import {GrDownloadDialog} from '../../change/gr-download-dialog/gr-download-dialog'; -import {browserModelToken} from '../../../models/browser/browser-model'; import {commentsModelToken} from '../../../models/comments/comments-model'; import {changeModelToken} from '../../../models/change/change-model'; import {resolve} from '../../../models/dependency'; @@ -122,6 +121,7 @@ import {createChangeUrl} from '../../../models/views/change'; import {createEditUrl} from '../../../models/views/edit'; import {GeneratedWebLink} from '../../../utils/weblink-util'; +import {userModelToken} from '../../../models/user/user-model'; const LOADING_BLAME = 'Loading blame...'; const LOADED_BLAME = 'Blame loaded'; @@ -291,17 +291,11 @@ // Private but used in tests. readonly routerModel = getAppContext().routerModel; - // Private but used in tests. - readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); - // Private but used in tests. - readonly getChangeModel = resolve(this, changeModelToken); + private readonly getChangeModel = resolve(this, changeModelToken); - // Private but used in tests. - readonly getBrowserModel = resolve(this, browserModelToken); - - // Private but used in tests. - readonly getCommentsModel = resolve(this, commentsModelToken); + private readonly getCommentsModel = resolve(this, commentsModelToken); private readonly getShortcutsService = resolve(this, shortcutsServiceToken); @@ -396,7 +390,7 @@ private setupSubscriptions() { subscribe( this, - () => this.userModel.loggedIn$, + () => this.getUserModel().loggedIn$, loggedIn => { this.loggedIn = loggedIn; } @@ -417,14 +411,14 @@ ); subscribe( this, - () => this.userModel.preferences$, + () => this.getUserModel().preferences$, preferences => { this.userPrefs = preferences; } ); subscribe( this, - () => this.userModel.diffPreferences$, + () => this.getUserModel().diffPreferences$, diffPreferences => { this.prefs = diffPreferences; } @@ -479,7 +473,7 @@ combineLatest([ this.getChangeModel().patchNum$, this.routerModel.routerView$, - this.userModel.diffPreferences$, + this.getUserModel().diffPreferences$, this.getChangeModel().reviewedFiles$, ]).pipe( filter( @@ -1315,9 +1309,9 @@ handleToggleDiffMode() { if (!this.userPrefs) return; if (this.userPrefs.diff_view === DiffViewMode.SIDE_BY_SIDE) { - this.userModel.updatePreferences({diff_view: DiffViewMode.UNIFIED}); + this.getUserModel().updatePreferences({diff_view: DiffViewMode.UNIFIED}); } else { - this.userModel.updatePreferences({ + this.getUserModel().updatePreferences({ diff_view: DiffViewMode.SIDE_BY_SIDE, }); } @@ -2266,7 +2260,7 @@ } private handleReloadingDiffPreference() { - this.userModel.getDiffPreferences(); + this.getUserModel().getDiffPreferences(); } private computeCanEdit() {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.ts index b6e26ab..2141224 100644 --- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.ts +++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.ts
@@ -20,7 +20,6 @@ queryAndAssert, stubReporting, stubRestApi, - stubUsers, waitEventLoop, waitUntil, } from '../../../test/test-utils'; @@ -60,7 +59,11 @@ import {Files, GrDiffView} from './gr-diff-view'; import {DropdownItem} from '../../shared/gr-dropdown-list/gr-dropdown-list'; import {SinonFakeTimers, SinonStub, SinonSpy} from 'sinon'; -import {LoadingStatus} from '../../../models/change/change-model'; +import { + changeModelToken, + ChangeModel, + LoadingStatus, +} from '../../../models/change/change-model'; import {CommentMap} from '../../../utils/comment-util'; import {ParsedChangeInfo} from '../../../types/types'; import {assertIsDefined} from '../../../utils/common-util'; @@ -70,6 +73,15 @@ import {Key} from '../../../utils/dom-util'; import {GrButton} from '../../shared/gr-button/gr-button'; import {testResolver} from '../../../test/common-test-setup'; +import {UserModel, userModelToken} from '../../../models/user/user-model'; +import { + commentsModelToken, + CommentsModel, +} from '../../../models/comments/comments-model'; +import { + BrowserModel, + browserModelToken, +} from '../../../models/browser/browser-model'; function createComment( id: string, @@ -93,6 +105,10 @@ let diffCommentsStub; let getDiffRestApiStub: SinonStub; let setUrlStub: SinonStub; + let changeModel: ChangeModel; + let commentsModel: CommentsModel; + let browserModel: BrowserModel; + let userModel: UserModel; function getFilesFromFileList(fileList: string[]): Files { const changeFilesByPath = fileList.reduce((files, path) => { @@ -140,8 +156,12 @@ ], }); await element.updateComplete; + commentsModel = testResolver(commentsModelToken); + changeModel = testResolver(changeModelToken); + browserModel = testResolver(browserModelToken); + userModel = testResolver(userModelToken); - element.getCommentsModel().setState({ + commentsModel.setState({ comments: {}, robotComments: {}, drafts: {}, @@ -192,7 +212,7 @@ assertIsDefined(element.diffHost); sinon.stub(element.diffHost, 'reload').returns(Promise.resolve()); viewStateChangedSpy = sinon.spy(element, 'viewStateChanged'); - element.getChangeModel().setState({ + changeModel.setState({ change: { ...createParsedChange(), revisions: createRevisions(11), @@ -202,7 +222,7 @@ }); test('comment url resolves to comment.patch_set vs latest', () => { - element.getCommentsModel().setState({ + commentsModel.setState({ comments: { '/COMMIT_MSG': [ createComment('c1', 10, 2, '/COMMIT_MSG'), @@ -265,7 +285,7 @@ }); test('unchanged diff X vs latest from comment links navigates to base vs X', async () => { - element.getCommentsModel().setState({ + commentsModel.setState({ comments: { '/COMMIT_MSG': [ createComment('c1', 10, 2, '/COMMIT_MSG'), @@ -284,7 +304,7 @@ sinon.stub(element.diffHost, 'reload').returns(Promise.resolve()); sinon.stub(element, 'isFileUnchanged').returns(true); const viewStateChangedSpy = sinon.spy(element, 'viewStateChanged'); - element.getChangeModel().setState({ + changeModel.setState({ change: { ...createParsedChange(), revisions: createRevisions(11), @@ -311,7 +331,7 @@ }); test('unchanged diff Base vs latest from comment does not navigate', async () => { - element.getCommentsModel().setState({ + commentsModel.setState({ comments: { '/COMMIT_MSG': [ createComment('c1', 10, 2, '/COMMIT_MSG'), @@ -330,7 +350,7 @@ sinon.stub(element.diffHost, 'reload').returns(Promise.resolve()); sinon.stub(element, 'isFileUnchanged').returns(true); const viewStateChangedSpy = sinon.spy(element, 'viewStateChanged'); - element.getChangeModel().setState({ + changeModel.setState({ change: { ...createParsedChange(), revisions: createRevisions(11), @@ -385,7 +405,7 @@ }); test('diff toast to go to latest is shown and not base', async () => { - element.getCommentsModel().setState({ + commentsModel.setState({ comments: { '/COMMIT_MSG': [ createComment('c1', 10, 2, '/COMMIT_MSG'), @@ -405,7 +425,7 @@ sinon.stub(element.diffHost, 'reload').returns(Promise.resolve()); const viewStateChangedSpy = sinon.spy(element, 'viewStateChanged'); element.change = undefined; - element.getChangeModel().setState({ + changeModel.setState({ change: { ...createParsedChange(), revisions: createRevisions(11), @@ -439,7 +459,7 @@ test('renders', async () => { clock = sinon.useFakeTimers(); element.changeNum = 42 as NumericChangeId; - element.getBrowserModel().setScreenWidth(0); + browserModel.setScreenWidth(0); element.patchRange = { basePatchNum: PARENT, patchNum: 10 as RevisionPatchSetNum, @@ -623,7 +643,7 @@ test('keyboard shortcuts', async () => { clock = sinon.useFakeTimers(); element.changeNum = 42 as NumericChangeId; - element.getBrowserModel().setScreenWidth(0); + browserModel.setScreenWidth(0); element.patchRange = { basePatchNum: PARENT, patchNum: 10 as RevisionPatchSetNum, @@ -1529,7 +1549,7 @@ 'automatically called', async () => { const setReviewedFileStatusStub = sinon - .stub(element.getChangeModel(), 'setReviewedFilesStatus') + .stub(changeModel, 'setReviewedFilesStatus') .callsFake(() => Promise.resolve()); const setReviewedStatusStub = sinon.spy(element, 'setReviewedStatus'); @@ -1541,8 +1561,8 @@ ...createDefaultDiffPrefs(), manual_review: true, }; - element.userModel.setDiffPreferences(diffPreferences); - element.getChangeModel().setState({ + userModel.setDiffPreferences(diffPreferences); + changeModel.setState({ change: createParsedChange(), diffPath: '/COMMIT_MSG', reviewedFiles: [], @@ -1564,7 +1584,7 @@ assert.isFalse(setReviewedFileStatusStub.called); // if prefs are updated then the reviewed status should not be set again - element.userModel.setDiffPreferences(createDefaultDiffPrefs()); + userModel.setDiffPreferences(createDefaultDiffPrefs()); await element.updateComplete; assert.isFalse(setReviewedFileStatusStub.called); @@ -1573,7 +1593,7 @@ test('_prefs.manual_review false means set reviewed is called', async () => { const setReviewedFileStatusStub = sinon - .stub(element.getChangeModel(), 'setReviewedFilesStatus') + .stub(changeModel, 'setReviewedFilesStatus') .callsFake(() => Promise.resolve()); assertIsDefined(element.diffHost); @@ -1583,8 +1603,8 @@ ...createDefaultDiffPrefs(), manual_review: false, }; - element.userModel.setDiffPreferences(diffPreferences); - element.getChangeModel().setState({ + userModel.setDiffPreferences(diffPreferences); + changeModel.setState({ change: createParsedChange(), diffPath: '/COMMIT_MSG', reviewedFiles: [], @@ -1607,7 +1627,7 @@ }); test('file review status', async () => { - element.getChangeModel().setState({ + changeModel.setState({ change: createParsedChange(), diffPath: '/COMMIT_MSG', reviewedFiles: [], @@ -1615,12 +1635,12 @@ }); element.loggedIn = true; const saveReviewedStub = sinon - .stub(element.getChangeModel(), 'setReviewedFilesStatus') + .stub(changeModel, 'setReviewedFilesStatus') .callsFake(() => Promise.resolve()); assertIsDefined(element.diffHost); sinon.stub(element.diffHost, 'reload'); - element.userModel.setDiffPreferences(createDefaultDiffPrefs()); + userModel.setDiffPreferences(createDefaultDiffPrefs()); element.routerModel.setState({ changeNum: TEST_NUMERIC_CHANGE_ID, @@ -1635,7 +1655,7 @@ await waitUntil(() => saveReviewedStub.called); - element.getChangeModel().updateStateFileReviewed('/COMMIT_MSG', true); + changeModel.updateStateFileReviewed('/COMMIT_MSG', true); await element.updateComplete; const reviewedStatusCheckBox = queryAndAssert<HTMLInputElement>( @@ -1660,7 +1680,7 @@ false, ]); - element.getChangeModel().updateStateFileReviewed('/COMMIT_MSG', false); + changeModel.updateStateFileReviewed('/COMMIT_MSG', false); await element.updateComplete; reviewedStatusCheckBox.click(); @@ -1688,7 +1708,7 @@ test('file review status with edit loaded', async () => { const saveReviewedStub = sinon.stub( - element.getChangeModel(), + changeModel, 'setReviewedFilesStatus' ); @@ -1730,9 +1750,9 @@ ...createDefaultPreferences(), diff_view: DiffViewMode.SIDE_BY_SIDE, }; - element.getBrowserModel().setScreenWidth(0); + browserModel.setScreenWidth(0); - const userStub = stubUsers('updatePreferences'); + const userStub = sinon.stub(userModel, 'updatePreferences'); await element.updateComplete; // The mode selected in the view state reflects the selected option. @@ -1926,7 +1946,7 @@ }); test('handleToggleDiffMode', () => { - const userStub = stubUsers('updatePreferences'); + const userStub = sinon.stub(userModel, 'updatePreferences'); element.userPrefs = { ...createDefaultPreferences(), diff_view: DiffViewMode.SIDE_BY_SIDE,
diff --git a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts index a15a575..e245ff5 100644 --- a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts +++ b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
@@ -33,6 +33,7 @@ import {ShortcutController} from '../../lit/shortcut-controller'; import {editViewModelToken, EditViewState} from '../../../models/views/edit'; import {createChangeUrl} from '../../../models/views/change'; +import {userModelToken} from '../../../models/user/user-model'; const RESTORED_MESSAGE = 'Content restored from a previous edit.'; const SAVING_MESSAGE = 'Saving changes...'; @@ -89,7 +90,7 @@ private readonly reporting = getAppContext().reportingService; - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly getChangeModel = resolve(this, changeModelToken); @@ -109,7 +110,7 @@ }); subscribe( this, - () => this.userModel.editPreferences$, + () => this.getUserModel().editPreferences$, editPreferences => (this.editPrefs = editPreferences) ); subscribe(
diff --git a/polygerrit-ui/app/elements/gr-app-element.ts b/polygerrit-ui/app/elements/gr-app-element.ts index c05e4c4..27d2857 100644 --- a/polygerrit-ui/app/elements/gr-app-element.ts +++ b/polygerrit-ui/app/elements/gr-app-element.ts
@@ -73,6 +73,7 @@ import {createSearchUrl, SearchViewState} from '../models/views/search'; import {createSettingsUrl} from '../models/views/settings'; import {createDashboardUrl} from '../models/views/dashboard'; +import {userModelToken} from '../models/user/user-model'; interface ErrorInfo { text: string; @@ -161,7 +162,7 @@ private readonly shortcuts = new ShortcutController(this); - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly routerModel = getAppContext().routerModel; @@ -210,7 +211,7 @@ subscribe( this, - () => this.userModel.preferenceTheme$, + () => this.getUserModel().preferenceTheme$, theme => { this.theme = theme; this.applyTheme(); @@ -257,14 +258,14 @@ // TODO(milutin): Remove saving preferences after while. This code is // for migration. if (window.localStorage.getItem('dark-theme')) { - this.userModel.updatePreferences({theme: AppTheme.DARK}); + this.getUserModel().updatePreferences({theme: AppTheme.DARK}); window.localStorage.removeItem('dark-theme'); this.reporting.reportExecution( Execution.REACHABLE_CODE, 'Dark theme was migrated from localstorage' ); } else if (window.localStorage.getItem('light-theme')) { - this.userModel.updatePreferences({theme: AppTheme.LIGHT}); + this.getUserModel().updatePreferences({theme: AppTheme.LIGHT}); window.localStorage.removeItem('light-theme'); this.reporting.reportExecution( Execution.REACHABLE_CODE,
diff --git a/polygerrit-ui/app/elements/gr-app.ts b/polygerrit-ui/app/elements/gr-app.ts index 2f7dfac..721b46d 100644 --- a/polygerrit-ui/app/elements/gr-app.ts +++ b/polygerrit-ui/app/elements/gr-app.ts
@@ -47,6 +47,7 @@ import {html, LitElement} from 'lit'; import {customElement} from 'lit/decorators.js'; import {ServiceWorkerInstaller} from '../services/service-worker-installer'; +import {userModelToken} from '../models/user/user-model'; const appContext = createAppContext(); injectAppContext(appContext); @@ -107,7 +108,7 @@ this.serviceWorkerInstaller = new ServiceWorkerInstaller( appContext.flagsService, appContext.reportingService, - appContext.userModel + resolver(userModelToken) ); } }
diff --git a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.ts b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.ts index b0993b9..2add2bb 100644 --- a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.ts +++ b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.ts
@@ -16,8 +16,7 @@ @state() config?: ServerInfo; - // visible for testing - readonly getConfigModel = resolve(this, configModelToken); + private readonly getConfigModel = resolve(this, configModelToken); constructor() { super();
diff --git a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.ts b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.ts index bb89d12..a58314e 100644 --- a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.ts +++ b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.ts
@@ -10,10 +10,16 @@ import {fixture, html, assert} from '@open-wc/testing'; import {SinonStub} from 'sinon'; import {createServerInfo} from '../../../test/test-data-generators'; +import { + ConfigModel, + configModelToken, +} from '../../../models/config/config-model'; +import {testResolver} from '../../../test/common-test-setup'; suite('gr-plugin-host tests', () => { let element: GrPluginHost; let loadPluginsStub: SinonStub; + let configModel: ConfigModel; setup(async () => { loadPluginsStub = sinon.stub(getPluginLoader(), 'loadPlugins'); @@ -21,13 +27,14 @@ <gr-plugin-host></gr-plugin-host> `); await element.updateComplete; + configModel = testResolver(configModelToken); sinon.stub(document.body, 'appendChild'); }); test('load plugins should be called', async () => { loadPluginsStub.reset(); - element.getConfigModel().updateServerConfig({ + configModel.updateServerConfig({ ...createServerInfo(), plugin: { has_avatars: false, @@ -46,7 +53,7 @@ test('theme plugins should be loaded if enabled', async () => { loadPluginsStub.reset(); - element.getConfigModel().updateServerConfig({ + configModel.updateServerConfig({ ...createServerInfo(), default_theme: 'gerrit-theme.js', plugin: { @@ -69,7 +76,7 @@ loadPluginsStub.reset(); const config = createServerInfo(); config.gerrit.instance_id = 'test-id'; - element.getConfigModel().updateServerConfig(config); + configModel.updateServerConfig(config); assert.isTrue(loadPluginsStub.calledOnce); assert.isTrue(loadPluginsStub.calledWith([], 'test-id')); });
diff --git a/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.ts b/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.ts index f554ff0..183425d 100644 --- a/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.ts +++ b/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.ts
@@ -7,7 +7,6 @@ import '../../shared/gr-button/gr-button'; import '../../shared/gr-select/gr-select'; import {EditPreferencesInfo} from '../../../types/common'; -import {getAppContext} from '../../../services/app-context'; import {formStyles} from '../../../styles/gr-form-styles'; import {menuPageStyles} from '../../../styles/gr-menu-page-styles'; import {sharedStyles} from '../../../styles/shared-styles'; @@ -15,6 +14,8 @@ import {customElement, query, state} from 'lit/decorators.js'; import {convertToString} from '../../../utils/string-util'; import {subscribe} from '../../lit/subscription-controller'; +import {resolve} from '../../../models/dependency'; +import {userModelToken} from '../../../models/user/user-model'; @customElement('gr-edit-preferences') export class GrEditPreferences extends LitElement { @@ -46,13 +47,13 @@ @state() private originalEditPrefs?: EditPreferencesInfo; - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); constructor() { super(); subscribe( this, - () => this.userModel.editPreferences$, + () => this.getUserModel().editPreferences$, editPreferences => { this.originalEditPrefs = editPreferences; this.editPrefs = {...editPreferences}; @@ -307,7 +308,7 @@ async save() { if (!this.editPrefs) return; - await this.userModel.updateEditPreference(this.editPrefs); + await this.getUserModel().updateEditPreference(this.editPrefs); } }
diff --git a/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor.ts b/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor.ts index 460cc7c..9c23857 100644 --- a/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor.ts +++ b/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor.ts
@@ -12,12 +12,13 @@ import {state, customElement} from 'lit/decorators.js'; import {BindValueChangeEvent} from '../../../types/events'; import {subscribe} from '../../lit/subscription-controller'; -import {getAppContext} from '../../../services/app-context'; import {deepEqual} from '../../../utils/deep-util'; import {createDefaultPreferences} from '../../../constants/constants'; import {fontStyles} from '../../../styles/gr-font-styles'; import {classMap} from 'lit/directives/class-map.js'; import {menuPageStyles} from '../../../styles/gr-menu-page-styles'; +import {userModelToken} from '../../../models/user/user-model'; +import {resolve} from '../../../models/dependency'; @customElement('gr-menu-editor') export class GrMenuEditor extends LitElement { @@ -33,13 +34,13 @@ @state() newUrl = ''; - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); constructor() { super(); subscribe( this, - () => this.userModel.preferences$, + () => this.getUserModel().preferences$, prefs => { this.originalPrefs = prefs; this.menuItems = [...prefs.my]; @@ -196,7 +197,7 @@ } private handleSave() { - this.userModel.updatePreferences({ + this.getUserModel().updatePreferences({ ...this.originalPrefs, my: this.menuItems, });
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts index ff2904a..92b1f86 100644 --- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts +++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
@@ -63,6 +63,7 @@ import {resolve} from '../../../models/dependency'; import {settingsViewModelToken} from '../../../models/views/settings'; import {areNotificationsEnabled} from '../../../utils/worker-util'; +import {userModelToken} from '../../../models/user/user-model'; const GERRIT_DOCS_BASE_URL = 'https://gerrit-review.googlesource.com/' + 'Documentation'; @@ -201,7 +202,7 @@ private readonly restApiService = getAppContext().restApiService; - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); // private but used in test readonly flagsService = getAppContext().flagsService; @@ -220,14 +221,14 @@ ); subscribe( this, - () => this.userModel.account$, + () => this.getUserModel().account$, acc => { this.account = acc; } ); subscribe( this, - () => this.userModel.preferences$, + () => this.getUserModel().preferences$, prefs => { if (!prefs) { throw new Error('getPreferences returned undefined'); @@ -1148,7 +1149,7 @@ // private but used in test handleSavePreferences() { - return this.userModel.updatePreferences(this.localPrefs); + return this.getUserModel().updatePreferences(this.localPrefs); } // private but used in test
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts index 9dfbc04..8c2c2db 100644 --- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts +++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
@@ -74,6 +74,7 @@ import {HtmlPatched} from '../../../utils/lit-util'; import {createDiffUrl} from '../../../models/views/diff'; import {createChangeUrl} from '../../../models/views/change'; +import {userModelToken} from '../../../models/user/user-model'; declare global { interface HTMLElementEventMap { @@ -247,12 +248,11 @@ @state() saving = false; - // Private but used in tests. - readonly getCommentsModel = resolve(this, commentsModelToken); + private readonly getCommentsModel = resolve(this, commentsModelToken); private readonly getChangeModel = resolve(this, changeModelToken); - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly reporting = getAppContext().reportingService; @@ -281,7 +281,7 @@ ); subscribe( this, - () => this.userModel.account$, + () => this.getUserModel().account$, x => (this.account = x) ); subscribe( @@ -291,12 +291,12 @@ ); subscribe( this, - () => this.userModel.diffPreferences$, + () => this.getUserModel().diffPreferences$, x => this.syntaxLayer.setEnabled(!!x.syntax_highlighting) ); subscribe( this, - () => this.userModel.preferences$, + () => this.getUserModel().preferences$, prefs => { const layers: DiffLayer[] = [this.syntaxLayer]; if (!prefs.disable_token_highlighting) { @@ -307,7 +307,7 @@ ); subscribe( this, - () => this.userModel.diffPreferences$, + () => this.getUserModel().diffPreferences$, prefs => { this.prefs = { ...prefs,
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.ts b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.ts index 10e54c7..97eafc9 100644 --- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.ts +++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.ts
@@ -30,6 +30,8 @@ import {GrButton} from '../gr-button/gr-button'; import {SpecialFilePath} from '../../../constants/constants'; import {GrIcon} from '../gr-icon/gr-icon'; +import {commentsModelToken} from '../../../models/comments/comments-model'; +import {testResolver} from '../../../test/common-test-setup'; const c1 = { author: {name: 'Kermit'}, @@ -311,7 +313,7 @@ setup(async () => { savePromise = mockPromise<DraftInfo>(); stub = sinon - .stub(element.getCommentsModel(), 'saveDraft') + .stub(testResolver(commentsModelToken), 'saveDraft') .returns(savePromise); element.thread = createThread(c1, {...c2, unresolved: true});
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts index 056dfe5..af82186 100644 --- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts +++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
@@ -64,6 +64,7 @@ import {KnownExperimentId} from '../../../services/flags/flags'; import {isBase64FileContent} from '../../../api/rest-api'; import {createDiffUrl} from '../../../models/views/diff'; +import {userModelToken} from '../../../models/user/user-model'; const UNSAVED_MESSAGE = 'Unable to save draft'; @@ -229,10 +230,9 @@ private readonly getChangeModel = resolve(this, changeModelToken); - // Private but used in tests. - readonly getCommentsModel = resolve(this, commentsModelToken); + private readonly getCommentsModel = resolve(this, commentsModelToken); - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly shortcuts = new ShortcutController(this); @@ -282,12 +282,12 @@ } subscribe( this, - () => this.userModel.account$, + () => this.getUserModel().account$, x => (this.account = x) ); subscribe( this, - () => this.userModel.isAdmin$, + () => this.getUserModel().isAdmin$, x => (this.isAdmin = x) );
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.ts b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.ts index 1b48658..4e8c70f 100644 --- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.ts +++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.ts
@@ -47,9 +47,15 @@ import {SinonStub} from 'sinon'; import {fixture, html, assert} from '@open-wc/testing'; import {GrButton} from '../gr-button/gr-button'; +import {testResolver} from '../../../test/common-test-setup'; +import { + CommentsModel, + commentsModelToken, +} from '../../../models/comments/comments-model'; suite('gr-comment tests', () => { let element: GrComment; + let commentsModel: CommentsModel; const account = { email: 'dhruvsri@google.com' as EmailAddress, name: 'Dhruv Srivastava', @@ -77,6 +83,7 @@ .comment=${comment} ></gr-comment>` ); + commentsModel = testResolver(commentsModelToken); }); suite('DOM rendering', () => { @@ -548,9 +555,7 @@ test('save', async () => { const savePromise = mockPromise<DraftInfo>(); - const stub = sinon - .stub(element.getCommentsModel(), 'saveDraft') - .returns(savePromise); + const stub = sinon.stub(commentsModel, 'saveDraft').returns(savePromise); element.comment = createDraft(); element.editing = true; @@ -595,7 +600,7 @@ test('save failed', async () => { sinon - .stub(element.getCommentsModel(), 'saveDraft') + .stub(commentsModel, 'saveDraft') .returns(Promise.reject(new Error('saving failed'))); element.comment = createDraft(); @@ -615,7 +620,7 @@ test('discard', async () => { const discardPromise = mockPromise<void>(); const stub = sinon - .stub(element.getCommentsModel(), 'discardDraft') + .stub(commentsModel, 'discardDraft') .returns(discardPromise); element.comment = createDraft(); @@ -638,7 +643,7 @@ }); test('resolved comment state indicated by checkbox', async () => { - const saveStub = sinon.stub(element.getCommentsModel(), 'saveDraft'); + const saveStub = sinon.stub(commentsModel, 'saveDraft'); element.comment = { ...createComment(), __draft: true, @@ -662,11 +667,8 @@ }); test('saving empty text calls discard()', async () => { - const saveStub = sinon.stub(element.getCommentsModel(), 'saveDraft'); - const discardStub = sinon.stub( - element.getCommentsModel(), - 'discardDraft' - ); + const saveStub = sinon.stub(commentsModel, 'saveDraft'); + const discardStub = sinon.stub(commentsModel, 'discardDraft'); element.comment = createDraft(); element.editing = true; await element.updateComplete; @@ -740,9 +742,7 @@ setup(async () => { clock = sinon.useFakeTimers(); savePromise = mockPromise<DraftInfo>(); - saveStub = sinon - .stub(element.getCommentsModel(), 'saveDraft') - .returns(savePromise); + saveStub = sinon.stub(commentsModel, 'saveDraft').returns(savePromise); element.comment = createUnsaved(); element.editing = true;
diff --git a/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences.ts b/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences.ts index 15d7072..019bec1 100644 --- a/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences.ts +++ b/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences.ts
@@ -8,7 +8,6 @@ import '../gr-button/gr-button'; import '../gr-select/gr-select'; import {DiffPreferencesInfo, IgnoreWhitespaceType} from '../../../types/diff'; -import {getAppContext} from '../../../services/app-context'; import {subscribe} from '../../lit/subscription-controller'; import {formStyles} from '../../../styles/gr-form-styles'; import {sharedStyles} from '../../../styles/shared-styles'; @@ -18,6 +17,8 @@ import {fire} from '../../../utils/event-util'; import {ValueChangedEvent} from '../../../types/events'; import {GrSelect} from '../gr-select/gr-select'; +import {resolve} from '../../../models/dependency'; +import {userModelToken} from '../../../models/user/user-model'; @customElement('gr-diff-preferences') export class GrDiffPreferences extends LitElement { @@ -51,13 +52,13 @@ @state() private originalDiffPrefs?: DiffPreferencesInfo; - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); constructor() { super(); subscribe( this, - () => this.userModel.diffPreferences$, + () => this.getUserModel().diffPreferences$, diffPreferences => { if (!diffPreferences) return; this.originalDiffPrefs = diffPreferences; @@ -314,7 +315,7 @@ async save() { if (!this.diffPrefs) return; - await this.userModel.updateDiffPreference(this.diffPrefs); + await this.getUserModel().updateDiffPreference(this.diffPrefs); fire(this, 'has-unsaved-changes-changed', { value: this.hasUnsavedChanges(), });
diff --git a/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands.ts b/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands.ts index 2d93227..886894e 100644 --- a/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands.ts +++ b/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands.ts
@@ -16,6 +16,8 @@ import {customElement, property, state} from 'lit/decorators.js'; import {fire} from '../../../utils/event-util'; import {BindValueChangeEvent} from '../../../types/events'; +import {resolve} from '../../../models/dependency'; +import {userModelToken} from '../../../models/user/user-model'; declare global { interface HTMLElementEventMap { @@ -53,7 +55,7 @@ private readonly restApiService = getAppContext().restApiService; // Private but used in tests. - readonly userModel = getAppContext().userModel; + readonly getUserModel = resolve(this, userModelToken); private subscriptions: Subscription[] = []; @@ -63,7 +65,7 @@ this.loggedIn = loggedIn; }); this.subscriptions.push( - this.userModel.preferences$.subscribe(prefs => { + this.getUserModel().preferences$.subscribe(prefs => { if (prefs?.download_scheme) { // Note (issue 5180): normalize the download scheme with lower-case. this.selectedScheme = prefs.download_scheme.toLowerCase(); @@ -194,7 +196,7 @@ this.selectedScheme = scheme; fire(this, 'selected-scheme-changed', {value: scheme}); if (this.loggedIn) { - this.userModel.updatePreferences({ + this.getUserModel().updatePreferences({ download_scheme: this.selectedScheme, }); }
diff --git a/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.ts b/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.ts index 695c674..b1d4e36 100644 --- a/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.ts +++ b/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.ts
@@ -18,6 +18,8 @@ import {PaperTabsElement} from '@polymer/paper-tabs/paper-tabs'; import {fixture, html, assert} from '@open-wc/testing'; import {PaperTabElement} from '@polymer/paper-tabs/paper-tab'; +import {UserModel, userModelToken} from '../../../models/user/user-model'; +import {testResolver} from '../../../test/common-test-setup'; suite('gr-download-commands', () => { let element: GrDownloadCommands; @@ -170,11 +172,16 @@ }); }); suite('authenticated', () => { - test('loads scheme from preferences', async () => { - const element: GrDownloadCommands = await fixture( + let element: GrDownloadCommands; + let userModel: UserModel; + setup(async () => { + userModel = testResolver(userModelToken); + element = await fixture( html`<gr-download-commands></gr-download-commands>` ); - element.userModel.setPreferences({ + }); + test('loads scheme from preferences', async () => { + userModel.setPreferences({ ...createPreferences(), download_scheme: 'repo', }); @@ -182,10 +189,7 @@ }); test('normalize scheme from preferences', async () => { - const element: GrDownloadCommands = await fixture( - html`<gr-download-commands></gr-download-commands>` - ); - element.userModel.setPreferences({ + userModel.setPreferences({ ...createPreferences(), download_scheme: 'REPO', });
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents.ts b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents.ts index 74dbec7..dc08648 100644 --- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents.ts +++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents.ts
@@ -45,6 +45,7 @@ import {createSearchUrl} from '../../../models/views/search'; import {createDashboardUrl} from '../../../models/views/dashboard'; import {fire, fireEvent} from '../../../utils/event-util'; +import {userModelToken} from '../../../models/user/user-model'; @customElement('gr-hovercard-account-contents') export class GrHovercardAccountContents extends LitElement { @@ -77,8 +78,7 @@ private readonly reporting = getAppContext().reportingService; - // private but used in tests - readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private readonly getConfigModel = resolve(this, configModelToken); @@ -86,7 +86,7 @@ super(); subscribe( this, - () => this.userModel.account$, + () => this.getUserModel().account$, x => (this.selfAccount = x) ); subscribe(
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents_test.ts b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents_test.ts index 4f9eb6c..b217562 100644 --- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents_test.ts +++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents_test.ts
@@ -27,6 +27,8 @@ } from '../../../test/test-data-generators'; import {GrButton} from '../gr-button/gr-button'; import {EventType} from '../../../types/events'; +import {testResolver} from '../../../test/common-test-setup'; +import {userModelToken} from '../../../models/user/user-model'; suite('gr-hovercard-account-contents tests', () => { let element: GrHovercardAccountContents; @@ -51,7 +53,7 @@ html`<gr-hovercard-account-contents .account=${ACCOUNT} .change=${change}> </gr-hovercard-account-contents>` ); - element.userModel.setAccount({...ACCOUNT}); + testResolver(userModelToken).setAccount({...ACCOUNT}); await element.updateComplete; });
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.ts b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.ts index 4f3c65e..40e4c75 100644 --- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.ts +++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.ts
@@ -15,7 +15,8 @@ } from '../../../test/test-data-generators'; import {GrButton} from '../gr-button/gr-button'; import {GrHovercardAccountContents} from './gr-hovercard-account-contents'; -import {getAppContext} from '../../../services/app-context'; +import {userModelToken} from '../../../models/user/user-model'; +import {testResolver} from '../../../test/common-test-setup'; suite('gr-hovercard-account tests', () => { let element: GrHovercardAccount; @@ -33,7 +34,7 @@ </gr-hovercard-account>` ); await element.show({}); - getAppContext().userModel.setAccount({...account}); + testResolver(userModelToken).setAccount({...account}); await element.updateComplete; contents = queryAndAssert(element, 'gr-hovercard-account-contents'); });
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-mode-selector/gr-diff-mode-selector.ts b/polygerrit-ui/app/embed/diff/gr-diff-mode-selector/gr-diff-mode-selector.ts index 5caffe6..5058ce8 100644 --- a/polygerrit-ui/app/embed/diff/gr-diff-mode-selector/gr-diff-mode-selector.ts +++ b/polygerrit-ui/app/embed/diff/gr-diff-mode-selector/gr-diff-mode-selector.ts
@@ -11,12 +11,12 @@ import {customElement, property, state} from 'lit/decorators.js'; import {IronA11yAnnouncer} from '@polymer/iron-a11y-announcer/iron-a11y-announcer'; import {FixIronA11yAnnouncer} from '../../../types/types'; -import {getAppContext} from '../../../services/app-context'; import {fireIronAnnounce} from '../../../utils/event-util'; import {browserModelToken} from '../../../models/browser/browser-model'; import {resolve} from '../../../models/dependency'; import {css, html, LitElement} from 'lit'; import {sharedStyles} from '../../../styles/shared-styles'; +import {userModelToken} from '../../../models/user/user-model'; @customElement('gr-diff-mode-selector') export class GrDiffModeSelector extends LitElement { @@ -34,7 +34,7 @@ private readonly getBrowserModel = resolve(this, browserModelToken); - private readonly userModel = getAppContext().userModel; + private readonly getUserModel = resolve(this, userModelToken); private subscriptions: Subscription[] = []; @@ -118,7 +118,7 @@ */ private setMode(newMode: DiffViewMode) { if (this.saveOnChange && this.mode && this.mode !== newMode) { - this.userModel.updatePreferences({diff_view: newMode}); + this.getUserModel().updatePreferences({diff_view: newMode}); } this.mode = newMode; let announcement;
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.ts b/polygerrit-ui/app/embed/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.ts index 34af01e..d646988 100644 --- a/polygerrit-ui/app/embed/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.ts +++ b/polygerrit-ui/app/embed/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.ts
@@ -7,21 +7,17 @@ import './gr-diff-mode-selector'; import {GrDiffModeSelector} from './gr-diff-mode-selector'; import {DiffViewMode} from '../../../constants/constants'; -import { - queryAndAssert, - stubUsers, - waitUntilObserved, -} from '../../../test/test-utils'; +import {queryAndAssert, waitUntilObserved} from '../../../test/test-utils'; import {fixture, html, assert} from '@open-wc/testing'; import {wrapInProvider} from '../../../models/di-provider-element'; import { BrowserModel, browserModelToken, } from '../../../models/browser/browser-model'; -import {getAppContext} from '../../../services/app-context'; -import {UserModel} from '../../../models/user/user-model'; +import {UserModel, userModelToken} from '../../../models/user/user-model'; import {createPreferences} from '../../../test/test-data-generators'; import {GrButton} from '../../../elements/shared/gr-button/gr-button'; +import {testResolver} from '../../../test/common-test-setup'; suite('gr-diff-mode-selector tests', () => { let element: GrDiffModeSelector; @@ -29,7 +25,7 @@ let userModel: UserModel; setup(async () => { - userModel = getAppContext().userModel; + userModel = testResolver(userModelToken); browserModel = new BrowserModel(userModel); element = ( await fixture( @@ -129,7 +125,7 @@ test('set mode', async () => { browserModel.setScreenWidth(0); - const saveStub = stubUsers('updatePreferences'); + const saveStub = sinon.stub(userModel, 'updatePreferences'); // Setting the mode initially does not save prefs. element.saveOnChange = true;
diff --git a/polygerrit-ui/app/embed/gr-diff-app-context-init.ts b/polygerrit-ui/app/embed/gr-diff-app-context-init.ts index f865d6d..e762985 100644 --- a/polygerrit-ui/app/embed/gr-diff-app-context-init.ts +++ b/polygerrit-ui/app/embed/gr-diff-app-context-init.ts
@@ -69,18 +69,12 @@ storageService: (_ctx: Partial<AppContext>) => { throw new Error('storageService is not implemented'); }, - userModel: (_ctx: Partial<AppContext>) => { - throw new Error('userModel is not implemented'); - }, accountsModel: (_ctx: Partial<AppContext>) => { throw new Error('accountsModel is not implemented'); }, routerModel: (_ctx: Partial<AppContext>) => { throw new Error('routerModel is not implemented'); }, - shortcutsService: (_ctx: Partial<AppContext>) => { - throw new Error('shortcutsService is not implemented'); - }, pluginsModel: (_ctx: Partial<AppContext>) => { throw new Error('pluginsModel is not implemented'); },
diff --git a/polygerrit-ui/app/models/change/change-model_test.ts b/polygerrit-ui/app/models/change/change-model_test.ts index 4b51d5b..ce699dc 100644 --- a/polygerrit-ui/app/models/change/change-model_test.ts +++ b/polygerrit-ui/app/models/change/change-model_test.ts
@@ -32,6 +32,8 @@ import {ChangeState, LoadingStatus, updateChangeWithEdit} from './change-model'; import {ChangeModel} from './change-model'; import {assert} from '@open-wc/testing'; +import {testResolver} from '../../test/common-test-setup'; +import {userModelToken} from '../user/user-model'; suite('updateChangeWithEdit() tests', () => { test('undefined change', async () => { @@ -83,7 +85,7 @@ changeModel = new ChangeModel( getAppContext().routerModel, getAppContext().restApiService, - getAppContext().userModel + testResolver(userModelToken) ); knownChange = { ...createChange(),
diff --git a/polygerrit-ui/app/models/user/user-model.ts b/polygerrit-ui/app/models/user/user-model.ts index ce142d7..97f90fa 100644 --- a/polygerrit-ui/app/models/user/user-model.ts +++ b/polygerrit-ui/app/models/user/user-model.ts
@@ -24,6 +24,7 @@ import {RestApiService} from '../../services/gr-rest-api/gr-rest-api'; import {DiffPreferencesInfo} from '../../types/diff'; import {select} from '../../utils/observable-util'; +import {define} from '../dependency'; import {Model} from '../model'; import {isDefined} from '../../types/types'; @@ -55,6 +56,8 @@ capabilities?: AccountCapabilityInfo; } +export const userModelToken = define<UserModel>('user-model'); + export class UserModel extends Model<UserState> { /** * Note that the initially emitted `undefined` value can mean "not loaded
diff --git a/polygerrit-ui/app/services/app-context-init.ts b/polygerrit-ui/app/services/app-context-init.ts index fe47fd5..ee6ca0e 100644 --- a/polygerrit-ui/app/services/app-context-init.ts +++ b/polygerrit-ui/app/services/app-context-init.ts
@@ -16,7 +16,7 @@ import {ChecksModel, checksModelToken} from '../models/checks/checks-model'; import {GrJsApiInterface} from '../elements/shared/gr-js-api-interface/gr-js-api-interface-element'; import {GrStorageService} from './storage/gr-storage_impl'; -import {UserModel} from '../models/user/user-model'; +import {UserModel, userModelToken} from '../models/user/user-model'; import { CommentsModel, commentsModelToken, @@ -87,10 +87,6 @@ return new GrJsApiInterface(reportingService); }, storageService: (_ctx: Partial<AppContext>) => new GrStorageService(), - userModel: (ctx: Partial<AppContext>) => { - assertIsDefined(ctx.restApiService, 'restApiService'); - return new UserModel(ctx.restApiService); - }, accountsModel: (ctx: Partial<AppContext>) => { assertIsDefined(ctx.restApiService, 'restApiService'); return new AccountsModel(ctx.restApiService); @@ -116,7 +112,9 @@ resolver: <T>(token: DependencyToken<T>) => T ): Map<DependencyToken<unknown>, Creator<unknown>> { const dependencies = new Map<DependencyToken<unknown>, Creator<unknown>>(); - const browserModelCreator = () => new BrowserModel(appContext.userModel); + const userModelCreator = () => new UserModel(appContext.restApiService); + dependencies.set(userModelToken, userModelCreator); + const browserModelCreator = () => new BrowserModel(resolver(userModelToken)); dependencies.set(browserModelToken, browserModelCreator); const adminViewModelCreator = () => new AdminViewModel(); @@ -140,8 +138,10 @@ const repoViewModelCreator = () => new RepoViewModel(); dependencies.set(repoViewModelToken, repoViewModelCreator); const searchViewModelCreator = () => - new SearchViewModel(appContext.restApiService, appContext.userModel, () => - resolver(navigationToken) + new SearchViewModel( + appContext.restApiService, + resolver(userModelToken), + () => resolver(navigationToken) ); dependencies.set(searchViewModelToken, searchViewModelCreator); const settingsViewModelCreator = () => new SettingsViewModel(); @@ -172,7 +172,7 @@ new ChangeModel( appContext.routerModel, appContext.restApiService, - appContext.userModel + resolver(userModelToken) ); dependencies.set(changeModelToken, changeModelCreator); @@ -210,7 +210,7 @@ dependencies.set(checksModelToken, checksModelCreator); const shortcutServiceCreator = () => - new ShortcutsService(appContext.userModel, appContext.reportingService); + new ShortcutsService(resolver(userModelToken), appContext.reportingService); dependencies.set(shortcutsServiceToken, shortcutServiceCreator); return dependencies;
diff --git a/polygerrit-ui/app/services/app-context.ts b/polygerrit-ui/app/services/app-context.ts index 5f47c43..62e6331 100644 --- a/polygerrit-ui/app/services/app-context.ts +++ b/polygerrit-ui/app/services/app-context.ts
@@ -11,7 +11,6 @@ import {RestApiService} from './gr-rest-api/gr-rest-api'; import {JsApiService} from '../elements/shared/gr-js-api-interface/gr-js-api-types'; import {StorageService} from './storage/gr-storage'; -import {UserModel} from '../models/user/user-model'; import {RouterModel} from './router/router-model'; import {PluginsModel} from '../models/plugins/plugins-model'; import {HighlightService} from './highlight/highlight-service'; @@ -26,7 +25,6 @@ restApiService: RestApiService; jsApiService: JsApiService; storageService: StorageService; - userModel: UserModel; accountsModel: AccountsModel; pluginsModel: PluginsModel; highlightService: HighlightService;
diff --git a/polygerrit-ui/app/services/service-worker-installer_test.ts b/polygerrit-ui/app/services/service-worker-installer_test.ts index d982dee..a036289 100644 --- a/polygerrit-ui/app/services/service-worker-installer_test.ts +++ b/polygerrit-ui/app/services/service-worker-installer_test.ts
@@ -9,13 +9,15 @@ import {assert} from '@open-wc/testing'; import {createDefaultPreferences} from '../constants/constants'; import {waitUntilObserved} from '../test/test-utils'; +import {testResolver} from '../test/common-test-setup'; +import {userModelToken} from '../models/user/user-model'; suite('service worker installer tests', () => { test('init', async () => { const registerStub = sinon.stub(window.navigator.serviceWorker, 'register'); const flagsService = getAppContext().flagsService; const reportingService = getAppContext().reportingService; - const userModel = getAppContext().userModel; + const userModel = testResolver(userModelToken); sinon.stub(flagsService, 'isEnabled').returns(true); new ServiceWorkerInstaller(flagsService, reportingService, userModel); const prefs = {
diff --git a/polygerrit-ui/app/services/shortcuts/shortcuts-service_test.ts b/polygerrit-ui/app/services/shortcuts/shortcuts-service_test.ts index 5b38a8a..0a5e0a4 100644 --- a/polygerrit-ui/app/services/shortcuts/shortcuts-service_test.ts +++ b/polygerrit-ui/app/services/shortcuts/shortcuts-service_test.ts
@@ -15,6 +15,8 @@ import {getAppContext} from '../app-context'; import {pressKey} from '../../test/test-utils'; import {assert} from '@open-wc/testing'; +import {testResolver} from '../../test/common-test-setup'; +import {userModelToken} from '../../models/user/user-model'; const KEY_A: Binding = {key: 'a'}; @@ -23,7 +25,7 @@ setup(() => { service = new ShortcutsService( - getAppContext().userModel, + testResolver(userModelToken), getAppContext().reportingService ); });
diff --git a/polygerrit-ui/app/test/test-app-context-init.ts b/polygerrit-ui/app/test/test-app-context-init.ts index f0d28be..33ff997 100644 --- a/polygerrit-ui/app/test/test-app-context-init.ts +++ b/polygerrit-ui/app/test/test-app-context-init.ts
@@ -19,8 +19,6 @@ import {PluginsModel} from '../models/plugins/plugins-model'; import {MockHighlightService} from '../services/highlight/highlight-service-mock'; import {AccountsModel} from '../models/accounts-model/accounts-model'; -import {UserModel} from '../models/user/user-model'; -import {ShortcutsService} from '../services/shortcuts/shortcuts-service'; import {createAppDependencies, Creator} from '../services/app-context-init'; import {navigationToken} from '../elements/core/gr-navigation/gr-navigation'; import {DependencyToken} from '../models/dependency'; @@ -42,20 +40,10 @@ return new GrJsApiInterface(ctx.reportingService); }, storageService: (_ctx: Partial<AppContext>) => grStorageMock, - userModel: (ctx: Partial<AppContext>) => { - assertIsDefined(ctx.restApiService, 'restApiService'); - return new UserModel(ctx.restApiService); - }, accountsModel: (ctx: Partial<AppContext>) => { assertIsDefined(ctx.restApiService, 'restApiService'); return new AccountsModel(ctx.restApiService); }, - shortcutsService: (ctx: Partial<AppContext>) => { - assertIsDefined(ctx.userModel, 'userModel'); - assertIsDefined(ctx.flagsService, 'flagsService'); - assertIsDefined(ctx.reportingService, 'reportingService'); - return new ShortcutsService(ctx.userModel, ctx.reportingService); - }, pluginsModel: (_ctx: Partial<AppContext>) => new PluginsModel(), highlightService: (ctx: Partial<AppContext>) => { assertIsDefined(ctx.reportingService, 'reportingService');
diff --git a/polygerrit-ui/app/test/test-utils.ts b/polygerrit-ui/app/test/test-utils.ts index 6d45ad4..384ed68 100644 --- a/polygerrit-ui/app/test/test-utils.ts +++ b/polygerrit-ui/app/test/test-utils.ts
@@ -12,7 +12,6 @@ import {StorageService} from '../services/storage/gr-storage'; import {AuthService} from '../services/gr-auth/gr-auth'; import {ReportingService} from '../services/gr-reporting/gr-reporting'; -import {UserModel} from '../models/user/user-model'; import {queryAndAssert, query} from '../utils/common-util'; import {FlagsService} from '../services/flags/flags'; import {Key, Modifier, whenVisible} from '../utils/dom-util'; @@ -109,10 +108,6 @@ return sinon.spy(getAppContext().restApiService, method); } -export function stubUsers<K extends keyof UserModel>(method: K) { - return sinon.stub(getAppContext().userModel, method); -} - export function stubHighlightService<K extends keyof HighlightService>( method: K ) {