@opra/testing 0.2.0 → 0.4.0

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 (72) hide show
  1. package/cjs/{expect/api-expect-array.js → api-expect/api-expect-collection.js} +48 -46
  2. package/cjs/{expect → api-expect}/api-expect-error.js +3 -4
  3. package/cjs/api-expect/api-expect-object.js +54 -0
  4. package/cjs/{expect → api-expect}/api-expect-operation-result.js +14 -6
  5. package/cjs/{expect → api-expect}/api-expect.js +30 -23
  6. package/cjs/constants.js +4 -0
  7. package/cjs/index.js +3 -22
  8. package/cjs/{expect/jest-extend → jest-extend}/common.extend.js +27 -26
  9. package/cjs/test-client.js +32 -0
  10. package/cjs/{expect/utils → utils}/object-matches.util.js +0 -0
  11. package/esm/api-expect/api-expect-collection.d.ts +19 -0
  12. package/esm/{expect/api-expect-array.js → api-expect/api-expect-collection.js} +46 -44
  13. package/esm/{expect → api-expect}/api-expect-error.d.ts +3 -3
  14. package/esm/{expect → api-expect}/api-expect-error.js +3 -4
  15. package/esm/api-expect/api-expect-object.d.ts +11 -0
  16. package/esm/api-expect/api-expect-object.js +49 -0
  17. package/esm/api-expect/api-expect-operation-result.d.ts +11 -0
  18. package/esm/{expect → api-expect}/api-expect-operation-result.js +14 -6
  19. package/esm/{expect → api-expect}/api-expect.d.ts +8 -7
  20. package/esm/{expect → api-expect}/api-expect.js +30 -23
  21. package/esm/constants.d.ts +1 -0
  22. package/esm/constants.js +1 -0
  23. package/esm/index.d.ts +2 -6
  24. package/esm/index.js +2 -19
  25. package/esm/{expect/jest-extend → jest-extend}/common.extend.d.ts +2 -2
  26. package/esm/{expect/jest-extend → jest-extend}/common.extend.js +26 -26
  27. package/esm/test-client.d.ts +18 -0
  28. package/esm/test-client.js +27 -0
  29. package/esm/{expect/utils → utils}/object-matches.util.d.ts +0 -0
  30. package/esm/{expect/utils → utils}/object-matches.util.js +0 -0
  31. package/package.json +6 -4
  32. package/cjs/api-response.js +0 -22
  33. package/cjs/expect/api-expect-object.js +0 -76
  34. package/cjs/expect/utils/print-errors.util.js +0 -15
  35. package/cjs/testers/base-operation-tester.js +0 -24
  36. package/cjs/testers/base-tester.js +0 -23
  37. package/cjs/testers/entity-create-tester.js +0 -43
  38. package/cjs/testers/entity-delete-many-tester.js +0 -27
  39. package/cjs/testers/entity-delete-tester.js +0 -24
  40. package/cjs/testers/entity-get-tester.js +0 -46
  41. package/cjs/testers/entity-search-tester.js +0 -75
  42. package/cjs/testers/entity-tester.js +0 -72
  43. package/cjs/testers/entity-update-many-tester.js +0 -31
  44. package/cjs/testers/entity-update-tester.js +0 -46
  45. package/esm/api-response.d.ts +0 -12
  46. package/esm/api-response.js +0 -18
  47. package/esm/expect/api-expect-array.d.ts +0 -17
  48. package/esm/expect/api-expect-object.d.ts +0 -12
  49. package/esm/expect/api-expect-object.js +0 -71
  50. package/esm/expect/api-expect-operation-result.d.ts +0 -9
  51. package/esm/expect/utils/print-errors.util.d.ts +0 -1
  52. package/esm/expect/utils/print-errors.util.js +0 -11
  53. package/esm/testers/base-operation-tester.d.ts +0 -8
  54. package/esm/testers/base-operation-tester.js +0 -20
  55. package/esm/testers/base-tester.d.ts +0 -13
  56. package/esm/testers/base-tester.js +0 -19
  57. package/esm/testers/entity-create-tester.d.ts +0 -17
  58. package/esm/testers/entity-create-tester.js +0 -38
  59. package/esm/testers/entity-delete-many-tester.d.ts +0 -14
  60. package/esm/testers/entity-delete-many-tester.js +0 -22
  61. package/esm/testers/entity-delete-tester.d.ts +0 -14
  62. package/esm/testers/entity-delete-tester.js +0 -19
  63. package/esm/testers/entity-get-tester.d.ts +0 -18
  64. package/esm/testers/entity-get-tester.js +0 -41
  65. package/esm/testers/entity-search-tester.d.ts +0 -22
  66. package/esm/testers/entity-search-tester.js +0 -70
  67. package/esm/testers/entity-tester.d.ts +0 -24
  68. package/esm/testers/entity-tester.js +0 -68
  69. package/esm/testers/entity-update-many-tester.d.ts +0 -16
  70. package/esm/testers/entity-update-many-tester.js +0 -26
  71. package/esm/testers/entity-update-tester.d.ts +0 -19
  72. package/esm/testers/entity-update-tester.js +0 -41
