Show diff for generated suggestions
- refactor diff preview from gr-user-suggestion-fix
- use it in gr-comment as well
- add button to add generated suggestion to comment (ui is temporary)
This is under feature flag UiFeature__ml_suggested_edit
It is still prototype that will be tested. UI is still not final.
Screenshot: https://imgur.com/a/zRXPxe2
Release-Notes: skip
Google-Bug-Id: b/293257977
Change-Id: Ib11161620f583927673eb6dd85360d29e066d4f5
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 cbbec74..9661547 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
@@ -14,6 +14,7 @@
import '../gr-tooltip-content/gr-tooltip-content';
import '../gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog';
import '../gr-account-label/gr-account-label';
+import '../gr-suggestion-diff-preview/gr-suggestion-diff-preview';
import {getAppContext} from '../../../services/app-context';
import {css, html, LitElement, nothing, PropertyValues} from 'lit';
import {when} from 'lit/directives/when.js';
@@ -295,6 +296,9 @@
this.addEventListener('open-user-suggest-preview', e => {
this.handleShowFix(e.detail.code);
});
+ this.addEventListener('add-generated-suggestion', e => {
+ this.handleAddGeneratedSuggestion(e.detail.code);
+ });
this.messagePlaceholder = 'Mention others with @';
subscribe(
this,
@@ -564,6 +568,16 @@
<gr-endpoint-slot name="above-actions"></gr-endpoint-slot>
${this.renderHumanActions()} ${this.renderRobotActions()}
</div>
+ ${when(
+ this.showGeneratedSuggestion() &&
+ this.generateSuggestion &&
+ this.generatedReplacement,
+ () =>
+ html`<gr-suggestion-diff-preview
+ .showAddSuggestionButton=${true}
+ .suggestion=${this.generatedReplacement}
+ ></gr-suggestion-diff-preview>`
+ )}
</div>
</gr-endpoint-decorator>
${this.renderConfirmDialog()}
@@ -899,17 +913,19 @@
`;
}
+ private showGeneratedSuggestion() {
+ return (
+ this.flagsService.isEnabled(KnownExperimentId.ML_SUGGESTED_EDIT) &&
+ this.editing &&
+ !this.permanentEditingMode &&
+ this.comment?.path !== SpecialFilePath.PATCHSET_LEVEL_COMMENTS &&
+ this.comment &&
+ !hasUserSuggestion(this.comment)
+ );
+ }
+
private renderGenerateSuggestEditButton() {
- if (!this.flagsService.isEnabled(KnownExperimentId.ML_SUGGESTED_EDIT)) {
- return nothing;
- }
- if (
- !this.editing ||
- this.permanentEditingMode ||
- this.comment?.path === SpecialFilePath.PATCHSET_LEVEL_COMMENTS ||
- !this.comment ||
- hasUserSuggestion(this.comment)
- ) {
+ if (!this.showGeneratedSuggestion()) {
return nothing;
}
const numberOfSuggestions = !this.generatedReplacement ? '' : ' (1)';
@@ -932,25 +948,14 @@
Generate Suggestion${numberOfSuggestions}
</label>
</div>
- ${when(
- this.generatedReplacement,
- () => html`<gr-button
- link
- class="action"
- @click=${this.addGeneratedSuggestEdit}
- >Add Suggestion</gr-button
- >`
- )}
`;
}
- // TODO(milutin): This is temporary solution for experimenting
- private addGeneratedSuggestEdit() {
- if (!this.generatedReplacement) return;
+ private handleAddGeneratedSuggestion(code: string) {
const addNewLine = this.messageText.length !== 0;
this.messageText += `${
addNewLine ? '\n' : ''
- }${USER_SUGGESTION_START_PATTERN}${this.generatedReplacement}${'\n```'}`;
+ }${USER_SUGGESTION_START_PATTERN}${code}${'\n```'}`;
}
private async generateSuggestEdit() {
@@ -1066,14 +1071,18 @@
whenVisible(this, () => this.textarea?.putCursorAtEnd());
}
}
- if (changed.has('changeNum') || changed.has('comment')) {
+ if (
+ changed.has('changeNum') ||
+ changed.has('comment') ||
+ changed.has('generatedReplacement')
+ ) {
if (
!this.flagsService.isEnabled(
KnownExperimentId.DIFF_FOR_USER_SUGGESTED_EDIT
) ||
!this.changeNum ||
!this.comment ||
- !hasUserSuggestion(this.comment)
+ (!hasUserSuggestion(this.comment) && !this.generatedReplacement)
)
return;
(async () => {
diff --git a/polygerrit-ui/app/elements/shared/gr-suggestion-diff-preview/gr-suggestion-diff-preview.ts b/polygerrit-ui/app/elements/shared/gr-suggestion-diff-preview/gr-suggestion-diff-preview.ts
new file mode 100644
index 0000000..00b5ba3
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-suggestion-diff-preview/gr-suggestion-diff-preview.ts
@@ -0,0 +1,256 @@
+/**
+ * @license
+ * Copyright 2023 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+import '../../../embed/diff/gr-diff/gr-diff';
+import {css, html, LitElement, nothing, PropertyValues} from 'lit';
+import {customElement, property, state} from 'lit/decorators.js';
+import {getAppContext} from '../../../services/app-context';
+import {Comment} from '../../../types/common';
+import {anyLineTooLong} from '../../../utils/diff-util';
+import {
+ DiffLayer,
+ DiffPreferencesInfo,
+ DiffViewMode,
+ RenderPreferences,
+} from '../../../api/diff';
+import {when} from 'lit/directives/when.js';
+import {GrSyntaxLayerWorker} from '../../../embed/diff/gr-syntax-layer/gr-syntax-layer-worker';
+import {resolve} from '../../../models/dependency';
+import {highlightServiceToken} from '../../../services/highlight/highlight-service';
+import {NumericChangeId} from '../../../api/rest-api';
+import {changeModelToken} from '../../../models/change/change-model';
+import {subscribe} from '../../lit/subscription-controller';
+import {FilePreview} from '../../diff/gr-apply-fix-dialog/gr-apply-fix-dialog';
+import {userModelToken} from '../../../models/user/user-model';
+import {createUserFixSuggestion} from '../../../utils/comment-util';
+import {KnownExperimentId} from '../../../services/flags/flags';
+import {commentModelToken} from '../gr-comment-model/gr-comment-model';
+import {fire} from '../../../utils/event-util';
+
+declare global {
+ interface HTMLElementEventMap {
+ 'add-generated-suggestion': AddGeneratedSuggestionEvent;
+ }
+}
+
+export type AddGeneratedSuggestionEvent =
+ CustomEvent<OpenUserSuggestionPreviewEventDetail>;
+export interface OpenUserSuggestionPreviewEventDetail {
+ code: string;
+}
+
+@customElement('gr-suggestion-diff-preview')
+export class GrSuggestionDiffPreview extends LitElement {
+ @property({type: String})
+ suggestion?: string;
+
+ @property({type: Boolean})
+ showAddSuggestionButton = false;
+
+ @state()
+ comment?: Comment;
+
+ @state()
+ commentedText?: string;
+
+ @state()
+ layers: DiffLayer[] = [];
+
+ @state()
+ previewLoadedFor?: string;
+
+ @state()
+ changeNum?: NumericChangeId;
+
+ @state()
+ preview?: FilePreview;
+
+ @state()
+ diffPrefs?: DiffPreferencesInfo;
+
+ @state()
+ renderPrefs: RenderPreferences = {
+ disable_context_control_buttons: true,
+ show_file_comment_button: false,
+ hide_line_length_indicator: true,
+ };
+
+ private readonly getChangeModel = resolve(this, changeModelToken);
+
+ private readonly restApiService = getAppContext().restApiService;
+
+ private readonly getUserModel = resolve(this, userModelToken);
+
+ private readonly getCommentModel = resolve(this, commentModelToken);
+
+ private readonly flagsService = getAppContext().flagsService;
+
+ private readonly syntaxLayer = new GrSyntaxLayerWorker(
+ resolve(this, highlightServiceToken),
+ () => getAppContext().reportingService
+ );
+
+ constructor() {
+ super();
+ subscribe(
+ this,
+ () => this.getChangeModel().changeNum$,
+ changeNum => (this.changeNum = changeNum)
+ );
+ subscribe(
+ this,
+ () => this.getUserModel().diffPreferences$,
+ diffPreferences => {
+ if (!diffPreferences) return;
+ this.diffPrefs = diffPreferences;
+ this.syntaxLayer.setEnabled(!!this.diffPrefs.syntax_highlighting);
+ }
+ );
+ subscribe(
+ this,
+ () => this.getCommentModel().comment$,
+ comment => (this.comment = comment)
+ );
+ subscribe(
+ this,
+ () => this.getCommentModel().commentedText$,
+ commentedText => (this.commentedText = commentedText)
+ );
+ }
+
+ static override get styles() {
+ return [
+ css`
+ .buttons {
+ text-align: right;
+ }
+ code {
+ max-width: var(--gr-formatted-text-prose-max-width, none);
+ background-color: var(--background-color-secondary);
+ border: 1px solid var(--border-color);
+ border-top: 0;
+ display: block;
+ font-family: var(--monospace-font-family);
+ font-size: var(--font-size-code);
+ line-height: var(--line-height-mono);
+ margin-bottom: var(--spacing-m);
+ padding: var(--spacing-xxs) var(--spacing-s);
+ overflow-x: auto;
+ /* Pre will preserve whitespace and line breaks but not wrap */
+ white-space: pre;
+ border-bottom-left-radius: var(--border-radius);
+ border-bottom-right-radius: var(--border-radius);
+ }
+ `,
+ ];
+ }
+
+ override updated(changed: PropertyValues) {
+ if (changed.has('commentedText') || changed.has('comment')) {
+ if (
+ this.flagsService.isEnabled(
+ KnownExperimentId.DIFF_FOR_USER_SUGGESTED_EDIT
+ )
+ ) {
+ if (this.previewLoadedFor !== this.suggestion) {
+ this.fetchFixPreview();
+ }
+ }
+ }
+ }
+
+ override render() {
+ if (!this.suggestion) return nothing;
+ const code = this.suggestion;
+ return html`
+ ${when(
+ this.previewLoadedFor,
+ () => this.renderDiff(),
+ () => html`<code>${code}</code>`
+ )}
+ ${when(
+ this.showAddSuggestionButton,
+ () =>
+ html`<div class="buttons">
+ <gr-button
+ link
+ class="action add-suggestion"
+ @click=${this.handleAddGeneratedSuggestion}
+ >
+ Add suggestion to comment
+ </gr-button>
+ </div>`
+ )}
+ `;
+ }
+
+ private renderDiff() {
+ if (!this.preview) return;
+ const diff = this.preview.preview;
+ if (!anyLineTooLong(diff)) {
+ this.syntaxLayer.process(diff);
+ }
+ return html`<gr-diff
+ .prefs=${this.overridePartialDiffPrefs()}
+ .path=${this.preview.filepath}
+ .diff=${diff}
+ .layers=${this.layers}
+ .renderPrefs=${this.renderPrefs}
+ .viewMode=${DiffViewMode.UNIFIED}
+ ></gr-diff>`;
+ }
+
+ private async fetchFixPreview() {
+ if (
+ !this.changeNum ||
+ !this.comment?.patch_set ||
+ !this.suggestion ||
+ !this.commentedText
+ )
+ return;
+
+ const fixSuggestions = createUserFixSuggestion(
+ this.comment,
+ this.commentedText,
+ this.suggestion
+ );
+ const res = await this.restApiService.getFixPreview(
+ this.changeNum,
+ this.comment?.patch_set,
+ fixSuggestions[0].replacements
+ );
+ if (!res) return;
+ const currentPreviews = Object.keys(res).map(key => {
+ return {filepath: key, preview: res[key]};
+ });
+ if (currentPreviews.length > 0) {
+ this.preview = currentPreviews[0];
+ this.previewLoadedFor = this.suggestion;
+ }
+
+ return res;
+ }
+
+ private overridePartialDiffPrefs() {
+ if (!this.diffPrefs) return undefined;
+ return {
+ ...this.diffPrefs,
+ context: 0,
+ line_length: Math.min(this.diffPrefs.line_length, 100),
+ line_wrapping: true,
+ };
+ }
+
+ handleAddGeneratedSuggestion() {
+ if (!this.suggestion) return;
+ fire(this, 'add-generated-suggestion', {code: this.suggestion});
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'gr-suggestion-diff-preview': GrSuggestionDiffPreview;
+ }
+}
diff --git a/polygerrit-ui/app/elements/shared/gr-suggestion-diff-preview/gr-suggestion-diff-preview_test.ts b/polygerrit-ui/app/elements/shared/gr-suggestion-diff-preview/gr-suggestion-diff-preview_test.ts
new file mode 100644
index 0000000..dd6d62d
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-suggestion-diff-preview/gr-suggestion-diff-preview_test.ts
@@ -0,0 +1,105 @@
+/**
+ * @license
+ * Copyright 2023 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+import '../../../test/common-test-setup';
+import './gr-suggestion-diff-preview';
+import {fixture, html, assert} from '@open-wc/testing';
+import {
+ CommentModel,
+ commentModelToken,
+} from '../gr-comment-model/gr-comment-model';
+import {wrapInProvider} from '../../../models/di-provider-element';
+import {createComment} from '../../../test/test-data-generators';
+import {getAppContext} from '../../../services/app-context';
+import {GrSuggestionDiffPreview} from './gr-suggestion-diff-preview';
+import {stubFlags} from '../../../test/test-utils';
+
+suite('gr-suggestion-diff-preview tests', () => {
+ let element: GrSuggestionDiffPreview;
+
+ setup(async () => {
+ const commentModel = new CommentModel(getAppContext().restApiService);
+ commentModel.updateState({
+ comment: createComment(),
+ });
+ element = (
+ await fixture<GrSuggestionDiffPreview>(
+ wrapInProvider(
+ html`
+ <gr-suggestion-diff-preview
+ .suggestion=${'Hello World'}
+ ></gr-suggestion-diff-preview>
+ `,
+ commentModelToken,
+ commentModel
+ )
+ )
+ ).querySelector<GrSuggestionDiffPreview>('gr-suggestion-diff-preview')!;
+ await element.updateComplete;
+ });
+
+ test('render', async () => {
+ await element.updateComplete;
+
+ assert.shadowDom.equal(element, /* HTML */ '<code>Hello World</code>');
+ });
+
+ test('render diff', async () => {
+ stubFlags('isEnabled').returns(true);
+ element.suggestion =
+ ' private handleClick(e: MouseEvent) {\ne.stopPropagation();\ne.preventDefault();';
+ element.previewLoadedFor =
+ ' private handleClick(e: MouseEvent) {\ne.stopPropagation();\ne.preventDefault();';
+ element.preview = {
+ filepath:
+ 'polygerrit-ui/app/elements/change/gr-change-summary/gr-summary-chip_test.ts',
+ preview: {
+ meta_a: {
+ name: 'polygerrit-ui/app/elements/change/gr-change-summary/gr-summary-chip_test.ts',
+ content_type: 'application/typescript',
+ lines: 6,
+ },
+ meta_b: {
+ name: 'polygerrit-ui/app/elements/change/gr-change-summary/gr-summary-chip_test.ts',
+ content_type: 'application/typescript',
+ lines: 6,
+ },
+ intraline_status: 'OK',
+ change_type: 'MODIFIED',
+ content: [
+ {
+ ab: ['export class SummaryChip {'],
+ },
+ {
+ a: [
+ ' private handleClick(event: MouseEvent) {',
+ ' event.stopPropagation();',
+ ' event.preventDefault();',
+ ' }',
+ ],
+ b: [
+ ' private handleClick(evt: MouseEvent) {',
+ ' evt.stopPropagation();',
+ ' evt.preventDefault();',
+ ' }',
+ ],
+ edit_a: [
+ [24, 2],
+ [23, 2],
+ [27, 2],
+ ],
+ edit_b: [],
+ },
+ {
+ ab: ['}'],
+ },
+ ],
+ },
+ };
+ await element.updateComplete;
+
+ assert.shadowDom.equal(element, /* HTML */ '<gr-diff></gr-diff>');
+ });
+});
diff --git a/polygerrit-ui/app/elements/shared/gr-user-suggestion-fix/gr-user-suggestion-fix.ts b/polygerrit-ui/app/elements/shared/gr-user-suggestion-fix/gr-user-suggestion-fix.ts
index 5e67a88b..f0e41b2 100644
--- a/polygerrit-ui/app/elements/shared/gr-user-suggestion-fix/gr-user-suggestion-fix.ts
+++ b/polygerrit-ui/app/elements/shared/gr-user-suggestion-fix/gr-user-suggestion-fix.ts
@@ -3,34 +3,13 @@
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
-import '../../../embed/diff/gr-diff/gr-diff';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-icon/gr-icon';
import '../../shared/gr-copy-clipboard/gr-copy-clipboard';
-import {css, html, LitElement, nothing, PropertyValues} from 'lit';
-import {customElement, state} from 'lit/decorators.js';
-import {getAppContext} from '../../../services/app-context';
-import {Comment} from '../../../types/common';
+import '../gr-suggestion-diff-preview/gr-suggestion-diff-preview';
+import {css, html, LitElement, nothing} from 'lit';
+import {customElement} from 'lit/decorators.js';
import {fire} from '../../../utils/event-util';
-import {anyLineTooLong} from '../../../utils/diff-util';
-import {
- DiffLayer,
- DiffPreferencesInfo,
- DiffViewMode,
- RenderPreferences,
-} from '../../../api/diff';
-import {when} from 'lit/directives/when.js';
-import {GrSyntaxLayerWorker} from '../../../embed/diff/gr-syntax-layer/gr-syntax-layer-worker';
-import {resolve} from '../../../models/dependency';
-import {highlightServiceToken} from '../../../services/highlight/highlight-service';
-import {NumericChangeId} from '../../../api/rest-api';
-import {changeModelToken} from '../../../models/change/change-model';
-import {subscribe} from '../../lit/subscription-controller';
-import {FilePreview} from '../../diff/gr-apply-fix-dialog/gr-apply-fix-dialog';
-import {userModelToken} from '../../../models/user/user-model';
-import {createUserFixSuggestion} from '../../../utils/comment-util';
-import {KnownExperimentId} from '../../../services/flags/flags';
-import {commentModelToken} from '../gr-comment-model/gr-comment-model';
declare global {
interface HTMLElementEventMap {
@@ -46,75 +25,8 @@
@customElement('gr-user-suggestion-fix')
export class GrUserSuggestionsFix extends LitElement {
- @state()
- comment?: Comment;
-
- @state()
- commentedText?: string;
-
- @state()
- layers: DiffLayer[] = [];
-
- @state()
- previewLoaded = false;
-
- @state()
- changeNum?: NumericChangeId;
-
- @state()
- preview?: FilePreview;
-
- @state()
- diffPrefs?: DiffPreferencesInfo;
-
- @state()
- renderPrefs: RenderPreferences = {
- disable_context_control_buttons: true,
- show_file_comment_button: false,
- hide_line_length_indicator: true,
- };
-
- private readonly getChangeModel = resolve(this, changeModelToken);
-
- private readonly restApiService = getAppContext().restApiService;
-
- private readonly getUserModel = resolve(this, userModelToken);
-
- private readonly getCommentModel = resolve(this, commentModelToken);
-
- private readonly flagsService = getAppContext().flagsService;
-
- private readonly syntaxLayer = new GrSyntaxLayerWorker(
- resolve(this, highlightServiceToken),
- () => getAppContext().reportingService
- );
-
constructor() {
super();
- subscribe(
- this,
- () => this.getChangeModel().changeNum$,
- changeNum => (this.changeNum = changeNum)
- );
- subscribe(
- this,
- () => this.getUserModel().diffPreferences$,
- diffPreferences => {
- if (!diffPreferences) return;
- this.diffPrefs = diffPreferences;
- this.syntaxLayer.setEnabled(!!this.diffPrefs.syntax_highlighting);
- }
- );
- subscribe(
- this,
- () => this.getCommentModel().comment$,
- comment => (this.comment = comment)
- );
- subscribe(
- this,
- () => this.getCommentModel().commentedText$,
- commentedText => (this.commentedText = commentedText)
- );
}
static override get styles() {
@@ -135,40 +47,10 @@
.copyButton {
margin-right: var(--spacing-l);
}
- code {
- max-width: var(--gr-formatted-text-prose-max-width, none);
- background-color: var(--background-color-secondary);
- border: 1px solid var(--border-color);
- border-top: 0;
- display: block;
- font-family: var(--monospace-font-family);
- font-size: var(--font-size-code);
- line-height: var(--line-height-mono);
- margin-bottom: var(--spacing-m);
- padding: var(--spacing-xxs) var(--spacing-s);
- overflow-x: auto;
- /* Pre will preserve whitespace and line breaks but not wrap */
- white-space: pre;
- border-bottom-left-radius: var(--border-radius);
- border-bottom-right-radius: var(--border-radius);
- }
`,
];
}
- override updated(changed: PropertyValues) {
- if (changed.has('commentedText') || changed.has('comment')) {
- if (
- this.flagsService.isEnabled(
- KnownExperimentId.DIFF_FOR_USER_SUGGESTED_EDIT
- ) &&
- !this.previewLoaded
- ) {
- this.fetchFixPreview();
- }
- }
- }
-
override render() {
if (!this.textContent) return nothing;
const code = this.textContent;
@@ -201,75 +83,15 @@
</gr-button>
</div>
</div>
- ${when(
- this.previewLoaded,
- () => this.renderDiff(),
- () => html`<code>${code}</code>`
- )} `;
+ <gr-suggestion-diff-preview
+ .suggestion=${this.textContent}
+ ></gr-suggestion-diff-preview>`;
}
handleShowFix() {
if (!this.textContent) return;
fire(this, 'open-user-suggest-preview', {code: this.textContent});
}
-
- private renderDiff() {
- if (!this.preview) return;
- const diff = this.preview.preview;
- if (!anyLineTooLong(diff)) {
- this.syntaxLayer.process(diff);
- }
- return html`<gr-diff
- .prefs=${this.overridePartialDiffPrefs()}
- .path=${this.preview.filepath}
- .diff=${diff}
- .layers=${this.layers}
- .renderPrefs=${this.renderPrefs}
- .viewMode=${DiffViewMode.UNIFIED}
- ></gr-diff>`;
- }
-
- private async fetchFixPreview() {
- if (
- !this.changeNum ||
- !this.comment?.patch_set ||
- !this.textContent ||
- !this.commentedText
- )
- return;
-
- const fixSuggestions = createUserFixSuggestion(
- this.comment,
- this.commentedText,
- this.textContent
- );
- const res = await this.restApiService.getFixPreview(
- this.changeNum,
- this.comment?.patch_set,
- fixSuggestions[0].replacements
- );
- if (res) {
- const currentPreviews = Object.keys(res).map(key => {
- return {filepath: key, preview: res[key]};
- });
- if (currentPreviews.length > 0) {
- this.preview = currentPreviews[0];
- this.previewLoaded = true;
- }
- }
-
- return res;
- }
-
- private overridePartialDiffPrefs() {
- if (!this.diffPrefs) return undefined;
- return {
- ...this.diffPrefs,
- context: 0,
- line_length: Math.min(this.diffPrefs.line_length, 100),
- line_wrapping: true,
- };
- }
}
declare global {
diff --git a/polygerrit-ui/app/elements/shared/gr-user-suggestion-fix/gr-user-suggestion-fix_test.ts b/polygerrit-ui/app/elements/shared/gr-user-suggestion-fix/gr-user-suggestion-fix_test.ts
index 35b2d90..91e9162 100644
--- a/polygerrit-ui/app/elements/shared/gr-user-suggestion-fix/gr-user-suggestion-fix_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-user-suggestion-fix/gr-user-suggestion-fix_test.ts
@@ -70,7 +70,7 @@
>
</div>
</div>
- <code>Hello World</code>`
+ <gr-suggestion-diff-preview></gr-suggestion-diff-preview>`
);
});
});