Refactor tests to be consistent for both runtimes
This commit is contained in:
parent
8b5fb17603
commit
2aaf1c678b
12
bunfig.toml
Normal file
12
bunfig.toml
Normal file
@ -0,0 +1,12 @@
|
||||
logLevel = "debug" # "debug" | "warn" | "error"
|
||||
telemetry = false
|
||||
|
||||
[install.lockfile]
|
||||
save = false
|
||||
|
||||
[test]
|
||||
# always enable coverage
|
||||
coverage = true
|
||||
|
||||
# disable code coverage counting test files
|
||||
coverageSkipTestFiles = true
|
@ -3,14 +3,12 @@
|
||||
*/
|
||||
|
||||
import { IRuntime, RunTimeType } from '../common/mod.ts';
|
||||
import BunFFI from './ffi.ts';
|
||||
import BunTerminalIO from './terminal_io.ts';
|
||||
import BunFileIO from './file_io.ts';
|
||||
|
||||
const BunRuntime: IRuntime = {
|
||||
name: RunTimeType.Bun,
|
||||
file: BunFileIO,
|
||||
ffi: BunFFI,
|
||||
term: BunTerminalIO,
|
||||
onEvent: (eventName: string, handler) => process.on(eventName, handler),
|
||||
onExit: (cb: () => void): void => {
|
||||
|
@ -1,14 +1,13 @@
|
||||
/**
|
||||
* Wrap the runtime-specific hook into stdin
|
||||
*/
|
||||
import { ITerminal, ITerminalSize } from '../common/mod.ts';
|
||||
import {
|
||||
defaultTerminalSize,
|
||||
ITerminal,
|
||||
ITerminalSize,
|
||||
} from '../common/mod.ts';
|
||||
import Ansi from '../common/ansi.ts';
|
||||
|
||||
const defaultTerminalSize: ITerminalSize = {
|
||||
rows: 24,
|
||||
cols: 80,
|
||||
};
|
||||
|
||||
const BunTerminalIO: ITerminal = {
|
||||
// Deno only returns arguments passed to the script, so
|
||||
// remove the bun runtime executable, and entry script arguments
|
||||
|
@ -1,42 +1,35 @@
|
||||
/**
|
||||
* Adapt the bun test interface to the shared testing interface
|
||||
*/
|
||||
import { expect, test as btest } from 'bun:test';
|
||||
import { describe, expect, test } from 'bun:test';
|
||||
import { ITestBase } from '../common/mod.ts';
|
||||
|
||||
class TestBase implements ITestBase {
|
||||
test(name: string, fn: () => void) {
|
||||
return btest(name, fn);
|
||||
}
|
||||
|
||||
assertEquals(actual: unknown, expected: unknown): void {
|
||||
return expect(actual).toEqual(expected);
|
||||
}
|
||||
|
||||
assertExists(actual: unknown): void {
|
||||
return expect(actual).toBeDefined();
|
||||
}
|
||||
|
||||
assertInstanceOf(actual: unknown, expectedType: any): void {
|
||||
return expect(actual).toBeInstanceOf(expectedType);
|
||||
}
|
||||
|
||||
assertNotEquals(actual: unknown, expected: unknown): void {
|
||||
return expect(actual).not.toBe(expected);
|
||||
}
|
||||
|
||||
assertFalse(actual: boolean): void {
|
||||
return expect(actual).toBe(false);
|
||||
}
|
||||
|
||||
assertTrue(actual: boolean): void {
|
||||
return expect(actual).toBe(true);
|
||||
}
|
||||
|
||||
assertStrictEquals(actual: unknown, expected: unknown): void {
|
||||
return expect(actual).toBe(expected);
|
||||
}
|
||||
export function testSuite(testObj: any) {
|
||||
Object.keys(testObj).forEach((group) => {
|
||||
describe(group, () => {
|
||||
const groupObj = testObj[group];
|
||||
Object.keys(groupObj).forEach((testName) => {
|
||||
test(testName, groupObj[testName]);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const testBase = new TestBase();
|
||||
export default testBase;
|
||||
const BunTestBase: ITestBase = {
|
||||
assertEquals: (actual: unknown, expected: unknown) =>
|
||||
expect(actual).toEqual(expected),
|
||||
assertExists: (actual: unknown) => expect(actual).toBeDefined(),
|
||||
assertFalse: (actual: boolean) => expect(actual).toBe(false),
|
||||
assertInstanceOf: (actual: unknown, expectedType: any) =>
|
||||
expect(actual).toBeInstanceOf(expectedType),
|
||||
assertNotEquals: (actual: unknown, expected: unknown) =>
|
||||
expect(actual).not.toBe(expected),
|
||||
assertStrictEquals: (actual: unknown, expected: unknown) =>
|
||||
expect(actual).toBe(expected),
|
||||
assertTrue: (actual: boolean) => expect(actual).toBe(true),
|
||||
test,
|
||||
testGroup: describe,
|
||||
testSuite,
|
||||
};
|
||||
|
||||
export default BunTestBase;
|
||||
|
177
src/common/all_test.ts
Normal file
177
src/common/all_test.ts
Normal file
@ -0,0 +1,177 @@
|
||||
import { getTestRunner } from './runtime.ts';
|
||||
import { Ansi, KeyCommand, readKey } from './ansi.ts';
|
||||
import { Document, Row } from './document.ts';
|
||||
import Buffer from './buffer.ts';
|
||||
import {
|
||||
chars,
|
||||
ctrl_key,
|
||||
is_ascii,
|
||||
is_control,
|
||||
noop,
|
||||
ord,
|
||||
strlen,
|
||||
truncate,
|
||||
} from './utils.ts';
|
||||
import { Editor } from './editor.ts';
|
||||
import { defaultTerminalSize } from './termios.ts';
|
||||
|
||||
const t = await getTestRunner();
|
||||
|
||||
const testObj = {
|
||||
'ANSI::ANSI utils': {
|
||||
'Ansi.moveCursor': () => {
|
||||
t.assertEquals(Ansi.moveCursor(1, 2), '\x1b[2;3H');
|
||||
},
|
||||
'Ansi.moveCursorForward': () => {
|
||||
t.assertEquals(Ansi.moveCursorForward(2), '\x1b[2C');
|
||||
},
|
||||
'Ansi.moveCursorDown': () => {
|
||||
t.assertEquals(Ansi.moveCursorDown(7), '\x1b[7B');
|
||||
},
|
||||
},
|
||||
'ANSI::readKey()': {
|
||||
'readKey passthrough': () => {
|
||||
// Ignore unhandled escape sequences
|
||||
t.assertEquals(readKey('\x1b[]'), '\x1b[]');
|
||||
|
||||
// Pass explicitly mapped values right through
|
||||
t.assertEquals(readKey(KeyCommand.ArrowUp), KeyCommand.ArrowUp);
|
||||
t.assertEquals(readKey(KeyCommand.Home), KeyCommand.Home);
|
||||
t.assertEquals(readKey(KeyCommand.Delete), KeyCommand.Delete);
|
||||
},
|
||||
'readKey Home': () => {
|
||||
['\x1b[1~', '\x1b[7~', '\x1b[H', '\x1bOH'].forEach((code) => {
|
||||
t.assertEquals(readKey(code), KeyCommand.Home);
|
||||
});
|
||||
},
|
||||
'readKey End': () => {
|
||||
['\x1b[4~', '\x1b[8~', '\x1b[F', '\x1bOF'].forEach((code) => {
|
||||
t.assertEquals(readKey(code), KeyCommand.End);
|
||||
});
|
||||
},
|
||||
},
|
||||
Buffer: {
|
||||
'Buffer exists': () => {
|
||||
const b = new Buffer();
|
||||
t.assertInstanceOf(b, Buffer);
|
||||
t.assertEquals(b.strlen(), 0);
|
||||
},
|
||||
'Buffer.appendLine': () => {
|
||||
const b = new Buffer();
|
||||
|
||||
// Carriage return and line feed
|
||||
b.appendLine();
|
||||
t.assertEquals(b.strlen(), 2);
|
||||
|
||||
b.clear();
|
||||
t.assertEquals(b.strlen(), 0);
|
||||
|
||||
b.appendLine('foo');
|
||||
t.assertEquals(b.strlen(), 5);
|
||||
},
|
||||
'Buffer.append': () => {
|
||||
const b = new Buffer();
|
||||
|
||||
b.append('foobar');
|
||||
t.assertEquals(b.strlen(), 6);
|
||||
b.clear();
|
||||
|
||||
b.append('foobar', 3);
|
||||
t.assertEquals(b.strlen(), 3);
|
||||
},
|
||||
'Buffer.flush': async () => {
|
||||
const b = new Buffer();
|
||||
b.appendLine('foobarbaz' + Ansi.ClearLine);
|
||||
t.assertEquals(b.strlen(), 14);
|
||||
|
||||
await b.flush();
|
||||
|
||||
t.assertEquals(b.strlen(), 0);
|
||||
},
|
||||
},
|
||||
Document: {
|
||||
'Document.empty': () => {
|
||||
const doc = Document.empty();
|
||||
t.assertEquals(doc.numRows, 0);
|
||||
t.assertTrue(doc.isEmpty());
|
||||
t.assertEquals(doc.row(0), null);
|
||||
},
|
||||
'Document.appendRow': () => {
|
||||
const doc = Document.empty();
|
||||
doc.appendRow('foobar');
|
||||
t.assertEquals(doc.numRows, 1);
|
||||
t.assertFalse(doc.isEmpty());
|
||||
t.assertInstanceOf(doc.row(0), Row);
|
||||
},
|
||||
},
|
||||
'Document::Row': {
|
||||
'new Row': () => {
|
||||
const row = new Row();
|
||||
t.assertEquals(row.toString(), '');
|
||||
},
|
||||
},
|
||||
Editor: {
|
||||
'new Editor': () => {
|
||||
const e = new Editor(defaultTerminalSize);
|
||||
t.assertInstanceOf(e, Editor);
|
||||
},
|
||||
},
|
||||
'Util::Misc fns': {
|
||||
'noop fn': () => {
|
||||
t.assertExists(noop);
|
||||
t.assertEquals(noop(), undefined);
|
||||
},
|
||||
},
|
||||
'Util::String fns': {
|
||||
'ord() returns 256 on invalid string': () => {
|
||||
t.assertEquals(ord(''), 256);
|
||||
},
|
||||
'ord() returns number on valid string': () => {
|
||||
t.assertEquals(ord('a'), 97);
|
||||
},
|
||||
'chars() properly splits strings into unicode characters': () => {
|
||||
t.assertEquals(chars('😺😸😹'), ['😺', '😸', '😹']);
|
||||
},
|
||||
'ctrl_key() returns expected values': () => {
|
||||
const ctrl_a = ctrl_key('a');
|
||||
t.assertTrue(is_control(ctrl_a));
|
||||
t.assertEquals(ctrl_a, String.fromCodePoint(0x01));
|
||||
|
||||
const invalid = ctrl_key('😺');
|
||||
t.assertFalse(is_control(invalid));
|
||||
t.assertEquals(invalid, '😺');
|
||||
},
|
||||
'is_ascii() properly discerns ascii chars': () => {
|
||||
t.assertTrue(is_ascii('asjyverkjhsdf1928374'));
|
||||
t.assertFalse(is_ascii('😺acalskjsdf'));
|
||||
t.assertFalse(is_ascii('ab😺ac'));
|
||||
},
|
||||
'is_control() works as expected': () => {
|
||||
t.assertFalse(is_control('abc'));
|
||||
t.assertTrue(is_control(String.fromCodePoint(0x01)));
|
||||
t.assertFalse(is_control('😺'));
|
||||
},
|
||||
'strlen() returns expected length for ascii strings': () => {
|
||||
t.assertEquals(strlen('abc'), 'abc'.length);
|
||||
},
|
||||
'strlen() returns expected length for multibyte characters': () => {
|
||||
t.assertEquals(strlen('😺😸😹'), 3);
|
||||
t.assertNotEquals('😺😸😹'.length, strlen('😺😸😹'));
|
||||
|
||||
// Skin tone modifier + base character
|
||||
t.assertEquals(strlen('🤰🏼'), 2);
|
||||
t.assertNotEquals('🤰🏼'.length, strlen('🤰🏼'));
|
||||
|
||||
// This has 4 sub-characters, and 3 zero-width-joiners
|
||||
t.assertEquals(strlen('👨👩👧👦'), 7);
|
||||
t.assertNotEquals('👨👩👧👦'.length, strlen('👨👩👧👦'));
|
||||
},
|
||||
'truncate() shortens strings': () => {
|
||||
t.assertEquals(truncate('😺😸😹', 1), '😺');
|
||||
t.assertEquals(truncate('😺😸😹', 5), '😺😸😹');
|
||||
t.assertEquals(truncate('👨👩👧👦', 5), '👨👩👧');
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
t.testSuite(testObj);
|
@ -4,10 +4,6 @@
|
||||
|
||||
export const ANSI_PREFIX = '\x1b[';
|
||||
|
||||
function esc(pieces: TemplateStringsArray): string {
|
||||
return ANSI_PREFIX + pieces[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* ANSI escapes for various inputs
|
||||
*/
|
||||
@ -26,12 +22,12 @@ export enum KeyCommand {
|
||||
}
|
||||
|
||||
export const Ansi = {
|
||||
ClearLine: esc`K`,
|
||||
ClearScreen: esc`2J`,
|
||||
ResetCursor: esc`H`,
|
||||
HideCursor: esc`?25l`,
|
||||
ShowCursor: esc`?25h`,
|
||||
GetCursorLocation: esc`6n`,
|
||||
ClearLine: ANSI_PREFIX + 'K',
|
||||
ClearScreen: ANSI_PREFIX + '2J',
|
||||
ResetCursor: ANSI_PREFIX + 'H',
|
||||
HideCursor: ANSI_PREFIX + '?25l',
|
||||
ShowCursor: ANSI_PREFIX + '?25h',
|
||||
GetCursorLocation: ANSI_PREFIX + '6n',
|
||||
moveCursor: function moveCursor(row: number, col: number): string {
|
||||
// Convert to 1-based counting
|
||||
row++;
|
||||
@ -57,15 +53,15 @@ export function readKey(parsed: string): string {
|
||||
|
||||
// Some keycodes have multiple potential inputs
|
||||
switch (parsed) {
|
||||
case '\x1bOH':
|
||||
case '\x1b[7~':
|
||||
case '\x1b[1~':
|
||||
case '\x1b[7~':
|
||||
case '\x1bOH':
|
||||
case '\x1b[H':
|
||||
return KeyCommand.Home;
|
||||
|
||||
case '\x1bOF':
|
||||
case '\x1b[8~':
|
||||
case '\x1b[4~':
|
||||
case '\x1b[8~':
|
||||
case '\x1bOF':
|
||||
case '\x1b[F':
|
||||
return KeyCommand.End;
|
||||
|
||||
|
@ -1,33 +0,0 @@
|
||||
import { getTestRunner } from './mod.ts';
|
||||
import Ansi, { KeyCommand, readKey } from './ansi.ts';
|
||||
|
||||
getTestRunner().then((t) => {
|
||||
t.test('Ansi.moveCursor', () => {
|
||||
t.assertEquals(Ansi.moveCursor(1, 2), '\x1b[2;3H');
|
||||
});
|
||||
|
||||
t.test('Ansi.moveCursorForward', () => {
|
||||
t.assertEquals(Ansi.moveCursorForward(2), '\x1b[2C');
|
||||
});
|
||||
|
||||
t.test('Ansi.moveCursorDown', () => {
|
||||
t.assertEquals(Ansi.moveCursorDown(7), '\x1b[7B');
|
||||
});
|
||||
|
||||
t.test('readKey', () => {
|
||||
// Ignore unhandled escape sequences
|
||||
t.assertEquals(readKey('\x1b[]'), '\x1b[]');
|
||||
|
||||
// Pass explicitly mapped values right through
|
||||
t.assertEquals(readKey(KeyCommand.ArrowUp), KeyCommand.ArrowUp);
|
||||
t.assertEquals(readKey(KeyCommand.Home), KeyCommand.Home);
|
||||
|
||||
['\x1bOH', '\x1b[7~', '\x1b[1~', '\x1b[H'].forEach((code) => {
|
||||
t.assertEquals(readKey(code), KeyCommand.Home);
|
||||
});
|
||||
|
||||
['\x1bOF', '\x1b[8~', '\x1b[4~', '\x1b[F'].forEach((code) => {
|
||||
t.assertEquals(readKey(code), KeyCommand.End);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
import { strlen, truncate } from './utils.ts';
|
||||
import { getRuntime, importForRuntime } from './runtime.ts';
|
||||
import { getRuntime } from './runtime.ts';
|
||||
|
||||
class Buffer {
|
||||
#b = '';
|
||||
@ -23,7 +23,7 @@ class Buffer {
|
||||
* Output the contents of the buffer into stdout
|
||||
*/
|
||||
public async flush() {
|
||||
const term = await importForRuntime('terminal_io');
|
||||
const { term } = await getRuntime();
|
||||
await term.writeStdout(this.#b);
|
||||
this.clear();
|
||||
}
|
||||
|
@ -1,45 +0,0 @@
|
||||
import { getTestRunner } from './runtime.ts';
|
||||
import Buffer from './buffer.ts';
|
||||
|
||||
getTestRunner().then((t) => {
|
||||
t.test('Buffer exists', () => {
|
||||
const b = new Buffer();
|
||||
t.assertInstanceOf(b, Buffer);
|
||||
t.assertEquals(b.strlen(), 0);
|
||||
});
|
||||
|
||||
t.test('Buffer.appendLine', () => {
|
||||
const b = new Buffer();
|
||||
|
||||
// Carriage return and line feed
|
||||
b.appendLine();
|
||||
t.assertEquals(b.strlen(), 2);
|
||||
|
||||
b.clear();
|
||||
t.assertEquals(b.strlen(), 0);
|
||||
|
||||
b.appendLine('foo');
|
||||
t.assertEquals(b.strlen(), 5);
|
||||
});
|
||||
|
||||
t.test('Buffer.append', () => {
|
||||
const b = new Buffer();
|
||||
|
||||
b.append('foobar');
|
||||
t.assertEquals(b.strlen(), 6);
|
||||
b.clear();
|
||||
|
||||
b.append('foobar', 3);
|
||||
t.assertEquals(b.strlen(), 3);
|
||||
});
|
||||
|
||||
t.test('Buffer.flush', async () => {
|
||||
const b = new Buffer();
|
||||
b.append('foobarbaz');
|
||||
t.assertEquals(b.strlen(), 9);
|
||||
|
||||
await b.flush();
|
||||
|
||||
t.assertEquals(b.strlen(), 0);
|
||||
});
|
||||
});
|
@ -55,7 +55,7 @@ export class Document {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected appendRow(s: string): void {
|
||||
public appendRow(s: string): void {
|
||||
this.#rows.push(new Row(s));
|
||||
}
|
||||
}
|
||||
|
@ -95,11 +95,6 @@ export interface IRuntime {
|
||||
*/
|
||||
name: RunTimeType;
|
||||
|
||||
/**
|
||||
* Runtime-specific FFI
|
||||
*/
|
||||
ffi: IFFI;
|
||||
|
||||
/**
|
||||
* Runtime-specific terminal functionality
|
||||
*/
|
||||
|
@ -1,10 +1,15 @@
|
||||
import { die, getRuntime, IFFI } from './mod.ts';
|
||||
import { die, IFFI, importForRuntime, ITerminalSize } from './mod.ts';
|
||||
|
||||
export const STDIN_FILENO = 0;
|
||||
export const TCSANOW = 0;
|
||||
|
||||
export const TERMIOS_SIZE = 60;
|
||||
|
||||
export const defaultTerminalSize: ITerminalSize = {
|
||||
rows: 24,
|
||||
cols: 80,
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation to toggle raw mode
|
||||
*/
|
||||
@ -112,7 +117,7 @@ export const getTermios = async () => {
|
||||
}
|
||||
|
||||
// Get the runtime-specific ffi wrappers
|
||||
const { ffi } = await getRuntime();
|
||||
const ffi = await importForRuntime('ffi');
|
||||
termiosSingleton = new Termios(ffi);
|
||||
|
||||
return termiosSingleton;
|
||||
|
@ -15,12 +15,14 @@ export interface IPoint {
|
||||
* The shared test interface, so tests can be run by both runtimes
|
||||
*/
|
||||
export interface ITestBase {
|
||||
test(name: string, fn: () => void): void;
|
||||
assertEquals(actual: unknown, expected: unknown): void;
|
||||
assertExists(actual: unknown): void;
|
||||
assertFalse(actual: boolean): void;
|
||||
assertInstanceOf(actual: unknown, expectedType: any): void;
|
||||
assertNotEquals(actual: unknown, expected: unknown): void;
|
||||
assertStrictEquals(actual: unknown, expected: unknown): void;
|
||||
assertExists(actual: unknown): void;
|
||||
assertInstanceOf(actual: unknown, expectedType: any): void;
|
||||
assertTrue(actual: boolean): void;
|
||||
assertFalse(actual: boolean): void;
|
||||
test(name: string, fn: () => void, timeout?: number): void;
|
||||
testGroup(name: string, fn: () => void): void;
|
||||
testSuite(testObj: any): void;
|
||||
}
|
||||
|
@ -1,74 +0,0 @@
|
||||
import { getTestRunner } from './mod.ts';
|
||||
import {
|
||||
chars,
|
||||
ctrl_key,
|
||||
is_ascii,
|
||||
is_control,
|
||||
noop,
|
||||
ord,
|
||||
strlen,
|
||||
truncate,
|
||||
} from './utils.ts';
|
||||
|
||||
getTestRunner().then((t) => {
|
||||
t.test('noop fn', () => {
|
||||
t.assertExists(noop);
|
||||
t.assertEquals(noop(), undefined);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Strings
|
||||
// ---------------------------------------------------------------------------
|
||||
t.test('ord fn returns 256 on invalid string', () => {
|
||||
t.assertEquals(ord(''), 256);
|
||||
});
|
||||
|
||||
t.test('chars fn properly splits strings into unicode characters', () => {
|
||||
t.assertEquals(chars('😺😸😹'), ['😺', '😸', '😹']);
|
||||
});
|
||||
|
||||
t.test('ctrl_key fn returns expected values', () => {
|
||||
const ctrl_a = ctrl_key('a');
|
||||
t.assertTrue(is_control(ctrl_a));
|
||||
t.assertEquals(ctrl_a, String.fromCodePoint(0x01));
|
||||
|
||||
const invalid = ctrl_key('😺');
|
||||
t.assertFalse(is_control(invalid));
|
||||
t.assertEquals(invalid, '😺');
|
||||
});
|
||||
|
||||
t.test('is_ascii properly discerns ascii chars', () => {
|
||||
t.assertTrue(is_ascii('asjyverkjhsdf1928374'));
|
||||
t.assertFalse(is_ascii('😺acalskjsdf'));
|
||||
t.assertFalse(is_ascii('ab😺ac'));
|
||||
});
|
||||
|
||||
t.test('is_control fn works as expected', () => {
|
||||
t.assertFalse(is_control('abc'));
|
||||
t.assertTrue(is_control(String.fromCodePoint(0x01)));
|
||||
t.assertFalse(is_control('😺'));
|
||||
});
|
||||
|
||||
t.test('strlen fn returns expected length for ascii strings', () => {
|
||||
t.assertEquals(strlen('abc'), 'abc'.length);
|
||||
});
|
||||
|
||||
t.test('strlen fn returns expected length for multibyte characters', () => {
|
||||
t.assertEquals(strlen('😺😸😹'), 3);
|
||||
t.assertNotEquals('😺😸😹'.length, strlen('😺😸😹'));
|
||||
|
||||
// Skin tone modifier + base character
|
||||
t.assertEquals(strlen('🤰🏼'), 2);
|
||||
t.assertNotEquals('🤰🏼'.length, strlen('🤰🏼'));
|
||||
|
||||
// This has 4 sub-characters, and 3 zero-width-joiners
|
||||
t.assertEquals(strlen('👨👩👧👦'), 7);
|
||||
t.assertNotEquals('👨👩👧👦'.length, strlen('👨👩👧👦'));
|
||||
});
|
||||
|
||||
t.test('truncate shortens strings', () => {
|
||||
t.assertEquals(truncate('😺😸😹', 1), '😺');
|
||||
t.assertEquals(truncate('😺😸😹', 5), '😺😸😹');
|
||||
t.assertEquals(truncate('👨👩👧👦', 5), '👨👩👧');
|
||||
});
|
||||
});
|
@ -2,14 +2,12 @@
|
||||
* The main entrypoint when using Deno as the runtime
|
||||
*/
|
||||
import { IRuntime, RunTimeType } from '../common/mod.ts';
|
||||
import DenoFFI from './ffi.ts';
|
||||
import DenoTerminalIO from './terminal_io.ts';
|
||||
import DenoFileIO from './file_io.ts';
|
||||
|
||||
const DenoRuntime: IRuntime = {
|
||||
name: RunTimeType.Deno,
|
||||
file: DenoFileIO,
|
||||
ffi: DenoFFI,
|
||||
term: DenoTerminalIO,
|
||||
onEvent: (eventName: string, handler) =>
|
||||
globalThis.addEventListener(eventName, handler),
|
||||
|
@ -9,43 +9,34 @@ const {
|
||||
assertStrictEquals,
|
||||
} = stdAssert;
|
||||
|
||||
class TestBase implements ITestBase {
|
||||
test(name: string, fn: () => void): void {
|
||||
return Deno.test(name, fn);
|
||||
}
|
||||
export function testSuite(testObj: any) {
|
||||
Object.keys(testObj).forEach((group) => {
|
||||
const groupObj = testObj[group];
|
||||
Object.keys(groupObj).forEach((testName) => {
|
||||
Deno.test(testName, groupObj[testName]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
assertEquals(actual: unknown, expected: unknown): void {
|
||||
return assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
assertStrictEquals(actual: unknown, expected: unknown) {
|
||||
return assertStrictEquals(actual, expected);
|
||||
}
|
||||
|
||||
assertNotEquals(actual: unknown, expected: unknown): void {
|
||||
return assertNotEquals(actual, expected);
|
||||
}
|
||||
|
||||
assertExists(actual: unknown, msg?: string): void {
|
||||
return assertExists(actual, msg);
|
||||
}
|
||||
|
||||
assertInstanceOf(actual: unknown, expectedType: any): void {
|
||||
return assertInstanceOf(actual, expectedType);
|
||||
}
|
||||
|
||||
assertTrue(actual: boolean): void {
|
||||
const DenoTestBase: ITestBase = {
|
||||
assertEquals,
|
||||
assertExists,
|
||||
assertInstanceOf,
|
||||
assertNotEquals,
|
||||
assertStrictEquals,
|
||||
assertTrue: function (actual: boolean): void {
|
||||
if (actual !== true) {
|
||||
throw new AssertionError(`actual: "${actual}" expected to be true"`);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
assertFalse(actual: boolean): void {
|
||||
if (actual !== false) {
|
||||
throw new AssertionError(`actual: "${actual}" expected to be false"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
test: Deno.test,
|
||||
testGroup: (_name: string, fn) => fn(),
|
||||
testSuite,
|
||||
};
|
||||
|
||||
const testBase = new TestBase();
|
||||
export default testBase;
|
||||
export default DenoTestBase;
|
||||
|
Loading…
Reference in New Issue
Block a user