@@ -1,77 +1,73 @@
1
1
  import _ from 'lodash';
2
2
  import ruleJudgment from 'rule-judgment';
3
3
  import { $parse, ArrayExpression, BooleanLiteral, ComparisonExpression, DateLiteral, LogicalExpression, NullLiteral, NumberLiteral, ParenthesesExpression, QualifiedIdentifier, StringLiteral, TimeLiteral } from '@opra/url';
4
- export class ApiExpectArray {
4
+ export class ApiExpectCollection {
5
5
  response;
6
- constructor(response) {
6
+ _isNot;
7
+ constructor(response, _isNot = false) {
7
8
  this.response = response;
9
+ this._isNot = _isNot;
8
10
  }
9
- toMatch(expected) {
10
- try {
11
- const v = _.omitBy(expected, _.isNil);
12
- for (const item of this.response.body) {
13
- expect(item).toMatchObject(v);
14
- }
15
- }
16
- catch (e) {
17
- Error.captureStackTrace(e, this.toMatch);
18
- throw e;
19
- }
20
- return this;
11
+ get not() {
12
+ return new ApiExpectCollection(this.response, !this._isNot);
21
13
  }
22
- toContainAllKeys(keys) {
23
- try {
24
- for (const item of this.response.body) {
25
- expect(item).toContainAllKeys(keys);
26
- }
27
- }
28
- catch (e) {
29
- Error.captureStackTrace(e, this.toContainAllKeys);
30
- throw e;
31
- }
14
+ forEach(callbackfn) {
15
+ this.response.data.forEach(callbackfn);
32
16
  return this;
33
17
  }
34
- toContainKeys(keys) {
18
+ toMatch(expected) {
35
19
  try {
36
- for (const item of this.response.body) {
37
- expect(item).toContainKeys(keys);
20
+ const v = _.omitBy(expected, _.isNil);
21
+ for (const item of this.response.data) {
22
+ this._expect(item).toMatchObject(v);
38
23
  }
39
24
  }
40
25
  catch (e) {
41
- Error.captureStackTrace(e, this.toContainKeys);
26
+ Error.captureStackTrace(e, this.toMatch);
42
27
  throw e;
43
28
  }
44
29
  return this;
45
30
  }
46
- notToContainKeys(keys) {
31
+ toHaveFields(keys) {
47
32
  try {
48
- for (const item of this.response.body) {
49
- expect(item).not.toContainKeys(keys);
33
+ for (const item of this.response.data) {
34
+ this._expect(item).toHaveFields(keys);
50
35
  }
51
36
  }
52
37
  catch (e) {
53
- Error.captureStackTrace(e, this.notToContainKeys);
38
+ Error.captureStackTrace(e, this.toHaveFields);
54
39
  throw e;
55
40
  }
56
41
  return this;
57
42
  }
58
- toHaveProperty(keyPath, value) {
43
+ toHaveFieldsOnly(keys) {
59
44
  try {
60
- for (const item of this.response.body) {
61
- expect(item).toHaveProperty(keyPath, value);
45
+ for (const item of this.response.data) {
46
+ this._expect(item).toHaveFieldsOnly(keys);
62
47
  }
63
48
  }
64
49
  catch (e) {
65
- Error.captureStackTrace(e, this.toHaveProperty);
50
+ Error.captureStackTrace(e, this.toHaveFieldsOnly);
66
51
  throw e;
67
52
  }
68
53
  return this;
69
54
  }
55
+ //
56
+ // toHaveProperty(keyPath, value?): this {
57
+ // try {
58
+ // for (const item of this.response.data) {
59
+ // this._expect(item).toHaveProperty(keyPath, value);
60
+ // }
61
+ //
62
+ // } catch (e: any) {
63
+ // Error.captureStackTrace(e, this.toHaveProperty);
64
+ // throw e;
65
+ // }
66
+ // return this;
67
+ // }
70
68
  toBeSortedBy(...fields) {
71
69
  try {
72
- for (const item of this.response.body) {
73
- expect(item).toBeSortedBy(fields);
74
- }
70
+ this._expect(this.response.data).toBeSortedBy(fields);
75
71
  }
76
72
  catch (e) {
77
73
  Error.captureStackTrace(e, this.toBeSortedBy);
@@ -83,9 +79,9 @@ export class ApiExpectArray {
83
79
  const f = convertFilter(filter);
84
80
  if (f) {
85
81
  const j = ruleJudgment(f);
86
- const filtered = this.response.body.filter(j);
82
+ const filtered = this.response.data.filter(j);
87
83
  try {
88
- expect(this.response.body).toStrictEqual(filtered);
84
+ this._expect(this.response.data).toStrictEqual(filtered);
89
85
  }
90
86
  catch (e) {
91
87
  Error.captureStackTrace(e, this.toBeFilteredBy);
@@ -96,7 +92,7 @@ export class ApiExpectArray {
96
92
  }
97
93
  toHaveExactItems(expected) {
98
94
  try {
99
- expect(this.response.body).toHaveLength(expected);
95
+ this._expect(this.response.data).toHaveLength(expected);
100
96
  }
101
97
  catch (e) {
102
98
  Error.captureStackTrace(e, this.toHaveExactItems);
@@ -106,7 +102,7 @@ export class ApiExpectArray {
106
102
  }
107
103
  toHaveMaxItems(expected) {
108
104
  try {
109
- expect(this.response.body.length).toBeLessThanOrEqual(expected);
105
+ this._expect(this.response.data.length).toBeLessThanOrEqual(expected);
110
106
  }
111
107
  catch (e) {
112
108
  Error.captureStackTrace(e, this.toHaveMaxItems);
@@ -116,7 +112,7 @@ export class ApiExpectArray {
116
112
  }
117
113
  toHaveMinItems(expected) {
118
114
  try {
119
- expect(this.response.body.length).toBeGreaterThanOrEqual(expected);
115
+ this._expect(this.response.data.length).toBeGreaterThanOrEqual(expected);
120
116
  }
121
117
  catch (e) {
122
118
  Error.captureStackTrace(e, this.toHaveMinItems);
@@ -124,6 +120,12 @@ export class ApiExpectArray {
124
120
  }
125
121
  return this;
126
122
  }
123
+ _expect(expected) {
124
+ const out = expect(expected);
125
+ if (this._isNot)
126
+ return out.not;
127
+ return out;
128
+ }
127
129
  }
128
130
  export function convertFilter(str) {
129
131
  const ast = typeof str === 'string' ? $parse(str) : str;
@@ -1,8 +1,8 @@
1
- import type { ApiResponse } from '../api-response';
1
+ import { OpraResponse } from '@opra/client';
2
2
  import { ApiExpectObject } from './api-expect-object.js';
3
3
  export declare class ApiExpectError extends ApiExpectObject {
4
- readonly response: ApiResponse;
5
- constructor(response: ApiResponse);
4
+ readonly response: OpraResponse;
5
+ constructor(response: OpraResponse);
6
6
  toContainDetail(...matching: any[]): void;
7
7
  }
8
8
  declare global {
@@ -1,6 +1,6 @@
1
1
  import matcherUtils from 'jest-matcher-utils';
2
+ import { objectMatches } from '../utils/object-matches.util.js';
2
3
  import { ApiExpectObject } from './api-expect-object.js';
3
- import { objectMatches } from './utils/object-matches.util.js';
4
4
  export class ApiExpectError extends ApiExpectObject {
5
5
  response;
6
6
  constructor(response) {
@@ -9,9 +9,8 @@ export class ApiExpectError extends ApiExpectObject {
9
9
  }
10
10
  toContainDetail(...matching) {
11
11
  try {
12
- expect(this.response.body['@@Schema']).toStrictEqual('Opra:Exception');
13
- expect(this.response.body.issues).toBeDefined();
14
- expect(this.response.body.issues).apiErrorDetailToContain(matching);
12
+ expect(this.response.data.issues).toBeDefined();
13
+ expect(this.response.data.issues).apiErrorDetailToContain(matching);
15
14
  }
16
15
  catch (e) {
17
16
  Error.captureStackTrace(e, this.toContainDetail);
@@ -0,0 +1,11 @@
1
+ import { OpraResponse } from '@opra/client';
2
+ export declare class ApiExpectObject {
3
+ readonly response: OpraResponse;
4
+ protected _isNot: boolean;
5
+ constructor(response: OpraResponse, _isNot?: boolean);
6
+ get not(): ApiExpectObject;
7
+ toMatch<T extends {}>(expected: T): this;
8
+ toHaveFields(fields: string[]): this;
9
+ toHaveFieldsOnly(fields: string[]): this;
10
+ protected _expect(expected: any): jest.Matchers<any>;
11
+ }
@@ -0,0 +1,49 @@
1
+ import _ from 'lodash';
2
+ export class ApiExpectObject {
3
+ response;
4
+ _isNot;
5
+ constructor(response, _isNot = false) {
6
+ this.response = response;
7
+ this._isNot = _isNot;
8
+ }
9
+ get not() {
10
+ return new ApiExpectObject(this.response, !this._isNot);
11
+ }
12
+ toMatch(expected) {
13
+ try {
14
+ const v = _.omitBy(expected, _.isNil);
15
+ this._expect(this.response.data).toMatchObject(v);
16
+ }
17
+ catch (e) {
18
+ Error.captureStackTrace(e, this.toMatch);
19
+ throw e;
20
+ }
21
+ return this;
22
+ }
23
+ toHaveFields(fields) {
24
+ try {
25
+ this._expect(this.response.data).toHaveFields(fields);
26
+ }
27
+ catch (e) {
28
+ Error.captureStackTrace(e, this.toHaveFields);
29
+ throw e;
30
+ }
31
+ return this;
32
+ }
33
+ toHaveFieldsOnly(fields) {
34
+ try {
35
+ this._expect(this.response.data).toHaveFieldsOnly(fields);
36
+ }
37
+ catch (e) {
38
+ Error.captureStackTrace(e, this.toHaveFieldsOnly);
39
+ throw e;
40
+ }
41
+ return this;
42
+ }
43
+ _expect(expected) {
44
+ const out = expect(expected);
45
+ if (this._isNot)
46
+ return out.not;
47
+ return out;
48
+ }
49
+ }
@@ -0,0 +1,11 @@
1
+ import { OpraResponse } from '@opra/client';
2
+ export declare class ApiExpectOperationResult {
3
+ readonly response: OpraResponse;
4
+ protected _isNot: boolean;
5
+ constructor(response: OpraResponse, _isNot?: boolean);
6
+ get not(): ApiExpectOperationResult;
7
+ toBeAffectedExact(expected: number): this;
8
+ toBeAffectedMin(expected: number): this;
9
+ toBeAffectedMax(expected: number): this;
10
+ protected _expect(expected: any): jest.Matchers<any>;
11
+ }
@@ -1,14 +1,16 @@
1
1
  export class ApiExpectOperationResult {
2
2
  response;
3
- constructor(response) {
3
+ _isNot;
4
+ constructor(response, _isNot = false) {
4
5
  this.response = response;
6
+ this._isNot = _isNot;
5
7
  }
6
- get body() {
7
- return this.response.body;
8
+ get not() {
9
+ return new ApiExpectOperationResult(this.response, !this._isNot);
8
10
  }
9
11
  toBeAffectedExact(expected) {
10
12
  try {
11
- expect(this.response.body.affected).toStrictEqual(expected);
13
+ this._expect(this.response.data.affected).toStrictEqual(expected);
12
14
  }
13
15
  catch (e) {
14
16
  Error.captureStackTrace(e, this.toBeAffectedExact);
@@ -18,7 +20,7 @@ export class ApiExpectOperationResult {
18
20
  }
19
21
  toBeAffectedMin(expected) {
20
22
  try {
21
- expect(this.response.body.affected).toBeGreaterThanOrEqual(expected);
23
+ this._expect(this.response.data.affected).toBeGreaterThanOrEqual(expected);
22
24
  }
23
25
  catch (e) {
24
26
  Error.captureStackTrace(e, this.toBeAffectedMin);
@@ -28,7 +30,7 @@ export class ApiExpectOperationResult {
28
30
  }
29
31
  toBeAffectedMax(expected) {
30
32
  try {
31
- expect(this.response.body.affected).toBeLessThanOrEqual(expected);
33
+ this._expect(this.response.data.affected).toBeLessThanOrEqual(expected);
32
34
  }
33
35
  catch (e) {
34
36
  Error.captureStackTrace(e, this.toBeAffectedMax);
@@ -36,4 +38,10 @@ export class ApiExpectOperationResult {
36
38
  }
37
39
  return this;
38
40
  }
41
+ _expect(expected) {
42
+ const out = expect(expected);
43
+ if (this._isNot)
44
+ return out.not;
45
+ return out;
46
+ }
39
47
  }
@@ -1,16 +1,17 @@
1
- import './jest-extend/common.extend.js';
2
- import type { ApiResponse } from '../api-response';
3
- import { ApiExpectArray } from './api-expect-array.js';
1
+ import { OpraResponse } from '@opra/client';
2
+ import { ApiExpectCollection } from './api-expect-collection.js';
4
3
  import { ApiExpectError } from './api-expect-error.js';
5
4
  import { ApiExpectObject } from './api-expect-object.js';
6
5
  import { ApiExpectOperationResult } from './api-expect-operation-result.js';
7
6
  export declare class ApiExpect {
8
- readonly response: ApiResponse;
9
- constructor(response: ApiResponse);
10
- get body(): any;
7
+ readonly response: OpraResponse;
8
+ protected _isNot: boolean;
9
+ constructor(response: OpraResponse, _isNot?: boolean);
10
+ get not(): ApiExpect;
11
11
  toSuccess(status?: number): this;
12
12
  toFail(status?: number): ApiExpectError;
13
13
  toReturnOperationResult(): ApiExpectOperationResult;
14
14
  toReturnObject(): ApiExpectObject;
15
- toReturnArray(): ApiExpectArray;
15
+ toReturnCollection(): ApiExpectCollection;
16
+ protected _expect(expected: any): jest.Matchers<any>;
16
17
  }
@@ -1,21 +1,22 @@
1
- import './jest-extend/common.extend.js';
2
- import { ApiExpectArray } from './api-expect-array.js';
1
+ import { ApiExpectCollection } from './api-expect-collection.js';
3
2
  import { ApiExpectError } from './api-expect-error.js';
4
3
  import { ApiExpectObject } from './api-expect-object.js';
5
4
  import { ApiExpectOperationResult } from './api-expect-operation-result.js';
6
5
  export class ApiExpect {
7
6
  response;
8
- constructor(response) {
7
+ _isNot;
8
+ constructor(response, _isNot = false) {
9
9
  this.response = response;
10
+ this._isNot = _isNot;
10
11
  }
11
- get body() {
12
- return this.response.body;
12
+ get not() {
13
+ return new ApiExpect(this.response, !this._isNot);
13
14
  }
14
15
  toSuccess(status = 200) {
15
- let msg = ';';
16
+ let msg = '';
16
17
  try {
17
- msg = 'Response "status" is not valid';
18
- expect(this.response.status).toStrictEqual(status);
18
+ msg = 'Unexpected "status" returned';
19
+ this._expect(this.response.status).toStrictEqual(status);
19
20
  }
20
21
  catch (e) {
21
22
  if (msg)
@@ -26,7 +27,7 @@ export class ApiExpect {
26
27
  return this;
27
28
  }
28
29
  toFail(status = 400) {
29
- let msg = ';';
30
+ let msg = '';
30
31
  try {
31
32
  msg = 'Response "status" does not match';
32
33
  if (status) {
@@ -37,8 +38,8 @@ export class ApiExpect {
37
38
  expect(this.response.status).toBeLessThanOrEqual(599);
38
39
  }
39
40
  msg = 'Api did not returned "errors"';
40
- expect(this.response.body.errors).toBeArray();
41
- expect(this.response.body.errors.length).toBeGreaterThan(0);
41
+ expect(this.response.data.errors).toBeArray();
42
+ expect(this.response.data.errors.length).toBeGreaterThan(0);
42
43
  }
43
44
  catch (e) {
44
45
  if (msg)
@@ -49,26 +50,26 @@ export class ApiExpect {
49
50
  return new ApiExpectError(this.response);
50
51
  }
51
52
  toReturnOperationResult() {
52
- let msg = ';';
53
+ let msg = '';
53
54
  try {
54
55
  msg = '"body" is empty';
55
- expect(this.response.body).toBeDefined();
56
+ expect(this.response.data).toBeDefined();
56
57
  msg = '"operation" property is empty';
57
- expect(this.response.body.operation).toBeDefined();
58
+ expect(this.response.data.operation).toBeDefined();
58
59
  }
59
60
  catch (e) {
60
61
  if (msg)
61
62
  e.message = msg + '\n\n' + e.message;
62
- Error.captureStackTrace(e, this.toReturnObject);
63
+ Error.captureStackTrace(e, this.toReturnOperationResult);
63
64
  throw e;
64
65
  }
65
66
  return new ApiExpectOperationResult(this.response);
66
67
  }
67
68
  toReturnObject() {
68
- let msg = ';';
69
+ let msg = '';
69
70
  try {
70
71
  msg = '"body" is empty';
71
- expect(this.response.body).toBeDefined();
72
+ expect(this.response.data).toBeDefined();
72
73
  }
73
74
  catch (e) {
74
75
  if (msg)
@@ -78,20 +79,26 @@ export class ApiExpect {
78
79
  }
79
80
  return new ApiExpectObject(this.response);
80
81
  }
81
- toReturnArray() {
82
- let msg = ';';
82
+ toReturnCollection() {
83
+ let msg = '';
83
84
  try {
84
85
  msg = '"body" is empty';
85
- expect(this.response.body).toBeDefined();
86
+ expect(this.response.data).toBeDefined();
86
87
  msg = '"body" is not an array';
87
- expect(this.response.body).toBeArray();
88
+ expect(this.response.data).toBeArray();
88
89
  }
89
90
  catch (e) {
90
91
  if (msg)
91
92
  e.message = msg + '\n\n' + e.message;
92
- Error.captureStackTrace(e, this.toReturnArray);
93
+ Error.captureStackTrace(e, this.toReturnCollection);
93
94
  throw e;
94
95
  }
95
- return new ApiExpectArray(this.response);
96
+ return new ApiExpectCollection(this.response);
97
+ }
98
+ _expect(expected) {
99
+ const out = expect(expected);
100
+ if (this._isNot)
101
+ return out.not;
102
+ return out;
96
103
  }
97
104
  }
@@ -0,0 +1 @@
1
+ export declare const expectSymbolTag: unique symbol;
@@ -0,0 +1 @@
1
+ export const expectSymbolTag = Symbol('opra.test.expect');
package/esm/index.d.ts CHANGED
@@ -1,6 +1,2 @@
1
- import { BaseTester, OpraTesterParams } from './testers/base-tester.js';
2
- import { OpraEntityTester } from './testers/entity-tester.js';
3
- export declare function opraTest(app: any, options?: Partial<Omit<OpraTesterParams, 'app'>>): OpraTester;
4
- export declare class OpraTester extends BaseTester {
5
- entity(path: string): OpraEntityTester;
6
- }
1
+ import './jest-extend/common.extend.js';
2
+ export * from './test-client.js';
package/esm/index.js CHANGED
@@ -1,19 +1,2 @@
1
- import { BaseTester } from './testers/base-tester.js';
2
- import { OpraEntityTester } from './testers/entity-tester.js';
3
- export function opraTest(app, options) {
4
- return new OpraTester({
5
- app,
6
- ...options,
7
- prefix: options?.prefix || '',
8
- headers: options?.headers || {}
9
- });
10
- }
11
- export class OpraTester extends BaseTester {
12
- entity(path) {
13
- return new OpraEntityTester({
14
- ...this._params,
15
- headers: { ...this._params.headers },
16
- path
17
- });
18
- }
19
- }
1
+ import './jest-extend/common.extend.js';
2
+ export * from './test-client.js';
@@ -1,8 +1,8 @@
1
1
  declare global {
2
2
  namespace jest {
3
3
  interface Matchers<R> {
4
- toContainKeys(expected: string[]): any;
5
- toContainAllKeys(expected: string[]): any;
4
+ toHaveFields(expected: string[]): any;
5
+ toHaveFieldsOnly(expected: string[]): any;
6
6
  toBeArray(): any;
7
7
  toBeSorted(compareFn?: (a: any, b: any) => number): any;
8
8
  toBeSortedBy(properties: string[]): any;
@@ -1,30 +1,30 @@
1
+ import colors from "ansi-colors";
1
2
  import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils';
2
3
  expect.extend({
3
- toContainKeys(received, expected) {
4
- if (typeof received === 'object') {
5
- const keys = Array.isArray(expected) ? expected : Object.keys(expected);
6
- const additionalKeys = Object.keys(received).filter(x => !keys.includes(x));
7
- if (!Object.keys(received).find(x => keys.includes(x))) {
8
- return {
9
- pass: false,
10
- message: () => `Object contains unexpected additional keys (${additionalKeys})`
11
- };
12
- }
4
+ toHaveFields(received, expected) {
5
+ const expectedKeys = (Array.isArray(expected) ? expected : Object.keys(expected)).map(x => x.toLowerCase());
6
+ const objectKeys = Object.keys(received).map(x => x.toLowerCase());
7
+ const filteredKeys = expectedKeys.filter(x => !objectKeys.includes(x));
8
+ const pass = !filteredKeys.length === !this.isNot;
9
+ if (!pass) {
10
+ const message = () => `Expects keys to${this.isNot ? ' not' : ''} contain: ${colors.yellow('' + expectedKeys)}\n` +
11
+ `${this.isNot ? 'Unsolicited' : 'Missing'} fields: ${colors.yellow('' + filteredKeys)}\n`;
12
+ return { message, pass: !!this.isNot };
13
13
  }
14
- return { actual: received, pass: true, message: () => '' };
14
+ return { actual: received, pass: !this.isNot, message: () => '' };
15
15
  },
16
- toContainAllKeys(received, expected) {
17
- if (typeof received === 'object') {
18
- const keys = Array.isArray(expected) ? expected : Object.keys(expected);
19
- const additionalKeys = Object.keys(received).filter(x => !keys.includes(x));
20
- if (additionalKeys.length) {
21
- return {
22
- pass: false,
23
- message: () => `Object contains unexpected additional keys (${additionalKeys})`
24
- };
25
- }
16
+ toHaveFieldsOnly(received, expected) {
17
+ const expectedKeys = (Array.isArray(expected) ? expected : Object.keys(expected)).map(x => x.toLowerCase());
18
+ const objectKeys = Object.keys(received).map(x => x.toLowerCase());
19
+ const filteredKeys = objectKeys.filter(x => !expectedKeys.includes(x));
20
+ const pass = !filteredKeys.length === !this.isNot;
21
+ if (!pass) {
22
+ const message = () => `${!this.isNot ? 'Do not expects' : 'Expects'} additional keys other than: ${colors.yellow('' + expectedKeys)}\n` +
23
+ (filteredKeys ? `Additional keys received: ${colors.yellow('' + filteredKeys)}\n` :
24
+ 'No additional keys received\n');
25
+ return { message, pass };
26
26
  }
27
- return { actual: received, pass: true, message: () => '' };
27
+ return { actual: received, pass: !this.isNot, message: () => '' };
28
28
  },
29
29
  toBeArray(received) {
30
30
  if (Array.isArray(received)) {
@@ -36,10 +36,10 @@ expect.extend({
36
36
  };
37
37
  },
38
38
  toBeSorted(received, compareFn) {
39
- let pass = Array.isArray(received);
39
+ let pass = true;
40
40
  let message;
41
41
  if (pass) {
42
- const sorted = [...received];
42
+ const sorted = [...(received || [])];
43
43
  sorted.sort(compareFn);
44
44
  try {
45
45
  expect(received).toEqual(sorted);
@@ -65,10 +65,10 @@ expect.extend({
65
65
  }
66
66
  return v;
67
67
  };
68
- let pass = Array.isArray(received);
68
+ let pass = true;
69
69
  let message;
70
70
  if (pass) {
71
- const sorted = [...received];
71
+ const sorted = [...(received || [])];
72
72
  sorted.sort((a, b) => {
73
73
  for (const sortField of fieldsMap) {
74
74
  const l = getValue(a, sortField);
@@ -0,0 +1,18 @@
1
+ /// <reference types="node" />
2
+ import { AxiosRequestConfig } from 'axios';
3
+ import { IncomingMessage, Server, ServerResponse } from 'http';
4
+ import { CollectionService, CommonRequestOptions, OpraClient, OpraClientOptions, OpraResponse } from '@opra/client';
5
+ import { SingletonService } from '@opra/client/src/services/singleton-service';
6
+ import { ApiExpect } from './api-expect/api-expect.js';
7
+ declare type RequestListener = (req: IncomingMessage, res: ServerResponse) => void;
8
+ declare type Handler = RequestListener | Server;
9
+ declare type OpraTestResponse<T = any> = OpraResponse<T> & {
10
+ expect: ApiExpect;
11
+ };
12
+ export declare class OpraTestClient extends OpraClient {
13
+ collection<T = any, TResponse extends OpraTestResponse<T> = OpraTestResponse<T>>(name: string): CollectionService<T, TResponse>;
14
+ singleton<T = any, TResponse extends OpraTestResponse<T> = OpraTestResponse<T>>(name: string): SingletonService<T, TResponse>;
15
+ protected _send(req: AxiosRequestConfig, options: CommonRequestOptions): Promise<OpraTestResponse>;
16
+ static create(app: Handler, options?: OpraClientOptions): Promise<OpraTestClient>;
17
+ }
18
+ export {};
@@ -0,0 +1,27 @@
1
+ import * as axiosist from 'axiosist';
2
+ import { OpraClient } from '@opra/client';
3
+ import { ApiExpect } from './api-expect/api-expect.js';
4
+ export class OpraTestClient extends OpraClient {
5
+ // @ts-ignore
6
+ collection(name) {
7
+ return super.collection(name);
8
+ }
9
+ // @ts-ignore
10
+ singleton(name) {
11
+ return super.singleton(name);
12
+ }
13
+ async _send(req, options) {
14
+ const resp = (await super._send(req, options));
15
+ resp.expect = new ApiExpect(resp);
16
+ return resp;
17
+ }
18
+ static async create(app, options) {
19
+ const instance = await super.create('/', {
20
+ validateStatus: false,
21
+ ...options,
22
+ adapter: axiosist.createAdapter(app)
23
+ });
24
+ Object.setPrototypeOf(instance, OpraTestClient.prototype);
25
+ return instance;
26
+ }
27
+ }