From b2553c17b4e074f2029d9a302555a9a53a56d77d Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 9 Mar 2026 12:42:38 +0900 Subject: [PATCH 1/3] Clarify indexes in CharData and IColorRGB Part of #5740 --- src/common/Types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/Types.ts b/src/common/Types.ts index a46f47b2a..a4040ab55 100644 --- a/src/common/Types.ts +++ b/src/common/Types.ts @@ -101,13 +101,13 @@ export interface ICharset { [key: string]: string | undefined; } -export type CharData = [number, string, number, number]; +export type CharData = [attrIndex: number, charIndex: string, width: number, code: number]; export interface IColor { readonly css: string; readonly rgba: number; // 32-bit int with rgba in each byte } -export type IColorRGB = [number, number, number]; +export type IColorRGB = [red: number, green: number, blue: number]; export interface IExtendedAttrs { ext: number; From df5393ec45714736aea308d6ed29d597429f53d4 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 9 Mar 2026 12:54:27 +0900 Subject: [PATCH 2/3] Use helper function and const for cell data tests --- src/common/Types.ts | 2 +- src/common/buffer/BufferLine.test.ts | 350 ++++++++++++++------------- 2 files changed, 179 insertions(+), 173 deletions(-) diff --git a/src/common/Types.ts b/src/common/Types.ts index a4040ab55..7ceda21d2 100644 --- a/src/common/Types.ts +++ b/src/common/Types.ts @@ -101,7 +101,7 @@ export interface ICharset { [key: string]: string | undefined; } -export type CharData = [attrIndex: number, charIndex: string, width: number, code: number]; +export type CharData = [attr: number, char: string, width: number, code: number]; export interface IColor { readonly css: string; diff --git a/src/common/buffer/BufferLine.test.ts b/src/common/buffer/BufferLine.test.ts index 9d08c2bef..eaceaa45f 100644 --- a/src/common/buffer/BufferLine.test.ts +++ b/src/common/buffer/BufferLine.test.ts @@ -24,6 +24,12 @@ class TestBufferLine extends BufferLine { } } +function createCellData(attr: number, char: string, width: number): CellData { + return CellData.fromCharData([attr, char, width, char.length === 0 ? 0 : char.charCodeAt(0)]); +} + +const NULL_CELL_DATA = Object.freeze(createCellData(DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH)); + describe('AttributeData', () => { describe('extended attributes', () => { it('hasExtendedAttrs', () => { @@ -173,78 +179,78 @@ describe('BufferLine', function(): void { assert.equal(line.length, 10); assert.deepEqual(line.loadCell(0, new CellData()).getAsCharData(), [0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]); assert.equal(line.isWrapped, true); - line = new TestBufferLine(10, CellData.fromCharData([123, 'a', 456, 'a'.charCodeAt(0)]), true); + line = new TestBufferLine(10, createCellData(123, 'a', 456), true); assert.equal(line.length, 10); assert.deepEqual(line.loadCell(0, new CellData()).getAsCharData(), [123, 'a', 456, 'a'.charCodeAt(0)]); assert.equal(line.isWrapped, true); }); it('insertCells', function(): void { const line = new TestBufferLine(3); - line.setCell(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - line.setCell(1, CellData.fromCharData([2, 'b', 0, 'b'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([3, 'c', 0, 'c'.charCodeAt(0)])); - line.insertCells(1, 3, CellData.fromCharData([4, 'd', 0, 'd'.charCodeAt(0)])); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(1, createCellData(2, 'b', 1)); + line.setCell(2, createCellData(3, 'c', 1)); + line.insertCells(1, 3, createCellData(4, 'd', 1)); assert.deepEqual(line.toArray(), [ - [1, 'a', 0, 'a'.charCodeAt(0)], - [4, 'd', 0, 'd'.charCodeAt(0)], - [4, 'd', 0, 'd'.charCodeAt(0)] + [1, 'a', 1, 'a'.charCodeAt(0)], + [4, 'd', 1, 'd'.charCodeAt(0)], + [4, 'd', 1, 'd'.charCodeAt(0)] ]); }); it('deleteCells', function(): void { const line = new TestBufferLine(5); - line.setCell(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - line.setCell(1, CellData.fromCharData([2, 'b', 0, 'b'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([3, 'c', 0, 'c'.charCodeAt(0)])); - line.setCell(3, CellData.fromCharData([4, 'd', 0, 'd'.charCodeAt(0)])); - line.setCell(4, CellData.fromCharData([5, 'e', 0, 'e'.charCodeAt(0)])); - line.deleteCells(1, 2, CellData.fromCharData([6, 'f', 0, 'f'.charCodeAt(0)])); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(1, createCellData(2, 'b', 1)); + line.setCell(2, createCellData(3, 'c', 1)); + line.setCell(3, createCellData(4, 'd', 1)); + line.setCell(4, createCellData(5, 'e', 1)); + line.deleteCells(1, 2, createCellData(6, 'f', 1)); assert.deepEqual(line.toArray(), [ - [1, 'a', 0, 'a'.charCodeAt(0)], - [4, 'd', 0, 'd'.charCodeAt(0)], - [5, 'e', 0, 'e'.charCodeAt(0)], - [6, 'f', 0, 'f'.charCodeAt(0)], - [6, 'f', 0, 'f'.charCodeAt(0)] + [1, 'a', 1, 'a'.charCodeAt(0)], + [4, 'd', 1, 'd'.charCodeAt(0)], + [5, 'e', 1, 'e'.charCodeAt(0)], + [6, 'f', 1, 'f'.charCodeAt(0)], + [6, 'f', 1, 'f'.charCodeAt(0)] ]); }); it('replaceCells', function(): void { const line = new TestBufferLine(5); - line.setCell(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - line.setCell(1, CellData.fromCharData([2, 'b', 0, 'b'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([3, 'c', 0, 'c'.charCodeAt(0)])); - line.setCell(3, CellData.fromCharData([4, 'd', 0, 'd'.charCodeAt(0)])); - line.setCell(4, CellData.fromCharData([5, 'e', 0, 'e'.charCodeAt(0)])); - line.replaceCells(2, 4, CellData.fromCharData([6, 'f', 0, 'f'.charCodeAt(0)])); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(1, createCellData(2, 'b', 1)); + line.setCell(2, createCellData(3, 'c', 1)); + line.setCell(3, createCellData(4, 'd', 1)); + line.setCell(4, createCellData(5, 'e', 1)); + line.replaceCells(2, 4, createCellData(6, 'f', 1)); assert.deepEqual(line.toArray(), [ - [1, 'a', 0, 'a'.charCodeAt(0)], - [2, 'b', 0, 'b'.charCodeAt(0)], - [6, 'f', 0, 'f'.charCodeAt(0)], - [6, 'f', 0, 'f'.charCodeAt(0)], - [5, 'e', 0, 'e'.charCodeAt(0)] + [1, 'a', 1, 'a'.charCodeAt(0)], + [2, 'b', 1, 'b'.charCodeAt(0)], + [6, 'f', 1, 'f'.charCodeAt(0)], + [6, 'f', 1, 'f'.charCodeAt(0)], + [5, 'e', 1, 'e'.charCodeAt(0)] ]); }); it('fill', function(): void { const line = new TestBufferLine(5); - line.setCell(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - line.setCell(1, CellData.fromCharData([2, 'b', 0, 'b'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([3, 'c', 0, 'c'.charCodeAt(0)])); - line.setCell(3, CellData.fromCharData([4, 'd', 0, 'd'.charCodeAt(0)])); - line.setCell(4, CellData.fromCharData([5, 'e', 0, 'e'.charCodeAt(0)])); - line.fill(CellData.fromCharData([123, 'z', 0, 'z'.charCodeAt(0)])); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(1, createCellData(2, 'b', 1)); + line.setCell(2, createCellData(3, 'c', 1)); + line.setCell(3, createCellData(4, 'd', 1)); + line.setCell(4, createCellData(5, 'e', 1)); + line.fill(createCellData(123, 'z', 1)); assert.deepEqual(line.toArray(), [ - [123, 'z', 0, 'z'.charCodeAt(0)], - [123, 'z', 0, 'z'.charCodeAt(0)], - [123, 'z', 0, 'z'.charCodeAt(0)], - [123, 'z', 0, 'z'.charCodeAt(0)], - [123, 'z', 0, 'z'.charCodeAt(0)] + [123, 'z', 1, 'z'.charCodeAt(0)], + [123, 'z', 1, 'z'.charCodeAt(0)], + [123, 'z', 1, 'z'.charCodeAt(0)], + [123, 'z', 1, 'z'.charCodeAt(0)], + [123, 'z', 1, 'z'.charCodeAt(0)] ]); }); it('clone', function(): void { const line = new TestBufferLine(5, undefined, true); - line.setCell(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - line.setCell(1, CellData.fromCharData([2, 'b', 0, 'b'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([3, 'c', 0, 'c'.charCodeAt(0)])); - line.setCell(3, CellData.fromCharData([4, 'd', 0, 'd'.charCodeAt(0)])); - line.setCell(4, CellData.fromCharData([5, 'e', 0, 'e'.charCodeAt(0)])); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(1, createCellData(2, 'b', 1)); + line.setCell(2, createCellData(3, 'c', 1)); + line.setCell(3, createCellData(4, 'd', 1)); + line.setCell(4, createCellData(5, 'e', 1)); const line2 = line.clone(); assert.deepEqual(TestBufferLine.prototype.toArray.apply(line2), line.toArray()); assert.equal(line2.length, line.length); @@ -252,12 +258,12 @@ describe('BufferLine', function(): void { }); it('copyFrom', function(): void { const line = new TestBufferLine(5); - line.setCell(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - line.setCell(1, CellData.fromCharData([2, 'b', 0, 'b'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([3, 'c', 0, 'c'.charCodeAt(0)])); - line.setCell(3, CellData.fromCharData([4, 'd', 0, 'd'.charCodeAt(0)])); - line.setCell(4, CellData.fromCharData([5, 'e', 0, 'e'.charCodeAt(0)])); - const line2 = new TestBufferLine(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), true); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(1, createCellData(2, 'b', 1)); + line.setCell(2, createCellData(3, 'c', 1)); + line.setCell(3, createCellData(4, 'd', 1)); + line.setCell(4, createCellData(5, 'e', 1)); + const line2 = new TestBufferLine(5, createCellData(1, 'a', 1), true); line2.copyFrom(line); assert.deepEqual(line2.toArray(), line.toArray()); assert.equal(line2.length, line.length); @@ -267,9 +273,9 @@ describe('BufferLine', function(): void { // CHAR_DATA_CODE_INDEX resembles current behavior in InputHandler.print // --> set code to the last charCodeAt value of the string // Note: needs to be fixed once the string pointer is in place - const line = new TestBufferLine(2, CellData.fromCharData([1, 'e\u0301', 0, '\u0301'.charCodeAt(0)])); - assert.deepEqual(line.toArray(), [[1, 'e\u0301', 0, '\u0301'.charCodeAt(0)], [1, 'e\u0301', 0, '\u0301'.charCodeAt(0)]]); - const line2 = new TestBufferLine(5, CellData.fromCharData([1, 'a', 0, '\u0301'.charCodeAt(0)]), true); + const line = new TestBufferLine(2, createCellData(1, 'e\u0301', 1)); + assert.deepEqual(line.toArray(), [[1, 'e\u0301', 1, '\u0301'.charCodeAt(0)], [1, 'e\u0301', 1, '\u0301'.charCodeAt(0)]]); + const line2 = new TestBufferLine(5, createCellData(1, 'a', 1), true); line2.copyFrom(line); assert.deepEqual(line2.toArray(), line.toArray()); const line3 = line.clone(); @@ -277,72 +283,72 @@ describe('BufferLine', function(): void { }); describe('resize', function(): void { it('enlarge(false)', function(): void { - const line = new TestBufferLine(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); - line.resize(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - assert.deepEqual(line.toArray(), (Array(10) as any).fill([1, 'a', 0, 'a'.charCodeAt(0)])); + const line = new TestBufferLine(5, createCellData(1, 'a', 1), false); + line.resize(10, createCellData(1, 'a', 1)); + assert.deepEqual(line.toArray(), (Array(10) as any).fill([1, 'a', 1, 'a'.charCodeAt(0)])); }); it('enlarge(true)', function(): void { - const line = new TestBufferLine(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); - line.resize(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - assert.deepEqual(line.toArray(), (Array(10) as any).fill([1, 'a', 0, 'a'.charCodeAt(0)])); + const line = new TestBufferLine(5, createCellData(1, 'a', 1), false); + line.resize(10, createCellData(1, 'a', 1)); + assert.deepEqual(line.toArray(), (Array(10) as any).fill([1, 'a', 1, 'a'.charCodeAt(0)])); }); it('shrink(true) - should apply new size', function(): void { - const line = new TestBufferLine(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); - line.resize(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - assert.deepEqual(line.toArray(), (Array(5) as any).fill([1, 'a', 0, 'a'.charCodeAt(0)])); + const line = new TestBufferLine(10, createCellData(1, 'a', 1), false); + line.resize(5, createCellData(1, 'a', 1)); + assert.deepEqual(line.toArray(), (Array(5) as any).fill([1, 'a', 1, 'a'.charCodeAt(0)])); }); it('shrink to 0 length', function(): void { - const line = new TestBufferLine(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); - line.resize(0, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); - assert.deepEqual(line.toArray(), (Array(0) as any).fill([1, 'a', 0, 'a'.charCodeAt(0)])); + const line = new TestBufferLine(10, createCellData(1, 'a', 1), false); + line.resize(0, createCellData(1, 'a', 1)); + assert.deepEqual(line.toArray(), (Array(0) as any).fill([1, 'a', 1, 'a'.charCodeAt(0)])); }); it('should remove combining data on replaced cells after shrinking then enlarging', () => { - const line = new TestBufferLine(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]), false); + const line = new TestBufferLine(10, createCellData(1, 'a', 1), false); line.set(2, [ 0, '😁', 1, '😁'.charCodeAt(0) ]); line.set(9, [ 0, '😁', 1, '😁'.charCodeAt(0) ]); assert.equal(line.translateToString(), 'aa😁aaaaaa😁'); assert.equal(Object.keys(line.combined).length, 2); - line.resize(5, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); + line.resize(5, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), 'aa😁aa'); - line.resize(10, CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)])); + line.resize(10, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), 'aa😁aaaaaaa'); assert.equal(Object.keys(line.combined).length, 1); }); }); describe('getTrimLength', function(): void { it('empty line', function(): void { - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); assert.equal(line.getTrimmedLength(), 0); }); it('ASCII', function(): void { - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); - line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(2, createCellData(1, 'a', 1)); assert.equal(line.getTrimmedLength(), 3); }); it('surrogate', function(): void { - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); - line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([1, '𝄞', 1, '𝄞'.charCodeAt(0)])); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(2, createCellData(1, '𝄞', 1)); assert.equal(line.getTrimmedLength(), 3); }); it('combining', function(): void { - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); - line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([1, 'e\u0301', 1, '\u0301'.charCodeAt(0)])); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(2, createCellData(1, 'e\u0301', 1)); assert.equal(line.getTrimmedLength(), 3); }); it('fullwidth', function(): void { - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); - line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)])); - line.setCell(3, CellData.fromCharData([0, '', 0, 0])); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(2, createCellData(1, '1', 2)); + line.setCell(3, createCellData(0, '', 0)); assert.equal(line.getTrimmedLength(), 4); // also counts null cell after fullwidth }); }); describe('translateToString with and w\'o trimming', function(): void { it('empty line', function(): void { - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); const columns: number[] = []; assert.equal(line.translateToString(false, undefined, undefined, columns), ' '); assert.deepEqual(columns, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); @@ -351,11 +357,11 @@ describe('BufferLine', function(): void { }); it('ASCII', function(): void { const columns: number[] = []; - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); - line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(4, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(5, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(2, createCellData(1, 'a', 1)); + line.setCell(4, createCellData(1, 'a', 1)); + line.setCell(5, createCellData(1, 'a', 1)); assert.equal(line.translateToString(false, undefined, undefined, columns), 'a a aa '); assert.deepEqual(columns, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); assert.equal(line.translateToString(true, undefined, undefined, columns), 'a a aa'); @@ -372,11 +378,11 @@ describe('BufferLine', function(): void { }); it('surrogate', function(): void { const columns: number[] = []; - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); - line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([1, '𝄞', 1, '𝄞'.charCodeAt(0)])); - line.setCell(4, CellData.fromCharData([1, '𝄞', 1, '𝄞'.charCodeAt(0)])); - line.setCell(5, CellData.fromCharData([1, '𝄞', 1, '𝄞'.charCodeAt(0)])); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(2, createCellData(1, '𝄞', 1)); + line.setCell(4, createCellData(1, '𝄞', 1)); + line.setCell(5, createCellData(1, '𝄞', 1)); assert.equal(line.translateToString(false, undefined, undefined, columns), 'a 𝄞 𝄞𝄞 '); assert.deepEqual(columns, [0, 1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10]); assert.equal(line.translateToString(true, undefined, undefined, columns), 'a 𝄞 𝄞𝄞'); @@ -392,11 +398,11 @@ describe('BufferLine', function(): void { }); it('combining', function(): void { const columns: number[] = []; - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); - line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([1, 'e\u0301', 1, '\u0301'.charCodeAt(0)])); - line.setCell(4, CellData.fromCharData([1, 'e\u0301', 1, '\u0301'.charCodeAt(0)])); - line.setCell(5, CellData.fromCharData([1, 'e\u0301', 1, '\u0301'.charCodeAt(0)])); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(2, createCellData(1, 'e\u0301', 1)); + line.setCell(4, createCellData(1, 'e\u0301', 1)); + line.setCell(5, createCellData(1, 'e\u0301', 1)); assert.equal(line.translateToString(false, undefined, undefined, columns), 'a e\u0301 e\u0301e\u0301 '); assert.deepEqual(columns, [0, 1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10]); assert.equal(line.translateToString(true, undefined, undefined, columns), 'a e\u0301 e\u0301e\u0301'); @@ -412,14 +418,14 @@ describe('BufferLine', function(): void { }); it('fullwidth', function(): void { const columns: number[] = []; - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); - line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)])); - line.setCell(3, CellData.fromCharData([0, '', 0, 0])); - line.setCell(5, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)])); - line.setCell(6, CellData.fromCharData([0, '', 0, 0])); - line.setCell(7, CellData.fromCharData([1, '1', 2, '1'.charCodeAt(0)])); - line.setCell(8, CellData.fromCharData([0, '', 0, 0])); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(2, createCellData(1, '1', 2)); + line.setCell(3, createCellData(0, '', 0)); + line.setCell(5, createCellData(1, '1', 2)); + line.setCell(6, createCellData(0, '', 0)); + line.setCell(7, createCellData(1, '1', 2)); + line.setCell(8, createCellData(0, '', 0)); assert.equal(line.translateToString(false, undefined, undefined, columns), 'a 1 11 '); assert.deepEqual(columns, [0, 1, 2, 4, 5, 7, 9, 10]); assert.equal(line.translateToString(true, undefined, undefined, columns), 'a 1 11'); @@ -441,12 +447,12 @@ describe('BufferLine', function(): void { }); it('space at end', function(): void { const columns: number[] = []; - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); - line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(4, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(5, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(6, CellData.fromCharData([1, ' ', 1, ' '.charCodeAt(0)])); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); + line.setCell(0, createCellData(1, 'a', 1)); + line.setCell(2, createCellData(1, 'a', 1)); + line.setCell(4, createCellData(1, 'a', 1)); + line.setCell(5, createCellData(1, 'a', 1)); + line.setCell(6, createCellData(1, ' ', 1)); assert.equal(line.translateToString(false, undefined, undefined, columns), 'a a aa '); assert.deepEqual(columns, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); assert.equal(line.translateToString(true, undefined, undefined, columns), 'a a aa '); @@ -457,7 +463,7 @@ describe('BufferLine', function(): void { // sanity check - broken line with invalid out of bound null width cells // this can atm happen with deleting/inserting chars in inputhandler by "breaking" // fullwidth pairs --> needs to be fixed after settling BufferLine impl - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); assert.equal(line.translateToString(false, undefined, undefined, columns), ' '); assert.deepEqual(columns, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); assert.equal(line.translateToString(true, undefined, undefined, columns), ''); @@ -465,15 +471,15 @@ describe('BufferLine', function(): void { }); it('should work with endCol=0', () => { const columns: number[] = []; - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); - line.setCell(0, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); + line.setCell(0, createCellData(1, 'a', 1)); assert.equal(line.translateToString(true, 0, 0, columns), ''); assert.deepEqual(columns, [0]); }); }); describe('addCharToCell', () => { it('should set width to 1 for empty cell', () => { - const line = new TestBufferLine(3, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); + const line = new TestBufferLine(3, NULL_CELL_DATA, false); line.addCodepointToCell(0, '\u0301'.charCodeAt(0), 0); const cell = line.loadCell(0, new CellData()); // chars contains single combining char @@ -483,7 +489,7 @@ describe('BufferLine', function(): void { assert.equal(cell.isCombined(), 0); }); it('should add char to combining string in cell', () => { - const line = new TestBufferLine(3, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); + const line = new TestBufferLine(3, NULL_CELL_DATA, false); const cell = line .loadCell(0, new CellData()); cell.setFromCharData([123, 'e\u0301', 1, 'e\u0301'.charCodeAt(1)]); line.setCell(0, cell); @@ -496,7 +502,7 @@ describe('BufferLine', function(): void { assert.equal(cell.isCombined(), Content.IS_COMBINED_MASK); }); it('should create combining string on taken cell', () => { - const line = new TestBufferLine(3, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]), false); + const line = new TestBufferLine(3, NULL_CELL_DATA, false); const cell = line .loadCell(0, new CellData()); cell.setFromCharData([123, 'e', 1, 'e'.charCodeAt(1)]); line.setCell(0, cell); @@ -511,98 +517,98 @@ describe('BufferLine', function(): void { }); describe('correct fullwidth handling', () => { function populate(line: BufferLine): void { - const cell = CellData.fromCharData([1, '¥', 2, '¥'.charCodeAt(0)]); + const cell = createCellData(1, '¥', 2); for (let i = 0; i < line.length; i += 2) { line.setCell(i, cell); } } it('insert - wide char at pos', () => { - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.insertCells(9, 1, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.insertCells(9, 1, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), '¥¥¥¥ a'); - line.insertCells(8, 1, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.insertCells(8, 1, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), '¥¥¥¥a '); - line.insertCells(1, 1, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.insertCells(1, 1, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), ' a ¥¥¥a'); }); it('insert - wide char at end', () => { - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.insertCells(0, 3, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.insertCells(0, 3, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), 'aaa¥¥¥ '); - line.insertCells(4, 1, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.insertCells(4, 1, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), 'aaa a ¥¥'); - line.insertCells(4, 1, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.insertCells(4, 1, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), 'aaa aa ¥ '); }); it('delete', () => { - const line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + const line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.deleteCells(0, 1, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.deleteCells(0, 1, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), ' ¥¥¥¥a'); - line.deleteCells(5, 2, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.deleteCells(5, 2, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), ' ¥¥¥aaa'); - line.deleteCells(0, 2, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.deleteCells(0, 2, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), ' ¥¥aaaaa'); }); it('replace - start at 0', () => { - let line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + let line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.replaceCells(0, 1, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.replaceCells(0, 1, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), 'a ¥¥¥¥'); - line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.replaceCells(0, 2, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.replaceCells(0, 2, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), 'aa¥¥¥¥'); - line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.replaceCells(0, 3, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.replaceCells(0, 3, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), 'aaa ¥¥¥'); - line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.replaceCells(0, 8, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.replaceCells(0, 8, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), 'aaaaaaaa¥'); - line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.replaceCells(0, 9, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.replaceCells(0, 9, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), 'aaaaaaaaa '); - line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.replaceCells(0, 10, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.replaceCells(0, 10, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), 'aaaaaaaaaa'); }); it('replace - start at 1', () => { - let line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + let line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.replaceCells(1, 2, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.replaceCells(1, 2, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), ' a¥¥¥¥'); - line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.replaceCells(1, 3, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.replaceCells(1, 3, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), ' aa ¥¥¥'); - line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.replaceCells(1, 4, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.replaceCells(1, 4, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), ' aaa¥¥¥'); - line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.replaceCells(1, 8, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.replaceCells(1, 8, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), ' aaaaaaa¥'); - line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.replaceCells(1, 9, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.replaceCells(1, 9, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), ' aaaaaaaa '); - line = new TestBufferLine(10, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, 0, NULL_CELL_CODE]), false); + line = new TestBufferLine(10, NULL_CELL_DATA, false); populate(line); - line.replaceCells(1, 10, CellData.fromCharData([1, 'a', 1, 'a'.charCodeAt(0)])); + line.replaceCells(1, 10, createCellData(1, 'a', 1)); assert.equal(line.translateToString(), ' aaaaaaaaa'); }); }); describe('extended attributes', () => { it('setCells', function(): void { const line = new TestBufferLine(5); - const cell = CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]); + const cell = createCellData(1, 'a', 1); // no eAttrs line.setCell(0, cell); @@ -612,7 +618,7 @@ describe('BufferLine', function(): void { line.setCell(1, cell); // same eAttr, different codepoint - cell.content = 65; // 'A' + cell.content = createCellData(1, 'A', 1).content; line.setCell(2, cell); // different eAttr @@ -625,11 +631,11 @@ describe('BufferLine', function(): void { line.setCell(4, cell); assert.deepEqual(line.toArray(), [ - [1, 'a', 0, 'a'.charCodeAt(0)], - [1, 'a', 0, 'a'.charCodeAt(0)], - [1, 'A', 0, 'A'.charCodeAt(0)], - [1, 'A', 0, 'A'.charCodeAt(0)], - [1, 'A', 0, 'A'.charCodeAt(0)] + [1, 'a', 1, 'a'.charCodeAt(0)], + [1, 'a', 1, 'a'.charCodeAt(0)], + [1, 'A', 1, 'A'.charCodeAt(0)], + [1, 'A', 1, 'A'.charCodeAt(0)], + [1, 'A', 1, 'A'.charCodeAt(0)] ]); assert.equal((line as any)._extendedAttrs[0], undefined); assert.equal((line as any)._extendedAttrs[1].underlineStyle, UnderlineStyle.CURLY); @@ -643,7 +649,7 @@ describe('BufferLine', function(): void { }); it('loadCell', () => { const line = new TestBufferLine(5); - const cell = CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]); + const cell = createCellData(1, 'a', 1); // no eAttrs line.setCell(0, cell); @@ -686,7 +692,7 @@ describe('BufferLine', function(): void { }); it('fill', () => { const line = new TestBufferLine(3); - const cell = CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]); + const cell = createCellData(1, 'a', 1); cell.extended.underlineStyle = UnderlineStyle.CURLY; cell.bg |= BgFlags.HAS_EXTENDED; line.fill(cell); @@ -696,7 +702,7 @@ describe('BufferLine', function(): void { }); it('insertCells', () => { const line = new TestBufferLine(5); - const cell = CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]); + const cell = createCellData(1, 'a', 1); cell.extended.underlineStyle = UnderlineStyle.CURLY; cell.bg |= BgFlags.HAS_EXTENDED; line.insertCells(1, 3, cell); @@ -714,7 +720,7 @@ describe('BufferLine', function(): void { }); it('deleteCells', () => { const line = new TestBufferLine(5); - const fillCell = CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]); + const fillCell = createCellData(1, 'a', 1); fillCell.extended.underlineStyle = UnderlineStyle.CURLY; fillCell.bg |= BgFlags.HAS_EXTENDED; line.fill(fillCell); @@ -729,7 +735,7 @@ describe('BufferLine', function(): void { }); it('replaceCells', () => { const line = new TestBufferLine(5); - const fillCell = CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]); + const fillCell = createCellData(1, 'a', 1); fillCell.extended.underlineStyle = UnderlineStyle.CURLY; fillCell.bg |= BgFlags.HAS_EXTENDED; line.fill(fillCell); @@ -744,7 +750,7 @@ describe('BufferLine', function(): void { }); it('clone', () => { const line = new TestBufferLine(5); - const cell = CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]); + const cell = createCellData(1, 'a', 1); // no eAttrs line.setCell(0, cell); @@ -775,7 +781,7 @@ describe('BufferLine', function(): void { }); it('copyFrom', () => { const initial = new TestBufferLine(5); - const cell = CellData.fromCharData([1, 'a', 0, 'a'.charCodeAt(0)]); + const cell = createCellData(1, 'a', 1); // no eAttrs initial.setCell(0, cell); @@ -798,7 +804,7 @@ describe('BufferLine', function(): void { initial.setCell(4, cell); const line = new TestBufferLine(5); - line.fill(CellData.fromCharData([1, 'b', 0, 'b'.charCodeAt(0)])); + line.fill(createCellData(1, 'b', 1)); line.copyFrom(initial); assert.equal((line as any)._extendedAttrs[0], (initial as any)._extendedAttrs[0]); assert.equal((line as any)._extendedAttrs[1], (initial as any)._extendedAttrs[1]); From 671425bf5a6530ce664f68dc2298108364db1374 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 9 Mar 2026 13:03:00 +0900 Subject: [PATCH 3/3] Use helpers in other tests --- src/browser/Terminal.test.ts | 64 +++++----- .../dom/DomRendererRowFactory.test.ts | 110 +++++++++--------- .../services/CharacterJoinerService.test.ts | 16 +-- src/browser/services/SelectionService.test.ts | 6 +- src/common/TestUtils.test.ts | 8 ++ src/common/buffer/Buffer.test.ts | 36 +++--- src/common/buffer/BufferLine.test.ts | 7 +- 7 files changed, 125 insertions(+), 122 deletions(-) diff --git a/src/browser/Terminal.test.ts b/src/browser/Terminal.test.ts index ba2ce6dd5..c651c248a 100644 --- a/src/browser/Terminal.test.ts +++ b/src/browser/Terminal.test.ts @@ -8,7 +8,7 @@ import type { IBrowser } from 'browser/Types'; import { assert } from 'chai'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { CellData } from 'common/buffer/CellData'; -import { MockUnicodeService } from 'common/TestUtils.test'; +import { MockUnicodeService, createCellData } from 'common/TestUtils.test'; import { IMarker } from 'common/Types'; const INIT_COLS = 80; @@ -440,8 +440,8 @@ 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, createCellData(0, 'a', 0)); + term.buffer.lines.get(INIT_ROWS - 1)!.setCell(0, createCellData(0, 'b', 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); @@ -451,9 +451,9 @@ describe('Terminal', () => { }); 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, createCellData(0, 'a', 0)); + term.buffer.lines.get(1)!.setCell(0, createCellData(0, 'b', 0)); + term.buffer.lines.get(2)!.setCell(0, createCellData(0, 'c', 0)); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.buffer.scrollTop = 1; term.scroll(DEFAULT_ATTR_DATA.clone()); @@ -463,11 +463,11 @@ describe('Terminal', () => { }); 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, createCellData(0, 'a', 0)); + term.buffer.lines.get(1)!.setCell(0, createCellData(0, 'b', 0)); + term.buffer.lines.get(2)!.setCell(0, createCellData(0, 'c', 0)); + term.buffer.lines.get(3)!.setCell(0, createCellData(0, 'd', 0)); + term.buffer.lines.get(4)!.setCell(0, createCellData(0, 'e', 0)); term.buffer.y = 3; term.buffer.scrollBottom = 3; term.scroll(DEFAULT_ATTR_DATA.clone()); @@ -481,11 +481,11 @@ describe('Terminal', () => { }); 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, createCellData(0, 'a', 0)); + term.buffer.lines.get(1)!.setCell(0, createCellData(0, 'b', 0)); + term.buffer.lines.get(2)!.setCell(0, createCellData(0, 'c', 0)); + term.buffer.lines.get(3)!.setCell(0, createCellData(0, 'd', 0)); + term.buffer.lines.get(4)!.setCell(0, createCellData(0, 'e', 0)); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.buffer.scrollTop = 1; term.buffer.scrollBottom = 3; @@ -506,9 +506,9 @@ 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, createCellData(0, 'a', 0)); + term.buffer.lines.get(1)!.setCell(0, createCellData(0, 'b', 0)); + term.buffer.lines.get(INIT_ROWS - 1)!.setCell(0, createCellData(0, 'c', 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()); @@ -521,9 +521,9 @@ describe('Terminal', () => { }); 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, createCellData(0, 'a', 0)); + term.buffer.lines.get(1)!.setCell(0, createCellData(0, 'b', 0)); + term.buffer.lines.get(2)!.setCell(0, createCellData(0, 'c', 0)); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.buffer.scrollTop = 1; term.scroll(DEFAULT_ATTR_DATA.clone()); @@ -533,11 +533,11 @@ describe('Terminal', () => { }); 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, createCellData(0, 'a', 0)); + term.buffer.lines.get(1)!.setCell(0, createCellData(0, 'b', 0)); + term.buffer.lines.get(2)!.setCell(0, createCellData(0, 'c', 0)); + term.buffer.lines.get(3)!.setCell(0, createCellData(0, 'd', 0)); + term.buffer.lines.get(4)!.setCell(0, createCellData(0, 'e', 0)); term.buffer.y = 3; term.buffer.scrollBottom = 3; term.scroll(DEFAULT_ATTR_DATA.clone()); @@ -550,11 +550,11 @@ describe('Terminal', () => { }); 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, createCellData(0, 'a', 0)); + term.buffer.lines.get(1)!.setCell(0, createCellData(0, 'b', 0)); + term.buffer.lines.get(2)!.setCell(0, createCellData(0, 'c', 0)); + term.buffer.lines.get(3)!.setCell(0, createCellData(0, 'd', 0)); + term.buffer.lines.get(4)!.setCell(0, createCellData(0, 'e', 0)); term.buffer.y = INIT_ROWS - 1; // Move cursor to last line term.buffer.scrollTop = 1; term.buffer.scrollBottom = 3; diff --git a/src/browser/renderer/dom/DomRendererRowFactory.test.ts b/src/browser/renderer/dom/DomRendererRowFactory.test.ts index b6f6eedca..05fc8000c 100644 --- a/src/browser/renderer/dom/DomRendererRowFactory.test.ts +++ b/src/browser/renderer/dom/DomRendererRowFactory.test.ts @@ -10,7 +10,7 @@ import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR, FgFlags, import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { IBufferLine } from 'common/Types'; import { CellData } from 'common/buffer/CellData'; -import { MockCoreService, MockDecorationService, MockOptionsService } from 'common/TestUtils.test'; +import { MockCoreService, MockDecorationService, MockOptionsService, createCellData, NULL_CELL_DATA } from 'common/TestUtils.test'; import { MockCharacterJoinerService, MockCoreBrowserService, MockThemeService } from 'browser/TestUtils.test'; import { TestWidthCache } from 'browser/renderer/dom/WidthCache.test'; @@ -48,9 +48,9 @@ describe('DomRendererRowFactory', () => { it('should set correct attributes for double width characters', () => { widthCache.setWidths({ '語': 10 }); - lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, '語', 2, '語'.charCodeAt(0)])); + lineData.setCell(0, createCellData(DEFAULT_ATTR, '語', 2)); // There should be no element for the following "empty" cell - lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, '', 0, 0])); + lineData.setCell(1, createCellData(DEFAULT_ATTR, '', 0)); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); assert.equal(extractHtml(spans), '語' @@ -117,7 +117,7 @@ describe('DomRendererRowFactory', () => { describe('attributes', () => { it('should add class for bold', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg = DEFAULT_ATTR_DATA.fg | FgFlags.BOLD; lineData.setCell(0, cell); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); @@ -127,7 +127,7 @@ describe('DomRendererRowFactory', () => { }); it('should add class for italic', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.ITALIC; lineData.setCell(0, cell); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); @@ -137,7 +137,7 @@ describe('DomRendererRowFactory', () => { }); it('should add class for dim', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.DIM; lineData.setCell(0, cell); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); @@ -148,7 +148,7 @@ describe('DomRendererRowFactory', () => { describe('underline', () => { it('should add class for straight underline style', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg = DEFAULT_ATTR_DATA.fg | FgFlags.UNDERLINE; cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.HAS_EXTENDED; cell.extended.underlineStyle = UnderlineStyle.SINGLE; @@ -159,7 +159,7 @@ describe('DomRendererRowFactory', () => { ); }); it('should add class for double underline style', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg = DEFAULT_ATTR_DATA.fg | FgFlags.UNDERLINE; cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.HAS_EXTENDED; cell.extended.underlineStyle = UnderlineStyle.DOUBLE; @@ -170,7 +170,7 @@ describe('DomRendererRowFactory', () => { ); }); it('should add class for curly underline style', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg = DEFAULT_ATTR_DATA.fg | FgFlags.UNDERLINE; cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.HAS_EXTENDED; cell.extended.underlineStyle = UnderlineStyle.CURLY; @@ -181,7 +181,7 @@ describe('DomRendererRowFactory', () => { ); }); it('should add class for double dotted style', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg = DEFAULT_ATTR_DATA.fg | FgFlags.UNDERLINE; cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.HAS_EXTENDED; cell.extended.underlineStyle = UnderlineStyle.DOTTED; @@ -192,7 +192,7 @@ describe('DomRendererRowFactory', () => { ); }); it('should add class for dashed underline style', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg = DEFAULT_ATTR_DATA.fg | FgFlags.UNDERLINE; cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.HAS_EXTENDED; cell.extended.underlineStyle = UnderlineStyle.DASHED; @@ -205,7 +205,7 @@ describe('DomRendererRowFactory', () => { }); it('should add class for overline', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.OVERLINE; lineData.setCell(0, cell); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); @@ -215,7 +215,7 @@ describe('DomRendererRowFactory', () => { }); it('should add class for strikethrough', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg = DEFAULT_ATTR_DATA.fg | FgFlags.STRIKETHROUGH; lineData.setCell(0, cell); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); @@ -225,7 +225,7 @@ describe('DomRendererRowFactory', () => { }); it('should hide blinking text when blink is off', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg = DEFAULT_ATTR_DATA.fg | FgFlags.BLINK | FgFlags.UNDERLINE; cell.bg = DEFAULT_ATTR_DATA.bg | BgFlags.HAS_EXTENDED; cell.extended.underlineStyle = UnderlineStyle.SINGLE; @@ -241,7 +241,7 @@ describe('DomRendererRowFactory', () => { }); it('should add classes for 256 foreground colors', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg |= Attributes.CM_P256; for (let i = 0; i < 256; i++) { cell.fg &= ~Attributes.PCOLOR_MASK; @@ -255,7 +255,7 @@ describe('DomRendererRowFactory', () => { }); it('should add classes for 256 background colors', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.bg |= Attributes.CM_P256; for (let i = 0; i < 256; i++) { cell.bg &= ~Attributes.PCOLOR_MASK; @@ -269,7 +269,7 @@ describe('DomRendererRowFactory', () => { }); it('should correctly invert colors', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg |= Attributes.CM_P16 | 2 | FgFlags.INVERSE; cell.bg |= Attributes.CM_P16 | 1; lineData.setCell(0, cell); @@ -280,7 +280,7 @@ describe('DomRendererRowFactory', () => { }); it('should correctly invert default fg color', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg |= FgFlags.INVERSE; cell.bg |= Attributes.CM_P16 | 1; lineData.setCell(0, cell); @@ -291,7 +291,7 @@ describe('DomRendererRowFactory', () => { }); it('should correctly invert default bg color', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg |= Attributes.CM_P16 | 1 | FgFlags.INVERSE; lineData.setCell(0, cell); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); @@ -301,7 +301,7 @@ describe('DomRendererRowFactory', () => { }); it('should turn bold fg text bright', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg |= FgFlags.BOLD | Attributes.CM_P16; for (let i = 0; i < 8; i++) { cell.fg &= ~Attributes.PCOLOR_MASK; @@ -315,7 +315,7 @@ describe('DomRendererRowFactory', () => { }); it('should set style attribute for RBG', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg |= Attributes.CM_RGB | 1 << 16 | 2 << 8 | 3; cell.bg |= Attributes.CM_RGB | 4 << 16 | 5 << 8 | 6; lineData.setCell(0, cell); @@ -326,7 +326,7 @@ describe('DomRendererRowFactory', () => { }); it('should correctly invert RGB colors', () => { - const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]); + const cell = createCellData(0, 'a', 1); cell.fg |= Attributes.CM_RGB | 1 << 16 | 2 << 8 | 3 | FgFlags.INVERSE; cell.bg |= Attributes.CM_RGB | 4 << 16 | 5 << 8 | 6; lineData.setCell(0, cell); @@ -339,8 +339,8 @@ describe('DomRendererRowFactory', () => { describe('selectionForeground', () => { it('should force selected cells with content to be rendered above the background', () => { - lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); - lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, 'b', 1, 'b'.charCodeAt(0)])); + lineData.setCell(0, createCellData(DEFAULT_ATTR, 'a', 1)); + lineData.setCell(1, createCellData(DEFAULT_ATTR, 'b', 1)); rowFactory.handleSelectionChanged([1, 0], [2, 0], false); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); assert.equal(extractHtml(spans), @@ -348,7 +348,7 @@ describe('DomRendererRowFactory', () => { ); }); it('should force whitespace cells to be rendered above the background', () => { - lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); + lineData.setCell(1, createCellData(DEFAULT_ATTR, 'a', 1)); rowFactory.handleSelectionChanged([0, 0], [2, 0], false); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); assert.equal(extractHtml(spans), @@ -374,9 +374,9 @@ describe('DomRendererRowFactory', () => { }); it('can merge codepoints for equal spacing', () => { - lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); - lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, 'b', 1, 'b'.charCodeAt(0)])); - lineData.setCell(2, CellData.fromCharData([DEFAULT_ATTR, 'c', 1, 'c'.charCodeAt(0)])); + lineData.setCell(0, createCellData(DEFAULT_ATTR, 'a', 1)); + lineData.setCell(1, createCellData(DEFAULT_ATTR, 'b', 1)); + lineData.setCell(2, createCellData(DEFAULT_ATTR, 'c', 1)); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); assert.equal(extractHtml(spans), 'abc' @@ -385,9 +385,9 @@ describe('DomRendererRowFactory', () => { it('should not merge codepoints with different spacing', () => { widthCache.setWidths({ '€': 2 }); - lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); - lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, '€', 1, '€'.charCodeAt(0)])); - lineData.setCell(2, CellData.fromCharData([DEFAULT_ATTR, 'c', 1, 'c'.charCodeAt(0)])); + lineData.setCell(0, createCellData(DEFAULT_ATTR, 'a', 1)); + lineData.setCell(1, createCellData(DEFAULT_ATTR, '€', 1)); + lineData.setCell(2, createCellData(DEFAULT_ATTR, 'c', 1)); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); assert.equal(extractHtml(spans), 'a€c' @@ -395,9 +395,9 @@ describe('DomRendererRowFactory', () => { }); it('should not merge on FG change', () => { - const aColor1 = CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)]); + const aColor1 = createCellData(DEFAULT_ATTR, 'a', 1); aColor1.fg |= Attributes.CM_P16 | 1; - const bColor2 = CellData.fromCharData([DEFAULT_ATTR, 'b', 1, 'b'.charCodeAt(0)]); + const bColor2 = createCellData(DEFAULT_ATTR, 'b', 1); bColor2.fg |= Attributes.CM_P16 | 2; lineData.setCell(0, aColor1); lineData.setCell(1, aColor1); @@ -410,11 +410,11 @@ describe('DomRendererRowFactory', () => { }); it('should not merge cursor cell', () => { - lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); - lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); - lineData.setCell(2, CellData.fromCharData([DEFAULT_ATTR, 'X', 1, 'X'.charCodeAt(0)])); - lineData.setCell(3, CellData.fromCharData([DEFAULT_ATTR, 'b', 1, 'b'.charCodeAt(0)])); - lineData.setCell(4, CellData.fromCharData([DEFAULT_ATTR, 'b', 1, 'b'.charCodeAt(0)])); + lineData.setCell(0, createCellData(DEFAULT_ATTR, 'a', 1)); + lineData.setCell(1, createCellData(DEFAULT_ATTR, 'a', 1)); + lineData.setCell(2, createCellData(DEFAULT_ATTR, 'X', 1)); + lineData.setCell(3, createCellData(DEFAULT_ATTR, 'b', 1)); + lineData.setCell(4, createCellData(DEFAULT_ATTR, 'b', 1)); const spans = rowFactory.createRow(lineData, 0, true, undefined, undefined, 2, false, true, 5, widthCache, -1, -1); assert.equal(extractHtml(spans), 'aaXbb' @@ -453,7 +453,7 @@ describe('DomRendererRowFactory', () => { assert.equal(extractHtml(spans), ' ' ); - lineData.setCell(4, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); + lineData.setCell(4, createCellData(DEFAULT_ATTR, 'a', 1)); spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); assert.equal(extractHtml(spans), ' a' @@ -462,9 +462,9 @@ describe('DomRendererRowFactory', () => { it('should apply correct positive or negative spacing', () => { widthCache.setWidths({ '€': 2, '語': 10, '𝄞': 7 }); // €: too small (+3px), 語: exact, 𝄞: too wide (-2px) - lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); - lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, '€', 1, '€'.charCodeAt(0)])); - lineData.setCell(2, CellData.fromCharData([DEFAULT_ATTR, 'c', 1, 'c'.charCodeAt(0)])); + lineData.setCell(0, createCellData(DEFAULT_ATTR, 'a', 1)); + lineData.setCell(1, createCellData(DEFAULT_ATTR, '€', 1)); + lineData.setCell(2, createCellData(DEFAULT_ATTR, 'c', 1)); lineData.setCell(3, CellData.fromCharData([DEFAULT_ATTR, '語', 2, 'c'.charCodeAt(0)])); lineData.setCell(4, CellData.fromCharData([DEFAULT_ATTR, '𝄞', 1, 'c'.charCodeAt(0)])); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -1, -1); @@ -474,13 +474,13 @@ describe('DomRendererRowFactory', () => { }); it('should not merge across link borders', () => { - lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); - lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); - lineData.setCell(2, CellData.fromCharData([DEFAULT_ATTR, 'x', 1, 'x'.charCodeAt(0)])); - lineData.setCell(3, CellData.fromCharData([DEFAULT_ATTR, 'x', 1, 'x'.charCodeAt(0)])); - lineData.setCell(4, CellData.fromCharData([DEFAULT_ATTR, 'x', 1, 'x'.charCodeAt(0)])); - lineData.setCell(5, CellData.fromCharData([DEFAULT_ATTR, 'b', 1, 'b'.charCodeAt(0)])); - lineData.setCell(6, CellData.fromCharData([DEFAULT_ATTR, 'b', 1, 'b'.charCodeAt(0)])); + lineData.setCell(0, createCellData(DEFAULT_ATTR, 'a', 1)); + lineData.setCell(1, createCellData(DEFAULT_ATTR, 'a', 1)); + lineData.setCell(2, createCellData(DEFAULT_ATTR, 'x', 1)); + lineData.setCell(3, createCellData(DEFAULT_ATTR, 'x', 1)); + lineData.setCell(4, createCellData(DEFAULT_ATTR, 'x', 1)); + lineData.setCell(5, createCellData(DEFAULT_ATTR, 'b', 1)); + lineData.setCell(6, createCellData(DEFAULT_ATTR, 'b', 1)); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, 2, 4); assert.equal(extractHtml(spans), 'aaxxxbb' @@ -488,10 +488,10 @@ describe('DomRendererRowFactory', () => { }); it('empty cells included in link underline', () => { - lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); - lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); - lineData.setCell(2, CellData.fromCharData([DEFAULT_ATTR, 'x', 1, 'x'.charCodeAt(0)])); - lineData.setCell(4, CellData.fromCharData([DEFAULT_ATTR, 'x', 1, 'x'.charCodeAt(0)])); + lineData.setCell(0, createCellData(DEFAULT_ATTR, 'a', 1)); + lineData.setCell(1, createCellData(DEFAULT_ATTR, 'a', 1)); + lineData.setCell(2, createCellData(DEFAULT_ATTR, 'x', 1)); + lineData.setCell(4, createCellData(DEFAULT_ATTR, 'x', 1)); const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, 2, 4); assert.equal(extractHtml(spans), 'aax x' @@ -500,7 +500,7 @@ describe('DomRendererRowFactory', () => { it('link range gets capped to actual line borders', () => { for (let i = 0; i < 10; ++i) { - lineData.setCell(i, CellData.fromCharData([DEFAULT_ATTR, 'a', 1, 'a'.charCodeAt(0)])); + lineData.setCell(i, createCellData(DEFAULT_ATTR, 'a', 1)); } const spans = rowFactory.createRow(lineData, 0, false, undefined, undefined, 0, false, true, 5, widthCache, -100, 100); assert.equal(extractHtml(spans), @@ -519,7 +519,7 @@ describe('DomRendererRowFactory', () => { function createEmptyLineData(cols: number): IBufferLine { const lineData = new BufferLine(cols); for (let i = 0; i < cols; i++) { - lineData.setCell(i, CellData.fromCharData([DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE])); + lineData.setCell(i, NULL_CELL_DATA); } return lineData; } diff --git a/src/browser/services/CharacterJoinerService.test.ts b/src/browser/services/CharacterJoinerService.test.ts index 6b5326d93..a0ccc67d6 100644 --- a/src/browser/services/CharacterJoinerService.test.ts +++ b/src/browser/services/CharacterJoinerService.test.ts @@ -9,7 +9,7 @@ import { CharacterJoinerService } from 'browser/services/CharacterJoinerService' import { BufferLine } from 'common/buffer/BufferLine'; import { IBufferLine } from 'common/Types'; import { CellData } from 'common/buffer/CellData'; -import { MockBufferService } from 'common/TestUtils.test'; +import { MockBufferService, createCellData } from 'common/TestUtils.test'; describe('CharacterJoinerService', () => { let service: ICharacterJoinerService; @@ -25,17 +25,17 @@ describe('CharacterJoinerService', () => { lines.set(4, new BufferLine(0)); lines.set(5, lineData([['a', 0x11111111], [' -> b -> c -> '], ['d', 0x22222222]])); const line6 = lineData([['wi']]); - line6.resize(line6.length + 1, CellData.fromCharData([0, '¥', 2, '¥'.charCodeAt(0)])); - line6.resize(line6.length + 1, CellData.fromCharData([0, '', 0, 0])); + line6.resize(line6.length + 1, createCellData(0, '¥', 2)); + line6.resize(line6.length + 1, createCellData(0, '', 0)); let sub = lineData([['deemo']]); let oldSize = line6.length; - line6.resize(oldSize + sub.length, CellData.fromCharData([0, '', 0, 0])); + line6.resize(oldSize + sub.length, createCellData(0, '', 0)); for (let i = 0; i < sub.length; ++i) line6.setCell(i + oldSize, sub.loadCell(i, new CellData())); line6.resize(line6.length + 1, CellData.fromCharData([0, '\xf0\x9f\x98\x81', 1, 128513])); - line6.resize(line6.length + 1, CellData.fromCharData([0, ' ', 1, ' '.charCodeAt(0)])); + line6.resize(line6.length + 1, createCellData(0, ' ', 1)); sub = lineData([['jiabc']]); oldSize = line6.length; - line6.resize(oldSize + sub.length, CellData.fromCharData([0, '', 0, 0])); + line6.resize(oldSize + sub.length, createCellData(0, '', 0)); for (let i = 0; i < sub.length; ++i) line6.setCell(i + oldSize, sub.loadCell(i, new CellData())); lines.set(6, line6); @@ -272,8 +272,8 @@ function lineData(data: IPartialLineData[]): IBufferLine { const line = data[i][0]; const attr = (data[i][1] || 0) as number; const offset = tline.length; - tline.resize(tline.length + line.split('').length, CellData.fromCharData([0, '', 0, 0])); - line.split('').map((char, idx) => tline.setCell(idx + offset, CellData.fromCharData([attr, char, 1, char.charCodeAt(0)]))); + tline.resize(tline.length + line.split('').length, createCellData(0, '', 0)); + line.split('').map((char, idx) => tline.setCell(idx + offset, createCellData(attr, char, 1))); } return tline; } diff --git a/src/browser/services/SelectionService.test.ts b/src/browser/services/SelectionService.test.ts index 67158def0..8deedb751 100644 --- a/src/browser/services/SelectionService.test.ts +++ b/src/browser/services/SelectionService.test.ts @@ -7,7 +7,7 @@ import { assert } from 'chai'; import { SelectionService, SelectionMode } from './SelectionService'; import { SelectionModel } from 'browser/selection/SelectionModel'; import { IBufferLine } from 'common/Types'; -import { MockBufferService, MockOptionsService, MockCoreService } from 'common/TestUtils.test'; +import { MockBufferService, MockOptionsService, MockCoreService, createCellData } from 'common/TestUtils.test'; import { BufferLine } from 'common/buffer/BufferLine'; import { IBufferService, IOptionsService } from 'common/services/Services'; import { MockCoreBrowserService, MockMouseService, MockRenderService } from 'browser/TestUtils.test'; @@ -57,14 +57,14 @@ describe('SelectionService', () => { function stringToRow(text: string): IBufferLine { const result = new BufferLine(text.length); for (let i = 0; i < text.length; i++) { - result.setCell(i, CellData.fromCharData([0, text.charAt(i), 1, text.charCodeAt(i)])); + result.setCell(i, createCellData(0, text.charAt(i), 1)); } return result; } function stringArrayToRow(chars: string[]): IBufferLine { const line = new BufferLine(chars.length); - chars.map((c, idx) => line.setCell(idx, CellData.fromCharData([0, c, 1, c.charCodeAt(0)]))); + chars.map((c, idx) => line.setCell(idx, createCellData(0, c, 1))); return line; } diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 6e6f0b642..0f982b302 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -13,6 +13,14 @@ import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEventType, ICharset, IModes import { UnicodeV6 } from 'common/input/UnicodeV6'; import { IDecorationOptions, IDecoration } from '@xterm/xterm'; import { Emitter, type IEvent } from 'common/Event'; +import { CellData } from 'common/buffer/CellData'; +import { DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH } from 'common/buffer/Constants'; + +export function createCellData(attr: number, char: string, width: number): CellData { + return CellData.fromCharData([attr, char, width, char.length === 0 ? 0 : char.charCodeAt(0)]); +} + +export const NULL_CELL_DATA = Object.freeze(createCellData(DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH)); export class MockBufferService implements IBufferService { public serviceBrand: any; diff --git a/src/common/buffer/Buffer.test.ts b/src/common/buffer/Buffer.test.ts index f9e3e1b14..9c013c5de 100644 --- a/src/common/buffer/Buffer.test.ts +++ b/src/common/buffer/Buffer.test.ts @@ -6,7 +6,7 @@ import { assert } from 'chai'; import { Buffer } from 'common/buffer/Buffer'; import { CircularList } from 'common/CircularList'; -import { MockOptionsService, MockBufferService, MockLogService } from 'common/TestUtils.test'; +import { MockOptionsService, MockBufferService, MockLogService, createCellData } from 'common/TestUtils.test'; import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { CellData } from 'common/buffer/CellData'; import { ExtendedAttrs } from 'common/buffer/AttributeData'; @@ -1105,10 +1105,10 @@ describe('Buffer', () => { describe ('translateBufferLineToString', () => { it('should handle selecting a section of ascii text', () => { const line = new BufferLine(4); - line.setCell(0, CellData.fromCharData([ 0, 'a', 1, 'a'.charCodeAt(0)])); - line.setCell(1, CellData.fromCharData([ 0, 'b', 1, 'b'.charCodeAt(0)])); - line.setCell(2, CellData.fromCharData([ 0, 'c', 1, 'c'.charCodeAt(0)])); - line.setCell(3, CellData.fromCharData([ 0, 'd', 1, 'd'.charCodeAt(0)])); + line.setCell(0, createCellData(0, 'a', 1)); + line.setCell(1, createCellData(0, 'b', 1)); + line.setCell(2, createCellData(0, 'c', 1)); + line.setCell(3, createCellData(0, 'd', 1)); buffer.lines.set(0, line); const str = buffer.translateBufferLineToString(0, true, 0, 2); @@ -1117,9 +1117,9 @@ describe('Buffer', () => { it('should handle a cut-off double width character by including it', () => { const line = new BufferLine(3); - line.setCell(0, CellData.fromCharData([ 0, '語', 2, 35486 ])); - line.setCell(1, CellData.fromCharData([ 0, '', 0, 0])); - line.setCell(2, CellData.fromCharData([ 0, 'a', 1, 'a'.charCodeAt(0)])); + line.setCell(0, createCellData(0, '語', 2)); + line.setCell(1, createCellData(0, '', 0)); + line.setCell(2, createCellData(0, 'a', 1)); buffer.lines.set(0, line); const str1 = buffer.translateBufferLineToString(0, true, 0, 1); @@ -1128,9 +1128,9 @@ describe('Buffer', () => { it('should handle a zero width character in the middle of the string by not including it', () => { const line = new BufferLine(3); - line.setCell(0, CellData.fromCharData([ 0, '語', 2, '語'.charCodeAt(0) ])); - line.setCell(1, CellData.fromCharData([ 0, '', 0, 0])); - line.setCell(2, CellData.fromCharData([ 0, 'a', 1, 'a'.charCodeAt(0)])); + line.setCell(0, createCellData(0, '語', 2)); + line.setCell(1, createCellData(0, '', 0)); + line.setCell(2, createCellData(0, 'a', 1)); buffer.lines.set(0, line); const str0 = buffer.translateBufferLineToString(0, true, 0, 1); @@ -1145,8 +1145,8 @@ describe('Buffer', () => { it('should handle single width emojis', () => { const line = new BufferLine(2); - line.setCell(0, CellData.fromCharData([ 0, '😁', 1, '😁'.charCodeAt(0) ])); - line.setCell(1, CellData.fromCharData([ 0, 'a', 1, 'a'.charCodeAt(0)])); + line.setCell(0, createCellData(0, '😁', 1)); + line.setCell(1, createCellData(0, 'a', 1)); buffer.lines.set(0, line); const str1 = buffer.translateBufferLineToString(0, true, 0, 1); @@ -1158,8 +1158,8 @@ describe('Buffer', () => { it('should handle double width emojis', () => { const line = new BufferLine(2); - line.setCell(0, CellData.fromCharData([ 0, '😁', 2, '😁'.charCodeAt(0) ])); - line.setCell(1, CellData.fromCharData([ 0, '', 0, 0])); + line.setCell(0, createCellData(0, '😁', 2)); + line.setCell(1, createCellData(0, '', 0)); buffer.lines.set(0, line); const str1 = buffer.translateBufferLineToString(0, true, 0, 1); @@ -1169,9 +1169,9 @@ describe('Buffer', () => { assert.equal(str2, '😁'); const line2 = new BufferLine(3); - line2.setCell(0, CellData.fromCharData([ 0, '😁', 2, '😁'.charCodeAt(0) ])); - line2.setCell(1, CellData.fromCharData([ 0, '', 0, 0])); - line2.setCell(2, CellData.fromCharData([ 0, 'a', 1, 'a'.charCodeAt(0)])); + line2.setCell(0, createCellData(0, '😁', 2)); + line2.setCell(1, createCellData(0, '', 0)); + line2.setCell(2, createCellData(0, 'a', 1)); buffer.lines.set(0, line2); const str3 = buffer.translateBufferLineToString(0, true, 0, 3); diff --git a/src/common/buffer/BufferLine.test.ts b/src/common/buffer/BufferLine.test.ts index eaceaa45f..100b730d9 100644 --- a/src/common/buffer/BufferLine.test.ts +++ b/src/common/buffer/BufferLine.test.ts @@ -8,6 +8,7 @@ import { CellData } from 'common/buffer/CellData'; import { CharData, IBufferLine } from '../Types'; import { assert } from 'chai'; import { AttributeData } from 'common/buffer/AttributeData'; +import { createCellData, NULL_CELL_DATA } from 'common/TestUtils.test'; class TestBufferLine extends BufferLine { @@ -24,12 +25,6 @@ class TestBufferLine extends BufferLine { } } -function createCellData(attr: number, char: string, width: number): CellData { - return CellData.fromCharData([attr, char, width, char.length === 0 ? 0 : char.charCodeAt(0)]); -} - -const NULL_CELL_DATA = Object.freeze(createCellData(DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH)); - describe('AttributeData', () => { describe('extended attributes', () => { it('hasExtendedAttrs', () => {