Cross-runtime testing
This commit is contained in:
parent
7dcd42da13
commit
2fcfe4328c
@ -3,7 +3,8 @@
|
||||
"lint": {
|
||||
"include": ["src/"],
|
||||
"rules": {
|
||||
"tags": ["recommended"]
|
||||
"tags": ["recommended"],
|
||||
"exclude": ["no-explicit-any"]
|
||||
}
|
||||
},
|
||||
"fmt": {
|
||||
|
37
justfile
37
justfile
@ -3,24 +3,51 @@ default:
|
||||
@just --list
|
||||
|
||||
# Typescript checking
|
||||
check:
|
||||
check: lint
|
||||
deno check --unstable --all -c deno.jsonc ./src/deno/*.ts ./src/common/*.ts
|
||||
|
||||
# Code linting
|
||||
deno-lint:
|
||||
lint:
|
||||
deno lint
|
||||
|
||||
# Reformat the code
|
||||
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
|
||||
bun-run:
|
||||
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
|
||||
deno-run:
|
||||
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
|
||||
*
|
||||
* 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')`;
|
||||
*
|
||||
* @param path - the path within the runtime module
|
||||
@ -49,3 +49,18 @@ export const importForRuntime = async (path: string) => {
|
||||
|
||||
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 } from './strings.ts';
|
||||
import { chars, importDefaultForRuntime, is_ascii, ITestBase } from './mod.ts';
|
||||
|
||||
const { test, assertEquals } = await importForRuntime('test_base');
|
||||
const t: ITestBase = await importDefaultForRuntime('test_base');
|
||||
|
||||
test('chars fn properly splits strings into unicode characters', () => {
|
||||
assertEquals(chars('😺😸😹'), ['😺', '😸', '😹']);
|
||||
t.test('chars fn properly splits strings into unicode characters', () => {
|
||||
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 STOUT_FILENO = 1;
|
||||
@ -122,7 +122,7 @@ export const getTermios = async () => {
|
||||
}
|
||||
|
||||
const oldTermiosPtr = getPointer(this.#cookedTermios);
|
||||
let res = tcsetattr(STDIN_FILENO, TCSANOW, oldTermiosPtr);
|
||||
const res = tcsetattr(STDIN_FILENO, TCSANOW, oldTermiosPtr);
|
||||
if (res === -1) {
|
||||
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;
|
||||
export {
|
||||
assert,
|
||||
import { ITestBase } from '../common/mod.ts';
|
||||
|
||||
import {
|
||||
assertEquals,
|
||||
assertExists,
|
||||
assertInstanceOf,
|
||||
AssertionError,
|
||||
assertNotEquals,
|
||||
assertStrictEquals,
|
||||
} 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',
|
||||
}
|
||||
|
||||
import { importForRuntime } from './common/index.ts';
|
||||
import { importForRuntime } from './common/mod.ts';
|
||||
|
||||
/**
|
||||
* Determine the runtime strategy, and go!
|
||||
*/
|
||||
(async () => {
|
||||
const { main } = await importForRuntime('./index.ts');
|
||||
const { main } = await importForRuntime('./mod.ts');
|
||||
await main();
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user