@elastic/synthetics 1.0.0-beta.2 → 1.0.0-beta.22

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 (122) hide show
  1. package/CHANGELOG.md +235 -0
  2. package/NOTICE.txt +250 -0
  3. package/README.md +2 -1
  4. package/dist/cli.js +87 -56
  5. package/dist/cli.js.map +1 -1
  6. package/dist/common_types.d.ts +116 -14
  7. package/dist/common_types.d.ts.map +1 -1
  8. package/dist/config.d.ts +2 -5
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/config.js +5 -5
  11. package/dist/config.js.map +1 -1
  12. package/dist/core/browser-service.js +5 -5
  13. package/dist/core/browser-service.js.map +1 -1
  14. package/dist/core/expect.d.ts +177 -0
  15. package/dist/core/expect.d.ts.map +1 -0
  16. package/dist/core/expect.js +33 -0
  17. package/dist/core/expect.js.map +1 -0
  18. package/dist/core/gatherer.d.ts +4 -7
  19. package/dist/core/gatherer.d.ts.map +1 -1
  20. package/dist/core/gatherer.js +39 -12
  21. package/dist/core/gatherer.js.map +1 -1
  22. package/dist/core/index.d.ts +5 -5
  23. package/dist/core/index.d.ts.map +1 -1
  24. package/dist/core/index.js +2 -2
  25. package/dist/core/index.js.map +1 -1
  26. package/dist/core/logger.d.ts +0 -1
  27. package/dist/core/logger.d.ts.map +1 -1
  28. package/dist/core/logger.js +3 -16
  29. package/dist/core/logger.js.map +1 -1
  30. package/dist/core/runner.d.ts +54 -45
  31. package/dist/core/runner.d.ts.map +1 -1
  32. package/dist/core/runner.js +181 -71
  33. package/dist/core/runner.js.map +1 -1
  34. package/dist/dsl/journey.d.ts +13 -4
  35. package/dist/dsl/journey.d.ts.map +1 -1
  36. package/dist/dsl/journey.js +40 -1
  37. package/dist/dsl/journey.js.map +1 -1
  38. package/dist/formatter/javascript.d.ts +73 -0
  39. package/dist/formatter/javascript.d.ts.map +1 -0
  40. package/dist/formatter/javascript.js +274 -0
  41. package/dist/formatter/javascript.js.map +1 -0
  42. package/dist/helpers.d.ts +33 -12
  43. package/dist/helpers.d.ts.map +1 -1
  44. package/dist/helpers.js +108 -54
  45. package/dist/helpers.js.map +1 -1
  46. package/dist/index.d.ts +8 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +6 -7
  49. package/dist/index.js.map +1 -1
  50. package/dist/parse_args.d.ts +5 -2
  51. package/dist/parse_args.d.ts.map +1 -1
  52. package/dist/parse_args.js +59 -16
  53. package/dist/parse_args.js.map +1 -1
  54. package/dist/plugins/browser-console.d.ts +5 -8
  55. package/dist/plugins/browser-console.d.ts.map +1 -1
  56. package/dist/plugins/browser-console.js +27 -8
  57. package/dist/plugins/browser-console.js.map +1 -1
  58. package/dist/plugins/network.d.ts +23 -20
  59. package/dist/plugins/network.d.ts.map +1 -1
  60. package/dist/plugins/network.js +149 -124
  61. package/dist/plugins/network.js.map +1 -1
  62. package/dist/plugins/performance.d.ts +5 -5
  63. package/dist/plugins/performance.d.ts.map +1 -1
  64. package/dist/plugins/performance.js +5 -5
  65. package/dist/plugins/performance.js.map +1 -1
  66. package/dist/plugins/plugin-manager.d.ts +11 -11
  67. package/dist/plugins/plugin-manager.d.ts.map +1 -1
  68. package/dist/plugins/plugin-manager.js +40 -24
  69. package/dist/plugins/plugin-manager.js.map +1 -1
  70. package/dist/plugins/tracing.d.ts +10 -25
  71. package/dist/plugins/tracing.d.ts.map +1 -1
  72. package/dist/plugins/tracing.js +40 -26
  73. package/dist/plugins/tracing.js.map +1 -1
  74. package/dist/reporters/base.d.ts +0 -1
  75. package/dist/reporters/base.d.ts.map +1 -1
  76. package/dist/reporters/base.js +34 -32
  77. package/dist/reporters/base.js.map +1 -1
  78. package/dist/reporters/json.d.ts +46 -59
  79. package/dist/reporters/json.d.ts.map +1 -1
  80. package/dist/reporters/json.js +188 -70
  81. package/dist/reporters/json.js.map +1 -1
  82. package/dist/reporters/junit.d.ts.map +1 -1
  83. package/dist/reporters/junit.js +7 -7
  84. package/dist/reporters/junit.js.map +1 -1
  85. package/dist/sdk/lh-trace-processor.d.ts +304 -0
  86. package/dist/sdk/lh-trace-processor.d.ts.map +1 -0
  87. package/dist/sdk/lh-trace-processor.js +832 -0
  88. package/dist/sdk/lh-trace-processor.js.map +1 -0
  89. package/dist/sdk/trace-metrics.d.ts +61 -0
  90. package/dist/sdk/trace-metrics.d.ts.map +1 -0
  91. package/dist/sdk/trace-metrics.js +252 -0
  92. package/dist/sdk/trace-metrics.js.map +1 -0
  93. package/dist/sdk/trace-processor.d.ts +106 -0
  94. package/dist/sdk/trace-processor.d.ts.map +1 -0
  95. package/dist/sdk/trace-processor.js +74 -0
  96. package/dist/sdk/trace-processor.js.map +1 -0
  97. package/dist/tsconfig.tsbuildinfo +1 -1575
  98. package/package.json +27 -16
  99. package/src/cli.ts +68 -45
  100. package/src/common_types.ts +138 -14
  101. package/src/config.ts +2 -5
  102. package/src/core/expect.ts +187 -0
  103. package/src/core/gatherer.ts +48 -24
  104. package/src/core/index.ts +6 -6
  105. package/src/core/logger.ts +1 -12
  106. package/src/core/runner.ts +259 -112
  107. package/src/dsl/journey.ts +28 -6
  108. package/src/formatter/javascript.ts +330 -0
  109. package/src/helpers.ts +114 -24
  110. package/src/index.ts +7 -6
  111. package/src/parse_args.ts +97 -22
  112. package/src/plugins/browser-console.ts +30 -13
  113. package/src/plugins/network.ts +175 -159
  114. package/src/plugins/performance.ts +7 -7
  115. package/src/plugins/plugin-manager.ts +47 -36
  116. package/src/plugins/tracing.ts +43 -54
  117. package/src/reporters/base.ts +29 -23
  118. package/src/reporters/json.ts +259 -80
  119. package/src/reporters/junit.ts +1 -1
  120. package/src/sdk/lh-trace-processor.ts +1033 -0
  121. package/src/sdk/trace-metrics.ts +287 -0
  122. package/src/sdk/trace-processor.ts +147 -0
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@elastic/synthetics",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.22",
4
4
  "description": "Elastic synthetic monitoring agent",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
