Merge "Display AI-powered checks with dedicated styling."
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 4bbd8be..42a5f8e 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
@@ -514,9 +514,11 @@
(sum, run) => sum + (resultFilter(run).length || 1),
0
);
+ const hasAiPowered = runs.some(run => run.isAiPowered);
if (count === 0) return;
const handler = () => this.onChipClick({statusOrCategory});
return html`<gr-checks-chip
+ .isAiPowered=${hasAiPowered}
.statusOrCategory=${statusOrCategory}
.text=${`${count}`}
@click=${handler}
@@ -549,6 +551,7 @@
const links = [];
if (run.statusLink) links.push(run.statusLink);
const text = `${run.checkName}`;
+ const isAiPowered = run.isAiPowered;
const tabState: ChecksTabState = {
checkName: run.checkName,
statusOrCategory,
@@ -564,6 +567,7 @@
const handler = () => this.onChipClick(tabState);
return html`<gr-checks-chip
.statusOrCategory=${statusOrCategory}
+ .isAiPowered=${isAiPowered}
.text=${text}
.links=${links}
@click=${handler}
diff --git a/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary_screenshot_test.ts b/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary_screenshot_test.ts
index ed3e0d0..8a537d9 100644
--- a/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary_screenshot_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary_screenshot_test.ts
@@ -97,4 +97,22 @@
'gr-change-summary-with-ai-review-prompt'
);
});
+
+ test('screenshot with AI powered check runs', async () => {
+ element.runs = [
+ createRun({
+ status: RunStatus.COMPLETED,
+ checkName: 'ai-warning-check',
+ isAiPowered: true,
+ results: [createCheckResult({category: Category.WARNING})],
+ }),
+ ];
+ await element.updateComplete;
+
+ await visualDiff(element, 'gr-change-summary-with-ai-powered-check-runs');
+ await visualDiffDarkTheme(
+ element,
+ 'gr-change-summary-with-ai-powered-check-runs'
+ );
+ });
});
diff --git a/polygerrit-ui/app/elements/change/gr-change-summary/gr-checks-chip.ts b/polygerrit-ui/app/elements/change/gr-change-summary/gr-checks-chip.ts
index 1315385..9754382 100644
--- a/polygerrit-ui/app/elements/change/gr-change-summary/gr-checks-chip.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-summary/gr-checks-chip.ts
@@ -28,6 +28,9 @@
@property({type: Array})
links: string[] = [];
+ @property({type: Boolean})
+ isAiPowered = false;
+
private readonly reporting = getAppContext().reportingService;
static override get styles() {
@@ -75,6 +78,7 @@
}
gr-icon {
font-size: var(--line-height-small);
+ --gr-icon-size: var(--line-height-small);
}
.checksChip a gr-icon.launch {
color: var(--link-color);
@@ -108,18 +112,22 @@
.checksChip.warning gr-icon {
color: var(--warning-foreground);
}
- .checksChip.info {
+ .checksChip.info,
+ .checksChip.ai {
border-color: var(--info-foreground);
background: var(--info-background);
}
- .checksChip.info:hover {
+ .checksChip.info:hover,
+ .checksChip.ai:hover {
background: var(--info-background-hover);
box-shadow: var(--elevation-level-1);
}
- .checksChip.info:focus-within {
+ .checksChip.info:focus-within,
+ .checksChip.ai:focus-within {
background: var(--info-background-focus);
}
- .checksChip.info gr-icon {
+ .checksChip.info gr-icon,
+ .checksChip.ai gr-icon {
color: var(--info-foreground);
}
.checksChip.check_circle {
@@ -161,7 +169,7 @@
override render() {
if (!this.text) return;
if (!this.statusOrCategory) return;
- const icon = iconFor(this.statusOrCategory);
+ const icon = iconFor(this.statusOrCategory, this.isAiPowered);
const ariaLabel = this.computeAriaLabel();
const chipClass = `checksChip font-small ${icon.name}`;
const chipClassFullLength = `${chipClass} hoverFullLength`;
diff --git a/polygerrit-ui/app/elements/change/gr-change-summary/gr-checks-chip_test.ts b/polygerrit-ui/app/elements/change/gr-change-summary/gr-checks-chip_test.ts
index 6816609..f78734c 100644
--- a/polygerrit-ui/app/elements/change/gr-change-summary/gr-checks-chip_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-summary/gr-checks-chip_test.ts
@@ -85,4 +85,25 @@
`
);
});
+
+ test('renders ai chip', async () => {
+ element.text = 'AI Suggestion';
+ element.statusOrCategory = Category.INFO;
+ element.isAiPowered = true;
+ await element.updateComplete;
+ assert.shadowDom.equal(
+ element,
+ /* HTML */ `
+ <div
+ aria-label="info for check AI Suggestion"
+ class="checksChip ai font-small"
+ role="link"
+ tabindex="0"
+ >
+ <gr-icon icon="ai" filled></gr-icon>
+ <div class="text">AI Suggestion</div>
+ </div>
+ `
+ );
+ });
});
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 dc28545..6fa8b72 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
@@ -712,6 +712,7 @@
color: var(--primary-text-color);
& gr-icon {
font-size: var(--line-height-small);
+ --gr-icon-size: var(--line-height-small);
}
&.info {
border-color: var(--info-foreground);
@@ -720,6 +721,13 @@
color: var(--info-foreground);
}
}
+ &.ai {
+ border-color: var(--info-foreground);
+ background-color: var(--info-background);
+ & gr-icon {
+ color: var(--info-foreground);
+ }
+ }
&.warning {
border-color: var(--warning-foreground);
background-color: var(--warning-background);
@@ -1847,7 +1855,7 @@
) {
continue;
}
- const icon = iconFor(result.category);
+ const icon = iconFor(result.category, result.isAiPowered);
iconsByName[icon.name] ??= [];
iconsByName[icon.name].push(icon);
}
diff --git a/polygerrit-ui/app/elements/checks/gr-diff-check-result.ts b/polygerrit-ui/app/elements/checks/gr-diff-check-result.ts
index 40a3c94..1f1ef11 100644
--- a/polygerrit-ui/app/elements/checks/gr-diff-check-result.ts
+++ b/polygerrit-ui/app/elements/checks/gr-diff-check-result.ts
@@ -22,7 +22,7 @@
import './gr-hovercard-run';
import './gr-checks-tag';
import {fontStyles} from '../../styles/gr-font-styles';
-import {Action, Category} from '../../api/checks';
+import {Action, Category, Tag} from '../../api/checks';
import {assertIsDefined} from '../../utils/common-util';
import {resolve} from '../../models/dependency';
import {commentsModelToken} from '../../models/comments/comments-model';
@@ -96,13 +96,6 @@
padding: var(--spacing-xs) var(--spacing-m);
border: 1px solid #888;
}
- .container.info {
- border-color: var(--info-foreground);
- background-color: var(--info-background);
- }
- .container.info gr-icon {
- color: var(--info-foreground);
- }
.container.warning {
border-color: var(--warning-foreground);
background-color: var(--warning-background);
@@ -110,6 +103,17 @@
.container.warning gr-icon {
color: var(--warning-foreground);
}
+ .container.info {
+ border-color: var(--info-foreground);
+ background-color: var(--info-background);
+ }
+ .container.info gr-icon {
+ color: var(--info-foreground);
+ }
+ .container .note {
+ font-style: italic;
+ margin-left: var(--spacing-s);
+ }
.container.error {
border-color: var(--error-foreground);
background-color: var(--error-background);
@@ -117,6 +121,13 @@
.container.error gr-icon {
color: var(--error-foreground);
}
+ .container.ai-powered {
+ border-color: var(--info-foreground);
+ background-color: var(--info-background);
+ }
+ .container.ai-powered gr-icon {
+ color: var(--info-foreground);
+ }
.header {
display: flex;
white-space: nowrap;
@@ -151,9 +162,11 @@
}
gr-icon {
font-size: var(--line-height-normal);
+ --gr-icon-size: var(--line-height-normal);
}
.icon gr-icon {
font-size: calc(var(--line-height-normal) - 4px);
+ --gr-icon-size: calc(var(--line-height-normal) - 4px);
position: relative;
top: 2px;
}
@@ -212,14 +225,14 @@
override render() {
if (!this.result) return;
const cat = this.result.category.toLowerCase();
- const icon = iconFor(this.result.category);
- const aiIcon = this.result.isAiPowered
- ? html`<div class="ai-icon-wrapper">
- <gr-icon small icon="ai"></gr-icon>
- </div>`
- : nothing;
+ const icon = iconFor(this.result.category, this.result.isAiPowered);
return html`
- <div class="${cat} container font-normal" @copy=${this.handleCopy}>
+ <div
+ class="${cat} container font-normal ${this.result.isAiPowered
+ ? 'ai-powered'
+ : ''}"
+ @copy=${this.handleCopy}
+ >
<div class="header" @click=${this.toggleExpandedClick}>
<div class="icon">
<gr-icon icon=${icon.name} ?filled=${!!icon.filled}></gr-icon>
@@ -232,10 +245,9 @@
tabindex="0"
@keydown=${this.toggleExpandedPress}
>
- ${this.result.checkName}
+ ${this.result.checkName}${this.renderDetail(this.result.tags)}
</div>
</div>
- ${aiIcon}
<!-- The is for being able to shrink a tiny amount without
the text itself getting shrunk with an ellipsis. -->
<div class="summary">${this.result.summary} </div>
@@ -289,8 +301,21 @@
></gr-checks-fix-preview>`;
}
+ private renderDetail(tags: Tag[] | undefined) {
+ for (const tag of tags ?? []) {
+ if (tag.name === 'Unpublished') {
+ return html`<span class="note">(${tag.name})</span>`;
+ }
+ }
+ return nothing;
+ }
+
private renderTags() {
- const tags = this.result?.tags ?? [];
+ // Filter out the "Unpublished" tag as it is rendered in the header via
+ // renderDetail.
+ const tags = (this.result?.tags ?? []).filter(
+ tag => tag.name !== 'Unpublished'
+ );
return html`<div class="tags">
${tags.map(tag => html`<gr-checks-tag .tag=${tag}></gr-checks-tag>`)}
</div>`;
diff --git a/polygerrit-ui/app/elements/checks/gr-diff-check-result_screenshot_test.ts b/polygerrit-ui/app/elements/checks/gr-diff-check-result_screenshot_test.ts
index 7ef3577..57cee38 100644
--- a/polygerrit-ui/app/elements/checks/gr-diff-check-result_screenshot_test.ts
+++ b/polygerrit-ui/app/elements/checks/gr-diff-check-result_screenshot_test.ts
@@ -9,6 +9,10 @@
// @ts-ignore
import {visualDiff} from '@web/test-runner-visual-regression';
import {visualDiffDarkTheme} from '../../test/test-utils';
+import {testResolver} from '../../test/common-test-setup';
+import {changeModelToken} from '../../models/change/change-model';
+import {checksModelToken} from '../../models/checks/checks-model';
+import {suggestionsServiceToken} from '../../services/suggestions/suggestions-service';
import {GrDiffCheckResult} from './gr-diff-check-result';
import './gr-diff-check-result';
import {checkRun1} from '../../test/test-data-generators';
@@ -18,14 +22,27 @@
let element: GrDiffCheckResult;
setup(async () => {
+ testResolver(changeModelToken);
+ testResolver(checksModelToken);
+ const suggestionsService = testResolver(suggestionsServiceToken);
+ sinon
+ .stub(suggestionsService, 'isGeneratedSuggestedFixEnabled')
+ .returns(true);
+
element = await fixture(
html`<gr-diff-check-result></gr-diff-check-result>`
);
+ element.style.display = 'block';
+ element.style.width = '600px';
+ await element.updateComplete;
});
test('collapsed', async () => {
element.result = {...checkRun1, ...checkRun1.results?.[0]} as RunResult;
+ element.result.isAiPowered = false;
await element.updateComplete;
+ await document.fonts.ready;
+ await new Promise(resolve => setTimeout(resolve, 500));
await visualDiff(element, 'gr-diff-check-result-collapsed');
await visualDiffDarkTheme(element, 'gr-diff-check-result-collapsed');
@@ -34,9 +51,46 @@
test('expanded', async () => {
element.result = {...checkRun1, ...checkRun1.results?.[2]} as RunResult;
element.isExpanded = true;
+ element.result.isAiPowered = false;
await element.updateComplete;
+ await document.fonts.ready;
+ await new Promise(resolve => setTimeout(resolve, 500));
await visualDiff(element, 'gr-diff-check-result-expanded');
await visualDiffDarkTheme(element, 'gr-diff-check-result-expanded');
});
+
+ test('collapsed with AI powered check results', async () => {
+ element.result = {...checkRun1, ...checkRun1.results?.[0]} as RunResult;
+ await element.updateComplete;
+
+ await visualDiff(element, 'gr-diff-check-result-collapsed-ai-powered');
+ await visualDiffDarkTheme(
+ element,
+ 'gr-diff-check-result-collapsed-ai-powered'
+ );
+ });
+
+ test('expanded with AI powered check results', async () => {
+ element.result = {...checkRun1, ...checkRun1.results?.[2]} as RunResult;
+ element.isExpanded = true;
+ await element.updateComplete;
+
+ await visualDiff(element, 'gr-diff-check-result-expanded-ai-powered');
+ await visualDiffDarkTheme(
+ element,
+ 'gr-diff-check-result-expanded-ai-powered'
+ );
+ });
+
+ test('with unpublished tag', async () => {
+ element.result = {
+ ...checkRun1,
+ ...checkRun1.results?.[0],
+ tags: [{name: 'Unpublished', tooltip: 'This is unpublished'}],
+ } as RunResult;
+ await element.updateComplete;
+ await visualDiff(element, 'gr-diff-check-result-unpublished');
+ await visualDiffDarkTheme(element, 'gr-diff-check-result-unpublished');
+ });
});
diff --git a/polygerrit-ui/app/elements/checks/gr-diff-check-result_test.ts b/polygerrit-ui/app/elements/checks/gr-diff-check-result_test.ts
index 1b83b79..71e832b 100644
--- a/polygerrit-ui/app/elements/checks/gr-diff-check-result_test.ts
+++ b/polygerrit-ui/app/elements/checks/gr-diff-check-result_test.ts
@@ -74,10 +74,10 @@
assert.shadowDom.equal(
element,
`
- <div class="container font-normal warning">
+ <div class="ai-powered container font-normal warning">
<div class="header">
<div class="icon">
- <gr-icon icon="warning" filled></gr-icon>
+ <gr-icon custom="" filled="" icon="ai"></gr-icon>
</div>
<div class="name">
<gr-hovercard-run> </gr-hovercard-run>
@@ -85,9 +85,6 @@
FAKE Super Check
</div>
</div>
- <div class="ai-icon-wrapper">
- <gr-icon custom="" icon="ai" small></gr-icon>
- </div>
<div class="summary">We think that you could improve this.</div>
<div class="message">
There is a lot to be said. A lot. I say, a lot.
diff --git a/polygerrit-ui/app/models/checks/checks-util.ts b/polygerrit-ui/app/models/checks/checks-util.ts
index aaabe67..ee2eb91 100644
--- a/polygerrit-ui/app/models/checks/checks-util.ts
+++ b/polygerrit-ui/app/models/checks/checks-util.ts
@@ -268,7 +268,13 @@
}
}
-export function iconFor(catStat: Category | RunStatus): ChecksIcon {
+export function iconFor(
+ catStat: Category | RunStatus,
+ isAiPowered?: boolean
+): ChecksIcon {
+ if (isAiPowered) {
+ return {name: 'ai', filled: true};
+ }
switch (catStat) {
case Category.ERROR:
return {name: 'error', filled: true};
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-change-summary-with-ai-powered-check-runs-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-change-summary-with-ai-powered-check-runs-dark.png
new file mode 100644
index 0000000..4761ba9
--- /dev/null
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-change-summary-with-ai-powered-check-runs-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-change-summary-with-ai-powered-check-runs.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-change-summary-with-ai-powered-check-runs.png
new file mode 100644
index 0000000..17be795
--- /dev/null
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-change-summary-with-ai-powered-check-runs.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed-ai-powered-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed-ai-powered-dark.png
new file mode 100644
index 0000000..650ab5c
--- /dev/null
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed-ai-powered-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed-ai-powered.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed-ai-powered.png
new file mode 100644
index 0000000..2141a7c
--- /dev/null
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed-ai-powered.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed-dark.png
index 1a01ce2..fc9d8fb 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed.png
index cd8f54b..d18f15e 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-collapsed.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded-ai-powered-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded-ai-powered-dark.png
new file mode 100644
index 0000000..ee6c53f
--- /dev/null
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded-ai-powered-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded-ai-powered.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded-ai-powered.png
new file mode 100644
index 0000000..5ee62cc
--- /dev/null
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded-ai-powered.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded-dark.png
index 484426d..d505239 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded.png
index 49002e6..bfde038 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-expanded.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-unpublished-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-unpublished-dark.png
new file mode 100644
index 0000000..4006054
--- /dev/null
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-unpublished-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-unpublished.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-unpublished.png
new file mode 100644
index 0000000..fdd0c65
--- /dev/null
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-diff-check-result-unpublished.png
Binary files differ