| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import {setupLocaleHooks} from '../../../testing/LocaleHelpers.js'; |
| import * as Diff from '../../../third_party/diff/diff.js'; |
| |
| import * as DiffView from './diff_view.js'; |
| |
| function buildDiff(original: string, updated: string): Promise<DocumentFragment> { |
| const diff = Diff.Diff.DiffWrapper.lineDiff(original.split('\n'), updated.split('\n')); |
| const view = new DiffView.DiffView.DiffView({diff, mimeType: 'text/javascript'}); |
| return view.loaded.then(() => view.shadowRoot as DocumentFragment); |
| } |
| |
| let cachedSimpleDiff: Promise<DocumentFragment>|null = null; |
| |
| const original = 'let x = `one\ntwo` /* with a\ncomment */\nreturn okay()'; |
| const updated = 'let x = `one\nthree` // with a\n"comment"\nreturn okay()'; |
| |
| function simpleDiff(): Promise<DocumentFragment> { |
| if (!cachedSimpleDiff) { |
| cachedSimpleDiff = buildDiff(original, updated); |
| } |
| return cachedSimpleDiff; |
| } |
| |
| function text(elt: Node): string { |
| if (elt instanceof Text) { |
| return elt.nodeValue as string; |
| } |
| if (elt instanceof HTMLElement && !elt.classList.contains('diff-hidden-text')) { |
| return Array.from(elt.childNodes).map(text).join(''); |
| } |
| return ''; |
| } |
| |
| describe('DiffView', () => { |
| setupLocaleHooks(); |
| it('renders the proper content', async () => { |
| const output = await simpleDiff(); |
| const lines = Array.from(output.querySelectorAll('.diff-line-content')); |
| assert.lengthOf(lines, 6); |
| assert.strictEqual(lines.filter(l => !l.classList.contains('diff-line-addition')).map(text).join('\n'), original); |
| assert.strictEqual(lines.filter(l => !l.classList.contains('diff-line-deletion')).map(text).join('\n'), updated); |
| }); |
| |
| it('renders line numbers', async () => { |
| const output = await simpleDiff(); |
| const numbers = Array.from(output.querySelectorAll('.diff-line-number')); |
| // Line numbers are rendered pairwise per line, with one number |
| // omitted from inserted/deleted lines |
| assert.strictEqual(numbers.map(text).join('-'), '1-1-2--3---2--3-4-4'); |
| }); |
| |
| it('highlights code properly', async () => { |
| const output = await simpleDiff(); |
| const lines = output.querySelectorAll('.diff-line-content'); |
| // Basic highlighting |
| assert.isNotNull(lines[0].querySelector('.token-keyword')); |
| // Accurate per-file highlighting |
| // - lines[2] holds 'comment */', lines[4] holds '"comment"'. |
| assert.isNotNull(lines[2].querySelector('.token-comment')); |
| assert.isNotNull(lines[4].querySelector('.token-string')); |
| }); |
| |
| it('collapses long stretches of equal text', async () => { |
| const original = 'boring\n'.repeat(100); |
| const changed = 'interesting\n' + original.slice(0, 500) + '...' + original.slice(500); |
| const view = await buildDiff(original, changed); |
| assert.isTrue(view.querySelectorAll('.diff-line-content').length < 100); |
| assert.isNotNull(view.querySelector('.diff-line-spacer')); |
| }); |
| |
| it('renders no-diff state when the diff is empty', async () => { |
| const view = new DiffView.DiffView.DiffView({diff: [], mimeType: ''}); |
| await view.loaded; |
| |
| assert.exists(view.shadowRoot?.querySelector('[data-testid="no-diff"]')); |
| }); |
| }); |
| |
| describe('DiffWrapper', () => { |
| describe('lineDiff', () => { |
| it('should work with no changes', () => { |
| let diff = Diff.Diff.DiffWrapper.lineDiff([''], ['']); |
| |
| assert.deepEqual(diff, []); |
| |
| diff = Diff.Diff.DiffWrapper.lineDiff(['initial'], ['initial']); |
| |
| assert.deepEqual(diff, []); |
| }); |
| }); |
| }); |