Merge "Fix issue with search view not updating"
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
index c0433dd..3255d75 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
@@ -1253,7 +1253,6 @@
       query: ctx.params[0],
       offset: ctx.params[2],
       loading: false,
-      changes: [],
     };
     // Note that router model view must be updated before view models.
     this.setState(state as AppElementParams);
@@ -1269,7 +1268,6 @@
       query: ctx.params[0],
       offset: undefined,
       loading: false,
-      changes: [],
     };
     // Note that router model view must be updated before view models.
     this.setState(state as AppElementParams);
diff --git a/polygerrit-ui/app/elements/integration_test.ts b/polygerrit-ui/app/elements/integration_test.ts
new file mode 100644
index 0000000..2f9006f
--- /dev/null
+++ b/polygerrit-ui/app/elements/integration_test.ts
@@ -0,0 +1,74 @@
+/**
+ * @license
+ * Copyright 2023 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+import '../test/common-test-setup';
+import './gr-app-element';
+import {testResolver} from '../test/common-test-setup';
+import {fixture, html, assert} from '@open-wc/testing';
+import {GrRouter, routerToken} from './core/gr-router/gr-router';
+import {
+  queryAndAssert,
+  queryAll,
+  stubRestApi,
+  waitQueryAndAssert,
+} from '../test/test-utils';
+import {GrAppElement} from './gr-app-element';
+import {LitElement} from 'lit';
+import {createSearchUrl} from '../models/views/search';
+import {createChange} from '../test/test-data-generators';
+import {NumericChangeId} from '../api/rest-api';
+import {createSettingsUrl} from '../models/views/settings';
+
+suite('integration tests', () => {
+  let appElement: GrAppElement;
+  let router: GrRouter;
+
+  const assertView = async function <T extends LitElement>(tagName: string) {
+    await appElement.updateComplete;
+    const view = await waitQueryAndAssert<T>(appElement, tagName);
+    assert.isOk(view);
+    return view;
+  };
+
+  const assertItems = function (el: HTMLElement) {
+    const list = queryAndAssert(el, 'gr-change-list');
+    const section = queryAndAssert(list, 'gr-change-list-section');
+    return queryAll(section, 'gr-change-list-item');
+  };
+
+  setup(async () => {
+    appElement = await fixture<GrAppElement>(
+      html`<gr-app-element id="app-element"></gr-app-element>`
+    );
+    router = testResolver(routerToken);
+    router._testOnly_startRouter();
+    await appElement.updateComplete;
+  });
+
+  teardown(async () => {
+    router.finalize();
+  });
+
+  test('navigate from search view page to settings page and back', async () => {
+    stubRestApi('getChanges').returns(
+      Promise.resolve([
+        createChange({_number: 1 as NumericChangeId}),
+        createChange({_number: 2 as NumericChangeId}),
+        createChange({_number: 3 as NumericChangeId}),
+      ])
+    );
+
+    router.setUrl(createSearchUrl({query: 'asdf'}));
+    let view = await assertView('gr-change-list-view');
+    assert.equal(assertItems(view).length, 3);
+
+    router.setUrl(createSettingsUrl());
+    await assertView('gr-settings-view');
+
+    router.setUrl(createSearchUrl({query: 'asdf'}));
+    view = await assertView('gr-change-list-view');
+    assert.equal(assertItems(view).length, 3);
+  });
+});
diff --git a/polygerrit-ui/app/models/views/search.ts b/polygerrit-ui/app/models/views/search.ts
index 48775ce..f3b803b 100644
--- a/polygerrit-ui/app/models/views/search.ts
+++ b/polygerrit-ui/app/models/views/search.ts
@@ -64,8 +64,13 @@
 
   /**
    * The search results for the current query.
+   * `undefined` must be allowed here, because updating state with a partial
+   * state without `changes` must be possible without overwriting existing
+   * changes.
+   * TODO: We should consider moving `changes` to a another model. This is not
+   * really "view" state. View state must directly correlate to the URL.
    */
-  changes: ChangeInfo[];
+  changes?: ChangeInfo[];
 }
 
 export interface SearchUrlOptions {
diff --git a/polygerrit-ui/app/test/test-data-generators.ts b/polygerrit-ui/app/test/test-data-generators.ts
index b480bfe..fe33302 100644
--- a/polygerrit-ui/app/test/test-data-generators.ts
+++ b/polygerrit-ui/app/test/test-data-generators.ts
@@ -415,7 +415,7 @@
   };
 }
 
-export function createChange(): ChangeInfo {
+export function createChange(partial: Partial<ChangeInfo> = {}): ChangeInfo {
   return {
     id: TEST_CHANGE_INFO_ID,
     project: TEST_PROJECT_NAME,
@@ -431,6 +431,7 @@
     owner: createAccountWithId(),
     // This is documented as optional, but actually always set.
     reviewers: createReviewers(),
+    ...partial,
   };
 }
 
@@ -751,7 +752,6 @@
     query: '',
     offset: undefined,
     loading: false,
-    changes: [],
   };
 }