Spaces:
Sleeping
Sleeping
File size: 3,907 Bytes
4450790 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
/**
* @fileoverview A set of methods that mimic a bit of the Jasmine testing library, but simpler and
* more succinct for manipulating a comfy integration test.
*/
import { wait } from "rgthree/common/shared_utils.js";
type TestContext = {
label?: string;
beforeEach?: Function[];
};
let contexts: TestContext[] = [];
export function describe(label: string, fn: Function) {
return async () => {
await describeRun(label, fn);
};
}
export async function describeRun(label: string, fn: Function) {
await wait();
contexts.push({ label });
console.group(`[Start] ${contexts[contexts.length - 1]!.label}`);
await fn();
contexts.pop();
console.groupEnd();
}
export async function should(declaration: string, fn: Function) {
if (!contexts[contexts.length - 1]) {
throw Error("Called should outside of a describe.");
}
console.group(`...should ${declaration}`);
try {
for (const context of contexts) {
for (const beforeEachFn of context?.beforeEach || []) {
await beforeEachFn();
}
}
await fn();
} catch (e: any) {
fail(e);
}
console.groupEnd();
}
export async function beforeEach(fn: Function) {
if (!contexts[contexts.length - 1]) {
throw Error("Called beforeEach outside of a describe.");
}
const last = contexts[contexts.length - 1]!;
last.beforeEach = last?.beforeEach || [];
last.beforeEach.push(fn);
}
export function fail(e: Error) {
log(`X Failure: ${e}`, "color:#600; background:#fdd; padding: 2px 6px;");
}
function log(msg: string, styles: string) {
if (styles) {
console.log(`%c ${msg}`, styles);
} else {
console.log(msg);
}
}
class Expectation {
private propertyLabel: string | null = "";
private expectedLabel: string | null = "";
private expectedFn!: (v: any) => boolean;
private value: any;
constructor(value: any) {
this.value = value;
}
toBe(labelOrExpected: any, maybeExpected?: any) {
const expected = maybeExpected !== undefined ? maybeExpected : labelOrExpected;
this.propertyLabel = maybeExpected !== undefined ? labelOrExpected : null;
this.expectedLabel = JSON.stringify(expected);
this.expectedFn = (v) => v == expected;
return this.toBeEval();
}
toBeUndefined(propertyLabel: string) {
this.expectedFn = (v) => v === undefined;
this.propertyLabel = propertyLabel || "";
this.expectedLabel = "undefined";
return this.toBeEval(true);
}
toBeNullOrUndefined(propertyLabel: string) {
this.expectedFn = (v) => v == null;
this.propertyLabel = propertyLabel || "";
this.expectedLabel = "null or undefined";
return this.toBeEval(true);
}
toBeTruthy(propertyLabel: string) {
this.expectedFn = (v) => !v;
this.propertyLabel = propertyLabel || "";
this.expectedLabel = "truthy";
return this.toBeEval(false);
}
toBeANumber(propertyLabel: string) {
this.expectedFn = (v) => typeof v === "number";
this.propertyLabel = propertyLabel || "";
this.expectedLabel = "a number";
return this.toBeEval();
}
toBeEval(strict = false) {
let evaluation = this.expectedFn(this.value);
let msg = `Expected ${this.propertyLabel ? this.propertyLabel + " to be " : ""}${
this.expectedLabel
}`;
msg += evaluation ? "." : `, but was ${JSON.stringify(this.value)}`;
this.log(evaluation, msg);
return evaluation;
}
log(value: boolean, msg: string) {
if (value) {
log(`🗸 ${msg}`, "color:#060; background:#cec; padding: 2px 6px;");
} else {
log(`X ${msg}`, "color:#600; background:#fdd; padding: 2px 6px;");
}
}
}
export function expect(value: any, msg?: string) {
const expectation = new Expectation(value);
if (msg) {
expectation.log(value, msg);
}
return expectation;
}
|