Use node apis for test setup, refactor a bunch of runtime stuff
All checks were successful
timw4mail/scroll/pipeline/head This commit looks good

This commit is contained in:
Timothy Warren 2024-07-11 17:27:49 -04:00
parent b2169cf54b
commit 2c21bf0c9b
14 changed files with 155 additions and 171 deletions

View File

@ -3,10 +3,9 @@
*/
import { IRuntime, RunTimeType } from '../common/runtime.ts';
import TerminalIO from '../tsx/terminal_io.ts';
import FileIO from '../tsx/file_io.ts';
import process from 'node:process';
import { process } from '../common/runtime/node.ts';
import TerminalIO from '../common/runtime/terminal_io.ts';
import FileIO from '../common/runtime/file_io.ts';
/**
* The Bun Runtime implementation

View File

@ -1,11 +1,10 @@
/**
* Adapt the bun test interface to the shared testing interface
*/
import { deepStrictEqual, notStrictEqual, strictEqual } from 'node:assert';
import { describe, test } from 'bun:test';
import { ITestBase } from '../common/types.ts';
export function testSuite(testObj: any) {
import AbstractTestBase from '../common/runtime/test_base.ts';
class BunTestBase extends AbstractTestBase {
public static testSuite(testObj: any): void {
Object.keys(testObj).forEach((group) => {
describe(group, () => {
const groupObj = testObj[group];
@ -14,21 +13,7 @@ export function testSuite(testObj: any) {
});
});
});
}
}
const BunTestBase: ITestBase = {
assertEquivalent: (actual: unknown, expected: unknown) =>
deepStrictEqual(actual, expected),
assertExists: (actual: unknown) => notStrictEqual(actual, undefined),
assertFalse: (actual: boolean) => strictEqual(actual, false),
assertInstanceOf: (actual: unknown, expectedType: any) =>
strictEqual(actual instanceof expectedType, true),
assertNotEquals: (actual: unknown, expected: unknown) =>
notStrictEqual(actual, expected),
assertEquals: (actual: unknown, expected: unknown) =>
strictEqual(actual, expected),
assertTrue: (actual: boolean) => strictEqual(actual, true),
testSuite,
};
export default BunTestBase;

View File

