|
| 1 | +/** |
| 2 | + * @license MIT |
| 3 | + */ |
| 4 | +import jsdom = require('jsdom'); |
| 5 | +import { assert } from 'chai'; |
| 6 | +import { ITerminal } from './Interfaces'; |
| 7 | +import { CharMeasure } from './utils/CharMeasure'; |
| 8 | +import { CircularList } from './utils/CircularList'; |
| 9 | +import { SelectionManager } from './SelectionManager'; |
| 10 | +import { SelectionModel } from './SelectionModel'; |
| 11 | + |
| 12 | +class TestSelectionManager extends SelectionManager { |
| 13 | + constructor( |
| 14 | + terminal: ITerminal, |
| 15 | + buffer: CircularList<any>, |
| 16 | + rowContainer: HTMLElement, |
| 17 | + charMeasure: CharMeasure |
| 18 | + ) { |
| 19 | + super(terminal, buffer, rowContainer, charMeasure); |
| 20 | + } |
| 21 | + |
| 22 | + public get model(): SelectionModel { return this._model; } |
| 23 | + |
| 24 | + public selectLineAt(line: number): void { this._selectLineAt(line); } |
| 25 | + public selectWordAt(coords: [number, number]): void { this._selectWordAt(coords); } |
| 26 | + |
| 27 | + // Disable DOM interaction |
| 28 | + public enable(): void {} |
| 29 | + public disable(): void {} |
| 30 | + public refresh(): void {} |
| 31 | +} |
| 32 | + |
| 33 | +describe('SelectionManager', () => { |
| 34 | + let window: Window; |
| 35 | + let document: Document; |
| 36 | + |
| 37 | + let terminal: ITerminal; |
| 38 | + let buffer: CircularList<any>; |
| 39 | + let rowContainer: HTMLElement; |
| 40 | + let selectionManager: TestSelectionManager; |
| 41 | + |
| 42 | + beforeEach(done => { |
| 43 | + jsdom.env('', (err, w) => { |
| 44 | + window = w; |
| 45 | + document = window.document; |
| 46 | + buffer = new CircularList<any>(100); |
| 47 | + terminal = <any>{ cols: 80, rows: 2 }; |
| 48 | + selectionManager = new TestSelectionManager(terminal, buffer, rowContainer, null); |
| 49 | + done(); |
| 50 | + }); |
| 51 | + }); |
| 52 | + |
| 53 | + function stringToRow(text: string): [number, string, number][] { |
| 54 | + let result: [number, string, number][] = []; |
| 55 | + for (let i = 0; i < text.length; i++) { |
| 56 | + result.push([0, text.charAt(i), 1]); |
| 57 | + } |
| 58 | + return result; |
| 59 | + } |
| 60 | + |
| 61 | + describe('_selectWordAt', () => { |
| 62 | + it('should expand selection for normal width chars', () => { |
| 63 | + buffer.push(stringToRow('foo bar')); |
| 64 | + selectionManager.selectWordAt([0, 0]); |
| 65 | + assert.equal(selectionManager.selectionText, 'foo'); |
| 66 | + selectionManager.selectWordAt([1, 0]); |
| 67 | + assert.equal(selectionManager.selectionText, 'foo'); |
| 68 | + selectionManager.selectWordAt([2, 0]); |
| 69 | + assert.equal(selectionManager.selectionText, 'foo'); |
| 70 | + selectionManager.selectWordAt([3, 0]); |
| 71 | + assert.equal(selectionManager.selectionText, ' '); |
| 72 | + selectionManager.selectWordAt([4, 0]); |
| 73 | + assert.equal(selectionManager.selectionText, 'bar'); |
| 74 | + selectionManager.selectWordAt([5, 0]); |
| 75 | + assert.equal(selectionManager.selectionText, 'bar'); |
| 76 | + selectionManager.selectWordAt([6, 0]); |
| 77 | + assert.equal(selectionManager.selectionText, 'bar'); |
| 78 | + }); |
| 79 | + it('should expand selection for whitespace', () => { |
| 80 | + buffer.push(stringToRow('a b')); |
| 81 | + selectionManager.selectWordAt([0, 0]); |
| 82 | + assert.equal(selectionManager.selectionText, 'a'); |
| 83 | + selectionManager.selectWordAt([1, 0]); |
| 84 | + assert.equal(selectionManager.selectionText, ' '); |
| 85 | + selectionManager.selectWordAt([2, 0]); |
| 86 | + assert.equal(selectionManager.selectionText, ' '); |
| 87 | + selectionManager.selectWordAt([3, 0]); |
| 88 | + assert.equal(selectionManager.selectionText, ' '); |
| 89 | + selectionManager.selectWordAt([4, 0]); |
| 90 | + assert.equal(selectionManager.selectionText, 'b'); |
| 91 | + }); |
| 92 | + it('should expand selection for wide characters', () => { |
| 93 | + // Wide characters use a special format |
| 94 | + buffer.push([ |
| 95 | + [null, '中', 2], |
| 96 | + [null, '', 0], |
| 97 | + [null, '文', 2], |
| 98 | + [null, '', 0], |
| 99 | + [null, ' ', 1], |
| 100 | + [null, 'a', 1], |
| 101 | + [null, '中', 2], |
| 102 | + [null, '', 0], |
| 103 | + [null, '文', 2], |
| 104 | + [null, '', 0], |
| 105 | + [null, 'b', 1], |
| 106 | + [null, ' ', 1], |
| 107 | + [null, 'f', 1], |
| 108 | + [null, 'o', 1], |
| 109 | + [null, 'o', 1] |
| 110 | + ]); |
| 111 | + // Ensure wide characters take up 2 columns |
| 112 | + selectionManager.selectWordAt([0, 0]); |
| 113 | + assert.equal(selectionManager.selectionText, '中文'); |
| 114 | + selectionManager.selectWordAt([1, 0]); |
| 115 | + assert.equal(selectionManager.selectionText, '中文'); |
| 116 | + selectionManager.selectWordAt([2, 0]); |
| 117 | + assert.equal(selectionManager.selectionText, '中文'); |
| 118 | + selectionManager.selectWordAt([3, 0]); |
| 119 | + assert.equal(selectionManager.selectionText, '中文'); |
| 120 | + selectionManager.selectWordAt([4, 0]); |
| 121 | + assert.equal(selectionManager.selectionText, ' '); |
| 122 | + // Ensure wide characters work when wrapped in normal width characters |
| 123 | + selectionManager.selectWordAt([5, 0]); |
| 124 | + assert.equal(selectionManager.selectionText, 'a中文b'); |
| 125 | + selectionManager.selectWordAt([6, 0]); |
| 126 | + assert.equal(selectionManager.selectionText, 'a中文b'); |
| 127 | + selectionManager.selectWordAt([7, 0]); |
| 128 | + assert.equal(selectionManager.selectionText, 'a中文b'); |
| 129 | + selectionManager.selectWordAt([8, 0]); |
| 130 | + assert.equal(selectionManager.selectionText, 'a中文b'); |
| 131 | + selectionManager.selectWordAt([9, 0]); |
| 132 | + assert.equal(selectionManager.selectionText, 'a中文b'); |
| 133 | + selectionManager.selectWordAt([10, 0]); |
| 134 | + assert.equal(selectionManager.selectionText, 'a中文b'); |
| 135 | + selectionManager.selectWordAt([11, 0]); |
| 136 | + assert.equal(selectionManager.selectionText, ' '); |
| 137 | + // Ensure normal width characters work fine in a line containing wide characters |
| 138 | + selectionManager.selectWordAt([12, 0]); |
| 139 | + assert.equal(selectionManager.selectionText, 'foo'); |
| 140 | + selectionManager.selectWordAt([13, 0]); |
| 141 | + assert.equal(selectionManager.selectionText, 'foo'); |
| 142 | + selectionManager.selectWordAt([14, 0]); |
| 143 | + assert.equal(selectionManager.selectionText, 'foo'); |
| 144 | + }); |
| 145 | + }); |
| 146 | + |
| 147 | + describe('_selectLineAt', () => { |
| 148 | + it('should select the entire line', () => { |
| 149 | + buffer.push(stringToRow('foo bar')); |
| 150 | + selectionManager.selectLineAt(0); |
| 151 | + assert.equal(selectionManager.selectionText, 'foo bar', 'The selected text is correct'); |
| 152 | + assert.deepEqual(selectionManager.model.finalSelectionStart, [0, 0]); |
| 153 | + assert.deepEqual(selectionManager.model.finalSelectionEnd, [terminal.cols, 0], 'The actual selection spans the entire column'); |
| 154 | + }); |
| 155 | + }); |
| 156 | + |
| 157 | + describe('selectAll', () => { |
| 158 | + it('should select the entire buffer, beyond the viewport', () => { |
| 159 | + buffer.push(stringToRow('1')); |
| 160 | + buffer.push(stringToRow('2')); |
| 161 | + buffer.push(stringToRow('3')); |
| 162 | + buffer.push(stringToRow('4')); |
| 163 | + buffer.push(stringToRow('5')); |
| 164 | + selectionManager.selectAll(); |
| 165 | + terminal.ybase = buffer.length - terminal.rows; |
| 166 | + assert.equal(selectionManager.selectionText, '1\n2\n3\n4\n5'); |
| 167 | + }); |
| 168 | + }); |
| 169 | +}); |
0 commit comments