assertron 7.1.3 → 9.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +11 -29
  3. package/package.json +48 -34
  4. package/src/assert-order/AssertOrder.spec.ts +10 -11
  5. package/src/assert-order/AssertOrder.ts +7 -7
  6. package/src/assert-order/InvalidOrder.ts +6 -8
  7. package/src/assert-order/StateMachine.ts +4 -4
  8. package/src/assert-order/index.ts +3 -1
  9. package/src/assert-order/{interfaces.ts → types.ts} +0 -0
  10. package/src/assertron/assertron.spec.ts +2 -3
  11. package/src/assertron/assertron.ts +13 -14
  12. package/src/assertron/falsy.spec.ts +2 -3
  13. package/src/assertron/falsy.ts +2 -6
  14. package/src/assertron/pathEqual.spec.ts +2 -3
  15. package/src/assertron/pathEqual.ts +4 -7
  16. package/src/assertron/rejects.spec.ts +7 -8
  17. package/src/assertron/rejects.ts +3 -9
  18. package/src/assertron/repeat.spec.ts +7 -9
  19. package/src/assertron/repeat.ts +4 -9
  20. package/src/assertron/resolves.spec.ts +3 -4
  21. package/src/assertron/resolves.ts +3 -10
  22. package/src/assertron/satisfies.spec.ts +53 -21
  23. package/src/assertron/satisfies.ts +23 -10
  24. package/src/assertron/throws.spec.ts +46 -35
  25. package/src/assertron/throws.ts +29 -53
  26. package/src/assertron/truthy.spec.ts +2 -3
  27. package/src/assertron/truthy.ts +2 -3
  28. package/src/errors.ts +22 -0
  29. package/src/index.ts +2 -1
  30. package/src/testUtils.ts +16 -13
  31. package/src/{errors/interfaces.ts → types.ts} +0 -0
  32. package/src/utils/index.ts +12 -0
  33. package/src/{errors/util.ts → utils/isErrorConstructor.ts} +1 -1
  34. package/src/utils/notEqualMessage.ts +4 -0
  35. package/src/{errors → utils}/notSatisfiedMessage.spec.ts +0 -0
  36. package/src/{errors/NotSatisfied.ts → utils/notSatisfiedMessage.ts} +0 -0
  37. package/src/{errors → utils}/notThrownMessage.ts +0 -0
  38. package/src/utils/promiseMessages.ts +12 -0
  39. package/src/{errors → utils}/unexpectedErrorMessage.ts +4 -3
  40. package/lib/assert-order/AssertOrder.d.ts +0 -41
  41. package/lib/assert-order/AssertOrder.d.ts.map +0 -1
  42. package/lib/assert-order/AssertOrder.js +0 -147
  43. package/lib/assert-order/InvalidOrder.d.ts +0 -6
  44. package/lib/assert-order/InvalidOrder.d.ts.map +0 -1
  45. package/lib/assert-order/InvalidOrder.js +0 -43
  46. package/lib/assert-order/StateMachine.d.ts +0 -22
  47. package/lib/assert-order/StateMachine.d.ts.map +0 -1
  48. package/lib/assert-order/StateMachine.js +0 -109
  49. package/lib/assert-order/index.d.ts +0 -3
  50. package/lib/assert-order/index.d.ts.map +0 -1
  51. package/lib/assert-order/index.js +0 -5
  52. package/lib/assert-order/interfaces.d.ts +0 -8
  53. package/lib/assert-order/interfaces.d.ts.map +0 -1
  54. package/lib/assert-order/interfaces.js +0 -3
  55. package/lib/assertron/assertron.d.ts +0 -21
  56. package/lib/assertron/assertron.d.ts.map +0 -1
  57. package/lib/assertron/assertron.js +0 -31
  58. package/lib/assertron/falsy.d.ts +0 -2
  59. package/lib/assertron/falsy.d.ts.map +0 -1
  60. package/lib/assertron/falsy.js +0 -10
  61. package/lib/assertron/index.d.ts +0 -2
  62. package/lib/assertron/index.d.ts.map +0 -1
  63. package/lib/assertron/index.js +0 -5
  64. package/lib/assertron/pathEqual.d.ts +0 -2
  65. package/lib/assertron/pathEqual.d.ts.map +0 -1
  66. package/lib/assertron/pathEqual.js +0 -12
  67. package/lib/assertron/rejects.d.ts +0 -2
  68. package/lib/assertron/rejects.d.ts.map +0 -1
  69. package/lib/assertron/rejects.js +0 -13
  70. package/lib/assertron/repeat.d.ts +0 -12
  71. package/lib/assertron/repeat.d.ts.map +0 -1
  72. package/lib/assertron/repeat.js +0 -43
  73. package/lib/assertron/resolves.d.ts +0 -2
  74. package/lib/assertron/resolves.d.ts.map +0 -1
  75. package/lib/assertron/resolves.js +0 -16
  76. package/lib/assertron/satisfies.d.ts +0 -6
  77. package/lib/assertron/satisfies.d.ts.map +0 -1
  78. package/lib/assertron/satisfies.js +0 -18
  79. package/lib/assertron/throws.d.ts +0 -6
  80. package/lib/assertron/throws.d.ts.map +0 -1
  81. package/lib/assertron/throws.js +0 -59
  82. package/lib/assertron/truthy.d.ts +0 -2
  83. package/lib/assertron/truthy.d.ts.map +0 -1
  84. package/lib/assertron/truthy.js +0 -10
  85. package/lib/errors/NotSatisfied.d.ts +0 -3
  86. package/lib/errors/NotSatisfied.d.ts.map +0 -1
  87. package/lib/errors/NotSatisfied.js +0 -27
  88. package/lib/errors/index.d.ts +0 -8
  89. package/lib/errors/index.d.ts.map +0 -1
  90. package/lib/errors/index.js +0 -10
  91. package/lib/errors/interfaces.d.ts +0 -3
  92. package/lib/errors/interfaces.d.ts.map +0 -1
  93. package/lib/errors/interfaces.js +0 -3
  94. package/lib/errors/notEqualMessage.d.ts +0 -2
  95. package/lib/errors/notEqualMessage.d.ts.map +0 -1
  96. package/lib/errors/notEqualMessage.js +0 -7
  97. package/lib/errors/notRejectedMessage.d.ts +0 -2
  98. package/lib/errors/notRejectedMessage.d.ts.map +0 -1
  99. package/lib/errors/notRejectedMessage.js +0 -7
  100. package/lib/errors/notThrownMessage.d.ts +0 -2
  101. package/lib/errors/notThrownMessage.d.ts.map +0 -1
  102. package/lib/errors/notThrownMessage.js +0 -8
  103. package/lib/errors/returnNotRejectedMessage.d.ts +0 -2
  104. package/lib/errors/returnNotRejectedMessage.d.ts.map +0 -1
  105. package/lib/errors/returnNotRejectedMessage.js +0 -7
  106. package/lib/errors/unexpectedErrorMessage.d.ts +0 -3
  107. package/lib/errors/unexpectedErrorMessage.d.ts.map +0 -1
  108. package/lib/errors/unexpectedErrorMessage.js +0 -9
  109. package/lib/errors/util.d.ts +0 -3
  110. package/lib/errors/util.d.ts.map +0 -1
  111. package/lib/errors/util.js +0 -7
  112. package/lib/index.d.ts +0 -5
  113. package/lib/index.d.ts.map +0 -1
  114. package/lib/index.js +0 -8
  115. package/libm/assert-order/AssertOrder.js +0 -132
  116. package/libm/assert-order/InvalidOrder.js +0 -31
  117. package/libm/assert-order/StateMachine.js +0 -102
  118. package/libm/assert-order/index.js +0 -2
  119. package/libm/assert-order/interfaces.js +0 -1
  120. package/libm/assertron/assertron.js +0 -28
  121. package/libm/assertron/falsy.js +0 -6
  122. package/libm/assertron/index.js +0 -2
  123. package/libm/assertron/pathEqual.js +0 -8
  124. package/libm/assertron/rejects.js +0 -9
  125. package/libm/assertron/repeat.js +0 -35
  126. package/libm/assertron/resolves.js +0 -12
  127. package/libm/assertron/satisfies.js +0 -14
  128. package/libm/assertron/throws.js +0 -55
  129. package/libm/assertron/truthy.js +0 -6
  130. package/libm/errors/NotSatisfied.js +0 -23
  131. package/libm/errors/index.js +0 -7
  132. package/libm/errors/interfaces.js +0 -1
  133. package/libm/errors/notEqualMessage.js +0 -4
  134. package/libm/errors/notRejectedMessage.js +0 -4
  135. package/libm/errors/notThrownMessage.js +0 -5
  136. package/libm/errors/returnNotRejectedMessage.js +0 -4
  137. package/libm/errors/unexpectedErrorMessage.js +0 -6
  138. package/libm/errors/util.js +0 -4
  139. package/libm/index.js +0 -5
  140. package/src/errors/index.ts +0 -7
  141. package/src/errors/notEqualMessage.ts +0 -3
  142. package/src/errors/notRejectedMessage.ts +0 -3
  143. package/src/errors/returnNotRejectedMessage.ts +0 -3
