 1dd6700d07
			
		
	
	1dd6700d07
	
	
	
		
			
			_handleCopy function doesn't do anything in case of Polymer 2. All tests connected with this function doesn't shouldn't do anything in Polymer 2. Bug: Issue 10930 Change-Id: Id71cbd0b19f1569992843d6d4a249dc566ec8f94
		
			
				
	
	
		
			419 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			419 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html>
 | |
| <!--
 | |
| @license
 | |
| Copyright (C) 2016 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.
 | |
| -->
 | |
| 
 | |
| <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 | |
| <title>gr-diff-selection</title>
 | |
| <script src="/test/common-test-setup.js"></script>
 | |
| <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 | |
| 
 | |
| <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
 | |
| <script src="/bower_components/web-component-tester/browser.js"></script>
 | |
| <link rel="import" href="../../../test/common-test-setup.html"/>
 | |
| <link rel="import" href="gr-diff-selection.html">
 | |
| 
 | |
| <script>void(0);</script>
 | |
| 
 | |
| <test-fixture id="basic">
 | |
|   <template>
 | |
|     <gr-diff-selection>
 | |
|       <table id="diffTable" class="side-by-side">
 | |
|         <tr class="diff-row">
 | |
|           <td class="blame" data-line-number="1"></td>
 | |
|           <td class="lineNum left" data-value="1">1</td>
 | |
|           <td class="content">
 | |
|             <div class="contentText" data-side="left">ba ba</div>
 | |
|             <div data-side="left">
 | |
|               <div class="comment-thread">
 | |
|                 <div class="gr-formatted-text message">
 | |
|                   <span id="output" class="gr-linked-text">This is a comment</span>
 | |
|                 </div>
 | |
|               </div>
 | |
|             </div>
 | |
|           </td>
 | |
|           <td class="lineNum right" data-value="1">1</td>
 | |
|           <td class="content">
 | |
|             <div class="contentText" data-side="right">some other text</div>
 | |
|           </td>
 | |
|         </tr>
 | |
|         <tr class="diff-row">
 | |
|           <td class="blame" data-line-number="2"></td>
 | |
|           <td class="lineNum left" data-value="2">2</td>
 | |
|           <td class="content">
 | |
|             <div class="contentText" data-side="left">zin</div>
 | |
|           </td>
 | |
|           <td class="lineNum right" data-value="2">2</td>
 | |
|           <td class="content">
 | |
|             <div class="contentText" data-side="right">more more more</div>
 | |
|             <div data-side="right">
 | |
|               <div class="comment-thread">
 | |
|                 <div class="gr-formatted-text message">
 | |
|                   <span id="output" class="gr-linked-text">This is a comment on the right</span>
 | |
|                 </div>
 | |
|               </div>
 | |
|             </div>
 | |
|           </td>
 | |
|         </tr>
 | |
|         <tr class="diff-row">
 | |
|           <td class="blame" data-line-number="3"></td>
 | |
|           <td class="lineNum left" data-value="3">3</td>
 | |
|           <td class="content">
 | |
|             <div class="contentText" data-side="left">ga ga</div>
 | |
|             <div data-side="left">
 | |
|               <div class="comment-thread">
 | |
|                 <div class="gr-formatted-text message">
 | |
|                   <span id="output" class="gr-linked-text">This is <a>a</a> different comment 💩 unicode is fun</span>
 | |
|                 </div>
 | |
|               </div>
 | |
|             </div>
 | |
|           </td>
 | |
|           <td class="lineNum right" data-value="3">3</td>
 | |
|         </tr>
 | |
|         <tr class="diff-row">
 | |
|           <td class="blame" data-line-number="4"></td>
 | |
|           <td class="lineNum left" data-value="4">4</td>
 | |
|           <td class="content">
 | |
|             <div class="contentText" data-side="left">ga ga</div>
 | |
|             <div data-side="left">
 | |
|               <div class="comment-thread">
 | |
|                 <textarea data-side="right">test for textarea copying</textarea>
 | |
|               </div>
 | |
|             </div>
 | |
|           </td>
 | |
|           <td class="lineNum right" data-value="4">4</td>
 | |
|         </tr>
 | |
|         <tr class="not-diff-row">
 | |
|           <td class="other">
 | |
|             <div class="contentText" data-side="right">some other text</div>
 | |
|           </td>
 | |
|         </tr>
 | |
|       </table>
 | |
|     </gr-diff-selection>
 | |
|   </template>
 | |
| </test-fixture>
 | |
| 
 | |
| <script>
 | |