@ -1,7 +1,7 @@
import Row from './row.ts';
import { arrayInsert, maxAdd, minSub } from './fns.ts';
import Option, { None, Some } from './option.ts';
import { getRuntime, logDebug } from './runtime.ts';
import { getRuntime, logDebug, logWarning } from './runtime.ts';
import { Position, SearchDirection } from './types.ts';
export class Document {
@ -17,7 +17,7 @@ export class Document {
this.dirty = false;
}
get numRows(): number {
public get numRows(): number {
return this.#rows.length;
}
@ -66,6 +66,10 @@ export class Document {
direction: SearchDirection = SearchDirection.Forward,
): Option<Position> {
if (at.y >= this.numRows) {
logWarning('Trying to search beyond the end of the current file', {
at,
document: this,
});
return None;
}

View File

@ -1,6 +1,6 @@
import process from 'node:process';
import { process } from './runtime/node.ts';
import { readKey } from './fns.ts';
import { getRuntime, logError } from './runtime.ts';
import { getRuntime, logError, logWarning } from './runtime.ts';
import Editor from './editor.ts';
export async function main() {
@ -43,7 +43,9 @@ export async function main() {
for await (const char of term.inputLoop()) {
const parsed = readKey(char);
if (char.length === 0 || parsed.length === 0) {
continue;
logWarning('Empty input returned from runtime input loop');
return;
}
// Process input

View File

@ -1,7 +1,7 @@
/**
* Functions/Methods that depend on the current runtime to function
*/
import process from 'node:process';
import { process } from './runtime/node.ts';
import Ansi from './ansi.ts';
import { IRuntime, ITerminalSize, ITestBase } from './types.ts';
import { noop } from './fns.ts';

View File

@ -1,9 +1,9 @@
import { appendFile, readFile, writeFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { IFileIO } from '../common/runtime.ts';
import { IFileIO } from '../runtime.ts';
const TsxFileIO: IFileIO = {
const CommonFileIO: IFileIO = {
openFile: async function (path: string): Promise<string> {
const filePath = resolve(path);
const contents = await readFile(filePath, { encoding: 'utf8' });
@ -22,4 +22,4 @@ const TsxFileIO: IFileIO = {
},
};
export default TsxFileIO;
export default CommonFileIO;

View File

@ -0,0 +1,3 @@
import * as process from 'node:process';
export { process };

View File

@ -1,12 +1,11 @@
import process from 'node:process';
import { process } from './node.ts';
import { readKey } from '../fns.ts';
import { ITerminal, ITerminalSize } from '../types.ts';
import { readKey } from '../common/fns.ts';
import { ITerminal, ITerminalSize } from '../common/types.ts';
const TsxTerminalIO: ITerminal = {
const CommonTerminalIO: ITerminal = {
argv: (process.argv.length > 2) ? process.argv.slice(2) : [],
inputLoop: async function* (): AsyncGenerator<Uint8Array, null> {
yield (await TsxTerminalIO.readStdinRaw()) ?? new Uint8Array(0);
yield (await CommonTerminalIO.readStdinRaw()) ?? new Uint8Array(0);
return null;
},
@ -19,7 +18,7 @@ const TsxTerminalIO: ITerminal = {
});
},
readStdin: async function (): Promise<string | null> {
const raw = await TsxTerminalIO.readStdinRaw();
const raw = await CommonTerminalIO.readStdinRaw();
return readKey(raw ?? new Uint8Array(0));
},
readStdinRaw: function (): Promise<Uint8Array | null> {
@ -38,4 +37,4 @@ const TsxTerminalIO: ITerminal = {
},
};
export default TsxTerminalIO;
export default CommonTerminalIO;

View File

@ -0,0 +1,88 @@
/**
* Adapt the node test interface to the shared testing interface
*/
import { deepStrictEqual, notStrictEqual, strictEqual } from 'node:assert';
import Option from '../option.ts';
export interface ITestBase {
assertEquivalent(actual: unknown, expected: unknown): void;
assertExists(actual: unknown): void;
assertInstanceOf(actual: unknown, expectedType: any): void;
assertNotEquals(actual: unknown, expected: unknown): void;
assertEquals(actual: unknown, expected: unknown): void;
assertTrue(actual: boolean): void;
assertFalse(actual: boolean): void;
assertSome<T>(actual: Option<T>): void;
assertNone<T>(actual: Option<T>): void;
/**
* Convert the nested test object into a test suite for the current runtime
*/
testSuite(testObj: any): void;
}
abstract class AbstractTestBase implements Partial<ITestBase> {
/**
* The values (often objects) have all the same property values
*/
public static assertEquivalent(actual: unknown, expected: unknown): void {
return deepStrictEqual(actual, expected);
}
/**
* The value is not null or undefined
*/
public static assertExists(actual: unknown): void {
return notStrictEqual(actual, undefined);
}
/**
* `actual` is an object implementing `expectedType`
*/
public static assertInstanceOf(actual: unknown, expectedType: any): void {
return strictEqual(actual instanceof expectedType, true);
}
/**
* The values are not exactly equal (Different instance, type, value, etc)
*/
public static assertNotEquals(actual: unknown, expected: unknown): void {
return notStrictEqual(actual, expected);
}
/**
* The values are exactly the same
*/
public static assertEquals(actual: unknown, expected: unknown): void {
return strictEqual(actual, expected);
}
/**
* The value is true
*/
public static assertTrue(actual: boolean): void {
return strictEqual(actual, true);
}
/**
* The value is false
*/
public static assertFalse(actual: boolean): void {
return strictEqual(actual, false);
}
/**
* The value is a `Some` type `Option`
*/
public static assertSome<T>(actual: Option<T>): void {
return AbstractTestBase.assertTrue(actual.isSome());
}
/**
* The value is a `None` type `Option`
*/
public static assertNone<T>(actual: Option<T>): void {
return AbstractTestBase.assertTrue(actual.isNone());
}
}
export default AbstractTestBase;

View File

@ -1,6 +1,7 @@
import { RunTimeType } from './runtime.ts';
export { Position } from './position.ts';
export type { ITestBase } from './runtime/test_base.ts';
/**
* The size of terminal in rows and columns
@ -128,66 +129,3 @@ export interface IRuntime {
*/
exit(code?: number): void;
}
// ----------------------------------------------------------------------------
// Testing
// ----------------------------------------------------------------------------
/**
* The shared test interface, so tests can be run by both runtimes
*/
export interface ITestBase {
/**
* The values (often objects) have all the same property values
*
* @param actual
* @param expected
*/
assertEquivalent(actual: unknown, expected: unknown): void;
/**
* The value is not null or undefined
*
* @param actual
*/
assertExists(actual: unknown): void;
/**
* The value is false
*
* @param actual
*/
assertFalse(actual: boolean): void;
/**
* `actual` is an object implementing `expectedType`
*
* @param actual
* @param expectedType
*/
assertInstanceOf(actual: unknown, expectedType: any): void;
/**
* The values are not exactly equal (Different instance, type, value, etc)
*
* @param actual
* @param expected
*/
assertNotEquals(actual: unknown, expected: unknown): void;
/**
* The values are exactly the same
*
* @param actual
* @param expected
*/
assertEquals(actual: unknown, expected: unknown): void;
/**
* The value is true
*
* @param actual
*/
assertTrue(actual: boolean): void;
testSuite(testObj: any): void;
}

View File

@ -1,31 +1,15 @@
import { ITestBase } from '../common/types.ts';
import { stdAssert } from './deps.ts';
const {
assertEquals,
assertExists,
assertInstanceOf,
assertNotEquals,
assertStrictEquals,
} = stdAssert;
export function testSuite(testObj: any) {
// @ts-ignore The import exists, but tsc complains
import { test } from 'node:test';
import AbstractTestBase from '../common/runtime/test_base.ts';
class DenoTestBase extends AbstractTestBase {
public static testSuite(testObj: any) {
Object.keys(testObj).forEach((group) => {
const groupObj = testObj[group];
Object.keys(groupObj).forEach((testName) => {
Deno.test(testName, groupObj[testName]);
test(testName, groupObj[testName]);
});
});
}
}
const DenoTestBase: ITestBase = {
assertEquivalent: assertEquals,
assertExists,
assertInstanceOf,
assertNotEquals,
assertEquals: assertStrictEquals,
assertTrue: (actual: boolean) => assertStrictEquals(actual, true),
assertFalse: (actual: boolean) => assertStrictEquals(actual, false),
testSuite,
};
export default DenoTestBase;

View File

@ -2,17 +2,16 @@
* The main entrypoint when using Tsx as the runtime
*/
import { IRuntime, RunTimeType } from '../common/runtime.ts';
import TsxTerminalIO from './terminal_io.ts';
import TsxFileIO from './file_io.ts';
import process from 'node:process';
import { process } from '../common/runtime/node.ts';
import TsxTerminalIO from '../common/runtime/terminal_io.ts';
import FileIO from '../common/runtime/file_io.ts';
/**
* The Tsx Runtime implementation
*/
const TsxRuntime: IRuntime = {
name: RunTimeType.Tsx,
file: TsxFileIO,
file: FileIO,
term: TsxTerminalIO,
onEvent: (eventName: string, handler) => process.on(eventName, handler),
onExit: (cb: () => void): void => {

View File

@ -1,16 +1,12 @@
// @ts-nocheck: Bun is used for typescript checks, bun does not have 'node:assert' or 'node:test'
/**
* Adapt the node test interface to the shared testing interface
*/
import {
deepStrictEqual,
notStrictEqual,
strictEqual,
} from 'node:assert/strict';
// @ts-ignore The import exists, but tsc complains
import { describe, it } from 'node:test';
import { ITestBase } from '../common/types.ts';
import AbstractTestBase from '../common/runtime/test_base.ts';
export function testSuite(testObj: any) {
class TsxTestBase extends AbstractTestBase {
public static testSuite(testObj: any): void {
Object.keys(testObj).forEach((group) => {
describe(group, () => {
const groupObj = testObj[group];
@ -19,21 +15,7 @@ export function testSuite(testObj: any) {
});
});
});
}
}
const TsxTestBase: ITestBase = {
assertEquivalent: (actual: unknown, expected: unknown) =>
deepStrictEqual(actual, expected),
assertExists: (actual: unknown) => notStrictEqual(actual, undefined),
assertFalse: (actual: boolean) => strictEqual(actual, false),
assertInstanceOf: (actual: unknown, expectedType: any) =>
strictEqual(actual instanceof expectedType, true),
assertNotEquals: (actual: unknown, expected: unknown) =>
notStrictEqual(actual, expected),
assertEquals: (actual: unknown, expected: unknown) =>
strictEqual(actual, expected),
assertTrue: (actual: boolean) => strictEqual(actual, true),
testSuite,
};
export default TsxTestBase;

View File

@ -13,7 +13,8 @@
"skipLibCheck": true,
"composite": true,
"downlevelIteration": true,
"allowSyntheticDefaultImports": true
"esModuleInterop": false,
"allowSyntheticDefaultImports": false
},
"exclude": ["src/deno"]
}