@@ -1,5 +1,5 @@
1
1
  import isPromise from 'is-promise';
2
- import AssertionError from 'assertion-error'
2
+ import { FailOnOccurrence } from '../errors';
3
3
 
4
4
  /**
5
5
  * Repeat the specified function n times and return the last result.
@@ -17,7 +17,7 @@ function repeatRecur<R>(fn: () => R | (() => Promise<R>), i: number, times: numb
17
17
  if (isPromise(result)) {
18
18
  return result.then(
19
19
  () => repeatRecur(fn, i + 1, times),
20
- (e) => { throw new FailOnOccurance(i, e) }
20
+ (e) => { throw new FailOnOccurrence(i, e, { ssf: repeat }) }
21
21
  ) as any
22
22
  }
23
23
  else {
@@ -25,13 +25,8 @@ function repeatRecur<R>(fn: () => R | (() => Promise<R>), i: number, times: numb
25
25
  }
26
26
  }
27
27
  catch (e) {
28
- if (e instanceof FailOnOccurance) throw e
29
- throw new FailOnOccurance(i, e)
28
+ if (e instanceof FailOnOccurrence) throw e
29
+ throw new FailOnOccurrence(i, e, { ssf: repeat })
30
30
  }
31
31
  }
32
32
 
33
- export class FailOnOccurance extends AssertionError {
34
- constructor(public occurance: number, public error: any) {
35
- super(`Failed on ${occurance} occurance`)
36
- }
37
- }
@@ -1,7 +1,6 @@
1
- import t from 'assert';
2
- import a from '..';
3
- import AssertionError from 'assertion-error';
4
- import { assertAsyncThrows, noStackTraceFor } from '../testUtils';
1
+ import t from 'assert'
2
+ import a, { AssertionError } from '..'
3
+ import { assertAsyncThrows, noStackTraceFor } from '../testUtils'
5
4
 
6
5
 
7
6
  test('pass on resolved promise', async () => {
@@ -1,16 +1,9 @@
1
- import { tersify } from 'tersify';
2
- import AssertionError from 'assertion-error';
1
+ import { AssertionError } from '../errors'
2
+ import { notResolvedMessage } from '../utils'
3
3
 
4
4
  export function resolves(promise: Promise<any>) {
5
5
  return promise.then(
6
6
  () => { },
7
- error => {
8
- throw new AssertionError(`Expected promise to resolve, but it rejects with ${typeof error === 'string' ?
9
- `'${error}'` :
10
- error instanceof Error ?
11
- error :
12
- tersify(error, { maxLength: Infinity })}`, { error }, resolves
13
- )
14
- }
7
+ error => { throw new AssertionError(notResolvedMessage(error), { ssf: resolves }) }
15
8
  )
16
9
  }
@@ -1,20 +1,34 @@
1
- import AssertionError from 'assertion-error';
2
- import { every } from 'satisfier';
3
- import a from '..';
4
- import { assertThrows, noStackTraceFor } from '../testUtils';
5
-
6
- test('primitive types will pass', () => {
7
- a.satisfies(1, 1)
8
- a.satisfies('a', 'a')
9
- a.satisfies(true, true)
10
- })
11
-
12
- test('primitive types shows value directly in error', () => {
13
- a.throws(() => a.satisfies<number>(1, 2), e => e.message === 'Expect actual to satisfy 2, but received 1')
14
-
15
- a.throws(() => a.satisfies<boolean>(true, false), e => e.message === 'Expect actual to satisfy false, but received true')
16
-
17
- a.throws(() => a.satisfies<string>('a', 'b'), e => e.message === `Expect actual to satisfy 'b', but received 'a'`)
1
+ // import { every } from 'satisfier'
2
+ import { isType } from 'type-plus'
3
+ import a, { AssertionError } from '..'
4
+ import { assertThrows, noStackTraceFor } from '../testUtils'
5
+
6
+ describe('non-composable types', () => {
7
+ test('accept same type', () => {
8
+ a.satisfies(null, null)
9
+ a.satisfies(undefined, undefined)
10
+ a.satisfies(1, 1)
11
+ a.satisfies('a', 'a')
12
+ a.satisfies(true, true)
13
+ })
14
+
15
+ test('predicate parameter is the widen type', () => {
16
+ a.satisfies(null, (v) => isType<null>(v))
17
+ a.satisfies(undefined, (v) => isType<undefined>(v))
18
+ a.satisfies(1, (v) => isType<number>(v))
19
+ a.satisfies('a', (v) => isType<string>(v))
20
+ a.satisfies(true, (v) => isType<boolean>(v))
21
+ })
22
+
23
+ test('shows value directly in error', () => {
24
+ a.throws(() => a.satisfies(1, 2), e => e.message === 'Expect actual to satisfy 2, but received 1')
25
+ a.throws(() => a.satisfies(true, false), e => e.message === 'Expect actual to satisfy false, but received true')
26
+ a.throws(() => a.satisfies('a', 'b'), e => e.message === `Expect actual to satisfy 'b', but received 'a'`)
27
+ })
28
+
29
+ test('use regex to check against string', () => {
30
+ a.satisfies('abc', /a/)
31
+ })
18
32
  })
19
33
 
20
34
  test('empty object will pass any object', () => {
@@ -26,10 +40,10 @@ test('empty object will fail against primitive types', () => {
26
40
  a.throws(() => a.satisfies(1, {} as any), e => e.message === 'Expect actual to satisfy {}, but received 1')
27
41
  })
28
42
 
29
- test(`can use satisfier util function such as has()/every()`, () => {
30
- a.satisfies([1], every(1))
31
- a.throws(() => a.satisfies([1, 2], every(1)), e => e.message === 'Expect actual[1] to satisfy 1, but received 2')
32
- })
43
+ // test(`can use satisfier util function such as has()/every()`, () => {
44
+ // a.satisfies([1], every(1))
45
+ // a.throws(() => a.satisfies([1, 2], every(1)), e => e.message === 'Expect actual[1] to satisfy 1, but received 2')
46
+ // })
33
47
 
34
48
  test(`array entries are checked`, () => {
35
49
  a.throws(() => a.satisfies([1], [2]), e => e.message === `Expect actual[0] to satisfy 2, but received 1`)
@@ -109,3 +123,21 @@ test('does not contain internal stack trace', async () => {
109
123
  const err = assertThrows(() => a.satisfies({ a: 1 }, { a: 2 }), AssertionError)
110
124
  noStackTraceFor('satisfies.ts', err)
111
125
  })
126
+
127
+ test('allow partial expectation on array entries', () => {
128
+ type U = { type: 'a', a: string } | { type: 'b', b: string }
129
+ const x: U[] = [{ type: 'a', a: 'abc' }]
130
+ a.satisfies(x, [{ type: 'a' }])
131
+ })
132
+
133
+ test('allow predicate on array', () => {
134
+ type U = { type: 'a', a: string } | { type: 'b', b: string }
135
+ const x: U[] = [{ type: 'a', a: 'abc' }]
136
+ a.satisfies(x, (v) => v[0].type == 'a')
137
+ })
138
+
139
+ test('allow predicate on array entries', () => {
140
+ type U = { type: 'a', a: string } | { type: 'b', b: string }
141
+ const x: U[] = [{ type: 'a', a: 'abc' }]
142
+ a.satisfies(x, [(v) => v.type == 'a'])
143
+ })
@@ -1,18 +1,31 @@
1
- import AssertionError from 'assertion-error';
2
- import { createSatisfier } from 'satisfier';
3
- import { notSatisfiedMessage } from '../errors';
1
+ import { createSatisfier } from 'satisfier'
2
+ import { If, IsExtend, NonComposableTypes } from 'type-plus'
3
+ import { AssertionError } from '../errors'
4
+ import { notSatisfiedMessage } from '../utils'
5
+
6
+ export type SatisfyExpectation<T> = If<
7
+ IsExtend<T, string>,
8
+ T | RegExp,
9
+ If<
10
+ IsExtend<T, NonComposableTypes>,
11
+ T,
12
+ If<IsExtend<T, Array<any>>,
13
+ T extends Array<infer E> ? Array<SatisfyExpectation<E>> : never,
14
+ {
15
+ [P in keyof T]?: T[P] extends string
16
+ ? SatisfyExpectation<T[P]> | RegExp
17
+ : SatisfyExpectation<T[P]>
18
+ }
19
+ >>
20
+ > | ((v: T) => boolean)
4
21
 
5
22
  /**
6
23
  * Check if `actual` satisfies criteria in `expected`.
7
24
  * @param expected All properties can be a value which will be compared to the same property in `actual`, RegExp, or a predicate function that will be used to check against the property.
8
25
  */