- "clean": "rm -rf dist",
8
+ "clean": "rimraf dist",
9
9
  "prepublish": "npm run clean && npm run build",
10
10
  "build": "tsc",
11
11
  "watch": "tsc -w",
@@ -38,26 +38,37 @@
38
38
  "author": "",
39
39
  "license": "MIT",
40
40
  "dependencies": {
41
- "commander": "^7.0.0",
41
+ "commander": "^9.0.0",
42
+ "deepmerge": "^4.2.2",
43
+ "expect": "^27.0.2",
42
44
  "http-proxy": "^1.18.1",
43
- "kleur": "^4.1.3",
44
- "playwright-chromium": "=1.11.0",
45
+ "kleur": "^4.1.4",
46
+ "micromatch": "^4.0.4",
47
+ "playwright-chromium": "=1.14.0",
48
+ "sharp": "^0.30.1",
45
49
  "snakecase-keys": "^3.2.1",
46
- "sonic-boom": "^1.3.0",
47
- "source-map-support": "^0.5.19",
48
- "ts-node": "^9.1.1",
49
- "typescript": "^4.1.3"
50
+ "sonic-boom": "^2.6.0",
51
+ "source-map-support": "^0.5.21",
52
+ "ts-node": "^10.5.0",
53
+ "typescript": "^4.5.5"
50
54
  },
