Merge "Make gr-hovercard-run_test independent of `now` time"
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 0ac9903..a58c7bb 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
@@ -31,6 +31,9 @@
import {resolve} from '../../../models/dependency';
import {subscribe} from '../../lit/subscription-controller';
import {createChangeUrl} from '../../../models/views/change';
+import {debounce, DelayedTask} from '../../../utils/async-util';
+
+const GET_CHANGES_DEBOUNCE_INTERVAL_MS = 10;
const LOOKUP_QUERY_PATTERNS: RegExp[] = [
/^\s*i?[0-9a-f]{7,40}\s*$/i, // CHANGE_ID
@@ -141,12 +144,17 @@
this.preferences = x;
if (this.changesPerPage !== x.changes_per_page) {
this.changesPerPage = x.changes_per_page;
- this.viewStateChanged();
+ this.debouncedGetChanges();
}
}
);
}
+ override disconnectedCallback() {
+ this.getChangesTask?.flush();
+ super.disconnectedCallback();
+ }
+
static override get styles() {
return [
sharedStyles,
@@ -275,12 +283,7 @@
}
reload() {
- if (this.loading) return;
- this.loading = true;
- this.getChanges().then(changes => {
- this.changes = changes || [];
- this.loading = false;
- });
+ if (!this.loading) this.debouncedGetChanges();
}
// private, but visible for testing
@@ -300,33 +303,44 @@
// in an async so that attachment to the DOM can take place first.
setTimeout(() => fireTitleChange(this, this.query));
- return this.getChanges().then(changes => {
- changes = changes || [];
- if (this.query && changes.length === 1) {
- for (const queryPattern of LOOKUP_QUERY_PATTERNS) {
- if (this.query.match(queryPattern)) {
- // "Back"/"Forward" buttons work correctly only with replaceUrl()
- this.getNavigation().replaceUrl(
- createChangeUrl({change: changes[0]})
- );
- return;
- }
- }
- }
- this.changes = changes;
- this.loading = false;
- });
+ this.debouncedGetChanges(true);
}
- // private but used in test
- getChanges() {
- return this.restApiService.getChanges(
- this.changesPerPage,
- this.query,
- this.offset
+ private getChangesTask?: DelayedTask;
+
+ private debouncedGetChanges(shouldSingleMatchRedirect = false) {
+ this.getChangesTask = debounce(
+ this.getChangesTask,
+ () => {
+ this.getChanges(shouldSingleMatchRedirect);
+ },
+ GET_CHANGES_DEBOUNCE_INTERVAL_MS
);
}
+ async getChanges(shouldSingleMatchRedirect = false) {
+ this.loading = true;
+ const changes =
+ (await this.restApiService.getChanges(
+ this.changesPerPage,
+ this.query,
+ this.offset
+ )) ?? [];
+ if (shouldSingleMatchRedirect && this.query && changes.length === 1) {
+ for (const queryPattern of LOOKUP_QUERY_PATTERNS) {
+ if (this.query.match(queryPattern)) {
+ // "Back"/"Forward" buttons work correctly only with replaceUrl()
+ this.getNavigation().replaceUrl(
+ createChangeUrl({change: changes[0]})
+ );
+ return;
+ }
+ }
+ }
+ this.changes = changes;
+ this.loading = false;
+ }
+
// private but used in test
limitFor(query: string, defaultLimit?: number) {
if (defaultLimit === undefined) return 0;
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.ts
index 860f8a3..b003b66 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.ts
@@ -24,16 +24,22 @@
import {fixture, html, waitUntil, assert} from '@open-wc/testing';
import {GerritView} from '../../../services/router/router-model';
import {testResolver} from '../../../test/common-test-setup';
-import {SinonStub} from 'sinon';
+import {SinonFakeTimers, SinonStub} from 'sinon';
+import {GrChangeList} from '../gr-change-list/gr-change-list';
+import {GrChangeListSection} from '../gr-change-list-section/gr-change-list-section';
+import {GrChangeListItem} from '../gr-change-list-item/gr-change-list-item';
const CHANGE_ID = 'IcA3dAB3edAB9f60B8dcdA6ef71A75980e4B7127';
const COMMIT_HASH = '12345678';
suite('gr-change-list-view tests', () => {
let element: GrChangeListView;
+ let changes: ChangeInfo[] | undefined = [];
+ let clock: SinonFakeTimers;
setup(async () => {
- stubRestApi('getChanges').returns(Promise.resolve([]));
+ clock = sinon.useFakeTimers();
+ stubRestApi('getChanges').callsFake(() => Promise.resolve(changes));
element = await fixture(html`<gr-change-list-view></gr-change-list-view>`);
element.viewState = {
view: GerritView.SEARCH,
@@ -68,32 +74,39 @@
});
suite('bulk actions', () => {
- let getChangesStub: sinon.SinonStub;
setup(async () => {
stubFlags('isEnabled').returns(true);
- getChangesStub = sinon.stub(element, 'getChanges');
- getChangesStub.returns(Promise.resolve([createChange()]));
+ changes = [createChange()];
element.loading = false;
element.reload();
- await waitUntil(() => element.loading === false);
- element.requestUpdate();
+ clock.tick(100);
await element.updateComplete;
+ await waitUntil(() => element.loading === false);
});
test('checkboxes remain checked after soft reload', async () => {
+ const changeListEl = queryAndAssert<GrChangeList>(
+ element,
+ 'gr-change-list'
+ );
+ await changeListEl.updateComplete;
+ const changeListSectionEl = queryAndAssert<GrChangeListSection>(
+ changeListEl,
+ 'gr-change-list-section'
+ );
+ await changeListSectionEl.updateComplete;
+ const changeListItemEl = queryAndAssert<GrChangeListItem>(
+ changeListSectionEl,
+ 'gr-change-list-item'
+ );
+ await changeListItemEl.updateComplete;
let checkbox = queryAndAssert<HTMLInputElement>(
- query(
- query(query(element, 'gr-change-list'), 'gr-change-list-section'),
- 'gr-change-list-item'
- ),
+ changeListItemEl,
'.selection > label > input'
);
checkbox.click();
await waitUntil(() => checkbox.checked);
- getChangesStub.restore();
- getChangesStub.returns(Promise.resolve([[createChange()]]));
-
element.reload();
await element.updateComplete;
checkbox = queryAndAssert<HTMLInputElement>(
@@ -288,9 +301,10 @@
test('Searching for a change ID redirects to change', async () => {
const change = {...createChange(), _number: 1 as NumericChangeId};
- sinon.stub(element, 'getChanges').returns(Promise.resolve([change]));
+ changes = [change];
element.viewState = {view: GerritView.SEARCH, query: CHANGE_ID};
+ clock.tick(100);
await element.updateComplete;
assert.isTrue(replaceUrlStub.called);
@@ -299,9 +313,10 @@
test('Searching for a change num redirects to change', async () => {
const change = {...createChange(), _number: 1 as NumericChangeId};
- sinon.stub(element, 'getChanges').returns(Promise.resolve([change]));
+ changes = [change];
element.viewState = {view: GerritView.SEARCH, query: '1'};
+ clock.tick(100);
await element.updateComplete;
assert.isTrue(replaceUrlStub.called);
@@ -310,9 +325,10 @@
test('Commit hash redirects to change', async () => {
const change = {...createChange(), _number: 1 as NumericChangeId};
- sinon.stub(element, 'getChanges').returns(Promise.resolve([change]));
+ changes = [change];
element.viewState = {view: GerritView.SEARCH, query: COMMIT_HASH};
+ clock.tick(100);
await element.updateComplete;
assert.isTrue(replaceUrlStub.called);
@@ -320,18 +336,20 @@
});
test('Searching for an invalid change ID searches', async () => {
- sinon.stub(element, 'getChanges').returns(Promise.resolve([]));
+ changes = [];
element.viewState = {view: GerritView.SEARCH, query: CHANGE_ID};
+ clock.tick(100);
await element.updateComplete;
assert.isFalse(replaceUrlStub.called);
});
test('Change ID with multiple search results searches', async () => {
- sinon.stub(element, 'getChanges').returns(Promise.resolve(undefined));
+ changes = undefined;
element.viewState = {view: GerritView.SEARCH, query: CHANGE_ID};
+ clock.tick(100);
await element.updateComplete;
assert.isFalse(replaceUrlStub.called);
diff --git a/polygerrit-ui/app/elements/shared/gr-markdown/gr-markdown.ts b/polygerrit-ui/app/elements/shared/gr-markdown/gr-markdown.ts
index 50f0602..c315603 100644
--- a/polygerrit-ui/app/elements/shared/gr-markdown/gr-markdown.ts
+++ b/polygerrit-ui/app/elements/shared/gr-markdown/gr-markdown.ts
@@ -80,9 +80,9 @@
/* Pre will preserve whitespace and line breaks but not wrap */
white-space: pre;
}
- /* Code within a sentence needs display:inline to shrink and not take a
- whole row */
- p code {
+ /* Non-multiline code elements need display:inline to shrink and not take
+ a whole row */
+ :not(pre) > code {
display: inline;
}
p {