| /** |
| * @license |
| * Copyright (C) 2021 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| import '../../../test/common-test-setup-karma'; |
| import '../gr-diff/gr-diff-group'; |
| import './gr-context-controls'; |
| import {GrContextControls} from './gr-context-controls'; |
| import {flush} from '@polymer/polymer/lib/legacy/polymer.dom'; |
| |
| import {GrDiffLine, GrDiffLineType} from '../gr-diff/gr-diff-line'; |
| import {GrDiffGroup, GrDiffGroupType} from '../gr-diff/gr-diff-group'; |
| import {DiffFileMetaInfo, DiffInfo, SyntaxBlock} from '../../../api/diff'; |
| |
| const blankFixture = fixtureFromElement('div'); |
| |
| suite('gr-context-control tests', () => { |
| let element: GrContextControls; |
| |
| setup(async () => { |
| element = document.createElement('gr-context-controls'); |
| element.diff = ({content: []} as any) as DiffInfo; |
| element.renderPreferences = {}; |
| element.section = document.createElement('div'); |
| blankFixture.instantiate().appendChild(element); |
| await flush(); |
| }); |
| |
| function createContextGroups(options: {offset?: number; count?: number}) { |
| const offset = options.offset || 0; |
| const numLines = options.count || 10; |
| const lines = []; |
| for (let i = 0; i < numLines; i++) { |
| const line = new GrDiffLine(GrDiffLineType.BOTH); |
| line.beforeNumber = offset + i + 1; |
| line.afterNumber = offset + i + 1; |
| line.text = 'lorem upsum'; |
| lines.push(line); |
| } |
| |
| return [new GrDiffGroup(GrDiffGroupType.BOTH, lines)]; |
| } |
| |
| test('no +10 buttons for 10 or less lines', async () => { |
| element.contextGroups = createContextGroups({count: 10}); |
| |
| await flush(); |
| |
| const buttons = element.shadowRoot!.querySelectorAll( |
| 'gr-button.showContext' |
| ); |
| assert.equal(buttons.length, 1); |
| assert.equal(buttons[0].textContent!.trim(), '+10 common lines'); |
| }); |
| |
| test('context control at the top', async () => { |
| element.contextGroups = createContextGroups({offset: 0, count: 20}); |
| element.showBelow = true; |
| |
| await flush(); |
| |
| const buttons = element.shadowRoot!.querySelectorAll( |
| 'gr-button.showContext' |
| ); |
| |
| assert.equal(buttons.length, 2); |
| assert.equal(buttons[0].textContent!.trim(), '+20 common lines'); |
| assert.equal(buttons[1].textContent!.trim(), '+10'); |
| |
| assert.include([...buttons[0].classList.values()], 'belowButton'); |
| assert.include([...buttons[1].classList.values()], 'belowButton'); |
| }); |
| |
| test('context control in the middle', async () => { |
| element.contextGroups = createContextGroups({offset: 10, count: 20}); |
| element.showAbove = true; |
| element.showBelow = true; |
| |
| await flush(); |
| |
| const buttons = element.shadowRoot!.querySelectorAll( |
| 'gr-button.showContext' |
| ); |
| |
| assert.equal(buttons.length, 3); |
| assert.equal(buttons[0].textContent!.trim(), '+20 common lines'); |
| assert.equal(buttons[1].textContent!.trim(), '+10'); |
| assert.equal(buttons[2].textContent!.trim(), '+10'); |
| |
| assert.include([...buttons[0].classList.values()], 'centeredButton'); |
| assert.include([...buttons[1].classList.values()], 'aboveButton'); |
| assert.include([...buttons[2].classList.values()], 'belowButton'); |
| }); |
| |
| test('context control at the bottom', async () => { |
| element.contextGroups = createContextGroups({offset: 30, count: 20}); |
| element.showAbove = true; |
| |
| await flush(); |
| |
| const buttons = element.shadowRoot!.querySelectorAll( |
| 'gr-button.showContext' |
| ); |
| |
| assert.equal(buttons.length, 2); |
| assert.equal(buttons[0].textContent!.trim(), '+20 common lines'); |
| assert.equal(buttons[1].textContent!.trim(), '+10'); |
| |
| assert.include([...buttons[0].classList.values()], 'aboveButton'); |
| assert.include([...buttons[1].classList.values()], 'aboveButton'); |
| }); |
| |
| function prepareForBlockExpansion(syntaxTree: SyntaxBlock[]) { |
| element.renderPreferences!.use_block_expansion = true; |
| element.diff!.meta_b = ({ |
| syntax_tree: syntaxTree, |
| } as any) as DiffFileMetaInfo; |
| } |
| |
| test('context control with block expansion at the top', async () => { |
| prepareForBlockExpansion([]); |
| element.contextGroups = createContextGroups({offset: 0, count: 20}); |
| element.showBelow = true; |
| |
| await flush(); |
| |
| const fullExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.fullExpansion gr-button' |
| ); |
| const partialExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.partialExpansion gr-button' |
| ); |
| const blockExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.blockExpansion gr-button' |
| ); |
| assert.equal(fullExpansionButtons.length, 1); |
| assert.equal(partialExpansionButtons.length, 1); |
| assert.equal(blockExpansionButtons.length, 1); |
| assert.equal( |
| blockExpansionButtons[0].querySelector('span')!.textContent!.trim(), |
| '+Block' |
| ); |
| assert.include( |
| [...blockExpansionButtons[0].classList.values()], |
| 'belowButton' |
| ); |
| }); |
| |
| test('context control with block expansion in the middle', async () => { |
| prepareForBlockExpansion([]); |
| element.contextGroups = createContextGroups({offset: 10, count: 20}); |
| element.showAbove = true; |
| element.showBelow = true; |
| |
| await flush(); |
| |
| const fullExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.fullExpansion gr-button' |
| ); |
| const partialExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.partialExpansion gr-button' |
| ); |
| const blockExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.blockExpansion gr-button' |
| ); |
| assert.equal(fullExpansionButtons.length, 1); |
| assert.equal(partialExpansionButtons.length, 2); |
| assert.equal(blockExpansionButtons.length, 2); |
| assert.equal( |
| blockExpansionButtons[0].querySelector('span')!.textContent!.trim(), |
| '+Block' |
| ); |
| assert.equal( |
| blockExpansionButtons[1].querySelector('span')!.textContent!.trim(), |
| '+Block' |
| ); |
| assert.include( |
| [...blockExpansionButtons[0].classList.values()], |
| 'aboveButton' |
| ); |
| assert.include( |
| [...blockExpansionButtons[1].classList.values()], |
| 'belowButton' |
| ); |
| }); |
| |
| test('context control with block expansion at the bottom', async () => { |
| prepareForBlockExpansion([]); |
| element.contextGroups = createContextGroups({offset: 30, count: 20}); |
| element.showAbove = true; |
| |
| await flush(); |
| |
| const fullExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.fullExpansion gr-button' |
| ); |
| const partialExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.partialExpansion gr-button' |
| ); |
| const blockExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.blockExpansion gr-button' |
| ); |
| assert.equal(fullExpansionButtons.length, 1); |
| assert.equal(partialExpansionButtons.length, 1); |
| assert.equal(blockExpansionButtons.length, 1); |
| assert.equal( |
| blockExpansionButtons[0].querySelector('span')!.textContent!.trim(), |
| '+Block' |
| ); |
| assert.include( |
| [...blockExpansionButtons[0].classList.values()], |
| 'aboveButton' |
| ); |
| }); |
| |
| test('+ Block tooltip tooltip shows syntax block containing the target lines above and below', async () => { |
| prepareForBlockExpansion([ |
| { |
| name: 'aSpecificFunction', |
| range: {start_line: 1, start_column: 0, end_line: 25, end_column: 0}, |
| children: [], |
| }, |
| { |
| name: 'anotherFunction', |
| range: {start_line: 26, start_column: 0, end_line: 50, end_column: 0}, |
| children: [], |
| }, |
| ]); |
| element.contextGroups = createContextGroups({offset: 10, count: 20}); |
| element.showAbove = true; |
| element.showBelow = true; |
| |
| await flush(); |
| |
| const blockExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.blockExpansion gr-button' |
| ); |
| assert.equal( |
| blockExpansionButtons[0] |
| .querySelector('.breadcrumbTooltip')! |
| .textContent?.trim(), |
| 'aSpecificFunction' |
| ); |
| assert.equal( |
| blockExpansionButtons[1] |
| .querySelector('.breadcrumbTooltip')! |
| .textContent?.trim(), |
| 'anotherFunction' |
| ); |
| }); |
| |
| test('+Block tooltip shows nested syntax blocks as breadcrumbs', async () => { |
| prepareForBlockExpansion([ |
| { |
| name: 'aSpecificNamespace', |
| range: {start_line: 1, start_column: 0, end_line: 200, end_column: 0}, |
| children: [ |
| { |
| name: 'MyClass', |
| range: { |
| start_line: 2, |
| start_column: 0, |
| end_line: 100, |
| end_column: 0, |
| }, |
| children: [ |
| { |
| name: 'aMethod', |
| range: { |
| start_line: 5, |
| start_column: 0, |
| end_line: 80, |
| end_column: 0, |
| }, |
| children: [], |
| }, |
| ], |
| }, |
| ], |
| }, |
| ]); |
| element.contextGroups = createContextGroups({offset: 10, count: 20}); |
| element.showAbove = true; |
| element.showBelow = true; |
| |
| await flush(); |
| |
| const blockExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.blockExpansion gr-button' |
| ); |
| assert.equal( |
| blockExpansionButtons[0] |
| .querySelector('.breadcrumbTooltip')! |
| .textContent?.trim(), |
| 'aSpecificNamespace > MyClass > aMethod' |
| ); |
| }); |
| |
| test('+Block tooltip shows (anonymous) for empty blocks', async () => { |
| prepareForBlockExpansion([ |
| { |
| name: 'aSpecificNamespace', |
| range: {start_line: 1, start_column: 0, end_line: 200, end_column: 0}, |
| children: [ |
| { |
| name: '', |
| range: { |
| start_line: 2, |
| start_column: 0, |
| end_line: 100, |
| end_column: 0, |
| }, |
| children: [ |
| { |
| name: 'aMethod', |
| range: { |
| start_line: 5, |
| start_column: 0, |
| end_line: 80, |
| end_column: 0, |
| }, |
| children: [], |
| }, |
| ], |
| }, |
| ], |
| }, |
| ]); |
| element.contextGroups = createContextGroups({offset: 10, count: 20}); |
| element.showAbove = true; |
| element.showBelow = true; |
| await flush(); |
| |
| const blockExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.blockExpansion gr-button' |
| ); |
| assert.equal( |
| blockExpansionButtons[0] |
| .querySelector('.breadcrumbTooltip')! |
| .textContent?.trim(), |
| 'aSpecificNamespace > (anonymous) > aMethod' |
| ); |
| }); |
| |
| test('+Block tooltip shows "all common lines" for empty syntax tree', async () => { |
| prepareForBlockExpansion([]); |
| |
| element.contextGroups = createContextGroups({offset: 10, count: 20}); |
| element.showAbove = true; |
| element.showBelow = true; |
| await flush(); |
| |
| const blockExpansionButtons = element.shadowRoot!.querySelectorAll( |
| '.blockExpansion gr-button' |
| ); |
| const tooltipAbove = blockExpansionButtons[0].querySelector( |
| 'paper-tooltip' |
| )!; |
| const tooltipBelow = blockExpansionButtons[1].querySelector( |
| 'paper-tooltip' |
| )!; |
| assert.equal( |
| tooltipAbove.querySelector('.breadcrumbTooltip')!.textContent?.trim(), |
| '20 common lines' |
| ); |
| assert.equal( |
| tooltipBelow.querySelector('.breadcrumbTooltip')!.textContent?.trim(), |
| '20 common lines' |
| ); |
| assert.equal(tooltipAbove!.getAttribute('position'), 'top'); |
| assert.equal(tooltipBelow!.getAttribute('position'), 'bottom'); |
| }); |
| }); |