Skip to content

Commit d3cce6f

Browse files
Add toBeTypeOf() assertion
1 parent 51d7fd3 commit d3cce6f

File tree

9 files changed

+231
-2
lines changed

9 files changed

+231
-2
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## Unreleased
9+
### Added
10+
- Based on [Add New Assertions for Enhanced Testing Capabilities](https://github.com/scripterio-js/scripterio/issues/63):
11+
- `toBeTypeOf()` — Check that a variable has a correct type
12+
13+
- Contributors:
14+
- [Vadym Nastoiashchyi](https://github.com/VadimNastoyashchy)
915

1016
## 1.11.0 - 2025-07-08
1117
### Added

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ Use `expect(actual_value)` with assertions:
152152
| `.toBeGreaterThan()` | Check actual value to be greater than expected value |
153153
| `.toBeLessThan()` | Check actual value to be less than expected value |
154154
| `.toContain()` | Use when you want to check that an item is in an array or a string. |
155-
| `.toMatch()` | Use .toMatch() to check that a string matches a regular expression. |
155+
| `.toMatch()` | Use to check that a string matches a regular expression. |
156+
| `.toBeTypeOf()` | Use to check that a variable has a correct type |
156157

157158
---
158159

__tests__/assertions.test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,17 @@ describe('Unit tests for assertions', () => {
7777
expect('test').toMatch('test')
7878
expect('test').toMatch(/test/i)
7979
})
80+
81+
test('Check assertion toBeType()', () => {
82+
expect('Hello').toBeTypeOf('string')
83+
expect(['ScripterI/O', 123]).toBeTypeOf('array')
84+
expect(42).toBeTypeOf('number')
85+
expect(true).toBeTypeOf('boolean')
86+
expect({ key: 'value' }).toBeTypeOf('object')
87+
expect(undefined).toBeTypeOf('undefined')
88+
expect(null).toBeTypeOf('null')
89+
expect(Symbol('sym')).toBeTypeOf('symbol')
90+
expect(10n).toBeTypeOf('bigint')
91+
expect(function () {}).toBeTypeOf('function')
92+
})
8093
})

docs/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ Use `expect(actual_value)` with assertions:
126126
| `.toBeGreaterThan()` | Check actual value to be greater than expected value |
127127
| `.toBeLessThan()` | Check actual value to be less than expected value |
128128
| `.toContain()` | Use when you want to check that an item is in an array or a string. |
129-
| `.toMatch()` | Use .toMatch() to check that a string matches a regular expression. |
129+
| `.toMatch()` | Use to check that a string matches a regular expression. |
130+
| `.toBeTypeOf()` | Use to check that a variable has a correct type |
130131

131132
---
132133

src/assertions/assertions.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export { toBeGreaterThan } from './toBeGreaterThan.mjs'
1212
export { toBeLessThan } from './toBeLessThan.mjs'
1313
export { toContain } from './toContain.mjs'
1414
export { toMatch } from './toMatch.mjs'
15+
export { toBeTypeOf } from './toBeTypeOf.mjs'