51
55
  "devDependencies": {
52
- "@types/jest": "^26.0.19",
56
+ "@types/jest": "^27.4.0",
57
+ "@types/micromatch": "^4.0.1",
53
58
  "@types/node": "^14.14.14",
54
- "@typescript-eslint/eslint-plugin": "^3.10.1",
55
- "@typescript-eslint/parser": "^3.10.1",
56
- "eslint": "^7.15.0",
59
+ "@types/sharp": "^0.28.2",
60
+ "@typescript-eslint/eslint-plugin": "^5.0.0",
61
+ "@typescript-eslint/parser": "^5.0.0",
62
+ "eslint": "^8.0.1",
57
63
  "husky": "^4.3.6",
58
- "jest": "^26.6.3",
64
+ "jest": "^27.4.5",
59
65
  "lint-staged": "^10.5.3",
60
- "prettier": "^2.2.1",
61
- "ts-jest": "^26.4.4"
66
+ "prettier": "^2.4.1",
67
+ "rimraf": "^3.0.2",
68
+ "ts-jest": "^27.1.2"
69
+ },
70
+ "engines": {
71
+ "node": ">14.14.0",
72
+ "npm": "6"
62
73
  }
63
74
  }
package/src/cli.ts CHANGED
@@ -27,20 +27,21 @@
27
27
 
28
28
  import { stdin, cwd } from 'process';
29
29
  import { resolve } from 'path';
30
+ import merge from 'deepmerge';
30
31
  import { step, journey } from './core';
31
32
  import { log } from './core/logger';
32
- import program from './parse_args';
33
- import { CliArgs } from './common_types';
33
+ import program, { options } from './parse_args';
34
+ import { expect } from './core/expect';
34
35
  import {
35
36
  findPkgJsonByTraversing,
36
37
  isDepInstalled,
37
38
  isDirectory,
38
39
  totalist,
40
+ parseNetworkConditions,
39
41
  } from './helpers';
40
42
  import { run } from './';
41
43
  import { readConfig } from './config';
42
44
 
43
- const options = program.opts() as CliArgs;
44
45
  const resolvedCwd = cwd();
45
46
  /**
46
47
  * Set debug based on DEBUG ENV and -d flags
@@ -52,9 +53,17 @@ if (process.env.DEBUG === namespace || Boolean(options.debug)) {
52
53
  }
53
54
 
54
55
  const loadInlineScript = source => {
55
- const scriptFn = new Function('step', 'page', 'browser', 'params', source);
56
- journey('inline', async ({ page, browser, params }) => {
57
- scriptFn.apply(null, [step, page, browser, params]);
56
+ const scriptFn = new Function(
57
+ 'step',
58
+ 'page',
59
+ 'context',
60
+ 'browser',
61
+ 'params',
62
+ 'expect',
63
+ source
64
+ );
65
+ journey('inline', ({ page, context, browser, params }) => {
66
+ scriptFn.apply(null, [step, page, context, browser, params, expect]);
58
67
  });
59
68
  };
60
69
 
@@ -103,7 +112,7 @@ async function prepareSuites(inputs: string[]) {
103
112
  * the suites
104
113
  */
105
114
  findPkgJsonByTraversing(absPath, resolvedCwd);