9
- export function satisfies<Actual extends any>(actual: Actual, expected: any) {
10
- const diff = createSatisfier(expected).exec(actual);
26
+ export function satisfies<Actual>(actual: Actual, expected: SatisfyExpectation<Actual>) {
27
+ const diff = createSatisfier(expected as any).exec(actual);
11
28
  if (diff) {
12
- throw new AssertionError(
13
- notSatisfiedMessage(diff),
14
- { diff },
15
- satisfies
16
- )
29
+ throw new AssertionError(notSatisfiedMessage(diff), { ssf: satisfies })
17
30
  }
18
31
  }
@@ -1,59 +1,61 @@
1
- import t from 'assert';
2
- import AssertionError from 'assertion-error';
3
- import a from '..';
4
- import { assertAsyncThrows, assertIsError, assertIsPromise, assertThrows, noStackTraceFor } from '../testUtils';
1
+ import t from 'assert'
2
+ import a, { AssertionError } from '..'
3
+ import { assertAsyncThrows, assertIsError, assertIsPromise, assertThrows, noStackTraceFor } from '../testUtils'
5
4
 
6
- test('when value is PromiseLike returns Promise', async () => {
7
- let actual = a.throws(Promise.reject(new Error()), Error)
5
+ test('when value is PromiseLike returns a promise with the rejected value', async () => {
6
+ let actual = a.throws(Promise.reject(new Error('Miku')), Error)
8
7
  assertIsPromise(actual)
8
+ t.equal((await actual).message, 'Miku')
9
9
 
10
- actual = a.throws(Promise.reject(new Error()), () => true)
10
+ actual = a.throws(Promise.reject(new Error('Ren')), () => true)
11
11
  assertIsPromise(actual)
12
+ t.equal((await actual).message, 'Ren')
12
13
 
13
- actual = a.throws(Promise.reject(new Error()))
14
+ actual = a.throws(Promise.reject(new Error('Luka')))
14
15
  assertIsPromise(actual)
16
+ t.equal((await actual).message, 'Luka')
15
17
  })
16
18
 
17
- test('when value is function returning promise, will return promise', () => {
18
- let actual = a.throws(() => Promise.reject(new Error()), Error)
19
+ test('when value is function returning a promise, will return a promise with the rejected value', async () => {
20
+ let actual = a.throws(() => Promise.reject(new Error('Miku')), Error)
19
21
  assertIsPromise(actual)
22
+ t.equal((await actual).message, 'Miku')
20
23
 
21
- actual = a.throws(() => Promise.reject(new Error()), () => true)
24
+ actual = a.throws(() => Promise.reject(new Error('Luka')), () => true)
22
25
  assertIsPromise(actual)
26
+ t.equal((await actual).message, 'Luka')
23
27
 
24
- actual = a.throws(() => Promise.reject())
28
+ actual = a.throws(() => Promise.reject('Ren'))
25
29
  assertIsPromise(actual)
30
+ t.equal((await actual), 'Ren')
26
31
  })
27
32
 
28
33
  test('when value is function returns error', () => {
29
- let actual = a.throws((() => { throw new Error() }) as () => void, Error)
34
+ let actual = a.throws((() => { throw new Error() }), Error)
30
35
  assertIsError(actual)
31
36
 
32
- actual = a.throws((() => { throw new Error() }) as () => void)
37
+ actual = a.throws((() => { throw new Error() }))
33
38
  assertIsError(actual)
34
39
  })
35
40
 
36
- test('throws InvalidUsage if input is not a function or promise', () => {
41
+ test('throws if input is not a function or promise', () => {
37
42
  assertThrows(() => a.throws(0 as any))
38
43
  assertThrows(() => a.throws(true as any))
39
44
  assertThrows(() => a.throws('...' as any))
40
45
  assertThrows(() => a.throws(/foo/ as any))
41
46
  })
42
47
 
43
- test('throws for resolved promise', async () => {
44
- const actual = await assertAsyncThrows<AssertionError<{ value: string }>>(() => a.throws(Promise.resolve('ok')), AssertionError)
45
- t.strictEqual(actual.value, 'ok')
48
+ test('throws for resolved promise', () => {
49
+ return assertAsyncThrows(() => a.throws(Promise.resolve('ok')), AssertionError)
46
50
  })
47
51
 
48
52
  test('throws error does not contain internal stack trace for resolved promise', async () => {
49
- const err = await assertAsyncThrows<AssertionError<{ value: string }>>(() => a.throws(Promise.resolve('ok')), AssertionError)
53
+ const err = await assertAsyncThrows(() => a.throws(Promise.resolve('ok')), AssertionError)
50
54
  noStackTraceFor('throws.ts', err)
51
55
  })
52
56
 
53
57
  test('passes with rejected promise', async () => {
54
- const actual = await a.throws<string>(() => new Promise((_, r) => {
55
- setImmediate(() => r('no'))
56
- }))
58
+ const actual = await a.throws<string>(() => new Promise((_, r) => setImmediate(() => r('no'))))
57
59
  t.strictEqual(actual, 'no')
58
60
  })
59
61
 
@@ -62,13 +64,14 @@ test('passes with rejected promise passing validator', () => {
62
64
  })
63
65
 
64
66
  test('throws with rejected promise failing validator', async () => {
65
- const err = await assertAsyncThrows<AssertionError<{ actual: string }>>(() => a.throws(Promise.reject('no'), err => err !== 'no'))
66
-
67
- t.strictEqual(err.actual, 'no')
67
+ await assertAsyncThrows(
68
+ () => a.throws(Promise.reject('no'), err => err !== 'no'),
69
+ AssertionError)
68
70
  })
69
71
 
70
72
  test('thrown error does not contain internal stack trace with rejected promise failing validator', async () => {
71
- const err = await assertAsyncThrows<AssertionError<{ actual: string }>>(() => a.throws(Promise.reject('no'), err => err !== 'no'))
73
+ const err = await assertAsyncThrows(() => a.throws(Promise.reject('no'), err => err !== 'no'), AssertionError)
74
+ // Error.captureStackTrace(err, a.throws)
72
75
 
73
76
  noStackTraceFor('throws.ts', err)
74
77
  })
@@ -78,15 +81,14 @@ test('passes with throwing function', () => {
78
81
  })
79
82
 
80
83
  test('throws if function does not', () => {
81
- const err = assertThrows<AssertionError<{ value: string }>>(
84
+ assertThrows(
82
85
  () => a.throws(() => { return 'foo' }, AssertionError),
83
86
  AssertionError
84
87
  )
85
- t.strictEqual(err.value, 'foo')
86
88
  })
87
89
 
88
90
  test('thrown error does not contain internal stack track if function does not', () => {
89
- const err = assertThrows<AssertionError<{ value: string }>>(
91
+ const err = assertThrows(
90
92
  () => a.throws(() => { return 'foo' }, AssertionError),
91
93
  AssertionError
92
94
  )
@@ -94,12 +96,15 @@ test('thrown error does not contain internal stack track if function does not',
94
96
  })
95
97
 
96
98
  test('throws if function returns resolved promise', async () => {
97
- const err = await assertAsyncThrows<AssertionError<{ value: string }>>(() => a.throws(() => Promise.resolve('ok')), AssertionError)
98
- t.strictEqual(err.value, 'ok')
99
+ await assertAsyncThrows(
100
+ () => a.throws(() => Promise.resolve('ok')),
101
+ AssertionError)
99
102
  })
100
103
 
101
104
  test('thrown error does not contain internal stack trace if function returns resolved promise', async () => {
102
- const err = await assertAsyncThrows<AssertionError<{ value: string }>>(() => a.throws(() => Promise.resolve('ok')), AssertionError)
105
+ const err = await assertAsyncThrows(
106
+ () => a.throws(() => Promise.resolve('ok')),
107
+ AssertionError)
103
108
  noStackTraceFor('throws.ts', err)
104
109
  })
105
110
 
@@ -114,12 +119,18 @@ test('pass if function returns rejected promise passing valdation', () => {
114
119
  })
115
120
 
116
121
  test('throws if function returns rejected promise not passing valdation', async () => {
117
- const err = await assertAsyncThrows<AssertionError<{ actual: any }>>(() => a.throws(() => Promise.reject('ok'), err => err !== 'ok'))
118
- t.strictEqual(err.actual, 'ok')
122
+ await assertAsyncThrows(
123
+ () => a.throws(() => Promise.reject('ok'), err => err !== 'ok'),
124
+ AssertionError
125
+ )
119
126
  })
120
127
 
121
128
  test('thrown error does not contain stack trace if function returns rejected promise not passing valdation', async () => {
122
- const err = await assertAsyncThrows<AssertionError<{ actual: any }>>(() => a.throws(() => Promise.reject('ok'), err => err !== 'ok'))
129
+ const err = await assertAsyncThrows(
130
+ () => a.throws(() => Promise.reject('ok'), err => err !== 'ok'),
131
+ AssertionError
132
+ )
133
+ // console.log('got err', err)
123
134
  noStackTraceFor('throws.ts', err)
124
135
  })
125
136
 
@@ -1,7 +1,7 @@
1
- import AssertionError from 'assertion-error';
2
1
  import isPromise from 'is-promise';
3
- import { ErrorConstructor, ErrorValidator, notRejectedMessage, notThrownMessage, returnNotRejectedMessage, unexpectedErrorMessage } from '../errors';
4
- import { isErrorConstructor } from '../errors/util';
2
+ import { AssertionError } from '../errors';
3
+ import { ErrorConstructor, ErrorValidator } from '../types';
4
+ import { isErrorConstructor, notRejectedMessage, notThrownMessage, unexpectedErrorMessage } from '../utils';
5
5
 
6
6
  export function throws<E extends Error>(value: PromiseLike<any>, error?: ErrorValidator | ErrorConstructor<E>): Promise<E>
7
7
  export function throws<E extends Error>(value: (...args: any[]) => never, error?: ErrorValidator | ErrorConstructor<E>): E
@@ -10,51 +10,35 @@ export function throws<T, R = any>(value: (...args: any[]) => R, validator?: Err
10
10
  export function throws(value: PromiseLike<any> | (() => any | PromiseLike<any>), validator?: ErrorValidator | ErrorConstructor<any>): any {
11
11
  if (typeof value !== 'function' && !isPromise(value)) {
12
12
  throw new AssertionError(
13
- '`assertron.throws()` must be called with a functio n or promise.',
14
- undefined,
15
- throws
13
+ '`assertron.throws()` must be called with a function or promise.',
14
+ { ssf: throws }
16
15
  )
17
16
  }
18
17
 
19
- if (isPromise(value)) {
20
- return value.then(
21
- value => {
22
- throw new AssertionError(
23
- notRejectedMessage(value),
24
- { value },
25
- throws)
26
- },
27
- err => {
28
- validateError(validator, err)
29
- return err
18
+ if (!isPromise(value)) {
19
+ const { threw, err, result } = tryCatch(value)
20
+ if (threw) {
21
+ if (failValidation(validator, err)) {
22
+ throw new AssertionError(unexpectedErrorMessage(err, validator), { ssf: throws })
30
23
  }
31
- )
32
- }
33
- const { threw, err, result } = tryCatch(value)
34
- if (threw) {
35
- validateError(validator, err)
36
- return err
24
+ return err
25
+ }
26
+ value = result;
37
27
  }
38
- if (isPromise(result)) {
39
- return result.then(
40
- value => {
41
- throw new AssertionError(
42
- returnNotRejectedMessage(value),
43
- { value },
44
- throws)
45
- },
28
+
29
+ if (isPromise(value)) {
30
+ return value.then(
31
+ value => { throw new AssertionError(notRejectedMessage(value), { ssf: throws }) },
46
32
  err => {
47
- validateError(validator, err)
33
+ if (failValidation(validator, err)) {
34
+ throw new AssertionError(unexpectedErrorMessage(err, validator), { ssf: throws })
35
+ }
48
36
  return err
49
37
  }
50
38
  )
51
39
  }
52
40
 
53
- throw new AssertionError(
54
- notThrownMessage(result),
55
- { value: result },
56
- throws
57
- )
41
+ throw new AssertionError(notThrownMessage(value), { ssf: throws })
58
42
  }
59
43
 
60
44
  function tryCatch(fn: () => any) {
@@ -70,22 +54,14 @@ function tryCatch(fn: () => any) {
70
54
  }
71
55
  return { threw, err, result }
72
56
  }
57
+ function failValidation(validator: ErrorValidator | ErrorConstructor<any> | undefined, error: any): validator is ErrorValidator | ErrorConstructor<any> {
58
+ if (!validator) return false
73
59
 
74
- function validateError(validator: ErrorValidator | ErrorConstructor<any> | undefined, error: any) {
75
- if (validator) {
76
- if (isErrorConstructor(validator)) {
77
- if (!(error instanceof validator))
78
- throw new AssertionError(
79
- unexpectedErrorMessage(error, validator),
80
- { actual: error, expected: validator },
81
- throws
82
- )
83
- }
84
- else if (!validator(error))
85
- throw new AssertionError(
86
- unexpectedErrorMessage(error, validator),
87
- { actual: error, expected: validator },
88
- throws
89
- )
60
+ if (isErrorConstructor(validator)) {
61
+ return !(error instanceof validator)
62
+ }
63
+ else {
64
+ return !validator(error)
90
65
  }
91
66
  }
67
+
@@ -1,6 +1,5 @@
1
- import AssertionError from 'assertion-error';
2
- import a from '..';
3
- import { assertThrows, noStackTraceFor } from '../testUtils';
1
+ import a, { AssertionError } from '..'
2
+ import { assertThrows, noStackTraceFor } from '../testUtils'
4
3
 
5
4
  test('falsy statement throws', () => {
6
5
  assertThrows(() => a.truthy(false), AssertionError)
@@ -1,9 +1,8 @@
1
- import AssertionError from 'assertion-error';
1
+ import { AssertionError } from '../errors';
2
2
 
3
3
  export function truthy(value: any) {
4
4
  if (!value) throw new AssertionError(
5
5
  `Expected value to be truthy, but received ${value}`,
6
- { value },
7
- truthy
6
+ { ssf: truthy }
8
7
  )
9
8
  }
package/src/errors.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { IsoError, ModuleError } from 'iso-error'
2
+ import { RequiredPick } from 'type-plus'
3
+ import { failOnOccurrence } from './utils'
4
+
5
+ /**
6
+ * A base error for all assertion errors
7
+ */
8
+ export class AssertionError extends ModuleError {
9
+ constructor(message: string, options: AssertionError.Options) {
10
+ super('assertron', message, options)
11
+ }
12
+ }
13
+
14
+ export namespace AssertionError {
15
+ export type Options = RequiredPick<IsoError.Options, 'ssf'>
16
+ }
17
+
18
+ export class FailOnOccurrence extends AssertionError {
19
+ constructor(public occurrence: number, public error: any, options: AssertionError.Options) {
20
+ super(failOnOccurrence(occurrence, error), options)
21
+ }
22
+ }
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { assertron } from './assertron'
2
2
 
3
- export * from './assertron'
4
3
  export * from './assert-order'
4
+ export * from './errors'
5
+ export * from './assertron'
5
6
  export default assertron
package/src/testUtils.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  // istanbul ignore file
2
- import t from 'assert';
3
- import AssertionError from 'assertion-error';
4
- import isPromise from 'is-promise';
5
- import { isError } from 'lodash';
6
- import { ErrorConstructor } from './errors';
2
+ import t from 'assert'
3
+ import isPromise from 'is-promise'
4
+ import { isError } from 'lodash'
5
+ import { ErrorConstructor } from './types'
7
6
 
8
- export function runAsync(fn) {
7
+ export type AnyFunction = (...args: any[]) => any
8
+
9
+ export function runAsync(fn: AnyFunction) {
9
10
  return new Promise((resolve, reject) => {
10
11
  setTimeout(() => {
11
12
  try {
@@ -18,7 +19,7 @@ export function runAsync(fn) {
18
19
  })
19
20
  }
20
21
 
21
- export function runSequentialAsync(...fns) {
22
+ export function runSequentialAsync(...fns: AnyFunction[]) {
22
23
  return new Promise((resolve, reject) => {
23
24
  setTimeout(() => {
24
25
  try {
@@ -35,7 +36,7 @@ export function runSequentialAsync(...fns) {
35
36
  })
36
37
  }
37
38
 
38
- export function runParallelAsync(...fns) {
39
+ export function runParallelAsync(...fns: AnyFunction[]) {
39
40
  return Promise.all(fns.map(fn => runAsync(fn)))
40
41
  }
41
42
 
@@ -48,11 +49,11 @@ export function assertIsError(err: Error) {
48
49
  t(isError(err))
49
50
  }
50
51
 
51
- export function assertThrows<E extends Error>(fn, ErrorType?: ErrorConstructor<E>): E {
52
+ export function assertThrows<E extends Error>(fn: AnyFunction, ErrorType?: ErrorConstructor<E>): E {
52
53
  try {
53
54
  fn()
54
55
  }
55
- catch (e) {
56
+ catch (e: any) {
56
57
  if (ErrorType && !(e instanceof ErrorType)) {
57
58
  throw new Error(`thrown error ${e} is not of expected type ${ErrorType}`)
58
59
  }
@@ -61,21 +62,23 @@ export function assertThrows<E extends Error>(fn, ErrorType?: ErrorConstructor<E
61
62
  throw new Error(`${fn} does not throw as expected`)
62
63
  }
63
64
 
64
- export async function assertAsyncThrows<E extends Error>(fn, ErrorType?: ErrorConstructor<E>): Promise<E> {
65
+ export async function assertAsyncThrows<E extends Error>(fn: AnyFunction, ErrorType?: ErrorConstructor<E>): Promise<E> {
65
66
  try {
66
67
  await fn()
67
68
  }
68
- catch (e) {
69
+ catch (e: any) {
70
+ // console.log('catch clause', e)
69
71
  if (ErrorType && !(e instanceof ErrorType)) {
70
72
  throw new Error(`thrown error ${e} is not of expected type ${ErrorType}`)
71
73
  }
74
+ // console.log('returning e')
72
75
  return e
73
76
  }
74
77
  throw new Error(`${fn} does not throw as expected`)
75
78
  }
76
79
 
77
80
 
78
- export function noStackTraceFor(filename: string, err: AssertionError) {
81
+ export function noStackTraceFor(filename: string, err: Error) {
79
82
  if (err.stack && RegExp(filename).test(err.stack))
80
83
  throw new Error(`contains internal stack: \n${err.stack}`)
81
84
  }
File without changes
@@ -0,0 +1,12 @@
1
+ import { tersify } from 'tersify';
2
+
3
+ export * from './isErrorConstructor';
4
+ export * from './notEqualMessage';
5
+ export * from './notSatisfiedMessage';
6
+ export * from './notThrownMessage';
7
+ export * from './promiseMessages';
8
+ export * from './unexpectedErrorMessage';
9
+
10
+ export function failOnOccurrence(occurrence: number, error: any) {
11
+ return `Failed on ${occurrence} occurrence: ${tersify(error, { maxLength: Infinity })}`
12
+ }
@@ -1,4 +1,4 @@
1
- import { ErrorConstructor } from './interfaces'
1
+ import { ErrorConstructor } from '../types'
2
2
 
3
3
  export function isErrorConstructor(validator: any): validator is ErrorConstructor<any> {
4
4
  return Object.prototype.isPrototypeOf.call(Error.prototype, validator.prototype)
@@ -0,0 +1,4 @@
1
+
2
+ export function notEqualMessage(actual: any, expected: any) {
3
+ return `Expected value to equal ${expected}, but received ${actual}`
4
+ }
File without changes
@@ -0,0 +1,12 @@
1
+ import { tersify } from 'tersify'
2
+
3
+ export function notRejectedMessage(value: any) {
4
+ return `Expected promise to reject, but it resolves with ` + (typeof value === 'string'
5
+ ? `'${value}'` : tersify(value, { maxLength: Infinity }))
6
+ }
7
+
8
+ export function notResolvedMessage(error: any) {
9
+ return `Expected promise to resolve, but it rejects with ` + (typeof error === 'string'
10
+ ? `'${error}'` : error instanceof Error ? error : tersify(error, { maxLength: Infinity }))
11
+ }
12
+