src/assertions/toBeTypeOf.mjs

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import { AssertionError } from '../errors/assertion.mjs'
2+
import { RunnerError } from '../errors/runner.mjs'
3+
import { indentLine } from '../utils/transform.mjs'
4+
import { TYPES } from '../core/constants.mjs'
5+
import { EOL } from 'os'
6+
7+
export const toBeTypeOf = (actual, expected) => {
8+
if (typeof expected !== 'string') {
9+
throw new RunnerError(
10+
indentLine(`Provided type: ${typeof expected} is not a string`)
11+
)
12+
}
13+
14+
if (!(expected in TYPES)) {
15+
throw new RunnerError(
16+
indentLine(`Expect type: ${expected} is not a valid type`)
17+
)
18+
}
19+
20+
if (expected === 'array') {
21+
if (!Array.isArray(actual)) {
22+
throw new AssertionError(
23+
indentLine('Expected: <expected>') +
24+
' has an array type' +
25+
EOL +
26+
indentLine('Received: <actual>') +
27+
` has a ${Array.isArray(actual) ? 'array' : typeof actual} type`,
28+
{
29+
actual,
30+
expected,
31+
}
32+
)
33+
}
34+
} else if (expected === 'null') {
35+
if (actual !== null) {
36+
throw new AssertionError(
37+
indentLine('Expected: <expected>') +
38+
' has a null type' +
39+
EOL +
40+
indentLine('Received: <actual>') +
41+
` has a ${
42+
actual === undefined
43+
? 'undefined'
44+
: actual === null
45+
? 'null'
46+
: Array.isArray(actual)
47+
? 'array'
48+
: typeof actual
49+
} type`,
50+
{
51+
actual,
52+
expected,
53+
}
54+
)
55+
}
56+
} else if (expected === 'string') {
57+
if (typeof actual !== 'string') {
58+
throw new AssertionError(
59+
indentLine('Expected: <expected>') +
60+
' has a string type' +
61+
EOL +
62+
indentLine('Received: <actual>') +
63+
` has a ${typeof actual} type`,
64+
{
65+
actual,
66+
expected,
67+
}
68+
)
69+
}
70+
} else if (expected === 'number') {
71+
if (typeof actual !== 'number') {
72+
throw new AssertionError(
73+
indentLine('Expected: <expected>') +
74+
' has a number type' +
75+
EOL +
76+
indentLine('Received: <actual>') +
77+
` has a ${typeof actual} type`,
78+
{
79+
actual,
80+
expected,
81+
}
82+
)
83+
}
84+
} else if (expected === 'boolean') {
85+
if (typeof actual !== 'boolean') {
86+
throw new AssertionError(
87+
indentLine('Expected: <expected>') +
88+
' has a boolean type' +
89+
EOL +
90+
indentLine('Received: <actual>') +
91+
` has a ${typeof actual} type`,
92+
{
93+
actual,
94+
expected,
95+
}
96+
)
97+
}
98+
} else if (expected === 'object') {
99+
if (
100+
typeof actual !== 'object' ||
101+
actual === null ||
102+
Array.isArray(actual)
103+
) {
104+
throw new AssertionError(
105+
indentLine('Expected: <expected>') +
106+
' has an object type' +
107+
EOL +
108+
indentLine('Received: <actual>') +
109+
` has a ${typeof actual} type`,
110+
{
111+
actual,
112+
expected,
113+
}
114+
)
115+
}
116+
} else if (expected === 'function') {
117+
if (typeof actual !== 'function') {
118+
throw new AssertionError(
119+
indentLine('Expected: <expected>') +
120+
' has a function type' +
121+
EOL +
122+
indentLine('Received: <actual>') +
123+
` has a ${typeof actual} type`,
124+
{
125+
actual,
126+
expected,
127+
}
128+
)
129+
}
130+
} else if (expected === 'undefined') {
131+
if (typeof actual !== 'undefined') {
132+
throw new AssertionError(
133+
indentLine('Expected: <expected>') +
134+
' has an undefined type' +
135+
EOL +
136+
indentLine('Received: <actual>') +
137+
` has a ${typeof actual} type`,
138+
{
139+
actual,
140+
expected,
141+
}
142+
)
143+
}
144+
} else if (expected === 'symbol') {
145+
if (typeof actual !== 'symbol') {
146+
throw new AssertionError(
147+
indentLine('Expected: <expected>') +
148+
' has a symbol type' +
149+
EOL +
150+
indentLine('Received: <actual>') +
151+
` has a ${typeof actual} type`,
152+
{
153+
actual,
154+
expected,
155+
}
156+
)
157+
}
158+
} else if (expected === 'bigint') {
159+
if (typeof actual !== 'bigint') {
160+
throw new AssertionError(
161+
indentLine('Expected: <expected>') +
162+
' has a bigint type' +
163+
EOL +
164+
indentLine('Received: <actual>') +
165+
` has a ${typeof actual} type`,
166+
{
167+
actual,
168+
expected,
169+
}
170+
)
171+
}
172+
}
173+
}

src/core/constants.mjs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,16 @@ export const REPORTERS = {
3030
CONSOLE: 'console',
3131
HTML: 'html',
3232
}
33+
34+
export const TYPES = {
35+
bigint: 'bigint',
36+
boolean: 'boolean',
37+
function: 'function',
38+
number: 'number',
39+
object: 'object',
40+
string: 'string',
41+
symbol: 'symbol',
42+
array: 'array',
43+
null: 'null',
44+
undefined: 'undefined',
45+
}

src/index.d.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,26 @@ type Assertions = {
340340
* ```
341341
*/
342342
toMatch: (expected: any) => void
343+
344+
/**
345+
* Use .toBeTypeOf() to check that a variable has a correct type
346+
*
347+
* **Usage**
348+
*
349+
* ```js
350+
* expect('Hello').toBeTypeOf('string')
351+
* expect(['ScripterI/O', 123]).toBeTypeOf('array')
352+
* expect(42).toBeTypeOf('number')
353+
* expect(true).toBeTypeOf('boolean')
354+
* expect({ key: 'value' }).toBeTypeOf('object')
355+
* expect(undefined).toBeTypeOf('undefined')
356+
* expect(null).toBeTypeOf('null')
357+
* expect(Symbol('sym')).toBeTypeOf('symbol')
358+
* expect(10n).toBeTypeOf('bigint')
359+
* expect(function () {}).toBeTypeOf('function')
360+
* ```
361+
*/
362+
toBeTypeOf: (expected: any) => void
343363
}
344364

345365
/**

src/index.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ export const afterAll = (body) => core.afterAll(body)
254254
* @property {Function} toBeLessThan - Compare two numbers (received < expected).
255255
* @property {Function} toContain - Check that an item is in an array or a string contains a substring.
256256
* @property {Function} toMatch - Check that a string matches a regular expression.
257+
* @property {Function} toBeTypeOf - Check that a variable has a correct type
257258
*/
258259

259260
/**

0 commit comments

Comments
 (0)