106
- if (await isDirectory(absPath)) {
115
+ if (isDirectory(absPath)) {
107
116
  await totalist(absPath, (rel, abs) => {
108
117
  if (pattern.test(rel) && !ignored.test(rel)) {
109
118
  addSuite(abs);
@@ -117,6 +126,25 @@ async function prepareSuites(inputs: string[]) {
117
126
  }
118
127
 
119
128
  (async () => {
129
+ /**
130
+ * Transform `.ts` files out of the box by invoking
131
+ * the `ts-node` via `transpile-only` mode that compiles
132
+ * TS files without doing any extensive type checks.
133
+ *
134
+ * We must register `ts-node` _before_ loading inline
135
+ * scripts too because otherwise we will not be able to
136
+ * require `.ts` configuration files.
137
+ */
138
+ /* eslint-disable-next-line @typescript-eslint/no-var-requires */
139
+ require('ts-node').register({
140
+ transpileOnly: true,
141
+ compilerOptions: {
142
+ esModuleInterop: true,
143
+ allowJs: true,
144
+ target: 'es2018',
145
+ },
146
+ });
147
+
120
148
  if (options.inline) {
121
149
  const source = await readStdin();
122
150
  loadInlineScript(source);
@@ -132,20 +160,6 @@ async function prepareSuites(inputs: string[]) {
132
160
  throw new Error(`cannot find module '${name}'`);
133
161
  }
134
162
  }
135
- /**
136
- * Transform `.ts` files out of the box by invoking
137
- * the `ts-node` via `transpile-only` mode that compiles
138
- * TS files without doing any extensive type checks
139
- */
140
- /* eslint-disable-next-line @typescript-eslint/no-var-requires */
141
- require('ts-node').register({
142
- transpileOnly: true,
143
- compilerOptions: {
144
- esModuleInterop: true,
145
- allowJs: true,
146
- target: 'es2018',
147
- },
148
- });
149
163
  /**
150
164
  * Handle piped files by reading the STDIN
151
165
  * ex: ls example/suites/*.js | npx @elastic/synthetics
@@ -159,40 +173,49 @@ async function prepareSuites(inputs: string[]) {
159
173
  }
160
174
 
161
175
  /**
162
- * Use the NODE_ENV variable to control the environment if its not explicity
163
- * passed from either CLI or through the API
176
+ * Use the NODE_ENV variable to control the environment
164
177
  */
165
- const environment = options.environment || process.env['NODE_ENV'];
178
+ const environment = process.env['NODE_ENV'] || 'development';
166
179
  /**
167
180
  * Validate and handle configs
168
181
  */
169
- const config = readConfig(environment, options.config);
170
- const params = config.params || JSON.parse(options.suiteParams);
182
+ const config =
183
+ options.config || !options.inline
184
+ ? readConfig(environment, options.config)
185
+ : {};
186
+ const params = merge(config.params, options.params || {});
187
+
171
188
  /**
172
- * use JSON reporter if json flag is enabled
189
+ * Favor playwright options passed via cli to inline playwright options
173
190
  */
174
- const reporter = options.json ? 'json' : options.reporter;
191
+ const playwrightOptions = merge.all([
192
+ config.playwrightOptions || {},
193
+ options.playwrightOptions || {},
194
+ {
195
+ headless: options.headless,
196
+ chromiumSandbox: options.sandbox,
197
+ ignoreHTTPSErrors: options.ignoreHttpsErrors,
198
+ },
199
+ ]);
175
200
 
176
201
  const results = await run({
177
- params: Object.freeze({ ...params, environment }),
178
- reporter,
179
- headless: options.headless,
180
- screenshots: options.screenshots,
181
- dryRun: options.dryRun,
182
- journeyName: options.journeyName,
183
- network: options.network,
184
- pauseOnError: options.pauseOnError,
185
- outfd: options.outfd,
186
- metrics: options.metrics,
187
- sandbox: options.sandbox,
202
+ params: Object.freeze(params),
203
+ networkConditions: options.throttling
204
+ ? parseNetworkConditions(options.throttling as string)
205
+ : undefined,
206
+ environment,
207
+ playwrightOptions,
208
+ ...options,
188
209
  });
189
210
 
190
- /**
191
- * Exit with error status if any journey fails
192
- */
193
- for (const result of Object.values(results)) {
194
- if (result.status === 'failed') {
195
- process.exit(1);
211
+ if (!options.quietExitCode) {
212
+ /**
213
+ * Exit with error status if any journey fails
214
+ */
215
+ for (const result of Object.values(results)) {
216
+ if (result.status === 'failed') {
217
+ process.exit(1);
218
+ }
196
219
  }
197
220
  }
198
221
  })().catch(e => {
@@ -23,18 +23,65 @@
23
23
  *
24
24
  */
25
25
 
26
+ import {
27
+ BrowserContextOptions,
28
+ LaunchOptions,
29
+ CDPSession,
30
+ ChromiumBrowser,
31
+ ChromiumBrowserContext,
32
+ Page,
33
+ } from 'playwright-chromium';
26
34
  import { Protocol } from 'playwright-chromium/types/protocol';
27
35
  import { Step } from './dsl';
28
36
  import { reporters } from './reporters';
29
37
 
30
38
  export type VoidCallback = () => void;
39
+ export type Params = Record<string, any>;
40
+ export type NetworkConditions = {
41
+ offline: boolean;
42
+ downloadThroughput: number;
43
+ uploadThroughput: number;
44
+ latency: number;
45
+ };
46
+ export type HooksArgs = {
47
+ env: string;
48
+ params: Params;
49
+ };
50
+ export type HooksCallback = (args: HooksArgs) => void;
31
51
  export type StatusValue = 'succeeded' | 'failed' | 'skipped';
32
52
  export type Reporters = keyof typeof reporters;
33
53
 
34
- export type FilmStrip = {
35
- snapshot: string;
36
- ts: number;
37
- startTime: number;
54
+ export type Driver = {
55
+ browser: ChromiumBrowser;
56
+ context: ChromiumBrowserContext;
57
+ page: Page;
58
+ client: CDPSession;
59
+ };
60
+
61
+ export type TraceOutput = {
62
+ name: string;
63
+ type: string;
64
+ start: MetricDuration;
65
+ duration?: MetricDuration;
66
+ score?: number;
67
+ };
68
+
69
+ type MetricDuration = {
70
+ us: number;
71
+ };
72
+
73
+ export type PerfMetrics = {
74
+ fcp: MetricDuration;
75
+ lcp: MetricDuration;
76
+ dcl: MetricDuration;
77
+ load: MetricDuration;
78
+ cls: number;
79
+ };
80
+
81
+ export type Filmstrip = {
82
+ start: MetricDuration;
83
+ blob: string;
84
+ mime: string;
38
85
  };
39
86
 
40
87
  export type DefaultPluginOutput = {
@@ -47,18 +94,66 @@ export type BrowserInfo = {
47
94
  version: string;
48
95
  };
49
96
 
97
+ export type Screenshot = {
98
+ timestamp: number;
99
+ step: Step;
100
+ data: string;
101
+ };
102
+
103
+ export type SecurityDetails = {
104
+ issuer?: string;
105
+ protocol?: string;
106
+ subjectName?: string;
107
+ validFrom?: number;
108
+ validTo?: number;
109
+ };
110
+
111
+ export type Request = {
112
+ method: string;
113
+ url: string;
114
+ headers: Record<string, string>;
115
+ // Total size in bytes of the request (body and headers)
116
+ bytes?: number;
117
+ body?: {
118
+ // Size in bytes of the request body
119
+ bytes: number;
120
+ };
121
+ referrer?: string;
122
+ };
123
+
124
+ export type Response = {
125
+ url?: string;
126
+ protocol?: string;
127
+ status: number;
128
+ statusText?: string;
129
+ mimeType: string;
130
+ httpVersion?: string;
131
+ headers: Record<string, string>;
132
+ // Total size in bytes of the response (body and headers)
133
+ bytes?: number;
134
+ body?: {
135
+ // Size in bytes of the response body
136
+ bytes: number;
137
+ };
138
+ transferSize?: number;
139
+ redirectURL?: string;
140
+ securityDetails?: SecurityDetails;
141
+ remoteIPAddress?: string;
142
+ remotePort?: number;
143
+ fromServiceWorker?: boolean;
144
+ timing?: Protocol.Network.ResourceTiming;
145
+ };
146
+
50
147
  export type NetworkInfo = {
51
148
  url: string;
52
149
  browser: BrowserInfo;
53
- method: string;
54
150
  type: string;
55
- request: Protocol.Network.Request;
56
- response?: Protocol.Network.Response;
151
+ request: Request;
152
+ response?: Response;
57
153
  isNavigationRequest: boolean;
58
154
  requestSentTime: number;
59
155
  loadEndTime: number;
60
156
  responseReceivedTime: number;
61
- status: number;
62
157
  resourceSize: number;
63
158
  transferSize: number;
64
159
  timings?: {
@@ -75,25 +170,54 @@ export type NetworkInfo = {
75
170
  };
76
171
  } & DefaultPluginOutput;
77
172
 
173
+ export type BrowserMessage = {
174
+ text: string;
175
+ type: string;
176
+ error?: Error;
177
+ } & DefaultPluginOutput;
178
+
179
+ export type PluginOutput = {
180
+ filmstrips?: Array<Filmstrip>;
181
+ networkinfo?: Array<NetworkInfo>;
182
+ browserconsole?: Array<BrowserMessage>;
183
+ traces?: Array<TraceOutput>;
184
+ metrics?: PerfMetrics;
185
+ };
186
+
187
+ export type ScreenshotOptions = 'on' | 'off' | 'only-on-failure';
188
+
78
189
  export type CliArgs = {
190
+ capability?: Array<string>;
79
191
  config?: string;
80
- environment?: string;
81
192
  outfd?: number;
82
193
  headless?: boolean;
83
- screenshots?: boolean;
194
+ screenshots?: ScreenshotOptions;
195
+ ssblocks?: boolean;
84
196
  metrics?: boolean;
85
197
  filmstrips?: boolean;
198
+ trace?: boolean;
86
199
  dryRun?: boolean;
87
- journeyName?: string;
88
200
  network?: boolean;
89
201
  pauseOnError?: boolean;
202
+ quietExitCode?: boolean;
90
203
  reporter?: Reporters;
91
204
  wsEndpoint?: string;
92
205
  sandbox?: boolean;
93
- json?: boolean;
94
206
  pattern?: string;
95
207
  inline: boolean;
96
- require: string[];
208
+ match?: string;
209
+ tags?: Array<string>;
210
+ require: Array<string>;
97
211
  debug?: boolean;
98
- suiteParams?: string;
212
+ ignoreHttpsErrors?: boolean;
213
+ params?: Params;
214
+ throttling?: boolean | string;
215
+ playwrightOptions?: LaunchOptions & BrowserContextOptions;
216
+ richEvents?: boolean;
217
+ };
218
+
219
+ export type PlaywrightOptions = LaunchOptions & BrowserContextOptions;
220
+ export type SyntheticsConfig = {
221
+ params?: Params;
222
+ playwrightOptions?: PlaywrightOptions;
99
223
  };
package/src/config.ts CHANGED
@@ -24,13 +24,10 @@
24
24
  */
25
25
 
26
26
  import { isAbsolute, resolve, dirname } from 'path';
27
+ import { SyntheticsConfig } from './common_types';
27
28
  import { isFile } from './helpers';
28
29
 
29
- interface Config {
30
- params?: Record<string, unknown>;
31
- }
32
-
33
- export function readConfig(env: string, config?: string): Config {
30
+ export function readConfig(env: string, config?: string): SyntheticsConfig {
34
31
  let options = {};
35
32
  const cwd = process.cwd();
36
33
  /**
@@ -0,0 +1,187 @@
1
+ /**
2
+ * MIT License
3
+ *
4
+ * Copyright (c) 2020-present, Elastic NV
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ *
24
+ */
25
+
26
+ import expectLib from 'expect';
27
+ import type {
28
+ AsymmetricMatcher,
29
+ MatcherState,
30
+ ExpectedAssertionsErrors,
31
+ } from 'expect/build/types';
32
+
33
+ // Copied source code from expect/build/types.d.ts
34
+ export declare type Expect = {
35
+ <T = unknown>(actual: T): synthetics.Matchers<T>;
36
+ assertions(arg0: number): void;
37
+ extend(arg0: any): void;
38
+ extractExpectedAssertionsErrors: () => ExpectedAssertionsErrors;
39
+ getState(): MatcherState;
40
+ hasAssertions(): void;
41
+ setState(state: Partial<MatcherState>): void;
42
+ any(expectedObject: any): AsymmetricMatcher;
43
+ anything(): AsymmetricMatcher;
44
+ arrayContaining(sample: Array<unknown>): AsymmetricMatcher;
45
+ objectContaining(sample: Record<string, unknown>): AsymmetricMatcher;
46
+ stringContaining(expected: string): AsymmetricMatcher;
47
+ stringMatching(expected: string | RegExp): AsymmetricMatcher;
48
+ };
49
+
50
+ /**
51
+ * Override matchers from expect in our synthetic namespace to
52
+ * reduce support for spy and snapshot matchers which is
53
+ * impelemed via jest matchers
54
+ *
55
+ * We declare the types in global synthetics namespace which allows
56
+ * users to extend expect functionality without type errors
57
+ */
58
+ declare global {
59
+ export namespace synthetics {
60
+ export interface Matchers<R> {
61
+ /**
62
+ * If you know how to test something, `.not` lets you test its opposite.
63
+ */
64
+ not: Matchers<R>;
65
+ /**
66
+ * Use resolves to unwrap the value of a fulfilled promise so any other
67
+ * matcher can be chained. If the promise is rejected the assertion fails.
68
+ */
69
+ resolves: Matchers<Promise<R>>;
70
+ /**
71
+ * Unwraps the reason of a rejected promise so any other matcher can be chained.
72
+ * If the promise is fulfilled the assertion fails.
73
+ */
74
+ rejects: Matchers<Promise<R>>;
75
+ /**
76
+ * Checks that a value is what you expect. It uses `===` to check strict equality.
77
+ * Don't use `toBe` with floating-point numbers.
78
+ */
79
+ toBe(expected: unknown): R;
80
+ /**
81
+ * Using exact equality with floating point numbers is a bad idea.
82
+ * Rounding means that intuitive things fail.
83
+ * The default for numDigits is 2.
84
+ */
85
+ toBeCloseTo(expected: number, numDigits?: number): R;
86
+ /**
87
+ * Ensure that a variable is not undefined.
88
+ */
89
+ toBeDefined(): R;
90
+ /**
91
+ * When you don't care what a value is, you just want to
92
+ * ensure a value is false in a boolean context.
93
+ */
94
+ toBeFalsy(): R;
95
+ /**
96
+ * For comparing floating point numbers.
97
+ */
98
+ toBeGreaterThan(expected: number | bigint): R;
99
+ /**
100
+ * For comparing floating point numbers.
101
+ */
102
+ toBeGreaterThanOrEqual(expected: number | bigint): R;
103
+ /**
104
+ * Ensure that an object is an instance of a class.
105
+ * This matcher uses `instanceof` underneath.
106
+ */
107
+ /* eslint-disable-next-line */
108
+ toBeInstanceOf(expected: Function): R;
109
+ /**
110
+ * For comparing floating point numbers.
111
+ */
112
+ toBeLessThan(expected: number | bigint): R;
113
+ /**
114
+ * For comparing floating point numbers.
115
+ */
116
+ toBeLessThanOrEqual(expected: number | bigint): R;
117
+ /**
118
+ * This is the same as `.toBe(null)` but the error messages are a bit nicer.
119
+ * So use `.toBeNull()` when you want to check that something is null.
120
+ */
121
+ toBeNull(): R;
122
+ /**
123
+ * Use when you don't care what a value is, you just want to ensure a value
124
+ * is true in a boolean context. In JavaScript, there are six falsy values:
125
+ * `false`, `0`, `''`, `null`, `undefined`, and `NaN`. Everything else is truthy.
126
+ */
127
+ toBeTruthy(): R;
128
+ /**
129
+ * Used to check that a variable is undefined.
130
+ */
131
+ toBeUndefined(): R;
132
+ /**
133
+ * Used to check that a variable is NaN.
134
+ */
135
+ toBeNaN(): R;
136
+ /**
137
+ * Used when you want to check that an item is in a list.
138
+ * For testing the items in the list, this uses `===`, a strict equality check.
139
+ */
140
+ toContain(expected: unknown): R;
141
+ /**
142
+ * Used when you want to check that an item is in a list.
143
+ * For testing the items in the list, this matcher recursively checks the
144
+ * equality of all fields, rather than checking for object identity.
145
+ */
146
+ toContainEqual(expected: unknown): R;
147
+ /**
148
+ * Used when you want to check that two objects have the same value.
149
+ * This matcher recursively checks the equality of all fields, rather than checking for object identity.
150
+ */
151
+ toEqual(expected: unknown): R;
152
+ /**
153
+ * Used to check that an object has a `.length` property
154
+ * and it is set to a certain numeric value.
155
+ */
156
+ toHaveLength(expected: number): R;
157
+ /**
158
+ * Use to check if property at provided reference keyPath exists for an object.
159
+ * For checking deeply nested properties in an object you may use dot notation or an array containing
160
+ * the keyPath for deep references.
161
+ *
162
+ * Optionally, you can provide a value to check if it's equal to the value present at keyPath
163
+ * on the target object. This matcher uses 'deep equality' (like `toEqual()`) and recursively checks
164
+ * the equality of all fields.
165
+ *
166
+ * @example
167
+ *
168
+ * expect(houseForSale).toHaveProperty('kitchen.area', 20);
169
+ */
170
+ toHaveProperty(keyPath: string | Array<string>, value?: unknown): R;
171
+ /**
172
+ * Check that a string matches a regular expression.
173
+ */
174
+ toMatch(expected: string | RegExp): R;
175
+ /**
176
+ * Used to check that a JavaScript object matches a subset of the properties of an object
177
+ */
178
+ toMatchObject(expected: Record<string, unknown> | Array<unknown>): R;
179
+ /**
180
+ * Use to test that objects have the same types as well as structure.
181
+ */
182
+ toStrictEqual(expected: unknown): R;
183
+ }
184
+ }
185
+ }
186
+
187
+ export const expect: Expect = expectLib;