| /** | |
| * @license | |
| * Copyright 2016 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import '../../../test/common-test-setup'; | |
| import '../gr-diff/gr-diff'; | |
| import './gr-diff-cursor'; | |
| import {fixture, html, assert} from '@open-wc/testing'; | |
| import { | |
| mockPromise, | |
| queryAll, | |
| queryAndAssert, | |
| waitUntil, | |
| } from '../../../test/test-utils'; | |
| import {createDiff} from '../../../test/test-data-generators'; | |
| import {createDefaultDiffPrefs} from '../../../constants/constants'; | |
| import {GrDiffCursor} from './gr-diff-cursor'; | |
| import {waitForEventOnce} from '../../../utils/event-util'; | |
| import {DiffInfo, DiffViewMode, Side} from '../../../api/diff'; | |
| import {GrDiff} from '../gr-diff/gr-diff'; | |
| import {assertIsDefined} from '../../../utils/common-util'; | |
| suite('gr-diff-cursor tests', () => { | |
| let cursor: GrDiffCursor; | |
| let diffElement: GrDiff; | |
| let diff: DiffInfo; | |
| setup(async () => { | |
| diffElement = await fixture(html`<gr-diff></gr-diff>`); | |
| cursor = new GrDiffCursor(); | |
| // Register the diff with the cursor. | |
| cursor.replaceDiffs([diffElement]); | |
| diffElement.loggedIn = false; | |
| diffElement.path = 'some/path.ts'; | |
| const promise = mockPromise(); | |
| const setupDone = () => { | |
| cursor._updateStops(); | |
| cursor.moveToFirstChunk(); | |
| diffElement.removeEventListener('render', setupDone); | |
| promise.resolve(); | |
| }; | |
| diffElement.addEventListener('render', setupDone); | |
| diff = createDiff(); | |
| diffElement.prefs = createDefaultDiffPrefs(); | |
| diffElement.diff = diff; | |
| await promise; | |
| }); | |
| test('diff cursor functionality (side-by-side)', () => { | |
| assert.isOk(cursor.diffRow); | |
| const deltaRows = queryAll<HTMLTableRowElement>( | |
| diffElement, | |
| '.section.delta tr.diff-row' | |
| ); | |
| assert.equal(cursor.diffRow, deltaRows[0]); | |
| cursor.moveDown(); | |
| assert.notEqual(cursor.diffRow, deltaRows[0]); | |
| assert.equal(cursor.diffRow, deltaRows[1]); | |
| cursor.moveUp(); | |
| assert.notEqual(cursor.diffRow, deltaRows[1]); | |
| assert.equal(cursor.diffRow, deltaRows[0]); | |
| }); | |
| test('moveToFirstChunk', async () => { | |
| const diff: DiffInfo = { | |
| meta_a: { | |
| name: 'lorem-ipsum.txt', | |
| content_type: 'text/plain', | |
| lines: 3, | |
| }, | |
| meta_b: { | |
| name: 'lorem-ipsum.txt', | |
| content_type: 'text/plain', | |
| lines: 3, | |
| }, | |
| intraline_status: 'OK', | |
| change_type: 'MODIFIED', | |
| diff_header: [ | |
| 'diff --git a/lorem-ipsum.txt b/lorem-ipsum.txt', | |
| 'index b2adcf4..554ae49 100644', | |
| '--- a/lorem-ipsum.txt', | |
| '+++ b/lorem-ipsum.txt', | |
| ], | |
| content: [ | |
| {b: ['new line 1']}, | |
| {ab: ['unchanged line']}, | |
| {a: ['old line 2']}, | |
| {ab: ['more unchanged lines']}, | |
| ], | |
| }; | |
| diffElement.diff = diff; | |
| // The file comment button, if present, is a cursor stop. Ensure | |
| // moveToFirstChunk() works correctly even if the button is not shown. | |
| diffElement.prefs!.show_file_comment_button = false; | |
| await waitForEventOnce(diffElement, 'render'); | |
| cursor._updateStops(); | |
| const chunks = [ | |
| ...queryAll(diffElement, '.section.delta'), | |
| ] as HTMLElement[]; | |
| assert.equal(chunks.length, 2); | |
| const rows = [ | |
| ...queryAll(diffElement, '.section.delta tr.diff-row'), | |
| ] as HTMLTableRowElement[]; | |
| assert.equal(rows.length, 2); | |
| // Verify it works on fresh diff. | |
| cursor.moveToFirstChunk(); | |
| assert.ok(cursor.diffRow); | |
| assert.equal(cursor.diffRow, rows[0]); | |
| assert.equal(cursor.side, Side.RIGHT); | |
| // Verify it works from other cursor positions. | |
| cursor.moveToNextChunk(); | |
| assert.ok(cursor.diffRow); | |
| assert.equal(cursor.diffRow, rows[1]); | |
| assert.equal(cursor.side, Side.LEFT); | |
| cursor.moveToFirstChunk(); | |
| assert.ok(cursor.diffRow); | |
| assert.equal(cursor.diffRow, rows[0]); | |
| assert.equal(cursor.side, Side.RIGHT); | |
| }); | |
| test('moveToLastChunk', async () => { | |
| const diff: DiffInfo = { | |
| meta_a: { | |
| name: 'lorem-ipsum.txt', | |
| content_type: 'text/plain', | |
| lines: 3, | |
| }, | |
| meta_b: { | |
| name: 'lorem-ipsum.txt', | |
| content_type: 'text/plain', | |
| lines: 3, | |
| }, | |
| intraline_status: 'OK', | |
| change_type: 'MODIFIED', | |
| diff_header: [ | |
| 'diff --git a/lorem-ipsum.txt b/lorem-ipsum.txt', | |
| 'index b2adcf4..554ae49 100644', | |
| '--- a/lorem-ipsum.txt', | |
| '+++ b/lorem-ipsum.txt', | |
| ], | |
| content: [ | |
| {ab: ['unchanged line']}, | |
| {a: ['old line 2']}, | |
| {ab: ['more unchanged lines']}, | |
| {b: ['new line 3']}, | |
| ], | |
| }; | |
| diffElement.diff = diff; | |
| await waitForEventOnce(diffElement, 'render'); | |
| cursor._updateStops(); | |
| const chunks = [ | |
| ...queryAll(diffElement, '.section.delta'), | |
| ] as HTMLElement[]; | |
| assert.equal(chunks.length, 2); | |
| const rows = [ | |
| ...queryAll(diffElement, '.section.delta tr.diff-row'), | |
| ] as HTMLTableRowElement[]; | |
| assert.equal(rows.length, 2); | |
| // Verify it works on fresh diff. | |
| cursor.moveToLastChunk(); | |
| assert.ok(cursor.diffRow); | |
| assert.equal(cursor.diffRow, rows[1]); | |
| assert.equal(cursor.side, Side.RIGHT); | |
| // Verify it works from other cursor positions. | |
| cursor.moveToPreviousChunk(); | |
| assert.ok(cursor.diffRow); | |
| assert.equal(cursor.diffRow, rows[0]); | |
| assert.equal(cursor.side, Side.LEFT); | |
| cursor.moveToLastChunk(); | |
| assert.ok(cursor.diffRow); | |
| assert.equal(cursor.diffRow, rows[1]); | |
| assert.equal(cursor.side, Side.RIGHT); | |
| }); | |
| test('cursor scroll behavior', () => { | |
| assert.equal(cursor.cursorManager.scrollMode, 'keep-visible'); | |
| diffElement.dispatchEvent(new Event('render-start')); | |
| assert.isTrue(cursor.cursorManager.focusOnMove); | |
| window.dispatchEvent(new Event('scroll')); | |
| assert.equal(cursor.cursorManager.scrollMode, 'never'); | |
| assert.isFalse(cursor.cursorManager.focusOnMove); | |
| diffElement.dispatchEvent(new Event('render-content')); | |
| assert.isTrue(cursor.cursorManager.focusOnMove); | |
| cursor.reInitCursor(); | |
| assert.equal(cursor.cursorManager.scrollMode, 'keep-visible'); | |
| }); | |
| test('moves to selected line', () => { | |
| const moveToNumStub = sinon.stub(cursor, 'moveToLineNumber'); | |
| diffElement.dispatchEvent( | |
| new CustomEvent('line-selected', { | |
| detail: {number: '123', side: Side.RIGHT, path: 'some/file'}, | |
| }) | |
| ); | |
| assert.isTrue(moveToNumStub.called); | |
| assert.equal(moveToNumStub.lastCall.args[0], 123); | |
| assert.equal(moveToNumStub.lastCall.args[1], Side.RIGHT); | |
| assert.equal(moveToNumStub.lastCall.args[2], 'some/file'); | |
| }); | |
| suite('unified diff', () => { | |
| setup(async () => { | |
| diffElement.viewMode = DiffViewMode.UNIFIED; | |
| await waitForEventOnce(diffElement, 'render'); | |
| cursor.reInitCursor(); | |
| }); | |
| test('diff cursor functionality (unified)', () => { | |
| assert.isOk(cursor.diffRow); | |
| const rows = [ | |
| ...queryAll(diffElement, '.section.delta tr.diff-row'), | |
| ] as HTMLTableRowElement[]; | |
| assert.equal(cursor.diffRow, rows[0]); | |
| cursor.moveDown(); | |
| assert.notEqual(cursor.diffRow, rows[0]); | |
| assert.equal(cursor.diffRow, rows[1]); | |
| cursor.moveUp(); | |
| assert.notEqual(cursor.diffRow, rows[1]); | |
| assert.equal(cursor.diffRow, rows[0]); | |
| }); | |
| }); | |
| test('cursor side functionality', () => { | |
| // The side only applies to side-by-side mode, which should be the default | |
| // mode. | |
| assert.equal(diffElement.viewMode, 'SIDE_BY_SIDE'); | |
| const rows = [ | |
| ...queryAll(diffElement, '.section tr.diff-row'), | |
| ] as HTMLTableRowElement[]; | |
| assert.equal(rows.length, 50); | |
| const deltaRows = [ | |
| ...queryAll(diffElement, '.section.delta tr.diff-row'), | |
| ] as HTMLTableRowElement[]; | |
| assert.equal(deltaRows.length, 14); | |
| const indexFirstDelta = rows.indexOf(deltaRows[0]); | |
| const rowBeforeFirstDelta = rows[indexFirstDelta - 1]; | |
| // Because the first delta in this diff is on the right, it should be set | |
| // to the right side. | |
| assert.equal(cursor.side, Side.RIGHT); | |
| assert.equal(cursor.diffRow, deltaRows[0]); | |
| const firstIndex = cursor.cursorManager.index; | |
| // Move the side to the left. Because this delta only has a right side, we | |
| // should be moved up to the previous line where there is content on the | |
| // right. The previous row is part of the previous section. | |
| cursor.moveLeft(); | |
| assert.equal(cursor.side, Side.LEFT); | |
| assert.notEqual(cursor.diffRow, rows[0]); | |
| assert.equal(cursor.diffRow, rowBeforeFirstDelta); | |
| assert.equal(cursor.cursorManager.index, firstIndex - 1); | |
| // If we move down, we should skip everything in the first delta because | |
| // we are on the left side and the first delta has no content on the left. | |
| cursor.moveDown(); | |
| assert.equal(cursor.side, Side.LEFT); | |
| assert.notEqual(cursor.diffRow, rowBeforeFirstDelta); | |
| assert.notEqual(cursor.diffRow, rows[0]); | |
| assert.isTrue(cursor.cursorManager.index > firstIndex); | |
| }); | |
| test('chunk skip functionality', () => { | |
| const deltaChunks = [...queryAll(diffElement, 'tbody.section.delta')]; | |
| // We should be initialized to the first chunk. Since this chunk only has | |
| // content on the right side, our side should be right. | |
| assert.equal(cursor.diffRow, deltaChunks[0].querySelector('tr')); | |
| assert.equal(cursor.side, Side.RIGHT); | |
| // Move to the next chunk. | |
| cursor.moveToNextChunk(); | |
| // Since this chunk only has content on the left side. we should have been | |
| // automatically moved over. | |
| assert.equal(cursor.diffRow, deltaChunks[1].querySelector('tr')); | |
| assert.equal(cursor.side, Side.LEFT); | |
| }); | |
| suite('moved chunks without line range)', () => { | |
| setup(async () => { | |
| const promise = mockPromise(); | |
| const renderHandler = function () { | |
| diffElement.removeEventListener('render', renderHandler); | |
| cursor.reInitCursor(); | |
| promise.resolve(); | |
| }; | |
| diffElement.addEventListener('render', renderHandler); | |
| diffElement.diff = { | |
| ...diff, | |
| content: [ | |
| { | |
| ab: ['Lorem ipsum dolor sit amet, suspendisse inceptos vehicula, '], | |
| }, | |
| { | |
| b: [ | |
| 'Nullam neque, ligula ac, id blandit.', | |
| 'Sagittis tincidunt torquent, tempor nunc amet.', | |
| 'At rhoncus id.', | |
| ], | |
| move_details: {changed: false}, | |
| }, | |
| { | |
| ab: ['Sem nascetur, erat ut, non in.'], | |
| }, | |
| { | |
| a: [ | |
| 'Nullam neque, ligula ac, id blandit.', | |
| 'Sagittis tincidunt torquent, tempor nunc amet.', | |
| 'At rhoncus id.', | |
| ], | |
| move_details: {changed: false}, | |
| }, | |
| { | |
| ab: ['Arcu eget, rhoncus amet cursus, ipsum elementum.'], | |
| }, | |
| ], | |
| }; | |
| await promise; | |
| }); | |
| test('renders moveControls with simple descriptions', () => { | |
| const [movedIn, movedOut] = [ | |
| ...queryAll<HTMLElement>(diffElement, '.dueToMove tr.moveControls'), | |
| ]; | |
| assert.include(movedIn.innerText, 'Moved in'); | |
| assert.include(movedOut.innerText, 'Moved out'); | |
| }); | |
| }); | |
| suite('moved chunks (moveDetails)', () => { | |
| setup(async () => { | |
| const promise = mockPromise(); | |
| const renderHandler = function () { | |
| diffElement.removeEventListener('render', renderHandler); | |
| cursor.reInitCursor(); | |
| promise.resolve(); | |
| }; | |
| diffElement.addEventListener('render', renderHandler); | |
| diffElement.diff = { | |
| ...diff, | |
| content: [ | |
| { | |
| ab: ['Lorem ipsum dolor sit amet, suspendisse inceptos vehicula, '], | |
| }, | |
| { | |
| b: [ | |
| 'Nullam neque, ligula ac, id blandit.', | |
| 'Sagittis tincidunt torquent, tempor nunc amet.', | |
| 'At rhoncus id.', | |
| ], | |
| move_details: {changed: false, range: {start: 4, end: 6}}, | |
| }, | |
| { | |
| ab: ['Sem nascetur, erat ut, non in.'], | |
| }, | |
| { | |
| a: [ | |
| 'Nullam neque, ligula ac, id blandit.', | |
| 'Sagittis tincidunt torquent, tempor nunc amet.', | |
| 'At rhoncus id.', | |
| ], | |
| move_details: {changed: false, range: {start: 2, end: 4}}, | |
| }, | |
| { | |
| ab: ['Arcu eget, rhoncus amet cursus, ipsum elementum.'], | |
| }, | |
| ], | |
| }; | |
| await promise; | |
| }); | |
| test('renders moveControls with simple descriptions', () => { | |
| const [movedIn, movedOut] = [ | |
| ...queryAll<HTMLElement>(diffElement, '.dueToMove tr.moveControls'), | |
| ]; | |
| assert.include(movedIn.innerText, 'Moved from lines 4 - 6'); | |
| assert.include(movedOut.innerText, 'Moved to lines 2 - 4'); | |
| }); | |
| test('startLineAnchor of movedIn chunk fires events', async () => { | |
| const [movedIn] = [...queryAll(diffElement, '.dueToMove .moveControls')]; | |
| const [startLineAnchor] = movedIn.querySelectorAll('a'); | |
| const promise = mockPromise(); | |
| const onMovedLinkClicked = (e: CustomEvent) => { | |
| assert.deepEqual(e.detail, {lineNum: 4, side: Side.LEFT}); | |
| promise.resolve(); | |
| }; | |
| assert.equal(startLineAnchor.textContent, '4'); | |
| startLineAnchor.addEventListener( | |
| 'moved-link-clicked', | |
| onMovedLinkClicked | |
| ); | |
| startLineAnchor.click(); | |
| await promise; | |
| }); | |
| test('endLineAnchor of movedOut fires events', async () => { | |
| const [, movedOut] = [ | |
| ...queryAll(diffElement, '.dueToMove .moveControls'), | |
| ]; | |
| const [, endLineAnchor] = movedOut.querySelectorAll('a'); | |
| const promise = mockPromise(); | |
| const onMovedLinkClicked = (e: CustomEvent) => { | |
| assert.deepEqual(e.detail, {lineNum: 4, side: Side.RIGHT}); | |
| promise.resolve(); | |
| }; | |
| assert.equal(endLineAnchor.textContent, '4'); | |
| endLineAnchor.addEventListener('moved-link-clicked', onMovedLinkClicked); | |
| endLineAnchor.click(); | |
| await promise; | |
| }); | |
| }); | |
| test('initialLineNumber not provided', async () => { | |
| let scrollBehaviorDuringMove; | |
| const moveToNumStub = sinon.stub(cursor, 'moveToLineNumber'); | |
| const moveToChunkStub = sinon | |
| .stub(cursor, 'moveToFirstChunk') | |
| .callsFake(() => { | |
| scrollBehaviorDuringMove = cursor.cursorManager.scrollMode; | |
| }); | |
| diffElement.diff = createDiff(); | |
| await diffElement.updateComplete; | |
| await waitForEventOnce(diffElement, 'render'); | |
| cursor.reInitCursor(); | |
| assert.isFalse(moveToNumStub.called); | |
| assert.isTrue(moveToChunkStub.called); | |
| assert.equal(scrollBehaviorDuringMove, 'never'); | |
| assert.equal(cursor.cursorManager.scrollMode, 'keep-visible'); | |
| }); | |
| test('initialLineNumber provided', async () => { | |
| let scrollBehaviorDuringMove; | |
| const moveToNumStub = sinon | |
| .stub(cursor, 'moveToLineNumber') | |
| .callsFake(() => { | |
| scrollBehaviorDuringMove = cursor.cursorManager.scrollMode; | |
| }); | |
| const moveToChunkStub = sinon.stub(cursor, 'moveToFirstChunk'); | |
| cursor.initialLineNumber = 10; | |
| cursor.side = Side.RIGHT; | |
| diffElement.diff = createDiff(); | |
| await diffElement.updateComplete; | |
| await waitForEventOnce(diffElement, 'render'); | |
| cursor.reInitCursor(); | |
| assert.isFalse(moveToChunkStub.called); | |
| assert.isTrue(moveToNumStub.called); | |
| assert.equal(moveToNumStub.lastCall.args[0], 10); | |
| assert.equal(moveToNumStub.lastCall.args[1], Side.RIGHT); | |
| assert.equal(scrollBehaviorDuringMove, 'keep-visible'); | |
| assert.equal(cursor.cursorManager.scrollMode, 'keep-visible'); | |
| }); | |
| test('getTargetDiffElement', () => { | |
| cursor.initialLineNumber = 1; | |
| assert.isTrue(!!cursor.diffRow); | |
| assert.equal(cursor.getTargetDiffElement(), diffElement); | |
| }); | |
| suite('createCommentInPlace', () => { | |
| setup(() => { | |
| diffElement.loggedIn = true; | |
| }); | |
| test('adds new draft for selected line on the left', async () => { | |
| cursor.moveToLineNumber(2, Side.LEFT); | |
| const promise = mockPromise(); | |
| diffElement.addEventListener('create-comment', e => { | |
| const {lineNum, range, side} = e.detail; | |
| assert.equal(lineNum, 2); | |
| assert.equal(range, undefined); | |
| assert.equal(side, Side.LEFT); | |
| promise.resolve(); | |
| }); | |
| cursor.createCommentInPlace(); | |
| await promise; | |
| }); | |
| test('adds draft for selected line on the right', async () => { | |
| cursor.moveToLineNumber(4, Side.RIGHT); | |
| const promise = mockPromise(); | |
| diffElement.addEventListener('create-comment', e => { | |
| const {lineNum, range, side} = e.detail; | |
| assert.equal(lineNum, 4); | |
| assert.equal(range, undefined); | |
| assert.equal(side, Side.RIGHT); | |
| promise.resolve(); | |
| }); | |
| cursor.createCommentInPlace(); | |
| await promise; | |
| }); | |
| test('creates comment for range if selected', async () => { | |
| const someRange = { | |
| start_line: 2, | |
| start_character: 3, | |
| end_line: 6, | |
| end_character: 1, | |
| }; | |
| diffElement.highlights.selectedRange = { | |
| side: Side.RIGHT, | |
| range: someRange, | |
| }; | |
| const promise = mockPromise(); | |
| diffElement.addEventListener('create-comment', e => { | |
| const {lineNum, range, side} = e.detail; | |
| assert.equal(lineNum, 6); | |
| assert.equal(range, someRange); | |
| assert.equal(side, Side.RIGHT); | |
| promise.resolve(); | |
| }); | |
| cursor.createCommentInPlace(); | |
| await promise; | |
| }); | |
| test('ignores call if nothing is selected', () => { | |
| const createRangeCommentStub = sinon.stub( | |
| diffElement, | |
| 'createRangeComment' | |
| ); | |
| const addDraftAtLineStub = sinon.stub(diffElement, 'addDraftAtLine'); | |
| cursor.diffRow = undefined; | |
| cursor.createCommentInPlace(); | |
| assert.isFalse(createRangeCommentStub.called); | |
| assert.isFalse(addDraftAtLineStub.called); | |
| }); | |
| }); | |
| test('getAddress', () => { | |
| // It should initialize to the first chunk: line 5 of the revision. | |
| assert.deepEqual(cursor.getAddress(), {leftSide: false, number: 5}); | |
| // Revision line 4 is up. | |
| cursor.moveUp(); | |
| assert.deepEqual(cursor.getAddress(), {leftSide: false, number: 4}); | |
| // Base line 4 is left. | |
| cursor.moveLeft(); | |
| assert.deepEqual(cursor.getAddress(), {leftSide: true, number: 4}); | |
| // Moving to the next chunk takes it back to the start. | |
| cursor.moveToNextChunk(); | |
| assert.deepEqual(cursor.getAddress(), {leftSide: false, number: 5}); | |
| // The following chunk is a removal starting on line 10 of the base. | |
| cursor.moveToNextChunk(); | |
| assert.deepEqual(cursor.getAddress(), {leftSide: true, number: 10}); | |
| // Should be null if there is no selection. | |
| cursor.cursorManager.unsetCursor(); | |
| assert.isNotOk(cursor.getAddress()); | |
| }); | |
| test('_findRowByNumberAndFile', () => { | |
| // Get the first ab row after the first chunk. | |
| const rows = [...queryAll<HTMLTableRowElement>(diffElement, 'tr')]; | |
| const row = rows[9]; | |
| assert.ok(row); | |
| // It should be line 8 on the right, but line 5 on the left. | |
| assert.equal(cursor._findRowByNumberAndFile(8, Side.RIGHT), row); | |
| assert.equal(cursor._findRowByNumberAndFile(5, Side.LEFT), row); | |
| }); | |
| test('expand context updates stops', async () => { | |
| const spy = sinon.spy(cursor, '_updateStops'); | |
| const controls = queryAndAssert(diffElement, 'gr-context-controls'); | |
| const showContext = queryAndAssert<HTMLElement>(controls, '.showContext'); | |
| showContext.click(); | |
| await waitForEventOnce(diffElement, 'render'); | |
| await waitUntil(() => spy.called); | |
| assert.isTrue(spy.called); | |
| }); | |
| test('updates stops when loading changes', () => { | |
| const spy = sinon.spy(cursor, '_updateStops'); | |
| diffElement.dispatchEvent(new Event('loading-changed')); | |
| assert.isTrue(spy.called); | |
| }); | |
| suite('multi diff', () => { | |
| let diffElements: GrDiff[]; | |
| setup(async () => { | |
| diffElements = [ | |
| await fixture(html`<gr-diff></gr-diff>`), | |
| await fixture(html`<gr-diff></gr-diff>`), | |
| await fixture(html`<gr-diff></gr-diff>`), | |
| ]; | |
| cursor = new GrDiffCursor(); | |
| // Register the diff with the cursor. | |
| cursor.replaceDiffs(diffElements); | |
| for (const el of diffElements) { | |
| el.prefs = createDefaultDiffPrefs(); | |
| } | |
| }); | |
| function getTargetDiffIndex() { | |
| // Mocha has a bug where when `assert.equals` fails, it will try to | |
| // JSON.stringify the operands, which fails when they are cyclic structures | |
| // like GrDiffElement. The failure is difficult to attribute to a specific | |
| // assertion because of the async nature assertion errors are handled and | |
| // can cause the test simply timing out, causing a lot of debugging headache. | |
| // Working with indices circumvents the problem. | |
| const target = cursor.getTargetDiffElement(); | |
| assertIsDefined(target); | |
| return diffElements.indexOf(target); | |
| } | |
| test('do not skip loading diffs', async () => { | |
| diffElements[0].diff = createDiff(); | |
| diffElements[2].diff = createDiff(); | |
| await waitForEventOnce(diffElements[0], 'render'); | |
| await waitForEventOnce(diffElements[2], 'render'); | |
| const lastLine = diffElements[0].diff.meta_b?.lines; | |
| assertIsDefined(lastLine); | |
| // Goto second last line of the first diff | |
| cursor.moveToLineNumber(lastLine - 1, Side.RIGHT); | |
| assert.equal( | |
| cursor.getTargetLineElement()!.textContent?.trim(), | |
| `${lastLine - 1}` | |
| ); | |
| // Can move down until we reach the loading file | |
| cursor.moveDown(); | |
| assert.equal(getTargetDiffIndex(), 0); | |
| assert.equal( | |
| cursor.getTargetLineElement()!.textContent?.trim(), | |
| lastLine.toString() | |
| ); | |
| // Cannot move down while still loading the diff we would switch to | |
| cursor.moveDown(); | |
| assert.equal(getTargetDiffIndex(), 0); | |
| assert.equal( | |
| cursor.getTargetLineElement()!.textContent?.trim(), | |
| lastLine.toString() | |
| ); | |
| // Diff 1 finishing to load | |
| diffElements[1].diff = createDiff(); | |
| await waitForEventOnce(diffElements[1], 'render'); | |
| // Now we can go down | |
| cursor.moveDown(); // LOST | |
| cursor.moveDown(); // FILE | |
| assert.equal(getTargetDiffIndex(), 1); | |
| assert.equal(cursor.getTargetLineElement()!.textContent?.trim(), 'File'); | |
| }); | |
| }); | |
| }); |