Skip to content

Commit 4361233

Browse files
keithamuskoddsson
andauthored
feat: assertionresult and rename (#27)
* feat: add AssertionResult * refactor: rename index to mod.ts This is a Deno convention * Apply suggestions from code review Co-authored-by: Kristján Oddsson <koddsson@gmail.com> * refactor: remove unused ssf arg * refactor: remove ok/error factories * fix: add this.name back toJSON * test: add AssertionResult tests Co-authored-by: Kristján Oddsson <koddsson@gmail.com>
1 parent 95cb66a commit 4361233

5 files changed

Lines changed: 143 additions & 55 deletions

File tree

mod.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
const canElideFrames = 'captureStackTrace' in Error
2+
const startStackFrames = new WeakMap()
3+
4+
interface Result {
5+
name: 'AssertionError' | 'AssertionResult'
6+
ok: boolean
7+
toJSON(...args: unknown[]): Record<string, unknown>
8+
}
9+
10+
export class AssertionError<T> extends Error implements Result {
11+
[key: string]: unknown
12+
13+
get name(): 'AssertionError' {
14+
return 'AssertionError'
15+
}
16+
17+
get ok() {
18+
return false
19+
}
20+
21+
constructor(public message = 'Unspecified AssertionError', props?: T, ssf?: Function) {
22+
super(message)
23+
if (canElideFrames && ssf) startStackFrames.set(this, ssf)
24+
for (const key in props) {
25+
if (!(key in this)) {
26+
// @ts-ignore
27+
this[key] = props[key];
28+
}
29+
}
30+
}
31+
32+
get stack() {
33+
if (canElideFrames) {
34+
return (Error as any).captureStackTrace(this, startStackFrames.get(this) || AssertionError);
35+
} else {
36+
return super.stack
37+
}
38+
}
39+
40+
toJSON(stack: boolean): Record<string, unknown> {
41+
return {
42+
...this,
43+
name: this.name,
44+
message: this.message,
45+
ok: false,
46+
// include stack if exists and not turned off
47+
stack: stack !== false ? this.stack : undefined,
48+
}
49+
}
50+
51+
}
52+
53+
export class AssertionResult<T> implements Result {
54+
[key: string]: unknown
55+
56+
get name(): 'AssertionResult' {
57+
return 'AssertionResult'
58+
}
59+
60+
get ok() {
61+
return true
62+
}
63+
64+
constructor(props?: T) {
65+
for (const key in props) {
66+
if (!(key in this)) {
67+
// @ts-ignore
68+
this[key] = props[key];
69+
}
70+
}
71+
}
72+
73+
toJSON(): Record<string, unknown> {
74+
return {
75+
...this,
76+
name: this.name,
77+
ok: this.ok,
78+
}
79+
}
80+
}

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "Error constructor for test and validation frameworks that implements standardized AssertionError specification.",
55
"author": "Jake Luer <jake@qualiancy.com> (http://qualiancy.com)",
66
"license": "MIT",
7-
"types": "./dist/index.d.ts",
7+
"types": "./dist/mod.d.ts",
88
"keywords": [
99
"test",
1010
"assertion",
@@ -21,8 +21,8 @@
2121
"dist"
2222
],
2323
"type": "module",
24-
"module": "./dist/index.js",
25-
"main": "./dist/index.js",
24+
"module": "./dist/mod.js",
25+
"main": "./dist/mod.js",
2626
"scripts": {
2727
"build": "tsc",
2828
"pretest": "npm run build",

src/index.ts

Lines changed: 0 additions & 45 deletions
This file was deleted.

test/index.js

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Include lib
33
*/
44

5-
import AssertionError from '../dist/index.js'
5+
import {AssertionError, AssertionResult} from '../dist/mod.js'
66

77
/*!
88
* Simple test runner.
@@ -20,10 +20,10 @@ function assert (pass, msg) {
2020
if (!pass) throw new Error(msg);
2121
}
2222

23-
function suite(fn) {
23+
function suite(name, fn) {
2424
fn(test, assert);
2525

26-
console.log('');
26+
console.log(name);
2727
console.log(' Tests (%d)', tests.length);
2828

2929
tests.forEach(function (test) {
@@ -49,19 +49,20 @@ function suite(fn) {
4949
});
5050

5151
console.log('');
52-
process.exit(failures.length);
52+
if (failures.length) process.exit(failures.length);
5353
};
5454

5555
/*!
5656
* Load the tests
5757
*/
5858

59-
suite(function (test, assert) {
59+
suite('AssertionError', function (test, assert) {
6060
test('construction', function () {
6161
var err = new AssertionError();
6262
assert(err instanceof Error, 'instanceof Error');
6363
assert(err instanceof AssertionError, 'instanceof AssertionError');
6464
assert(err.name && err.name === 'AssertionError', 'name === "AssertionError"');
65+
assert(err.ok === false, 'has ok=false prop');
6566
});
6667

6768
test('message', function () {
@@ -78,12 +79,14 @@ suite(function (test, assert) {
7879
test('custom properties', function () {
7980
var err = new AssertionError('good message', {
8081
name: 'ShouldNotExist'
82+
, ok: true
8183
, hello: 'universe'
8284
, message: 'bad message'
8385
, stack: 'custom stack'
8486
});
8587

8688
assert(err.name === 'AssertionError', 'does not overwrite name');
89+
assert(err.ok === false, 'does not overwrite ok');
8790
assert(err.message === 'good message', 'does not overwrite message');
8891
assert(err.hello && err.hello === 'universe', 'has custom property');
8992

@@ -102,6 +105,7 @@ suite(function (test, assert) {
102105
var json = err.toJSON();
103106

104107
assert(json.name === 'AssertionError', 'json has name');
108+
assert(json.ok === false, 'json has ok');
105109
assert(json.message === 'some message', 'json has message');
106110
assert(json.hello === 'universe' && json.goodbye === 'known', 'json has custom properties');
107111

@@ -114,3 +118,52 @@ suite(function (test, assert) {
114118
assert(!nostack.stack, 'no stack on false argument');
115119
});
116120
});
121+
122+
suite('AssertionResult', function (test, assert) {
123+
test('construction', function () {
124+
var res = new AssertionResult();
125+
assert(res instanceof Error === false, 'not instanceof Error');
126+
assert(res instanceof AssertionResult, 'instanceof AssertionResult');
127+
assert(res.name && res.name === 'AssertionResult', 'name === "AssertionResult"');
128+
assert(res.ok === true, 'has ok=true prop');
129+
});
130+
131+
test('message', function () {
132+
var res = new AssertionResult('Oops.')
133+
assert('message' in res === false, 'has no message prop');
134+
});
135+
136+
test('stack', function() {
137+
var res = new AssertionResult()
138+
assert('stack' in res === false, 'has no stack');
139+
});
140+
141+
test('custom properties', function () {
142+
var res = new AssertionResult({
143+
name: 'ShouldNotExist'
144+
, ok: false
145+
, hello: 'universe'
146+
, message: 'good message'
147+
, stack: 'custom stack'
148+
});
149+
150+
assert(res.name === 'AssertionResult', 'does not overwrite name');
151+
assert(res.ok === true, 'does not overwrite ok property');
152+
assert(res.message === 'good message', 'can overwrite message');
153+
assert(res.hello && res.hello === 'universe', 'has custom property');
154+
assert(res.stack && res.stack === 'custom stack', 'can overwrite stack');
155+
});
156+
157+
test('.toJSON()', function () {
158+
var res = new AssertionResult({
159+
hello: 'universe'
160+
, goodbye: 'known'
161+
});
162+
163+
var json = res.toJSON();
164+
165+
assert(json.name === 'AssertionResult', 'json has name');
166+
assert(json.ok === true, 'json has ok');
167+
assert(json.hello === 'universe' && json.goodbye === 'known', 'json has custom properties');
168+
});
169+
});

tsconfig.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"allowSyntheticDefaultImports": true,
1111
"outDir": "dist"
1212
},
13-
"include": [
14-
"src"
13+
"files": [
14+
"./mod.ts"
1515
]
1616
}

0 commit comments

Comments
 (0)