From 03bfd2c842d9947544e19a35e3622ff6771033fc Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 26 Apr 2020 10:59:32 -0700 Subject: [PATCH] Move Terminal*.test into browser --- bin/test.js | 1 - src/TestUtils.test.ts | 326 ---------------------------- src/{ => browser}/Terminal.test.ts | 288 ++++++++++++------------ src/{ => browser}/Terminal2.test.ts | 6 +- src/browser/TestUtils.test.ts | 324 ++++++++++++++++++++++++++- 5 files changed, 468 insertions(+), 477 deletions(-) delete mode 100644 src/TestUtils.test.ts rename src/{ => browser}/Terminal.test.ts (80%) rename src/{ => browser}/Terminal2.test.ts (96%) diff --git a/bin/test.js b/bin/test.js index 1380a512..b9725acd 100644 --- a/bin/test.js +++ b/bin/test.js @@ -13,7 +13,6 @@ const env = { ...process.env }; env.NODE_PATH = path.resolve(__dirname, '../out'); let testFiles = [ - './out/*test.js', './out/**/*test.js', './addons/**/out/*test.js', ]; diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts deleted file mode 100644 index 102a5353..00000000 --- a/src/TestUtils.test.ts +++ /dev/null @@ -1,326 +0,0 @@ -/** - * Copyright (c) 2017 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types'; -import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types'; -import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, ITerminalOptions } from 'common/Types'; -import { Buffer } from 'common/buffer/Buffer'; -import * as Browser from 'common/Platform'; -import { IDisposable, IMarker, IEvent, ISelectionPosition, ILinkProvider } from 'xterm'; -import { Terminal } from './browser/Terminal'; -import { AttributeData } from 'common/buffer/AttributeData'; -import { IColorManager, IColorSet, ILinkMatcherOptions, ILinkifier, IViewport, ILinkifier2, ICompositionHelper, ITerminal, IBrowser } from 'browser/Types'; -import { IOptionsService, IUnicodeService } from 'common/services/Services'; -import { IParams, IFunctionIdentifier } from 'common/parser/Types'; -import { ISelectionService } from 'browser/services/Services'; - -export class TestTerminal extends Terminal { - public get curAttrData(): IAttributeData { return (this as any)._inputHandler._curAttrData; } - public keyDown(ev: any): boolean { return this._keyDown(ev); } - public keyPress(ev: any): boolean { return this._keyPress(ev); } -} - -export class MockTerminal implements ITerminal { - public onBlur: IEvent; - public onFocus: IEvent; - public onA11yChar: IEvent; - public onA11yTab: IEvent; - public onCursorMove: IEvent; - public onLineFeed: IEvent; - public onSelectionChange: IEvent; - public onData: IEvent; - public onBinary: IEvent; - public onTitleChange: IEvent; - public onScroll: IEvent; - public onKey: IEvent<{ key: string, domEvent: KeyboardEvent }>; - public onRender: IEvent<{ start: number, end: number }>; - public onResize: IEvent<{ cols: number, rows: number }>; - public markers: IMarker[]; - public optionsService: IOptionsService; - public unicodeService: IUnicodeService; - public addMarker(cursorYOffset: number): IMarker { - throw new Error('Method not implemented.'); - } - public selectLines(start: number, end: number): void { - throw new Error('Method not implemented.'); - } - public scrollToLine(line: number): void { - throw new Error('Method not implemented.'); - } - public static string: any; - public setOption(key: any, value: any): void { - throw new Error('Method not implemented.'); - } - public blur(): void { - throw new Error('Method not implemented.'); - } - public focus(): void { - throw new Error('Method not implemented.'); - } - public resize(columns: number, rows: number): void { - throw new Error('Method not implemented.'); - } - public writeln(data: string): void { - throw new Error('Method not implemented.'); - } - public paste(data: string): void { - throw new Error('Method not implemented.'); - } - public open(parent: HTMLElement): void { - throw new Error('Method not implemented.'); - } - public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void { - throw new Error('Method not implemented.'); - } - public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable { - throw new Error('Method not implemented.'); - } - public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable { - throw new Error('Method not implemented.'); - } - public addEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable { - throw new Error('Method not implemented.'); - } - public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable { - throw new Error('Method not implemented.'); - } - public registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void, options?: ILinkMatcherOptions): number { - throw new Error('Method not implemented.'); - } - public deregisterLinkMatcher(matcherId: number): void { - throw new Error('Method not implemented.'); - } - public registerLinkProvider(linkProvider: ILinkProvider): IDisposable { - throw new Error('Method not implemented.'); - } - public hasSelection(): boolean { - throw new Error('Method not implemented.'); - } - public getSelection(): string { - throw new Error('Method not implemented.'); - } - public getSelectionPosition(): ISelectionPosition | undefined { - throw new Error('Method not implemented.'); - } - public clearSelection(): void { - throw new Error('Method not implemented.'); - } - public select(column: number, row: number, length: number): void { - throw new Error('Method not implemented.'); - } - public selectAll(): void { - throw new Error('Method not implemented.'); - } - public dispose(): void { - throw new Error('Method not implemented.'); - } - public scrollPages(pageCount: number): void { - throw new Error('Method not implemented.'); - } - public scrollToTop(): void { - throw new Error('Method not implemented.'); - } - public scrollToBottom(): void { - throw new Error('Method not implemented.'); - } - public clear(): void { - throw new Error('Method not implemented.'); - } - public write(data: string): void { - throw new Error('Method not implemented.'); - } - public writeUtf8(data: Uint8Array): void { - throw new Error('Method not implemented.'); - } - public bracketedPasteMode: boolean; - public renderer: IRenderer; - public linkifier: ILinkifier; - public linkifier2: ILinkifier2; - public isFocused: boolean; - public options: ITerminalOptions = {}; - public element: HTMLElement; - public screenElement: HTMLElement; - public rowContainer: HTMLElement; - public selectionContainer: HTMLElement; - public selectionService: ISelectionService; - public textarea: HTMLTextAreaElement; - public rows: number; - public cols: number; - public browser: IBrowser = Browser; - public writeBuffer: string[]; - public children: HTMLElement[]; - public cursorHidden: boolean; - public cursorState: number; - public scrollback: number; - public buffers: IBufferSet; - public buffer: IBuffer; - public viewport: IViewport; - public applicationCursor: boolean; - public handler(data: string): void { - throw new Error('Method not implemented.'); - } - public on(event: string, callback: (...args: any[]) => void): void { - throw new Error('Method not implemented.'); - } - public off(type: string, listener: XtermListener): void { - throw new Error('Method not implemented.'); - } - public addDisposableListener(type: string, handler: XtermListener): IDisposable { - throw new Error('Method not implemented.'); - } - public scrollLines(disp: number): void { - throw new Error('Method not implemented.'); - } - public scrollToRow(absoluteRow: number): number { - throw new Error('Method not implemented.'); - } - public cancel(ev: Event, force?: boolean): void { - throw new Error('Method not implemented.'); - } - public log(text: string): void { - throw new Error('Method not implemented.'); - } - public emit(event: string, data: any): void { - throw new Error('Method not implemented.'); - } - public reset(): void { - throw new Error('Method not implemented.'); - } - public refresh(start: number, end: number): void { - throw new Error('Method not implemented.'); - } - public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } - public deregisterCharacterJoiner(joinerId: number): void { } -} - -export class MockBuffer implements IBuffer { - public markers: IMarker[]; - public addMarker(y: number): IMarker { - throw new Error('Method not implemented.'); - } - public isCursorInViewport: boolean; - public lines: ICircularList; - public ydisp: number; - public ybase: number; - public hasScrollback: boolean; - public y: number; - public x: number; - public tabs: any; - public scrollBottom: number; - public scrollTop: number; - public savedY: number; - public savedX: number; - public savedCharset: ICharset | null; - public savedCurAttrData = new AttributeData(); - public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string { - return Buffer.prototype.translateBufferLineToString.apply(this, arguments); - } - public getWrappedRangeForLine(y: number): { first: number, last: number } { - return Buffer.prototype.getWrappedRangeForLine.apply(this, arguments); - } - public nextStop(x?: number): number { - throw new Error('Method not implemented.'); - } - public prevStop(x?: number): number { - throw new Error('Method not implemented.'); - } - public setLines(lines: ICircularList): void { - this.lines = lines; - } - public getBlankLine(attr: IAttributeData, isWrapped?: boolean): IBufferLine { - return Buffer.prototype.getBlankLine.apply(this, arguments); - } - public stringIndexToBufferIndex(lineIndex: number, stringIndex: number): number[] { - return Buffer.prototype.stringIndexToBufferIndex.apply(this, arguments); - } - public iterator(trimRight: boolean, startIndex?: number, endIndex?: number): IBufferStringIterator { - return Buffer.prototype.iterator.apply(this, arguments); - } - public getNullCell(attr?: IAttributeData): ICellData { - throw new Error('Method not implemented.'); - } - public getWhitespaceCell(attr?: IAttributeData): ICellData { - throw new Error('Method not implemented.'); - } -} - -export class MockRenderer implements IRenderer { - public onRequestRedraw: IEvent; - public onCanvasResize: IEvent<{ width: number, height: number }>; - public onRender: IEvent<{ start: number, end: number }>; - public dispose(): void { - throw new Error('Method not implemented.'); - } - public colorManager: IColorManager; - public on(type: string, listener: XtermListener): void { - throw new Error('Method not implemented.'); - } - public off(type: string, listener: XtermListener): void { - throw new Error('Method not implemented.'); - } - public emit(type: string, data?: any): void { - throw new Error('Method not implemented.'); - } - public addDisposableListener(type: string, handler: XtermListener): IDisposable { - throw new Error('Method not implemented.'); - } - public dimensions: IRenderDimensions; - public setColors(colors: IColorSet): void { - throw new Error('Method not implemented.'); - } - public onResize(cols: number, rows: number): void { } - public onCharSizeChanged(): void { } - public onBlur(): void { } - public onFocus(): void { } - public onSelectionChanged(start: [number, number], end: [number, number]): void { } - public onCursorMove(): void { } - public onOptionsChanged(): void { } - public onDevicePixelRatioChange(): void { } - public clear(): void { } - public renderRows(start: number, end: number): void { } - public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } - public deregisterCharacterJoiner(): boolean { return true; } -} - -export class MockViewport implements IViewport { - public dispose(): void { - throw new Error('Method not implemented.'); - } - public scrollBarWidth: number = 0; - public onThemeChange(colors: IColorSet): void { - throw new Error('Method not implemented.'); - } - public onWheel(ev: WheelEvent): boolean { - throw new Error('Method not implemented.'); - } - public onTouchStart(ev: TouchEvent): void { - throw new Error('Method not implemented.'); - } - public onTouchMove(ev: TouchEvent): boolean { - throw new Error('Method not implemented.'); - } - public syncScrollArea(): void { } - public getLinesScrolled(ev: WheelEvent): number { - throw new Error('Method not implemented.'); - } -} - -export class MockCompositionHelper implements ICompositionHelper { - public compositionstart(): void { - throw new Error('Method not implemented.'); - } - public compositionupdate(ev: CompositionEvent): void { - throw new Error('Method not implemented.'); - } - public compositionend(): void { - throw new Error('Method not implemented.'); - } - public updateCompositionElements(dontRecurse?: boolean): void { - throw new Error('Method not implemented.'); - } - public keydown(ev: KeyboardEvent): boolean { - return true; - } -} diff --git a/src/Terminal.test.ts b/src/browser/Terminal.test.ts similarity index 80% rename from src/Terminal.test.ts rename to src/browser/Terminal.test.ts index 6488aa43..729c0d0f 100644 --- a/src/Terminal.test.ts +++ b/src/browser/Terminal.test.ts @@ -4,7 +4,7 @@ */ import { assert, expect } from 'chai'; -import { MockViewport, MockCompositionHelper, MockRenderer, TestTerminal } from './TestUtils.test'; +import { MockViewport, MockCompositionHelper, MockRenderer, TestTerminal } from 'browser/TestUtils.test'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { CellData } from 'common/buffer/CellData'; import { IBufferService, IUnicodeService } from 'common/services/Services'; @@ -395,62 +395,62 @@ describe('Terminal', () => { describe('scroll() function', () => { describe('when scrollback > 0', () => { it('should create a new line and scroll', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(INIT_ROWS - 1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(INIT_ROWS - 1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS + 1); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a'); - assert.equal(term.buffer.lines.get(INIT_ROWS - 1).loadCell(0, new CellData()).getChars(), 'b'); - assert.equal(term.buffer.lines.get(INIT_ROWS).loadCell(0, new CellData()).getChars(), ''); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a'); + assert.equal(term.buffer.lines.get(INIT_ROWS - 1)!.loadCell(0, new CellData()).getChars(), 'b'); + assert.equal(term.buffer.lines.get(INIT_ROWS)!.loadCell(0, new CellData()).getChars(), ''); }); it('should properly scroll inside a scroll region (scrollTop set)', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.buffer.scrollTop = 1; term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c'); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c'); }); it('should properly scroll inside a scroll region (scrollBottom set)', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); - term.buffer.lines.get(3).setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); - term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(3)!.setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); + term.buffer.lines.get(4)!.setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); term.buffer.y = 3; term.buffer.scrollBottom = 3; term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS + 1); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a', '\'a\' should be pushed to the scrollback'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'b'); - assert.equal(term.buffer.lines.get(2).loadCell(0, new CellData()).getChars(), 'c'); - assert.equal(term.buffer.lines.get(3).loadCell(0, new CellData()).getChars(), 'd'); - assert.equal(term.buffer.lines.get(4).loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); - assert.equal(term.buffer.lines.get(5).loadCell(0, new CellData()).getChars(), 'e'); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a', '\'a\' should be pushed to the scrollback'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'b'); + assert.equal(term.buffer.lines.get(2)!.loadCell(0, new CellData()).getChars(), 'c'); + assert.equal(term.buffer.lines.get(3)!.loadCell(0, new CellData()).getChars(), 'd'); + assert.equal(term.buffer.lines.get(4)!.loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); + assert.equal(term.buffer.lines.get(5)!.loadCell(0, new CellData()).getChars(), 'e'); }); it('should properly scroll inside a scroll region (scrollTop and scrollBottom set)', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); - term.buffer.lines.get(3).setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); - term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(3)!.setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); + term.buffer.lines.get(4)!.setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.buffer.scrollTop = 1; term.buffer.scrollBottom = 3; term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer'); - assert.equal(term.buffer.lines.get(2).loadCell(0, new CellData()).getChars(), 'd'); - assert.equal(term.buffer.lines.get(3).loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); - assert.equal(term.buffer.lines.get(4).loadCell(0, new CellData()).getChars(), 'e'); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer'); + assert.equal(term.buffer.lines.get(2)!.loadCell(0, new CellData()).getChars(), 'd'); + assert.equal(term.buffer.lines.get(3)!.loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); + assert.equal(term.buffer.lines.get(4)!.loadCell(0, new CellData()).getChars(), 'e'); }); }); @@ -461,65 +461,65 @@ describe('Terminal', () => { }); it('should create a new line and shift everything up', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(INIT_ROWS - 1).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(INIT_ROWS - 1)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line assert.equal(term.buffer.lines.length, INIT_ROWS); term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS); // 'a' gets pushed out of buffer - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'b'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), ''); - assert.equal(term.buffer.lines.get(INIT_ROWS - 2).loadCell(0, new CellData()).getChars(), 'c'); - assert.equal(term.buffer.lines.get(INIT_ROWS - 1).loadCell(0, new CellData()).getChars(), ''); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'b'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), ''); + assert.equal(term.buffer.lines.get(INIT_ROWS - 2)!.loadCell(0, new CellData()).getChars(), 'c'); + assert.equal(term.buffer.lines.get(INIT_ROWS - 1)!.loadCell(0, new CellData()).getChars(), ''); }); it('should properly scroll inside a scroll region (scrollTop set)', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.buffer.scrollTop = 1; term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c'); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c'); }); it('should properly scroll inside a scroll region (scrollBottom set)', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); - term.buffer.lines.get(3).setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); - term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(3)!.setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); + term.buffer.lines.get(4)!.setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); term.buffer.y = 3; term.buffer.scrollBottom = 3; term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'b'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c'); - assert.equal(term.buffer.lines.get(2).loadCell(0, new CellData()).getChars(), 'd'); - assert.equal(term.buffer.lines.get(3).loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); - assert.equal(term.buffer.lines.get(4).loadCell(0, new CellData()).getChars(), 'e'); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'b'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c'); + assert.equal(term.buffer.lines.get(2)!.loadCell(0, new CellData()).getChars(), 'd'); + assert.equal(term.buffer.lines.get(3)!.loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); + assert.equal(term.buffer.lines.get(4)!.loadCell(0, new CellData()).getChars(), 'e'); }); it('should properly scroll inside a scroll region (scrollTop and scrollBottom set)', () => { - term.buffer.lines.get(0).setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); - term.buffer.lines.get(1).setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); - term.buffer.lines.get(2).setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); - term.buffer.lines.get(3).setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); - term.buffer.lines.get(4).setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); + term.buffer.lines.get(0)!.setCell(0, CellData.fromCharData([0, 'a', 0, 'a'.charCodeAt(0)])); + term.buffer.lines.get(1)!.setCell(0, CellData.fromCharData([0, 'b', 0, 'b'.charCodeAt(0)])); + term.buffer.lines.get(2)!.setCell(0, CellData.fromCharData([0, 'c', 0, 'c'.charCodeAt(0)])); + term.buffer.lines.get(3)!.setCell(0, CellData.fromCharData([0, 'd', 0, 'd'.charCodeAt(0)])); + term.buffer.lines.get(4)!.setCell(0, CellData.fromCharData([0, 'e', 0, 'e'.charCodeAt(0)])); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.buffer.scrollTop = 1; term.buffer.scrollBottom = 3; term.scroll(DEFAULT_ATTR_DATA.clone()); assert.equal(term.buffer.lines.length, INIT_ROWS); - assert.equal(term.buffer.lines.get(0).loadCell(0, new CellData()).getChars(), 'a'); - assert.equal(term.buffer.lines.get(1).loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer'); - assert.equal(term.buffer.lines.get(2).loadCell(0, new CellData()).getChars(), 'd'); - assert.equal(term.buffer.lines.get(3).loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); - assert.equal(term.buffer.lines.get(4).loadCell(0, new CellData()).getChars(), 'e'); + assert.equal(term.buffer.lines.get(0)!.loadCell(0, new CellData()).getChars(), 'a'); + assert.equal(term.buffer.lines.get(1)!.loadCell(0, new CellData()).getChars(), 'c', '\'b\' should be removed from the buffer'); + assert.equal(term.buffer.lines.get(2)!.loadCell(0, new CellData()).getChars(), 'd'); + assert.equal(term.buffer.lines.get(3)!.loadCell(0, new CellData()).getChars(), '', 'a blank line should be added at scrollBottom\'s index'); + assert.equal(term.buffer.lines.get(4)!.loadCell(0, new CellData()).getChars(), 'e'); }); }); }); @@ -722,11 +722,11 @@ describe('Terminal', () => { const cell = new CellData(); for (let i = 0xDC00; i <= 0xDCFF; ++i) { term.writeSync(high + String.fromCharCode(i)); - const tchar = term.buffer.lines.get(0).loadCell(0, cell); + const tchar = term.buffer.lines.get(0)!.loadCell(0, cell); expect(tchar.getChars()).eql(high + String.fromCharCode(i)); expect(tchar.getChars().length).eql(2); expect(tchar.getWidth()).eql(1); - expect(term.buffer.lines.get(0).loadCell(1, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(1, cell).getChars()).eql(''); term.reset(); } }); @@ -736,9 +736,9 @@ describe('Terminal', () => { for (let i = 0xDC00; i <= 0xDCFF; ++i) { term.buffer.x = term.cols - 1; term.writeSync(high + String.fromCharCode(i)); - expect(term.buffer.lines.get(0).loadCell(term.buffer.x - 1, cell).getChars()).eql(high + String.fromCharCode(i)); - expect(term.buffer.lines.get(0).loadCell(term.buffer.x - 1, cell).getChars().length).eql(2); - expect(term.buffer.lines.get(1).loadCell(0, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(term.buffer.x - 1, cell).getChars()).eql(high + String.fromCharCode(i)); + expect(term.buffer.lines.get(0)!.loadCell(term.buffer.x - 1, cell).getChars().length).eql(2); + expect(term.buffer.lines.get(1)!.loadCell(0, cell).getChars()).eql(''); term.reset(); } }); @@ -749,10 +749,10 @@ describe('Terminal', () => { term.buffer.x = term.cols - 1; term.writeSync('a' + high + String.fromCharCode(i)); - expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars()).eql('a'); - expect(term.buffer.lines.get(1).loadCell(0, cell).getChars()).eql(high + String.fromCharCode(i)); - expect(term.buffer.lines.get(1).loadCell(0, cell).getChars().length).eql(2); - expect(term.buffer.lines.get(1).loadCell(1, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell).getChars()).eql('a'); + expect(term.buffer.lines.get(1)!.loadCell(0, cell).getChars()).eql(high + String.fromCharCode(i)); + expect(term.buffer.lines.get(1)!.loadCell(0, cell).getChars().length).eql(2); + expect(term.buffer.lines.get(1)!.loadCell(1, cell).getChars()).eql(''); term.reset(); } }); @@ -768,9 +768,9 @@ describe('Terminal', () => { } term.writeSync('a' + high + String.fromCharCode(i)); // auto wraparound mode should cut off the rest of the line - expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars()).eql(high + String.fromCharCode(i)); - expect(term.buffer.lines.get(0).loadCell(term.cols - 1, cell).getChars().length).eql(2); - expect(term.buffer.lines.get(1).loadCell(1, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell).getChars()).eql(high + String.fromCharCode(i)); + expect(term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell).getChars().length).eql(2); + expect(term.buffer.lines.get(1)!.loadCell(1, cell).getChars()).eql(''); term.reset(); } }); @@ -780,11 +780,11 @@ describe('Terminal', () => { for (let i = 0xDC00; i <= 0xDCFF; ++i) { term.writeSync(high); term.writeSync(String.fromCharCode(i)); - const tchar = term.buffer.lines.get(0).loadCell(0, cell); + const tchar = term.buffer.lines.get(0)!.loadCell(0, cell); expect(tchar.getChars()).eql(high + String.fromCharCode(i)); expect(tchar.getChars().length).eql(2); expect(tchar.getWidth()).eql(1); - expect(term.buffer.lines.get(0).loadCell(1, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(1, cell).getChars()).eql(''); term.reset(); } }); @@ -794,7 +794,7 @@ describe('Terminal', () => { const cell = new CellData(); it('café', () => { term.writeSync('cafe\u0301'); - term.buffer.lines.get(0).loadCell(3, cell); + term.buffer.lines.get(0)!.loadCell(3, cell); expect(cell.getChars()).eql('e\u0301'); expect(cell.getChars().length).eql(2); expect(cell.getWidth()).eql(1); @@ -802,11 +802,11 @@ describe('Terminal', () => { it('café - end of line', () => { term.buffer.x = term.cols - 1 - 3; term.writeSync('cafe\u0301'); - term.buffer.lines.get(0).loadCell(term.cols - 1, cell); + term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell); expect(cell.getChars()).eql('e\u0301'); expect(cell.getChars().length).eql(2); expect(cell.getWidth()).eql(1); - term.buffer.lines.get(0).loadCell(1, cell); + term.buffer.lines.get(0)!.loadCell(1, cell); expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); expect(cell.getWidth()).eql(1); @@ -814,12 +814,12 @@ describe('Terminal', () => { it('multiple combined é', () => { term.writeSync(Array(100).join('e\u0301')); for (let i = 0; i < term.cols; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); expect(cell.getChars()).eql('e\u0301'); expect(cell.getChars().length).eql(2); expect(cell.getWidth()).eql(1); } - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('e\u0301'); expect(cell.getChars().length).eql(2); expect(cell.getWidth()).eql(1); @@ -827,12 +827,12 @@ describe('Terminal', () => { it('multiple surrogate with combined', () => { term.writeSync(Array(100).join('\uD800\uDC00\u0301')); for (let i = 0; i < term.cols; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); expect(cell.getChars()).eql('\uD800\uDC00\u0301'); expect(cell.getChars().length).eql(3); expect(cell.getWidth()).eql(1); } - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('\uD800\uDC00\u0301'); expect(cell.getChars().length).eql(3); expect(cell.getWidth()).eql(1); @@ -855,7 +855,7 @@ describe('Terminal', () => { it('line of ¥ even', () => { term.writeSync(Array(50).join('¥')); for (let i = 0; i < term.cols; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); if (i % 2) { expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); @@ -866,7 +866,7 @@ describe('Terminal', () => { expect(cell.getWidth()).eql(2); } } - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('¥'); expect(cell.getChars().length).eql(1); expect(cell.getWidth()).eql(2); @@ -875,7 +875,7 @@ describe('Terminal', () => { term.buffer.x = 1; term.writeSync(Array(50).join('¥')); for (let i = 1; i < term.cols - 1; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); if (!(i % 2)) { expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); @@ -886,11 +886,11 @@ describe('Terminal', () => { expect(cell.getWidth()).eql(2); } } - term.buffer.lines.get(0).loadCell(term.cols - 1, cell); + term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell); expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); expect(cell.getWidth()).eql(1); - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('¥'); expect(cell.getChars().length).eql(1); expect(cell.getWidth()).eql(2); @@ -899,7 +899,7 @@ describe('Terminal', () => { term.buffer.x = 1; term.writeSync(Array(50).join('¥\u0301')); for (let i = 1; i < term.cols - 1; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); if (!(i % 2)) { expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); @@ -910,11 +910,11 @@ describe('Terminal', () => { expect(cell.getWidth()).eql(2); } } - term.buffer.lines.get(0).loadCell(term.cols - 1, cell); + term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell); expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); expect(cell.getWidth()).eql(1); - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('¥\u0301'); expect(cell.getChars().length).eql(2); expect(cell.getWidth()).eql(2); @@ -922,7 +922,7 @@ describe('Terminal', () => { it('line of ¥ with combining even', () => { term.writeSync(Array(50).join('¥\u0301')); for (let i = 0; i < term.cols; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); if (i % 2) { expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); @@ -933,7 +933,7 @@ describe('Terminal', () => { expect(cell.getWidth()).eql(2); } } - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('¥\u0301'); expect(cell.getChars().length).eql(2); expect(cell.getWidth()).eql(2); @@ -942,7 +942,7 @@ describe('Terminal', () => { term.buffer.x = 1; term.writeSync(Array(50).join('\ud843\ude6d\u0301')); for (let i = 1; i < term.cols - 1; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); if (!(i % 2)) { expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); @@ -953,11 +953,11 @@ describe('Terminal', () => { expect(cell.getWidth()).eql(2); } } - term.buffer.lines.get(0).loadCell(term.cols - 1, cell); + term.buffer.lines.get(0)!.loadCell(term.cols - 1, cell); expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); expect(cell.getWidth()).eql(1); - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('\ud843\ude6d\u0301'); expect(cell.getChars().length).eql(3); expect(cell.getWidth()).eql(2); @@ -965,7 +965,7 @@ describe('Terminal', () => { it('line of surrogate fullwidth with combining even', () => { term.writeSync(Array(50).join('\ud843\ude6d\u0301')); for (let i = 0; i < term.cols; ++i) { - term.buffer.lines.get(0).loadCell(i, cell); + term.buffer.lines.get(0)!.loadCell(i, cell); if (i % 2) { expect(cell.getChars()).eql(''); expect(cell.getChars().length).eql(0); @@ -976,7 +976,7 @@ describe('Terminal', () => { expect(cell.getWidth()).eql(2); } } - term.buffer.lines.get(1).loadCell(0, cell); + term.buffer.lines.get(1)!.loadCell(0, cell); expect(cell.getChars()).eql('\ud843\ude6d\u0301'); expect(cell.getChars().length).eql(3); expect(cell.getWidth()).eql(2); @@ -991,11 +991,11 @@ describe('Terminal', () => { term.buffer.y = 0; term.write('\x1b[4h'); term.writeSync('abcde'); - expect(term.buffer.lines.get(0).length).eql(term.cols); - expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('a'); - expect(term.buffer.lines.get(0).loadCell(14, cell).getChars()).eql('e'); - expect(term.buffer.lines.get(0).loadCell(15, cell).getChars()).eql('0'); - expect(term.buffer.lines.get(0).loadCell(79, cell).getChars()).eql('4'); + expect(term.buffer.lines.get(0)!.length).eql(term.cols); + expect(term.buffer.lines.get(0)!.loadCell(10, cell).getChars()).eql('a'); + expect(term.buffer.lines.get(0)!.loadCell(14, cell).getChars()).eql('e'); + expect(term.buffer.lines.get(0)!.loadCell(15, cell).getChars()).eql('0'); + expect(term.buffer.lines.get(0)!.loadCell(79, cell).getChars()).eql('4'); }); it('fullwidth - insert', () => { term.writeSync(Array(9).join('0123456789').slice(-80)); @@ -1003,12 +1003,12 @@ describe('Terminal', () => { term.buffer.y = 0; term.write('\x1b[4h'); term.writeSync('¥¥¥'); - expect(term.buffer.lines.get(0).length).eql(term.cols); - expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('¥'); - expect(term.buffer.lines.get(0).loadCell(11, cell).getChars()).eql(''); - expect(term.buffer.lines.get(0).loadCell(14, cell).getChars()).eql('¥'); - expect(term.buffer.lines.get(0).loadCell(15, cell).getChars()).eql(''); - expect(term.buffer.lines.get(0).loadCell(79, cell).getChars()).eql('3'); + expect(term.buffer.lines.get(0)!.length).eql(term.cols); + expect(term.buffer.lines.get(0)!.loadCell(10, cell).getChars()).eql('¥'); + expect(term.buffer.lines.get(0)!.loadCell(11, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(14, cell).getChars()).eql('¥'); + expect(term.buffer.lines.get(0)!.loadCell(15, cell).getChars()).eql(''); + expect(term.buffer.lines.get(0)!.loadCell(79, cell).getChars()).eql('3'); }); it('fullwidth - right border', () => { term.writeSync(Array(41).join('¥')); @@ -1016,15 +1016,15 @@ describe('Terminal', () => { term.buffer.y = 0; term.write('\x1b[4h'); term.writeSync('a'); - expect(term.buffer.lines.get(0).length).eql(term.cols); - expect(term.buffer.lines.get(0).loadCell(10, cell).getChars()).eql('a'); - expect(term.buffer.lines.get(0).loadCell(11, cell).getChars()).eql('¥'); - expect(term.buffer.lines.get(0).loadCell(79, cell).getChars()).eql(''); // fullwidth char got replaced + expect(term.buffer.lines.get(0)!.length).eql(term.cols); + expect(term.buffer.lines.get(0)!.loadCell(10, cell).getChars()).eql('a'); + expect(term.buffer.lines.get(0)!.loadCell(11, cell).getChars()).eql('¥'); + expect(term.buffer.lines.get(0)!.loadCell(79, cell).getChars()).eql(''); // fullwidth char got replaced term.writeSync('b'); - expect(term.buffer.lines.get(0).length).eql(term.cols); - expect(term.buffer.lines.get(0).loadCell(11, cell).getChars()).eql('b'); - expect(term.buffer.lines.get(0).loadCell(12, cell).getChars()).eql('¥'); - expect(term.buffer.lines.get(0).loadCell(79, cell).getChars()).eql(''); // empty cell after fullwidth + expect(term.buffer.lines.get(0)!.length).eql(term.cols); + expect(term.buffer.lines.get(0)!.loadCell(11, cell).getChars()).eql('b'); + expect(term.buffer.lines.get(0)!.loadCell(12, cell).getChars()).eql('¥'); + expect(term.buffer.lines.get(0)!.loadCell(79, cell).getChars()).eql(''); // empty cell after fullwidth }); }); @@ -1269,9 +1269,9 @@ describe('Terminal', () => { terminal.writeSync(input); const s = terminal.buffer.iterator(true).next().content; assert.equal(input, s); - const stringIndex = s.match(/😃/).index; + const stringIndex = s.match(/😃/)!.index!; const bufferIndex = terminal.buffer.stringIndexToBufferIndex(0, stringIndex); - assert(terminal.buffer.lines.get(bufferIndex[0]).loadCell(bufferIndex[1], new CellData()).getChars(), '😃'); + assert(terminal.buffer.lines.get(bufferIndex[0])!.loadCell(bufferIndex[1], new CellData()).getChars(), '😃'); }); it('multiline fullwidth chars with offset 1 (currently tests for broken behavior)', () => { @@ -1298,7 +1298,7 @@ describe('Terminal', () => { assert.equal(input, s); for (let i = 0; i < input.length; ++i) { const bufferIndex = terminal.buffer.stringIndexToBufferIndex(0, i, true); - assert.equal(input[i], terminal.buffer.lines.get(bufferIndex[0]).loadCell(bufferIndex[1], new CellData()).getChars()); + assert.equal(input[i], terminal.buffer.lines.get(bufferIndex[0])!.loadCell(bufferIndex[1], new CellData()).getChars()); } }); @@ -1316,7 +1316,7 @@ describe('Terminal', () => { : (i % 3 === 1) ? input.substr(i, 2) : input.substr(i - 1, 2), - terminal.buffer.lines.get(bufferIndex[0]).loadCell(bufferIndex[1], new CellData()).getChars()); + terminal.buffer.lines.get(bufferIndex[0])!.loadCell(bufferIndex[1], new CellData()).getChars()); } }); @@ -1370,15 +1370,15 @@ describe('Terminal', () => { const normalTerminal = new TestTerminal({rows: 5, cols: 10, windowsMode: false}); normalTerminal.writeSync(data.join('')); - assert.equal(normalTerminal.buffer.lines.get(0).isWrapped, false); - assert.equal(normalTerminal.buffer.lines.get(1).isWrapped, false); - assert.equal(normalTerminal.buffer.lines.get(2).isWrapped, false); + assert.equal(normalTerminal.buffer.lines.get(0)!.isWrapped, false); + assert.equal(normalTerminal.buffer.lines.get(1)!.isWrapped, false); + assert.equal(normalTerminal.buffer.lines.get(2)!.isWrapped, false); const windowsModeTerminal = new TestTerminal({rows: 5, cols: 10, windowsMode: true}); windowsModeTerminal.writeSync(data.join('')); - assert.equal(windowsModeTerminal.buffer.lines.get(0).isWrapped, false); - assert.equal(windowsModeTerminal.buffer.lines.get(1).isWrapped, true, 'This line should wrap in Windows mode as the previous line ends in a non-null character'); - assert.equal(windowsModeTerminal.buffer.lines.get(2).isWrapped, false); + assert.equal(windowsModeTerminal.buffer.lines.get(0)!.isWrapped, false); + assert.equal(windowsModeTerminal.buffer.lines.get(1)!.isWrapped, true, 'This line should wrap in Windows mode as the previous line ends in a non-null character'); + assert.equal(windowsModeTerminal.buffer.lines.get(2)!.isWrapped, false); }); it('should mark lines as wrapped when the line ends in a non-null character after a CUP', () => { @@ -1390,39 +1390,39 @@ describe('Terminal', () => { const normalTerminal = new TestTerminal({rows: 5, cols: 10, windowsMode: false}); normalTerminal.writeSync(data.join('')); - assert.equal(normalTerminal.buffer.lines.get(0).isWrapped, false); - assert.equal(normalTerminal.buffer.lines.get(1).isWrapped, false); - assert.equal(normalTerminal.buffer.lines.get(2).isWrapped, false); + assert.equal(normalTerminal.buffer.lines.get(0)!.isWrapped, false); + assert.equal(normalTerminal.buffer.lines.get(1)!.isWrapped, false); + assert.equal(normalTerminal.buffer.lines.get(2)!.isWrapped, false); const windowsModeTerminal = new TestTerminal({rows: 5, cols: 10, windowsMode: true}); windowsModeTerminal.writeSync(data.join('')); - assert.equal(windowsModeTerminal.buffer.lines.get(0).isWrapped, false); - assert.equal(windowsModeTerminal.buffer.lines.get(1).isWrapped, true, 'This line should wrap in Windows mode as the previous line ends in a non-null character'); - assert.equal(windowsModeTerminal.buffer.lines.get(2).isWrapped, false); + assert.equal(windowsModeTerminal.buffer.lines.get(0)!.isWrapped, false); + assert.equal(windowsModeTerminal.buffer.lines.get(1)!.isWrapped, true, 'This line should wrap in Windows mode as the previous line ends in a non-null character'); + assert.equal(windowsModeTerminal.buffer.lines.get(2)!.isWrapped, false); }); }); it('convertEol setting', function(): void { // not converting const termNotConverting = new TestTerminal({cols: 15, rows: 10}); termNotConverting.writeSync('Hello\nWorld'); - expect(termNotConverting.buffer.lines.get(0).translateToString(false)).equals('Hello '); - expect(termNotConverting.buffer.lines.get(1).translateToString(false)).equals(' World '); - expect(termNotConverting.buffer.lines.get(0).translateToString(true)).equals('Hello'); - expect(termNotConverting.buffer.lines.get(1).translateToString(true)).equals(' World'); + expect(termNotConverting.buffer.lines.get(0)!.translateToString(false)).equals('Hello '); + expect(termNotConverting.buffer.lines.get(1)!.translateToString(false)).equals(' World '); + expect(termNotConverting.buffer.lines.get(0)!.translateToString(true)).equals('Hello'); + expect(termNotConverting.buffer.lines.get(1)!.translateToString(true)).equals(' World'); // converting const termConverting = new TestTerminal({cols: 15, rows: 10, convertEol: true}); termConverting.writeSync('Hello\nWorld'); - expect(termConverting.buffer.lines.get(0).translateToString(false)).equals('Hello '); - expect(termConverting.buffer.lines.get(1).translateToString(false)).equals('World '); - expect(termConverting.buffer.lines.get(0).translateToString(true)).equals('Hello'); - expect(termConverting.buffer.lines.get(1).translateToString(true)).equals('World'); + expect(termConverting.buffer.lines.get(0)!.translateToString(false)).equals('Hello '); + expect(termConverting.buffer.lines.get(1)!.translateToString(false)).equals('World '); + expect(termConverting.buffer.lines.get(0)!.translateToString(true)).equals('Hello'); + expect(termConverting.buffer.lines.get(1)!.translateToString(true)).equals('World'); }); describe('Terminal InputHandler integration', () => { function getLines(term: TestTerminal, limit: number = term.rows): string[] { const res: string[] = []; for (let i = 0; i < limit; ++i) { - res.push(term.buffer.lines.get(i).translateToString(true)); + res.push(term.buffer.lines.get(i)!.translateToString(true)); } return res; } diff --git a/src/Terminal2.test.ts b/src/browser/Terminal2.test.ts similarity index 96% rename from src/Terminal2.test.ts rename to src/browser/Terminal2.test.ts index 720ea6b1..32a47b21 100644 --- a/src/Terminal2.test.ts +++ b/src/browser/Terminal2.test.ts @@ -8,14 +8,14 @@ import * as path from 'path'; import * as os from 'os'; import * as fs from 'fs'; import * as pty from 'node-pty'; -import { Terminal } from './browser/Terminal'; +import { Terminal } from 'browser/Terminal'; import { IDisposable } from 'xterm'; // all test files expect terminal in 80x25 const COLS = 80; const ROWS = 25; -const TESTFILES = glob.sync('**/escape_sequence_files/*.in', { cwd: path.join(__dirname, '..')}); +const TESTFILES = glob.sync('**/escape_sequence_files/*.in', { cwd: path.join(__dirname, '../..')}); const SKIP_FILES = [ 't0084-CBT.in', 't0101-NLM.in', @@ -124,7 +124,7 @@ function terminalToString(term: Terminal): string { let result = ''; let lineText = ''; for (let line = term.buffer.ybase; line < term.buffer.ybase + term.rows; line++) { - lineText = term.buffer.lines.get(line).translateToString(true); + lineText = term.buffer.lines.get(line)!.translateToString(true); // rtrim empty cells as xterm does lineText = lineText.replace(/\s+$/, ''); result += lineText; diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 1869ab87..2d6f6cbb 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -3,10 +3,328 @@ * @license MIT */ +import { IDisposable, IMarker, ISelectionPosition, ILinkProvider } from 'xterm'; import { IEvent, EventEmitter } from 'common/EventEmitter'; -import { ICharSizeService, IMouseService, IRenderService } from 'browser/services/Services'; -import { IRenderDimensions, IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types'; -import { IColorSet } from 'browser/Types'; +import { ICharSizeService, IMouseService, IRenderService, ISelectionService } from 'browser/services/Services'; +import { IRenderDimensions, IRenderer, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types'; +import { IColorSet, ILinkMatcherOptions, ITerminal, ILinkifier, ILinkifier2, IBrowser, IViewport, IColorManager, ICompositionHelper } from 'browser/Types'; +import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types'; +import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, ITerminalOptions } from 'common/Types'; +import { Buffer } from 'common/buffer/Buffer'; +import * as Browser from 'common/Platform'; +import { Terminal } from 'browser/Terminal'; +import { IUnicodeService, IOptionsService } from 'common/services/Services'; +import { IFunctionIdentifier, IParams } from 'common/parser/Types'; +import { AttributeData } from 'common/buffer/AttributeData'; + +export class TestTerminal extends Terminal { + public get curAttrData(): IAttributeData { return (this as any)._inputHandler._curAttrData; } + public keyDown(ev: any): boolean | undefined { return this._keyDown(ev); } + public keyPress(ev: any): boolean { return this._keyPress(ev); } +} + +export class MockTerminal implements ITerminal { + public onBlur!: IEvent; + public onFocus!: IEvent; + public onA11yChar!: IEvent; + public onA11yTab!: IEvent; + public onCursorMove!: IEvent; + public onLineFeed!: IEvent; + public onSelectionChange!: IEvent; + public onData!: IEvent; + public onBinary!: IEvent; + public onTitleChange!: IEvent; + public onScroll!: IEvent; + public onKey!: IEvent<{ key: string, domEvent: KeyboardEvent }>; + public onRender!: IEvent<{ start: number, end: number }>; + public onResize!: IEvent<{ cols: number, rows: number }>; + public markers!: IMarker[]; + public optionsService!: IOptionsService; + public unicodeService!: IUnicodeService; + public addMarker(cursorYOffset: number): IMarker { + throw new Error('Method not implemented.'); + } + public selectLines(start: number, end: number): void { + throw new Error('Method not implemented.'); + } + public scrollToLine(line: number): void { + throw new Error('Method not implemented.'); + } + public static string: any; + public setOption(key: any, value: any): void { + throw new Error('Method not implemented.'); + } + public blur(): void { + throw new Error('Method not implemented.'); + } + public focus(): void { + throw new Error('Method not implemented.'); + } + public resize(columns: number, rows: number): void { + throw new Error('Method not implemented.'); + } + public writeln(data: string): void { + throw new Error('Method not implemented.'); + } + public paste(data: string): void { + throw new Error('Method not implemented.'); + } + public open(parent: HTMLElement): void { + throw new Error('Method not implemented.'); + } + public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void { + throw new Error('Method not implemented.'); + } + public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable { + throw new Error('Method not implemented.'); + } + public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable { + throw new Error('Method not implemented.'); + } + public addEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable { + throw new Error('Method not implemented.'); + } + public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable { + throw new Error('Method not implemented.'); + } + public registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void, options?: ILinkMatcherOptions): number { + throw new Error('Method not implemented.'); + } + public deregisterLinkMatcher(matcherId: number): void { + throw new Error('Method not implemented.'); + } + public registerLinkProvider(linkProvider: ILinkProvider): IDisposable { + throw new Error('Method not implemented.'); + } + public hasSelection(): boolean { + throw new Error('Method not implemented.'); + } + public getSelection(): string { + throw new Error('Method not implemented.'); + } + public getSelectionPosition(): ISelectionPosition | undefined { + throw new Error('Method not implemented.'); + } + public clearSelection(): void { + throw new Error('Method not implemented.'); + } + public select(column: number, row: number, length: number): void { + throw new Error('Method not implemented.'); + } + public selectAll(): void { + throw new Error('Method not implemented.'); + } + public dispose(): void { + throw new Error('Method not implemented.'); + } + public scrollPages(pageCount: number): void { + throw new Error('Method not implemented.'); + } + public scrollToTop(): void { + throw new Error('Method not implemented.'); + } + public scrollToBottom(): void { + throw new Error('Method not implemented.'); + } + public clear(): void { + throw new Error('Method not implemented.'); + } + public write(data: string): void { + throw new Error('Method not implemented.'); + } + public writeUtf8(data: Uint8Array): void { + throw new Error('Method not implemented.'); + } + public bracketedPasteMode!: boolean; + public renderer!: IRenderer; + public linkifier!: ILinkifier; + public linkifier2!: ILinkifier2; + public isFocused!: boolean; + public options: ITerminalOptions = {}; + public element!: HTMLElement; + public screenElement!: HTMLElement; + public rowContainer!: HTMLElement; + public selectionContainer!: HTMLElement; + public selectionService!: ISelectionService; + public textarea!: HTMLTextAreaElement; + public rows!: number; + public cols!: number; + public browser: IBrowser = Browser; + public writeBuffer!: string[]; + public children!: HTMLElement[]; + public cursorHidden!: boolean; + public cursorState!: number; + public scrollback!: number; + public buffers!: IBufferSet; + public buffer!: IBuffer; + public viewport!: IViewport; + public applicationCursor!: boolean; + public handler(data: string): void { + throw new Error('Method not implemented.'); + } + public on(event: string, callback: (...args: any[]) => void): void { + throw new Error('Method not implemented.'); + } + public off(type: string, listener: XtermListener): void { + throw new Error('Method not implemented.'); + } + public addDisposableListener(type: string, handler: XtermListener): IDisposable { + throw new Error('Method not implemented.'); + } + public scrollLines(disp: number): void { + throw new Error('Method not implemented.'); + } + public scrollToRow(absoluteRow: number): number { + throw new Error('Method not implemented.'); + } + public cancel(ev: Event, force?: boolean): void { + throw new Error('Method not implemented.'); + } + public log(text: string): void { + throw new Error('Method not implemented.'); + } + public emit(event: string, data: any): void { + throw new Error('Method not implemented.'); + } + public reset(): void { + throw new Error('Method not implemented.'); + } + public refresh(start: number, end: number): void { + throw new Error('Method not implemented.'); + } + public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } + public deregisterCharacterJoiner(joinerId: number): void { } +} + +export class MockBuffer implements IBuffer { + public markers!: IMarker[]; + public addMarker(y: number): IMarker { + throw new Error('Method not implemented.'); + } + public isCursorInViewport!: boolean; + public lines!: ICircularList; + public ydisp!: number; + public ybase!: number; + public hasScrollback!: boolean; + public y!: number; + public x!: number; + public tabs: any; + public scrollBottom!: number; + public scrollTop!: number; + public savedY!: number; + public savedX!: number; + public savedCharset: ICharset | undefined; + public savedCurAttrData = new AttributeData(); + public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string { + return Buffer.prototype.translateBufferLineToString.apply(this, arguments as any); + } + public getWrappedRangeForLine(y: number): { first: number, last: number } { + return Buffer.prototype.getWrappedRangeForLine.apply(this, arguments as any); + } + public nextStop(x?: number): number { + throw new Error('Method not implemented.'); + } + public prevStop(x?: number): number { + throw new Error('Method not implemented.'); + } + public setLines(lines: ICircularList): void { + this.lines = lines; + } + public getBlankLine(attr: IAttributeData, isWrapped?: boolean): IBufferLine { + return Buffer.prototype.getBlankLine.apply(this, arguments as any); + } + public stringIndexToBufferIndex(lineIndex: number, stringIndex: number): number[] { + return Buffer.prototype.stringIndexToBufferIndex.apply(this, arguments as any); + } + public iterator(trimRight: boolean, startIndex?: number, endIndex?: number): IBufferStringIterator { + return Buffer.prototype.iterator.apply(this, arguments as any); + } + public getNullCell(attr?: IAttributeData): ICellData { + throw new Error('Method not implemented.'); + } + public getWhitespaceCell(attr?: IAttributeData): ICellData { + throw new Error('Method not implemented.'); + } +} + +export class MockRenderer implements IRenderer { + public onRequestRedraw!: IEvent; + public onCanvasResize!: IEvent<{ width: number, height: number }>; + public onRender!: IEvent<{ start: number, end: number }>; + public dispose(): void { + throw new Error('Method not implemented.'); + } + public colorManager!: IColorManager; + public on(type: string, listener: XtermListener): void { + throw new Error('Method not implemented.'); + } + public off(type: string, listener: XtermListener): void { + throw new Error('Method not implemented.'); + } + public emit(type: string, data?: any): void { + throw new Error('Method not implemented.'); + } + public addDisposableListener(type: string, handler: XtermListener): IDisposable { + throw new Error('Method not implemented.'); + } + public dimensions!: IRenderDimensions; + public setColors(colors: IColorSet): void { + throw new Error('Method not implemented.'); + } + public onResize(cols: number, rows: number): void { } + public onCharSizeChanged(): void { } + public onBlur(): void { } + public onFocus(): void { } + public onSelectionChanged(start: [number, number], end: [number, number]): void { } + public onCursorMove(): void { } + public onOptionsChanged(): void { } + public onDevicePixelRatioChange(): void { } + public clear(): void { } + public renderRows(start: number, end: number): void { } + public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; } + public deregisterCharacterJoiner(): boolean { return true; } +} + +export class MockViewport implements IViewport { + public dispose(): void { + throw new Error('Method not implemented.'); + } + public scrollBarWidth: number = 0; + public onThemeChange(colors: IColorSet): void { + throw new Error('Method not implemented.'); + } + public onWheel(ev: WheelEvent): boolean { + throw new Error('Method not implemented.'); + } + public onTouchStart(ev: TouchEvent): void { + throw new Error('Method not implemented.'); + } + public onTouchMove(ev: TouchEvent): boolean { + throw new Error('Method not implemented.'); + } + public syncScrollArea(): void { } + public getLinesScrolled(ev: WheelEvent): number { + throw new Error('Method not implemented.'); + } +} + +export class MockCompositionHelper implements ICompositionHelper { + public compositionstart(): void { + throw new Error('Method not implemented.'); + } + public compositionupdate(ev: CompositionEvent): void { + throw new Error('Method not implemented.'); + } + public compositionend(): void { + throw new Error('Method not implemented.'); + } + public updateCompositionElements(dontRecurse?: boolean): void { + throw new Error('Method not implemented.'); + } + public keydown(ev: KeyboardEvent): boolean { + return true; + } +} export class MockCharSizeService implements ICharSizeService { public serviceBrand: undefined;