codeceptjs 3.5.13-beta.2 → 3.5.13

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.
@@ -0,0 +1,13 @@
1
+ Verifies that a certain request is not part of network traffic.
2
+
3
+ Examples:
4
+
5
+ ```js
6
+ I.dontSeeTraffic({ name: 'Unexpected API Call', url: 'https://api.example.com' });
7
+ I.dontSeeTraffic({ name: 'Unexpected API Call of "user" endpoint', url: /api.example.com.*user/ });
8
+ ```
9
+
10
+ @param {Object} opts - options when checking the traffic network.
11
+ @param {string} opts.name A name of that request. Can be any value. Only relevant to have a more meaningful error message in case of fail.
12
+ @param {string|RegExp} opts.url Expected URL of request in network traffic. Can be a string or a regular expression.
13
+ @return {void} automatically synchronized promise through #recorder
@@ -0,0 +1,5 @@
1
+ Resets all recorded network requests.
2
+
3
+ ```js
4
+ I.flushNetworkTraffics();
5
+ ```
@@ -0,0 +1,10 @@
1
+ Grab the recording network traffics
2
+
3
+ ```js
4
+ const traffics = await I.grabRecordedNetworkTraffics();
5
+ expect(traffics[0].url).to.equal('https://reqres.in/api/comments/1');
6
+ expect(traffics[0].response.status).to.equal(200);
7
+ expect(traffics[0].response.body).to.contain({ name: 'this was mocked' });
8
+ ```
9
+
10
+ @return { Array } recorded network traffics
@@ -0,0 +1,36 @@
1
+ Verifies that a certain request is part of network traffic.
2
+
3
+ ```js
4
+ // checking the request url contains certain query strings
5
+ I.amOnPage('https://openai.com/blog/chatgpt');
6
+ I.startRecordingTraffic();
7
+ await I.seeTraffic({
8
+ name: 'sentry event',
9
+ url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600',
10
+ parameters: {
11
+ width: '1919',
12
+ height: '1138',
13
+ },
14
+ });
15
+ ```
16
+
17
+ ```js
18
+ // checking the request url contains certain post data
19
+ I.amOnPage('https://openai.com/blog/chatgpt');
20
+ I.startRecordingTraffic();
21
+ await I.seeTraffic({
22
+ name: 'event',
23
+ url: 'https://cloudflareinsights.com/cdn-cgi/rum',
24
+ requestPostData: {
25
+ st: 2,
26
+ },
27
+ });
28
+ ```
29
+
30
+ @param {Object} opts - options when checking the traffic network.
31
+ @param {string} opts.name A name of that request. Can be any value. Only relevant to have a more meaningful error message in case of fail.
32
+ @param {string} opts.url Expected URL of request in network traffic
33
+ @param {Object} [opts.parameters] Expected parameters of that request in network traffic
34
+ @param {Object} [opts.requestPostData] Expected that request contains post data in network traffic
35
+ @param {number} [opts.timeout] Timeout to wait for request in seconds. Default is 10 seconds.
36
+ @return {void} automatically synchronized promise through #recorder
@@ -0,0 +1,8 @@
1
+ Starts recording the network traffics.
2
+ This also resets recorded network requests.
3
+
4
+ ```js
5
+ I.startRecordingTraffic();
6
+ ```
7
+
8
+ @returns {void} automatically synchronized promise through #recorder
@@ -0,0 +1,5 @@
1
+ Stops recording of network traffic. Recorded traffic is not flashed.
2
+
3
+ ```js
4
+ I.stopRecordingTraffic();
5
+ ```
@@ -6,7 +6,6 @@ const { v4: uuidv4 } = require('uuid');
6
6
  const assert = require('assert');
7
7
  const promiseRetry = require('promise-retry');
8
8
  const Locator = require('../locator');
9
- const store = require('../store');
10
9
  const recorder = require('../recorder');
11
10
  const stringIncludes = require('../assert/include').includes;
12
11
  const { urlEquals } = require('../assert/equal');