|   suite('gr-diff-selection', () => {
 | |
|     let element;
 | |
|     let sandbox;
 | |
| 
 | |
|     const emulateCopyOn = function(target) {
 | |
|       const fakeEvent = {
 | |
|         target,
 | |
|         preventDefault: sandbox.stub(),
 | |
|         clipboardData: {
 | |
|           setData: sandbox.stub(),
 | |
|         },
 | |
|       };
 | |
|       element._getCopyEventTarget.returns(target);
 | |
|       element._handleCopy(fakeEvent);
 | |
|       return fakeEvent;
 | |
|     };
 | |
| 
 | |
|     setup(() => {
 | |
|       element = fixture('basic');
 | |
|       sandbox = sinon.sandbox.create();
 | |
|       sandbox.stub(element, '_getCopyEventTarget');
 | |
|       element._cachedDiffBuilder = {
 | |
|         getLineElByChild: sandbox.stub().returns({}),
 | |
|         getSideByLineEl: sandbox.stub(),
 | |
|         diffElement: element.querySelector('#diffTable'),
 | |
|       };
 | |
|       element.diff = {
 | |
|         content: [
 | |
|           {
 | |
|             a: ['ba ba'],
 | |
|             b: ['some other text'],
 | |
|           },
 | |
|           {
 | |
|             a: ['zin'],
 | |
|             b: ['more more more'],
 | |
|           },
 | |
|           {
 | |
|             a: ['ga ga'],
 | |
|             b: ['some other text'],
 | |
|           },
 | |
|         ],
 | |
|       };
 | |
|     });
 | |
| 
 | |
|     teardown(() => {
 | |
|       sandbox.restore();
 | |
|     });
 | |
| 
 | |
|     test('applies selected-left on left side click', () => {
 | |
|       element.classList.add('selected-right');
 | |
|       element._cachedDiffBuilder.getSideByLineEl.returns('left');
 | |
|       MockInteractions.down(element);
 | |
|       assert.isTrue(
 | |
|           element.classList.contains('selected-left'), 'adds selected-left');
 | |
|       assert.isFalse(
 | |
|           element.classList.contains('selected-right'),
 | |
|           'removes selected-right');
 | |
|     });
 | |
| 
 | |
|     test('applies selected-right on right side click', () => {
 | |
|       element.classList.add('selected-left');
 | |
|       element._cachedDiffBuilder.getSideByLineEl.returns('right');
 | |
|       MockInteractions.down(element);
 | |
|       assert.isTrue(
 | |
|           element.classList.contains('selected-right'), 'adds selected-right');
 | |
|       assert.isFalse(
 | |
|           element.classList.contains('selected-left'), 'removes selected-left');
 | |
|     });
 | |
| 
 | |
|     test('applies selected-blame on blame click', () => {
 | |
|       element.classList.add('selected-left');
 | |
|       element.diffBuilder.getLineElByChild.returns(null);
 | |
|       sandbox.stub(element, '_elementDescendedFromClass',
 | |
|           (el, className) => className === 'blame');
 | |
|       MockInteractions.down(element);
 | |
|       assert.isTrue(
 | |
|           element.classList.contains('selected-blame'), 'adds selected-right');
 | |
|       assert.isFalse(
 | |
|           element.classList.contains('selected-left'), 'removes selected-left');
 | |
|     });
 | |
| 
 | |
|     test('ignores copy for non-content Element', () => {
 | |
|       // See _handleCopy for explanation
 | |
|       if (window.POLYMER2) return;
 | |
| 
 | |
|       sandbox.stub(element, '_getSelectedText');
 | |
|       emulateCopyOn(element.querySelector('.not-diff-row'));
 | |
|       assert.isFalse(element._getSelectedText.called);
 | |
|     });
 | |
| 
 | |
|     test('asks for text for left side Elements', () => {
 | |
|       // See _handleCopy for explanation
 | |
|       if (window.POLYMER2) return;
 | |
| 
 | |
|       element._cachedDiffBuilder.getSideByLineEl.returns('left');
 | |
|       sandbox.stub(element, '_getSelectedText');
 | |
|       emulateCopyOn(element.querySelector('div.contentText'));
 | |
|       assert.deepEqual(['left', false], element._getSelectedText.lastCall.args);
 | |
|     });
 | |
| 
 | |
|     test('reacts to copy for content Elements', () => {
 | |
|       // See _handleCopy for explanation
 | |
|       if (window.POLYMER2) return;
 | |
| 
 | |
|       sandbox.stub(element, '_getSelectedText');
 | |
|       emulateCopyOn(element.querySelector('div.contentText'));
 | |
|       assert.isTrue(element._getSelectedText.called);
 | |
|     });
 | |
| 
 | |
|     test('copy event is prevented for content Elements', () => {
 | |
|       // See _handleCopy for explanation
 | |
|       if (window.POLYMER2) return;
 | |
| 
 | |
|       sandbox.stub(element, '_getSelectedText');
 | |
|       element._cachedDiffBuilder.getSideByLineEl.returns('left');
 | |
|       element._getSelectedText.returns('test');
 | |
|       const event = emulateCopyOn(element.querySelector('div.contentText'));
 | |
|       assert.isTrue(event.preventDefault.called);
 | |
|     });
 | |
| 
 | |
|     test('inserts text into clipboard on copy', () => {
 | |
|       // See _handleCopy for explanation
 | |
|       if (window.POLYMER2) return;
 | |
| 
 | |
|       sandbox.stub(element, '_getSelectedText').returns('the text');
 | |
|       const event = emulateCopyOn(element.querySelector('div.contentText'));
 | |
|       assert.deepEqual(
 | |
|           ['Text', 'the text'], event.clipboardData.setData.lastCall.args);
 | |
|     });
 | |
| 
 | |
|     test('_setClasses adds given SelectionClass values, removes others', () => {
 | |
|       element.classList.add('selected-right');
 | |
|       element._setClasses(['selected-comment', 'selected-left']);
 | |
|       assert.isTrue(element.classList.contains('selected-comment'));
 | |
|       assert.isTrue(element.classList.contains('selected-left'));
 | |
|       assert.isFalse(element.classList.contains('selected-right'));
 | |
|       assert.isFalse(element.classList.contains('selected-blame'));
 | |
| 
 | |
|       element._setClasses(['selected-blame']);
 | |
|       assert.isFalse(element.classList.contains('selected-comment'));
 | |
|       assert.isFalse(element.classList.contains('selected-left'));
 | |
|       assert.isFalse(element.classList.contains('selected-right'));
 | |
|       assert.isTrue(element.classList.contains('selected-blame'));
 | |
|     });
 | |
| 
 | |
|     test('_setClasses removes before it ads', () => {
 | |
|       element.classList.add('selected-right');
 | |
|       const addStub = sandbox.stub(element.classList, 'add');
 | |
|       const removeStub = sandbox.stub(element.classList, 'remove', () => {
 | |
|         assert.isFalse(addStub.called);
 | |
|       });
 | |
|       element._setClasses(['selected-comment', 'selected-left']);
 | |
|       assert.isTrue(addStub.called);
 | |
|       assert.isTrue(removeStub.called);
 | |
|     });
 | |
| 
 | |
|     test('copies content correctly', () => {
 | |
|       // Fetch the line number.
 | |
|       element._cachedDiffBuilder.getLineElByChild = function(child) {
 | |
|         while (!child.classList.contains('content') && child.parentElement) {
 | |
|           child = child.parentElement;
 | |
|         }
 | |
|         return child.previousElementSibling;
 | |
|       };
 | |
| 
 | |
|       element.classList.add('selected-left');
 | |
|       element.classList.remove('selected-right');
 | |
| 
 | |
|       const selection = window.getSelection();
 | |
|       selection.removeAllRanges();
 | |
|       const range = document.createRange();
 | |
|       range.setStart(element.querySelector('div.contentText').firstChild, 3);
 | |
|       range.setEnd(
 | |
|           element.querySelectorAll('div.contentText')[4].firstChild, 2);
 | |
|       selection.addRange(range);
 | |
|       assert.equal(element._getSelectedText('left'), 'ba\nzin\nga');
 | |
|     });
 | |
| 
 | |
|     test('copies comments', () => {
 | |
|       element.classList.add('selected-left');
 | |
|       element.classList.add('selected-comment');
 | |
|       element.classList.remove('selected-right');
 | |
|       const selection = window.getSelection();
 | |
|       selection.removeAllRanges();
 | |
|       const range = document.createRange();
 | |
|       range.setStart(
 | |
|           element.querySelector('.gr-formatted-text *').firstChild, 3);
 | |
|       range.setEnd(
 | |
|           element.querySelectorAll('.gr-formatted-text *')[2].childNodes[2], 7);
 | |
|       selection.addRange(range);
 | |
|       assert.equal('s is a comment\nThis is a differ',
 | |
|           element._getSelectedText('left', true));
 | |
|     });
 | |
| 
 | |
|     test('respects astral chars in comments', () => {
 | |
|       element.classList.add('selected-left');
 | |
|       element.classList.add('selected-comment');
 | |
|       element.classList.remove('selected-right');
 | |
|       const selection = window.getSelection();
 | |
|       selection.removeAllRanges();
 | |
|       const range = document.createRange();
 | |
|       const nodes = element.querySelectorAll('.gr-formatted-text *');
 | |
|       range.setStart(nodes[2].childNodes[2], 13);
 | |
|       range.setEnd(nodes[2].childNodes[2], 23);
 | |
|       selection.addRange(range);
 | |
|       assert.equal('mment 💩 u',
 | |
|           element._getSelectedText('left', true));
 | |
|     });
 | |
| 
 | |
|     test('defers to default behavior for textarea', () => {
 | |
|       element.classList.add('selected-left');
 | |
|       element.classList.remove('selected-right');
 | |
|       const selectedTextSpy = sandbox.spy(element, '_getSelectedText');
 | |
|       emulateCopyOn(element.querySelector('textarea'));
 | |
|       assert.isFalse(selectedTextSpy.called);
 | |
|     });
 | |
| 
 | |
|     test('regression test for 4794', () => {
 | |
|       element._cachedDiffBuilder.getLineElByChild = function(child) {
 | |
|         while (!child.classList.contains('content') && child.parentElement) {
 | |
|           child = child.parentElement;
 | |
|         }
 | |
|         return child.previousElementSibling;
 | |
|       };
 | |
| 
 | |
|       element.classList.add('selected-right');
 | |
|       element.classList.remove('selected-left');
 | |
| 
 | |
|       const selection = window.getSelection();
 | |
|       selection.removeAllRanges();
 | |
|       const range = document.createRange();
 | |
|       range.setStart(
 | |
|           element.querySelectorAll('div.contentText')[1].firstChild, 4);
 | |
|       range.setEnd(
 | |
|           element.querySelectorAll('div.contentText')[1].firstChild, 10);
 | |
|       selection.addRange(range);
 | |
|       assert.equal(element._getSelectedText('right'), ' other');
 | |
|     });
 | |
| 
 | |
|     test('copies to end of side (issue 7895)', () => {
 | |
|       element._cachedDiffBuilder.getLineElByChild = function(child) {
 | |
|         // Return null for the end container.
 | |
|         if (child.textContent === 'ga ga') { return null; }
 | |
|         while (!child.classList.contains('content') && child.parentElement) {
 | |
|           child = child.parentElement;
 | |
|         }
 | |
|         return child.previousElementSibling;
 | |
|       };
 | |
|       element.classList.add('selected-left');
 | |
|       element.classList.remove('selected-right');
 | |
|       const selection = window.getSelection();
 | |
|       selection.removeAllRanges();
 | |
|       const range = document.createRange();
 | |
|       range.setStart(element.querySelector('div.contentText').firstChild, 3);
 | |
|       range.setEnd(
 | |
|           element.querySelectorAll('div.contentText')[4].firstChild, 2);
 | |
|       selection.addRange(range);
 | |
|       assert.equal(element._getSelectedText('left'), 'ba\nzin\nga');
 | |
|     });
 | |
| 
 | |
|     suite('_getTextContentForRange', () => {
 | |
|       let selection;
 | |
|       let range;
 | |
|       let nodes;
 | |
| 
 | |
|       setup(() => {
 | |
|         element.classList.add('selected-left');
 | |
|         element.classList.add('selected-comment');
 | |
|         element.classList.remove('selected-right');
 | |
|         selection = window.getSelection();
 | |
|         selection.removeAllRanges();
 | |
|         range = document.createRange();
 | |
|         nodes = element.querySelectorAll('.gr-formatted-text *');
 | |
|       });
 | |
| 
 | |
|       test('multi level element contained in range', () => {
 | |
|         range.setStart(nodes[2].childNodes[0], 1);
 | |
|         range.setEnd(nodes[2].childNodes[2], 7);
 | |
|         selection.addRange(range);
 | |
|         assert.equal(element._getTextContentForRange(element, selection, range),
 | |
|             'his is a differ');
 | |
|       });
 | |
| 
 | |
| 
 | |
|       test('multi level element as startContainer of range', () => {
 | |
|         range.setStart(nodes[2].childNodes[1], 0);
 | |
|         range.setEnd(nodes[2].childNodes[2], 7);
 | |
|         selection.addRange(range);
 | |
|         assert.equal(element._getTextContentForRange(element, selection, range),
 | |
|             'a differ');
 | |
|       });
 | |
| 
 | |
|       test('startContainer === endContainer', () => {
 | |
|         range.setStart(nodes[0].firstChild, 2);
 | |
|         range.setEnd(nodes[0].firstChild, 12);
 | |
|         selection.addRange(range);
 | |
|         assert.equal(element._getTextContentForRange(element, selection, range),
 | |
|             'is is a co');
 | |
|       });
 | |
|     });
 | |
| 
 | |
|     test('cache is reset when diff changes', () => {
 | |
|       element._linesCache = {left: 'test', right: 'test'};
 | |
|       element.diff = {};
 | |
|       flushAsynchronousOperations();
 | |
|       assert.deepEqual(element._linesCache, {left: null, right: null});
 | |
|     });
 | |
|   });
 | |
| </script>
 |