Cross-runtime testing
This commit is contained in:
parent
7dcd42da13
commit
2fcfe4328c
@ -3,7 +3,8 @@
|
|||||||
"lint": {
|
"lint": {
|
||||||
"include": ["src/"],
|
"include": ["src/"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"tags": ["recommended"]
|
"tags": ["recommended"],
|
||||||
|
"exclude": ["no-explicit-any"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fmt": {
|
"fmt": {
|
||||||
|
37
justfile
37
justfile
@ -3,24 +3,51 @@ default:
|
|||||||
@just --list
|
@just --list
|
||||||
|
|
||||||
# Typescript checking
|
# Typescript checking
|
||||||
check:
|
check: lint
|
||||||
deno check --unstable --all -c deno.jsonc ./src/deno/*.ts ./src/common/*.ts
|
deno check --unstable --all -c deno.jsonc ./src/deno/*.ts ./src/common/*.ts
|
||||||
|
|
||||||
# Code linting
|
# Code linting
|
||||||
deno-lint:
|
lint:
|
||||||
deno lint
|
deno lint
|
||||||
|
|
||||||
# Reformat the code
|
# Reformat the code
|
||||||
fmt:
|
fmt:
|
||||||
deno fmt
|
deno fmt
|
||||||
|
|
||||||
|
# Run tests with all the runtimes
|
||||||
|
test: deno-test bun-test
|
||||||
|
|
||||||
|
# Clean up any generated files
|
||||||
|
clean:
|
||||||
|
rm -rf .deno-cover
|
||||||
|
rm -rf cover
|
||||||
|
rm -rf docs
|
||||||
|
|
||||||
|
########################################################################################################################
|
||||||
|
# Bun-specific commands
|
||||||
|
########################################################################################################################
|
||||||
|
|
||||||
|
# Test with bun
|
||||||
|
bun-test:
|
||||||
|
bun test --coverage
|
||||||
|
|
||||||
# Run with bun
|
# Run with bun
|
||||||
bun-run:
|
bun-run:
|
||||||
bun run ./src/scroll.ts
|
bun run ./src/scroll.ts
|
||||||
|
|
||||||
|
########################################################################################################################
|
||||||
|
# Deno-specific commands
|
||||||
|
########################################################################################################################
|
||||||
|
|
||||||
|
# Test with deno
|
||||||
|
deno-test:
|
||||||
|
deno test --allow-all
|
||||||
|
|
||||||
|
# Create test coverage report with deno
|
||||||
|
deno-coverage:
|
||||||
|
deno test --allow-all --coverage=.deno-cover
|
||||||
|
deno coverage --lcov .deno-cover
|
||||||
|
|
||||||
# Run with deno
|
# Run with deno
|
||||||
deno-run:
|
deno-run:
|
||||||
deno run --allow-all --allow-ffi --deny-net --deny-hrtime --unstable ./src/scroll.ts
|
deno run --allow-all --allow-ffi --deny-net --deny-hrtime --unstable ./src/scroll.ts
|
||||||
|
|
||||||
deno-test:
|
|
||||||
deno test --allow-all
|
|
38
src/bun/test_base.ts
Normal file
38
src/bun/test_base.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* Adapt the bun test interface to the shared testing interface
|
||||||
|
*/
|
||||||
|
import {test as btest, expect } from 'bun:test';
|
||||||
|
import {ITestBase} from "../common/mod";
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testBase = new TestBase();
|
||||||
|
export default testBase;
|
3
src/common/mod.ts
Normal file
3
src/common/mod.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './runtime.ts';
|
||||||
|
export * from './strings.ts';
|
||||||
|
export type { ITestBase } from './test_base.ts';
|
@ -30,7 +30,7 @@ export const getRuntime = (): RunTime => {
|
|||||||
/**
|
/**
|
||||||
* Import a runtime-specific module
|
* Import a runtime-specific module
|
||||||
*
|
*
|
||||||
* eg. to load "src/bun/index.ts", if the runtime is bun,
|
* eg. to load "src/bun/mod.ts", if the runtime is bun,
|
||||||
* you can use like so `await importForRuntime('index')`;
|
* you can use like so `await importForRuntime('index')`;
|
||||||
*
|
*
|
||||||
* @param path - the path within the runtime module
|
* @param path - the path within the runtime module
|
||||||
@ -49,3 +49,18 @@ export const importForRuntime = async (path: string) => {
|
|||||||
|
|
||||||
return await import(importPath);
|
return await import(importPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import the default export for a runtime-specific module
|
||||||
|
* (this is just a simple wrapper of `importForRuntime`)
|
||||||
|
*
|
||||||
|
* @param path - the path within the runtime module
|
||||||
|
*/
|
||||||
|
export const importDefaultForRuntime = async (path: string) => {
|
||||||
|
const pkg = await importForRuntime(path);
|
||||||
|
if ('default' in pkg) {
|
||||||
|
return pkg.default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
@ -1,8 +1,12 @@
|
|||||||
import { importForRuntime } from './index.ts';
|
import { chars, importDefaultForRuntime, is_ascii, ITestBase } from './mod.ts';
|
||||||
import { chars } from './strings.ts';
|
|
||||||
|
|
||||||
const { test, assertEquals } = await importForRuntime('test_base');
|
const t: ITestBase = await importDefaultForRuntime('test_base');
|
||||||
|
|
||||||
test('chars fn properly splits strings into unicode characters', () => {
|
t.test('chars fn properly splits strings into unicode characters', () => {
|
||||||
assertEquals(chars('😺😸😹'), ['😺', '😸', '😹']);
|
t.assertEquals(chars('😺😸😹'), ['😺', '😸', '😹']);
|
||||||
|
});
|
||||||
|
|
||||||
|
t.test('is_ascii properly descerns ascii chars', () => {
|
||||||
|
t.assertTrue(is_ascii('asjyverkjhsdf1928374'));
|
||||||
|
t.assertFalse(is_ascii('😺acalskjsdf'));
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { die, importForRuntime } from './index.ts';
|
import { die, importForRuntime } from './mod.ts';
|
||||||
|
|
||||||
export const STDIN_FILENO = 0;
|
export const STDIN_FILENO = 0;
|
||||||
export const STOUT_FILENO = 1;
|
export const STOUT_FILENO = 1;
|
||||||
@ -122,7 +122,7 @@ export const getTermios = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const oldTermiosPtr = getPointer(this.#cookedTermios);
|
const oldTermiosPtr = getPointer(this.#cookedTermios);
|
||||||
let res = tcsetattr(STDIN_FILENO, TCSANOW, oldTermiosPtr);
|
const res = tcsetattr(STDIN_FILENO, TCSANOW, oldTermiosPtr);
|
||||||
if (res === -1) {
|
if (res === -1) {
|
||||||
die('Failed to restore canonical mode.');
|
die('Failed to restore canonical mode.');
|
||||||
}
|
}
|
||||||
|
13
src/common/test_base.ts
Normal file
13
src/common/test_base.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
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;
|
||||||
|
}
|
@ -1,7 +1,51 @@
|
|||||||
export const test = Deno.test;
|
import { ITestBase } from '../common/mod.ts';
|
||||||
export {
|
|
||||||
assert,
|
import {
|
||||||
assertEquals,
|
assertEquals,
|
||||||
|
assertExists,
|
||||||
|
assertInstanceOf,
|
||||||
|
AssertionError,
|
||||||
assertNotEquals,
|
assertNotEquals,
|
||||||
assertStrictEquals,
|
assertStrictEquals,
|
||||||
} from 'https://deno.land/std/assert/mod.ts';
|
} from 'https://deno.land/std/assert/mod.ts';
|
||||||
|
|
||||||
|
class TestBase implements ITestBase {
|
||||||
|
test(name: string, fn: () => void): void {
|
||||||
|
return Deno.test(name, fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const testBase = new TestBase();
|
||||||
|
export default testBase;
|
||||||
|
@ -8,12 +8,12 @@ export enum RunTime {
|
|||||||
Unknown = 'common',
|
Unknown = 'common',
|
||||||
}
|
}
|
||||||
|
|
||||||
import { importForRuntime } from './common/index.ts';
|
import { importForRuntime } from './common/mod.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the runtime strategy, and go!
|
* Determine the runtime strategy, and go!
|
||||||
*/
|
*/
|
||||||
(async () => {
|
(async () => {
|
||||||
const { main } = await importForRuntime('./index.ts');
|
const { main } = await importForRuntime('./mod.ts');
|
||||||
await main();
|
await main();
|
||||||
})();
|
})();
|
||||||
|
Loading…
Reference in New Issue
Block a user