Skip to content

Commit 63ab076

Browse files
committed
🌿 Refine and simplify tests of is
1 parent 3080125 commit 63ab076

File tree

1 file changed

+94
-165
lines changed

1 file changed

+94
-165
lines changed

is_test.ts

Lines changed: 94 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -17,93 +17,66 @@ import is, {
1717
isString,
1818
isTupleOf,
1919
isUndefined,
20+
Predicate,
2021
} from "./is.ts";
2122

22-
Deno.test("is defines aliases of functions", async () => {
23-
const mod = await import("./is.ts");
24-
const cases = Object.entries(mod)
25-
.filter(([k, _]) => k.startsWith("is"))
26-
.map(([k, v]) => [k.slice(2), v] as const);
27-
for (const [alias, fn] of cases) {
28-
assertStrictEquals(is[alias as keyof typeof is], fn);
23+
const examples = {
24+
string: ["", "Hello world"],
25+
number: [0, 1234567890],
26+
boolean: [true, false],
27+
array: [[], [0, 1, 2], ["a", "b", "c"], [0, "a", true]],
28+
record: [{}, { a: 0, b: 1, c: 2 }, { a: "a", b: "b", c: "c" }],
29+
function: [function () {}],
30+
null: [null],
31+
undefined: [undefined],
32+
};
33+
34+
function stringify(x: unknown): string {
35+
if (typeof x === "function") return x.toString();
36+
return JSON.stringify(x);
37+
}
38+
39+
async function testWithExamples<T>(
40+
t: Deno.TestContext,
41+
pred: Predicate<T>,
42+
validExamples: (keyof typeof examples)[],
43+
): Promise<void> {
44+
for (const [name, example] of Object.entries(examples)) {
45+
const expect = validExamples.includes(name as keyof typeof examples);
46+
for (const v of example) {
47+
await t.step(
48+
`returns ${expect} on ${stringify(v)}`,
49+
() => {
50+
assertEquals(pred(v), expect);
51+
},
52+
);
53+
}
2954
}
30-
assertEquals(
31-
Object.keys(is).length,
32-
cases.length,
33-
"The number of entries in `is` is not equal to `is*` functions",
34-
);
35-
});
55+
}
3656

3757
Deno.test("isString", async (t) => {
38-
await t.step("returns true on array", () => {
39-
assertEquals(isString(""), true);
40-
assertEquals(isString("Hello World"), true);
41-
});
42-
await t.step("returns false on non array", () => {
43-
assertEquals(isString(0), false);
44-
assertEquals(isString(true), false);
45-
assertEquals(isString(false), false);
46-
assertEquals(isString([]), false);
47-
assertEquals(isString({}), false);
48-
assertEquals(isString(function () {}), false);
49-
assertEquals(isString(null), false);
50-
assertEquals(isString(undefined), false);
51-
});
58+
await testWithExamples(t, isString, ["string"]);
5259
});
5360

5461
Deno.test("isNumber", async (t) => {
55-
await t.step("returns true on array", () => {
56-
assertEquals(isNumber(0), true);
57-
assertEquals(isNumber(1234567890), true);
58-
});
59-
await t.step("returns false on non array", () => {
60-
assertEquals(isNumber(""), false);
61-
assertEquals(isNumber(true), false);
62-
assertEquals(isNumber(false), false);
63-
assertEquals(isNumber([]), false);
64-
assertEquals(isNumber({}), false);
65-
assertEquals(isNumber(function () {}), false);
66-
assertEquals(isNumber(null), false);
67-
assertEquals(isNumber(undefined), false);
68-
});
62+
await testWithExamples(t, isNumber, ["number"]);
6963
});
7064

7165
Deno.test("isBoolean", async (t) => {
72-
await t.step("returns true on boolean", () => {
73-
assertEquals(isBoolean(true), true);
74-
assertEquals(isBoolean(false), true);
75-
});
76-
await t.step("returns false on non boolean", () => {
77-
assertEquals(isBoolean(0), false);
78-
assertEquals(isBoolean(""), false);
79-
assertEquals(isBoolean([]), false);
80-
assertEquals(isBoolean({}), false);
81-
assertEquals(isBoolean(function () {}), false);
82-
assertEquals(isBoolean(null), false);
83-
assertEquals(isBoolean(undefined), false);
84-
});
66+
await testWithExamples(t, isBoolean, ["boolean"]);
8567
});
8668

8769
Deno.test("isArray", async (t) => {
88-
await t.step("returns true on array", () => {
89-
assertEquals(isArray([]), true);
90-
assertEquals(isArray([0, 1, 2]), true);
91-
assertEquals(isArray(["a", "b", "c"]), true);
92-
assertEquals(isArray([0, "a", 1]), true);
93-
});
94-
await t.step("returns false on non array", () => {
95-
assertEquals(isArray(""), false);
96-
assertEquals(isArray(0), false);
97-
assertEquals(isArray(true), false);
98-
assertEquals(isArray(false), false);
99-
assertEquals(isArray({}), false);
100-
assertEquals(isArray(function () {}), false);
101-
assertEquals(isArray(null), false);
102-
assertEquals(isArray(undefined), false);
103-
});
70+
await testWithExamples(t, isArray, ["array"]);
10471
});
10572

10673
Deno.test("isArrayOf<T>", async (t) => {
74+
await t.step("returns proper type predicate", () => {
75+
const a: unknown = [0, 1, 2];
76+
if (isArrayOf(isNumber)(a)) {
77+
const _: number[] = a;
78+
}
79+
});
10780
await t.step("returns true on T array", () => {
10881
assertEquals(isArrayOf(isNumber)([0, 1, 2]), true);
10982
assertEquals(isArrayOf(isString)(["a", "b", "c"]), true);
@@ -117,6 +90,13 @@ Deno.test("isArrayOf<T>", async (t) => {
11790
});
11891

11992
Deno.test("isTupleOf<T>", async (t) => {
93+
await t.step("returns proper type predicate", () => {
94+
const predTup = [isNumber, isString, isBoolean] as const;
95+
const a: unknown = [0, "a", true];
96+
if (isTupleOf(predTup)(a)) {
97+
const _: [number, string, boolean] = a;
98+
}
99+
});
120100
await t.step("returns true on T tuple", () => {
121101
const predTup = [isNumber, isString, isBoolean] as const;
122102
assertEquals(isTupleOf(predTup)([0, "a", true]), true);
@@ -127,34 +107,19 @@ Deno.test("isTupleOf<T>", async (t) => {
127107
assertEquals(isTupleOf(predTup)([0, "a"]), false);
128108
assertEquals(isTupleOf(predTup)([0, "a", true, 0]), false);
129109
});
130-
await t.step("returns proper type predicate", () => {
131-
const predTup = [isNumber, isString, isBoolean] as const;
132-
const a: unknown = [0, "a", true];
133-
if (isTupleOf(predTup)(a)) {
134-
const _: [number, string, boolean] = a;
135-
}
136-
});
137110
});
138111

139112
Deno.test("isRecord", async (t) => {
140-
await t.step("returns true on record", () => {
141-
assertEquals(isRecord({}), true);
142-
assertEquals(isRecord({ a: 0 }), true);
143-
assertEquals(isRecord({ a: "a" }), true);
144-
});
145-
await t.step("returns false on non record", () => {
146-
assertEquals(isRecord(""), false);
147-
assertEquals(isRecord(0), false);
148-
assertEquals(isRecord(true), false);
149-
assertEquals(isRecord(false), false);
150-
assertEquals(isRecord([]), false);
151-
assertEquals(isRecord(function () {}), false);
152-
assertEquals(isRecord(null), false);
153-
assertEquals(isRecord(undefined), false);
154-
});
113+
await testWithExamples(t, isRecord, ["record"]);
155114
});
156115

157116
Deno.test("isRecordOf<T>", async (t) => {
117+
await t.step("returns proper type predicate", () => {
118+
const a: unknown = { a: 0 };
119+
if (isRecordOf(isNumber)(a)) {
120+
const _: Record<string | number | symbol, number> = a;
121+
}
122+
});
158123
await t.step("returns true on T record", () => {
159124
assertEquals(isRecordOf(isNumber)({ a: 0 }), true);
160125
assertEquals(isRecordOf(isString)({ a: "a" }), true);
@@ -168,6 +133,17 @@ Deno.test("isRecordOf<T>", async (t) => {
168133
});
169134

170135
Deno.test("isObjectOf<T>", async (t) => {
136+
await t.step("returns proper type predicate", () => {
137+
const predObj = {
138+
a: isNumber,
139+
b: isString,
140+
c: isBoolean,
141+
};
142+
const a: unknown = { a: 0, b: "a", c: true };
143+
if (isObjectOf(predObj)(a)) {
144+
const _: { a: number; b: string; c: boolean } = a;
145+
}
146+
});
171147
await t.step("returns true on T object", () => {
172148
const predObj = {
173149
a: isNumber,
@@ -198,87 +174,32 @@ Deno.test("isObjectOf<T>", async (t) => {
198174
false,
199175
);
200176
});
201-
await t.step("returns proper type predicate", () => {
202-
const predObj = {
203-
a: isNumber,
204-
b: isString,
205-
c: isBoolean,
206-
};
207-
const a: unknown = { a: 0, b: "a", c: true };
208-
if (isObjectOf(predObj)(a)) {
209-
const _: { a: number; b: string; c: boolean } = a;
210-
}
211-
});
212177
});
213178

214179
Deno.test("isFunction", async (t) => {
215-
await t.step("returns true on function", () => {
216-
assertEquals(isFunction(isFunction), true);
217-
assertEquals(isFunction(function () {}), true);
218-
assertEquals(isFunction(() => {}), true);
219-
assertEquals(isFunction(setTimeout), true);
220-
});
221-
await t.step("returns false on non function", () => {
222-
assertEquals(isFunction(""), false);
223-
assertEquals(isFunction(0), false);
224-
assertEquals(isFunction(true), false);
225-
assertEquals(isFunction(false), false);
226-
assertEquals(isFunction([]), false);
227-
assertEquals(isFunction({}), false);
228-
assertEquals(isFunction(null), false);
229-
assertEquals(isFunction(undefined), false);
230-
});
180+
await testWithExamples(t, isFunction, ["function"]);
231181
});
232182

233183
Deno.test("isNull", async (t) => {
234-
await t.step("returns true on null", () => {
235-
assertEquals(isNull(null), true);
236-
});
237-
await t.step("returns false on non null", () => {
238-
assertEquals(isNull(""), false);
239-
assertEquals(isNull(0), false);
240-
assertEquals(isNull(true), false);
241-
assertEquals(isNull(false), false);
242-
assertEquals(isNull([]), false);
243-
assertEquals(isNull({}), false);
244-
assertEquals(isNull(function () {}), false);
245-
assertEquals(isNull(undefined), false);
246-
});
184+
await testWithExamples(t, isNull, ["null"]);
247185
});
248186

249187
Deno.test("isUndefined", async (t) => {
250-
await t.step("returns true on null", () => {
251-
assertEquals(isUndefined(undefined), true);
252-
});
253-
await t.step("returns false on non null", () => {
254-
assertEquals(isUndefined(""), false);
255-
assertEquals(isUndefined(0), false);
256-
assertEquals(isUndefined(true), false);
257-
assertEquals(isUndefined(false), false);
258-
assertEquals(isUndefined([]), false);
259-
assertEquals(isUndefined({}), false);
260-
assertEquals(isUndefined(function () {}), false);
261-
assertEquals(isUndefined(null), false);
262-
});
188+
await testWithExamples(t, isUndefined, ["undefined"]);
263189
});
264190

265191
Deno.test("isNullish", async (t) => {
266-
await t.step("returns true on null/undefined", () => {
267-
assertEquals(isNullish(null), true);
268-
assertEquals(isNullish(undefined), true);
269-
});
270-
await t.step("returns false on non null/undefined", () => {
271-
assertEquals(isNullish(""), false);
272-
assertEquals(isNullish(0), false);
273-
assertEquals(isNullish(true), false);
274-
assertEquals(isNullish(false), false);
275-
assertEquals(isNullish([]), false);
276-
assertEquals(isNullish({}), false);
277-
assertEquals(isNullish(function () {}), false);
278-
});
192+
await testWithExamples(t, isNullish, ["null", "undefined"]);
279193
});
280194

281195
Deno.test("isOneOf<T>", async (t) => {
196+
await t.step("returns proper type predicate", () => {
197+
const preds = [isNumber, isString, isBoolean];
198+
const a: unknown = [0, "a", true];
199+
if (isOneOf(preds)(a)) {
200+
const _: number | string | boolean = a;
201+
}
202+
});
282203
await t.step("returns true on one of T", () => {
283204
const preds = [isNumber, isString, isBoolean];
284205
assertEquals(isOneOf(preds)(0), true);
@@ -293,11 +214,19 @@ Deno.test("isOneOf<T>", async (t) => {
293214
assertEquals(isOneOf(preds)(null), false);
294215
assertEquals(isOneOf(preds)(undefined), false);
295216
});
296-
await t.step("returns proper type predicate", () => {
297-
const preds = [isNumber, isString, isBoolean];
298-
const a: unknown = [0, "a", true];
299-
if (isOneOf(preds)(a)) {
300-
const _: number | string | boolean = a;
301-
}
302-
});
217+
});
218+
219+
Deno.test("is defines aliases of functions", async () => {
220+
const mod = await import("./is.ts");
221+
const cases = Object.entries(mod)
222+
.filter(([k, _]) => k.startsWith("is"))
223+
.map(([k, v]) => [k.slice(2), v] as const);
224+
for (const [alias, fn] of cases) {
225+
assertStrictEquals(is[alias as keyof typeof is], fn);
226+
}
227+
assertEquals(
228+
Object.keys(is).length,
229+
cases.length,
230+
"The number of entries in `is` is not equal to `is*` functions",
231+
);
303232
});

0 commit comments

Comments
 (0)