@@ -51,6 +50,7 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
51
50
  const {
52
51
  seeElementError, dontSeeElementError, dontSeeElementInDOMError, seeElementInDOMError,
53
52
  } = require('./errors/ElementAssertion');
53
+ const { createAdvancedTestResults, allParameterValuePairsMatchExtreme, extractQueryObjects } = require('./networkTraffics/utils');
54
54
  const { log } = require('../output');
55
55
 
56
56
  const pathSeparator = path.sep;
@@ -2678,6 +2678,7 @@ class Playwright extends Helper {
2678
2678
  */
2679
2679
  async waitForText(text, sec = null, context = null) {
2680
2680
  const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2681
+ const errorMessage = `Text "${text}" was not found on page after ${waitTimeout / 1000} sec.`;
2681
2682
  let waiter;
2682
2683
 
2683
2684
  const contextObject = await this._getContext();
@@ -2688,18 +2689,21 @@ class Playwright extends Helper {
2688
2689
  try {
2689
2690
  await contextObject.locator(`${locator.isCustom() ? `${locator.type}=${locator.value}` : locator.simplify()} >> text=${text}`).first().waitFor({ timeout: waitTimeout, state: 'visible' });
2690
2691
  } catch (e) {
2691
- console.log(e);
2692
- throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec\n${e.message}`);
2692
+ throw new Error(`${errorMessage}\n${e.message}`);
2693
2693
  }
2694
2694
  }
2695
2695
 
2696
2696
  if (locator.isXPath()) {
2697
- waiter = contextObject.waitForFunction(([locator, text, $XPath]) => {
2698
- eval($XPath); // eslint-disable-line no-eval
2699
- const el = $XPath(null, locator);
2700
- if (!el.length) return false;
2701
- return el[0].innerText.indexOf(text) > -1;
2702
- }, [locator.value, text, $XPath.toString()], { timeout: waitTimeout });
2697
+ try {
2698
+ await contextObject.waitForFunction(([locator, text, $XPath]) => {
2699
+ eval($XPath); // eslint-disable-line no-eval
2700
+ const el = $XPath(null, locator);
2701
+ if (!el.length) return false;
2702
+ return el[0].innerText.indexOf(text) > -1;
2703
+ }, [locator.value, text, $XPath.toString()], { timeout: waitTimeout });
2704
+ } catch (e) {
2705
+ throw new Error(`${errorMessage}\n${e.message}`);
2706
+ }
2703
2707
  }
2704
2708
  } else {
2705
2709
  // we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
@@ -2713,7 +2717,7 @@ class Playwright extends Helper {
2713
2717
  count += 1000;
2714
2718
  } while (count <= waitTimeout);
2715
2719
 
2716
- if (!waiter) throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec`);
2720
+ if (!waiter) throw new Error(`${errorMessage}`);
2717
2721
  }
2718
2722
  }
2719
2723
 
@@ -2976,14 +2980,8 @@ class Playwright extends Helper {
2976
2980
  }
2977
2981
 
2978
2982
  /**
2979
- * Starts recording the network traffics.
2980
- * This also resets recorded network requests.
2983
+ * {{> flushNetworkTraffics }}
2981
2984
  *
2982
- * ```js
2983
- * I.startRecordingTraffic();
2984
- * ```
2985
- *
2986
- * @return {void}
2987
2985
  */
2988
2986
  startRecordingTraffic() {
2989
2987
  this.flushNetworkTraffics();
@@ -3010,18 +3008,8 @@ class Playwright extends Helper {
3010
3008
  }
3011
3009
 
3012
3010
  /**
3013
- * Grab the recording network traffics
3014
- *
3015
- * ```js
3016
- * const traffics = await I.grabRecordedNetworkTraffics();
3017
- * expect(traffics[0].url).to.equal('https://reqres.in/api/comments/1');
3018
- * expect(traffics[0].response.status).to.equal(200);
3019
- * expect(traffics[0].response.body).to.contain({ name: 'this was mocked' });
3020
- * ```
3021
- *
3022
- * @return { Promise<Array<any>> }
3023
- *
3024
- */
3011
+ * {{> grabRecordedNetworkTraffics }}
3012
+ */
3025
3013
  async grabRecordedNetworkTraffics() {
3026
3014
  if (!this.recording || !this.recordedAtLeastOnce) {
3027
3015
  throw new Error('Failure in test automation. You use "I.grabRecordedNetworkTraffics", but "I.startRecordingTraffic" was never called before.');
@@ -3129,18 +3117,14 @@ class Playwright extends Helper {
3129
3117
  }
3130
3118
 
3131
3119
  /**
3132
- * Resets all recorded network requests.
3120
+ * {{> flushNetworkTraffics }}
3133
3121
  */
3134
3122
  flushNetworkTraffics() {
3135
3123
  this.requests = [];
3136
3124
  }
3137
3125
 
3138
3126
  /**
3139
- * Stops recording of network traffic. Recorded traffic is not flashed.
3140
- *
3141
- * ```js
3142
- * I.stopRecordingTraffic();
3143
- * ```
3127
+ * {{> stopRecordingTraffic }}
3144
3128
  */
3145
3129
  stopRecordingTraffic() {
3146
3130
  this.page.removeAllListeners('request');
@@ -3148,42 +3132,7 @@ class Playwright extends Helper {
3148
3132
  }
3149
3133
 
3150
3134
  /**
3151
- * Verifies that a certain request is part of network traffic.
3152
- *
3153
- * ```js
3154
- * // checking the request url contains certain query strings
3155
- * I.amOnPage('https://openai.com/blog/chatgpt');
3156
- * I.startRecordingTraffic();
3157
- * await I.seeTraffic({
3158
- * name: 'sentry event',
3159
- * url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600',
3160
- * parameters: {
3161
- * width: '1919',
3162
- * height: '1138',
3163
- * },
3164
- * });
3165
- * ```
3166
- *
3167
- * ```js
3168
- * // checking the request url contains certain post data
3169
- * I.amOnPage('https://openai.com/blog/chatgpt');
3170
- * I.startRecordingTraffic();
3171
- * await I.seeTraffic({
3172
- * name: 'event',
3173
- * url: 'https://cloudflareinsights.com/cdn-cgi/rum',
3174
- * requestPostData: {
3175
- * st: 2,
3176
- * },
3177
- * });
3178
- * ```
3179
- *
3180
- * @param {Object} opts - options when checking the traffic network.
3181
- * @param {string} opts.name A name of that request. Can be any value. Only relevant to have a more meaningful error message in case of fail.
3182
- * @param {string} opts.url Expected URL of request in network traffic
3183
- * @param {Object} [opts.parameters] Expected parameters of that request in network traffic
3184
- * @param {Object} [opts.requestPostData] Expected that request contains post data in network traffic
3185
- * @param {number} [opts.timeout] Timeout to wait for request in seconds. Default is 10 seconds.
3186
- * @return { Promise<*> }
3135
+ * {{> seeTraffic }}
3187
3136
  */
3188
3137
  async seeTraffic({
3189
3138
  name, url, parameters, requestPostData, timeout = 10,
@@ -3265,18 +3214,7 @@ class Playwright extends Helper {
3265
3214
  }
3266
3215
 
3267
3216
  /**
3268
- * Verifies that a certain request is not part of network traffic.
3269
- *
3270
- * Examples:
3271
- *
3272
- * ```js
3273
- * I.dontSeeTraffic({ name: 'Unexpected API Call', url: 'https://api.example.com' });
3274
- * I.dontSeeTraffic({ name: 'Unexpected API Call of "user" endpoint', url: /api.example.com.*user/ });
3275
- * ```
3276
- *
3277
- * @param {Object} opts - options when checking the traffic network.
3278
- * @param {string} opts.name A name of that request. Can be any value. Only relevant to have a more meaningful error message in case of fail.
3279
- * @param {string|RegExp} opts.url Expected URL of request in network traffic. Can be a string or a regular expression.
3217
+ * {{> dontSeeTraffic }}
3280
3218
  *
3281
3219
  */
3282
3220
  dontSeeTraffic({ name, url }) {
@@ -3988,134 +3926,3 @@ async function highlightActiveElement(element) {
3988
3926
  });
3989
3927
  }
3990
3928
  }
3991
-
3992
- const createAdvancedTestResults = (url, dataToCheck, requests) => {
3993
- // Creates advanced test results for a network traffic check.
3994
- // Advanced test results only applies when expected parameters are set
3995
- if (!dataToCheck) return '';
3996
-
3997
- let urlFound = false;
3998
- let advancedResults;
3999
- requests.forEach((request) => {
4000
- // url not found in this request. continue with next request
4001
- if (urlFound || !request.url.match(new RegExp(url))) return;
4002
- urlFound = true;
4003
-
4004
- // Url found. Now we create advanced test report for that URL and show which parameters failed
4005
- if (!request.requestPostData) {
4006
- advancedResults = allParameterValuePairsMatchExtreme(extractQueryObjects(request.url), dataToCheck);
4007
- } else if (request.requestPostData) {
4008
- advancedResults = allRequestPostDataValuePairsMatchExtreme(request.requestPostData, dataToCheck);
4009
- }
4010
- });
4011
- return advancedResults;
4012
- };
4013
-
4014
- const extractQueryObjects = (queryString) => {
4015
- // Converts a string of GET parameters into an array of parameter objects. Each parameter object contains the properties "name" and "value".
4016
- if (queryString.indexOf('?') === -1) {
4017
- return [];
4018
- }
4019
- const queryObjects = [];
4020
-
4021
- const queryPart = queryString.split('?')[1];
4022
-
4023
- const queryParameters = queryPart.split('&');
4024
-
4025
- queryParameters.forEach((queryParameter) => {
4026
- const keyValue = queryParameter.split('=');
4027
- const queryObject = {};
4028
- // eslint-disable-next-line prefer-destructuring
4029
- queryObject.name = keyValue[0];
4030
- queryObject.value = decodeURIComponent(keyValue[1]);
4031
- queryObjects.push(queryObject);
4032
- });
4033
-
4034
- return queryObjects;
4035
- };
4036
-
4037
- const allParameterValuePairsMatchExtreme = (queryStringObject, advancedExpectedParameterValuePairs) => {
4038
- // More advanced check if all request parameters match with the expectations
4039
- let littleReport = '\nQuery parameters:\n';
4040
- let success = true;
4041
-
4042
- for (const expectedKey in advancedExpectedParameterValuePairs) {
4043
- if (!Object.prototype.hasOwnProperty.call(advancedExpectedParameterValuePairs, expectedKey)) {
4044
- continue;
4045
- }
4046
- let parameterFound = false;
4047
- const expectedValue = advancedExpectedParameterValuePairs[expectedKey];
4048
-
4049
- for (const queryParameter of queryStringObject) {
4050
- if (queryParameter.name === expectedKey) {
4051
- parameterFound = true;
4052
- if (expectedValue === undefined) {
4053
- littleReport += ` ${expectedKey.padStart(10, ' ')}\n`;
4054
- } else if (typeof expectedValue === 'object' && expectedValue.base64) {
4055
- const decodedActualValue = Buffer.from(queryParameter.value, 'base64').toString('utf8');
4056
- if (decodedActualValue === expectedValue.base64) {
4057
- littleReport += ` ${expectedKey.padStart(10, ' ')} = base64(${expectedValue.base64})\n`;
4058
- } else {
4059
- littleReport += ` ✖ ${expectedKey.padStart(10, ' ')} = base64(${expectedValue.base64}) -> actual value: "base64(${decodedActualValue})"\n`;
4060
- success = false;
4061
- }
4062
- } else if (queryParameter.value === expectedValue) {
4063
- littleReport += ` ${expectedKey.padStart(10, ' ')} = ${expectedValue}\n`;
4064
- } else {
4065
- littleReport += ` ✖ ${expectedKey.padStart(10, ' ')} = ${expectedValue} -> actual value: "${queryParameter.value}"\n`;
4066
- success = false;
4067
- }
4068
- }
4069
- }
4070
-
4071
- if (parameterFound === false) {
4072
- littleReport += ` ✖ ${expectedKey.padStart(10, ' ')}${expectedValue ? ` = ${JSON.stringify(expectedValue)}` : ''} -> parameter not found in request\n`;
4073
- success = false;
4074
- }
4075
- }
4076
-
4077
- return success ? true : littleReport;
4078
- };
4079
-
4080
- const allRequestPostDataValuePairsMatchExtreme = (RequestPostDataObject, advancedExpectedRequestPostValuePairs) => {
4081
- // More advanced check if all request post data match with the expectations
4082
- let littleReport = '\nRequest Post Data:\n';
4083
- let success = true;
4084
-
4085
- for (const expectedKey in advancedExpectedRequestPostValuePairs) {
4086
- if (!Object.prototype.hasOwnProperty.call(advancedExpectedRequestPostValuePairs, expectedKey)) {
4087
- continue;
4088
- }
4089
- let keyFound = false;
4090
- const expectedValue = advancedExpectedRequestPostValuePairs[expectedKey];
4091
-
4092
- for (const [key, value] of Object.entries(RequestPostDataObject)) {
4093
- if (key === expectedKey) {
4094
- keyFound = true;
4095
- if (expectedValue === undefined) {
4096
- littleReport += ` ${expectedKey.padStart(10, ' ')}\n`;
4097
- } else if (typeof expectedValue === 'object' && expectedValue.base64) {
4098
- const decodedActualValue = Buffer.from(value, 'base64').toString('utf8');
4099
- if (decodedActualValue === expectedValue.base64) {
4100
- littleReport += ` ${expectedKey.padStart(10, ' ')} = base64(${expectedValue.base64})\n`;
4101
- } else {
4102
- littleReport += ` ✖ ${expectedKey.padStart(10, ' ')} = base64(${expectedValue.base64}) -> actual value: "base64(${decodedActualValue})"\n`;
4103
- success = false;
4104
- }
4105
- } else if (value === expectedValue) {
4106
- littleReport += ` ${expectedKey.padStart(10, ' ')} = ${expectedValue}\n`;
4107
- } else {
4108
- littleReport += ` ✖ ${expectedKey.padStart(10, ' ')} = ${expectedValue} -> actual value: "${value}"\n`;
4109
- success = false;
4110
- }
4111
- }
4112
- }
4113
-
4114
- if (keyFound === false) {
4115
- littleReport += ` ✖ ${expectedKey.padStart(10, ' ')}${expectedValue ? ` = ${JSON.stringify(expectedValue)}` : ''} -> key not found in request\n`;
4116
- success = false;
4117
- }
4118
- }
4119
-
4120
- return success ? true : littleReport;
4121
- };
@@ -486,7 +486,7 @@ class Puppeteer extends Helper {
486
486
  if (!page) return;
487
487
  page.setDefaultNavigationTimeout(this.options.getPageTimeout);
488
488
  this.context = await this.page.$('body');
489
- if (this.config.browser === 'chrome') {
489
+ if (this.options.browser === 'chrome') {
490
490
  await page.bringToFront();
491
491
  }
492
492
  }
@@ -658,9 +658,9 @@ class Puppeteer extends Helper {
658
658
  url = this.options.url + url;
659
659
  }
660
660
 
661
- if (this.config.basicAuth && (this.isAuthenticated !== true)) {
661
+ if (this.options.basicAuth && (this.isAuthenticated !== true)) {
662
662
  if (url.includes(this.options.url)) {
663
- await this.page.authenticate(this.config.basicAuth);
663
+ await this.page.authenticate(this.options.basicAuth);
664
664
  this.isAuthenticated = true;
665
665
  }
666
666
  }
@@ -72,9 +72,12 @@ class REST extends Helper {
72
72
  this.options.maxBodyLength = maxContentLength;
73
73
  }
74
74
 
75
- this.options = { ...this.options, ...config };
75
+ // override defaults with config
76
+ this._setConfig(config);
77
+
76
78
  this.headers = { ...this.options.defaultHeaders };
77
79
  this.axios = axios.create();
80
+ // @ts-ignore
78
81
  this.axios.defaults.headers = this.options.defaultHeaders;
79
82
  }
80
83