codeceptjs 3.5.13-beta.1 → 3.5.13-beta.3

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 (124) hide show
  1. package/docs/webapi/amOnPage.mustache +11 -0
  2. package/docs/webapi/appendField.mustache +11 -0
  3. package/docs/webapi/attachFile.mustache +12 -0
  4. package/docs/webapi/blur.mustache +18 -0
  5. package/docs/webapi/checkOption.mustache +13 -0
  6. package/docs/webapi/clearCookie.mustache +9 -0
  7. package/docs/webapi/clearField.mustache +9 -0
  8. package/docs/webapi/click.mustache +25 -0
  9. package/docs/webapi/clickLink.mustache +8 -0
  10. package/docs/webapi/closeCurrentTab.mustache +7 -0
  11. package/docs/webapi/closeOtherTabs.mustache +8 -0
  12. package/docs/webapi/dontSee.mustache +11 -0
  13. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +10 -0
  14. package/docs/webapi/dontSeeCookie.mustache +8 -0
  15. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +10 -0
  16. package/docs/webapi/dontSeeElement.mustache +8 -0
  17. package/docs/webapi/dontSeeElementInDOM.mustache +8 -0
  18. package/docs/webapi/dontSeeInCurrentUrl.mustache +4 -0
  19. package/docs/webapi/dontSeeInField.mustache +11 -0
  20. package/docs/webapi/dontSeeInSource.mustache +8 -0
  21. package/docs/webapi/dontSeeInTitle.mustache +8 -0
  22. package/docs/webapi/dontSeeTraffic.mustache +13 -0
  23. package/docs/webapi/doubleClick.mustache +13 -0
  24. package/docs/webapi/downloadFile.mustache +12 -0
  25. package/docs/webapi/dragAndDrop.mustache +9 -0
  26. package/docs/webapi/dragSlider.mustache +11 -0
  27. package/docs/webapi/executeAsyncScript.mustache +24 -0
  28. package/docs/webapi/executeScript.mustache +26 -0
  29. package/docs/webapi/fillField.mustache +16 -0
  30. package/docs/webapi/flushNetworkTraffics.mustache +5 -0
  31. package/docs/webapi/focus.mustache +13 -0
  32. package/docs/webapi/forceClick.mustache +28 -0
  33. package/docs/webapi/forceRightClick.mustache +18 -0
  34. package/docs/webapi/grabAllWindowHandles.mustache +7 -0
  35. package/docs/webapi/grabAttributeFrom.mustache +10 -0
  36. package/docs/webapi/grabAttributeFromAll.mustache +9 -0
  37. package/docs/webapi/grabBrowserLogs.mustache +9 -0
  38. package/docs/webapi/grabCookie.mustache +11 -0
  39. package/docs/webapi/grabCssPropertyFrom.mustache +11 -0
  40. package/docs/webapi/grabCssPropertyFromAll.mustache +10 -0
  41. package/docs/webapi/grabCurrentUrl.mustache +9 -0
  42. package/docs/webapi/grabCurrentWindowHandle.mustache +6 -0
  43. package/docs/webapi/grabDataFromPerformanceTiming.mustache +20 -0
  44. package/docs/webapi/grabElementBoundingRect.mustache +20 -0
  45. package/docs/webapi/grabGeoLocation.mustache +8 -0
  46. package/docs/webapi/grabHTMLFrom.mustache +10 -0
  47. package/docs/webapi/grabHTMLFromAll.mustache +9 -0
  48. package/docs/webapi/grabNumberOfOpenTabs.mustache +8 -0
  49. package/docs/webapi/grabNumberOfVisibleElements.mustache +9 -0
  50. package/docs/webapi/grabPageScrollPosition.mustache +8 -0
  51. package/docs/webapi/grabPopupText.mustache +5 -0
  52. package/docs/webapi/grabRecordedNetworkTraffics.mustache +10 -0
  53. package/docs/webapi/grabSource.mustache +8 -0
  54. package/docs/webapi/grabTextFrom.mustache +10 -0
  55. package/docs/webapi/grabTextFromAll.mustache +9 -0
  56. package/docs/webapi/grabTitle.mustache +8 -0
  57. package/docs/webapi/grabValueFrom.mustache +9 -0
  58. package/docs/webapi/grabValueFromAll.mustache +8 -0
  59. package/docs/webapi/grabWebElement.mustache +9 -0
  60. package/docs/webapi/grabWebElements.mustache +9 -0
  61. package/docs/webapi/moveCursorTo.mustache +12 -0
  62. package/docs/webapi/openNewTab.mustache +7 -0
  63. package/docs/webapi/pressKey.mustache +12 -0
  64. package/docs/webapi/pressKeyDown.mustache +12 -0
  65. package/docs/webapi/pressKeyUp.mustache +12 -0
  66. package/docs/webapi/pressKeyWithKeyNormalization.mustache +60 -0
  67. package/docs/webapi/refreshPage.mustache +6 -0
  68. package/docs/webapi/resizeWindow.mustache +6 -0
  69. package/docs/webapi/rightClick.mustache +14 -0
  70. package/docs/webapi/saveElementScreenshot.mustache +10 -0
  71. package/docs/webapi/saveScreenshot.mustache +12 -0
  72. package/docs/webapi/say.mustache +10 -0
  73. package/docs/webapi/scrollIntoView.mustache +11 -0
  74. package/docs/webapi/scrollPageToBottom.mustache +6 -0
  75. package/docs/webapi/scrollPageToTop.mustache +6 -0
  76. package/docs/webapi/scrollTo.mustache +12 -0
  77. package/docs/webapi/see.mustache +11 -0
  78. package/docs/webapi/seeAttributesOnElements.mustache +9 -0
  79. package/docs/webapi/seeCheckboxIsChecked.mustache +10 -0
  80. package/docs/webapi/seeCookie.mustache +8 -0
  81. package/docs/webapi/seeCssPropertiesOnElements.mustache +9 -0
  82. package/docs/webapi/seeCurrentUrlEquals.mustache +11 -0
  83. package/docs/webapi/seeElement.mustache +8 -0
  84. package/docs/webapi/seeElementInDOM.mustache +8 -0
  85. package/docs/webapi/seeInCurrentUrl.mustache +8 -0
  86. package/docs/webapi/seeInField.mustache +12 -0
  87. package/docs/webapi/seeInPopup.mustache +8 -0
  88. package/docs/webapi/seeInSource.mustache +7 -0
  89. package/docs/webapi/seeInTitle.mustache +8 -0
  90. package/docs/webapi/seeNumberOfElements.mustache +11 -0
  91. package/docs/webapi/seeNumberOfVisibleElements.mustache +10 -0
  92. package/docs/webapi/seeTextEquals.mustache +9 -0
  93. package/docs/webapi/seeTitleEquals.mustache +8 -0
  94. package/docs/webapi/seeTraffic.mustache +36 -0
  95. package/docs/webapi/selectOption.mustache +21 -0
  96. package/docs/webapi/setCookie.mustache +16 -0
  97. package/docs/webapi/setGeoLocation.mustache +12 -0
  98. package/docs/webapi/startRecordingTraffic.mustache +8 -0
  99. package/docs/webapi/stopRecordingTraffic.mustache +5 -0
  100. package/docs/webapi/switchTo.mustache +9 -0
  101. package/docs/webapi/switchToNextTab.mustache +10 -0
  102. package/docs/webapi/switchToPreviousTab.mustache +10 -0
  103. package/docs/webapi/type.mustache +21 -0
  104. package/docs/webapi/uncheckOption.mustache +13 -0
  105. package/docs/webapi/wait.mustache +8 -0
  106. package/docs/webapi/waitForClickable.mustache +11 -0
  107. package/docs/webapi/waitForCookie.mustache +9 -0
  108. package/docs/webapi/waitForDetached.mustache +10 -0
  109. package/docs/webapi/waitForElement.mustache +11 -0
  110. package/docs/webapi/waitForEnabled.mustache +6 -0
  111. package/docs/webapi/waitForFunction.mustache +17 -0
  112. package/docs/webapi/waitForInvisible.mustache +10 -0
  113. package/docs/webapi/waitForNumberOfTabs.mustache +9 -0
  114. package/docs/webapi/waitForText.mustache +13 -0
  115. package/docs/webapi/waitForValue.mustache +10 -0
  116. package/docs/webapi/waitForVisible.mustache +10 -0
  117. package/docs/webapi/waitInUrl.mustache +9 -0
  118. package/docs/webapi/waitNumberOfVisibleElements.mustache +10 -0
  119. package/docs/webapi/waitToHide.mustache +10 -0
  120. package/docs/webapi/waitUrlEquals.mustache +10 -0
  121. package/lib/helper/Playwright.js +8 -204
  122. package/lib/helper/WebDriver.js +264 -3
  123. package/lib/helper/networkTraffics/utils.js +137 -0
  124. package/package.json +4 -3
@@ -36,6 +36,7 @@ const { blurElement } = require('./scripts/blurElement');
36
36
  const {
37
37
  dontSeeElementError, seeElementError, seeElementInDOMError, dontSeeElementInDOMError,
38
38
  } = require('./errors/ElementAssertion');
39
+ const { allParameterValuePairsMatchExtreme, extractQueryObjects, createAdvancedTestResults } = require('./networkTraffics/utils');
39
40
 
40
41
  const SHADOW = 'shadow';
41
42
  const webRoot = 'body';
@@ -452,6 +453,11 @@ class WebDriver extends Helper {
452
453
  this.activeSessionName = '';
453
454
  this.customLocatorStrategies = config.customLocatorStrategies;
454
455
 
456
+ // for network stuff
457
+ this.requests = [];
458
+ this.recording = false;
459
+ this.recordedAtLeastOnce = false;
460
+
455
461
  this._setConfig(config);
456
462
 
457
463
  Locator.addFilter((locator, result) => {
@@ -491,8 +497,9 @@ class WebDriver extends Helper {
491
497
  if (config.host) {
492
498
  // webdriverio spec
493
499
  config.hostname = config.host;
494
- config.path = '/wd/hub';
500
+ config.path = config.path ? config.path : '/wd/hub';
495
501
  }
502
+
496
503
  config.baseUrl = config.url || config.baseUrl;
497
504
  if (config.desiredCapabilities && Object.keys(config.desiredCapabilities).length) {
498
505
  config.capabilities = config.desiredCapabilities;
@@ -633,6 +640,11 @@ class WebDriver extends Helper {
633
640
  if (this.browser.capabilities && this.browser.capabilities.platformName) {
634
641
  this.browser.capabilities.platformName = this.browser.capabilities.platformName.toLowerCase();
635
642
  }
643
+
644
+ if (this.options.automationProtocol) {
645
+ this.puppeteerBrowser = await this.browser.getPuppeteer();
646
+ }
647
+
636
648
  return this.browser;
637
649
  }
638
650
 
@@ -2603,9 +2615,9 @@ class WebDriver extends Helper {
2603
2615
  return;
2604
2616
  }
2605
2617
  this.geoLocation = { latitude, longitude };
2606
- const puppeteerBrowser = await this.browser.getPuppeteer();
2618
+
2607
2619
  await this.browser.call(async () => {
2608
- const pages = await puppeteerBrowser.pages();
2620
+ const pages = await this.puppeteerBrowser.pages();
2609
2621
  await pages[0].setGeolocation({ latitude, longitude });
2610
2622
  });
2611
2623
  }
@@ -2667,6 +2679,255 @@ class WebDriver extends Helper {
2667
2679
  runInWeb(fn) {
2668
2680
  return fn();
2669
2681
  }
2682
+
2683
+ /**
2684
+ *
2685
+ * _Note:_ Only works when devtoolsProtocol is enabled.
2686
+ *
2687
+ * {{> flushNetworkTraffics }}
2688
+ */
2689
+ flushNetworkTraffics() {
2690
+ if (!this.options.automationProtocol) {
2691
+ console.log('* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration');
2692
+ return;
2693
+ }
2694
+ this.requests = [];
2695
+ }
2696
+
2697
+ /**
2698
+ *
2699
+ * _Note:_ Only works when devtoolsProtocol is enabled.
2700
+ *
2701
+ * {{> stopRecordingTraffic }}
2702
+ */
2703
+ stopRecordingTraffic() {
2704
+ if (!this.options.automationProtocol) {
2705
+ console.log('* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration');
2706
+ return;
2707
+ }
2708
+ this.page.removeAllListeners('request');
2709
+ this.recording = false;
2710
+ }
2711
+
2712
+ /**
2713
+ *
2714
+ * _Note:_ Only works when devtoolsProtocol is enabled.
2715
+ *
2716
+ * {{> startRecordingTraffic }}
2717
+ *
2718
+ */
2719
+ async startRecordingTraffic() {
2720
+ if (!this.options.automationProtocol) {
2721
+ console.log('* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration');
2722
+ return;
2723
+ }
2724
+ this.flushNetworkTraffics();
2725
+ this.recording = true;
2726
+ this.recordedAtLeastOnce = true;
2727
+
2728
+ this.page = (await this.puppeteerBrowser.pages())[0];
2729
+ await this.page.setRequestInterception(true);
2730
+
2731
+ this.page.on('request', (request) => {
2732
+ const information = {
2733
+ url: request.url(),
2734
+ method: request.method(),
2735
+ requestHeaders: request.headers(),
2736
+ requestPostData: request.postData(),
2737
+ response: request.response(),
2738
+ };
2739
+
2740
+ this.debugSection('REQUEST: ', JSON.stringify(information));
2741
+
2742
+ if (typeof information.requestPostData === 'object') {
2743
+ information.requestPostData = JSON.parse(information.requestPostData);
2744
+ }
2745
+ request.continue();
2746
+ this.requests.push(information);
2747
+ });
2748
+ }
2749
+
2750
+ /**
2751
+ *
2752
+ * _Note:_ Only works when devtoolsProtocol is enabled.
2753
+ *
2754
+ * {{> grabRecordedNetworkTraffics }}
2755
+ */
2756
+ async grabRecordedNetworkTraffics() {
2757
+ if (!this.options.automationProtocol) {
2758
+ console.log('* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration');
2759
+ return;
2760
+ }
2761
+ if (!this.recording || !this.recordedAtLeastOnce) {
2762
+ throw new Error('Failure in test automation. You use "I.grabRecordedNetworkTraffics", but "I.startRecordingTraffic" was never called before.');
2763
+ }
2764
+
2765
+ const promises = this.requests.map(async (request) => {
2766
+ const resp = await request.response;
2767
+
2768
+ if (!resp) {
2769
+ return {
2770
+ url: '',
2771
+ response: {
2772
+ status: '',
2773
+ statusText: '',
2774
+ body: '',
2775
+ },
2776
+ };
2777
+ }
2778
+
2779
+ let body;
2780
+ try {
2781
+ // There's no 'body' for some requests (redirect etc...)
2782
+ body = JSON.parse((await resp.body()).toString());
2783
+ } catch (e) {
2784
+ // only interested in JSON, not HTML responses.
2785
+ }
2786
+
2787
+ return {
2788
+ url: resp.url(),
2789
+ response: {
2790
+ status: resp.status(),
2791
+ statusText: resp.statusText(),
2792
+ body,
2793
+ },
2794
+ };
2795
+ });
2796
+ return Promise.all(promises);
2797
+ }
2798
+
2799
+ /**
2800
+ *
2801
+ * _Note:_ Only works when devtoolsProtocol is enabled.
2802
+ *
2803
+ * {{> seeTraffic }}
2804
+ */
2805
+ async seeTraffic({
2806
+ name, url, parameters, requestPostData, timeout = 10,
2807
+ }) {
2808
+ if (!this.options.automationProtocol) {
2809
+ console.log('* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration');
2810
+ return;
2811
+ }
2812
+ if (!name) {
2813
+ throw new Error('Missing required key "name" in object given to "I.seeTraffic".');
2814
+ }
2815
+
2816
+ if (!url) {
2817
+ throw new Error('Missing required key "url" in object given to "I.seeTraffic".');
2818
+ }
2819
+
2820
+ if (!this.recording || !this.recordedAtLeastOnce) {
2821
+ throw new Error('Failure in test automation. You use "I.seeTraffic", but "I.startRecordingTraffic" was never called before.');
2822
+ }
2823
+
2824
+ for (let i = 0; i <= timeout * 2; i++) {
2825
+ const found = this._isInTraffic(url, parameters);
2826
+ if (found) {
2827
+ return true;
2828
+ }
2829
+ await new Promise((done) => {
2830
+ setTimeout(done, 1000);
2831
+ });
2832
+ }
2833
+
2834
+ // check request post data
2835
+ if (requestPostData && this._isInTraffic(url)) {
2836
+ const advancedTestResults = createAdvancedTestResults(url, requestPostData, this.requests);
2837
+
2838
+ assert.equal(advancedTestResults, true, `Traffic named "${name}" found correct URL ${url}, BUT the post data did not match:\n ${advancedTestResults}`);
2839
+ } else if (parameters && this._isInTraffic(url)) {
2840
+ const advancedTestResults = createAdvancedTestResults(url, parameters, this.requests);
2841
+
2842
+ assert.fail(
2843
+ `Traffic named "${name}" found correct URL ${url}, BUT the query parameters did not match:\n`
2844
+ + `${advancedTestResults}`,
2845
+ );
2846
+ } else {
2847
+ assert.fail(
2848
+ `Traffic named "${name}" not found in recorded traffic within ${timeout} seconds.\n`
2849
+ + `Expected url: ${url}.\n`
2850
+ + `Recorded traffic:\n${this._getTrafficDump()}`,
2851
+ );
2852
+ }
2853
+ }
2854
+
2855
+ /**
2856
+ *
2857
+ * _Note:_ Only works when devtoolsProtocol is enabled.
2858
+ *
2859
+ * {{> dontSeeTraffic }}
2860
+ *
2861
+ */
2862
+ dontSeeTraffic({ name, url }) {
2863
+ if (!this.options.automationProtocol) {
2864
+ console.log('* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration');
2865
+ return;
2866
+ }
2867
+ if (!this.recordedAtLeastOnce) {
2868
+ throw new Error('Failure in test automation. You use "I.dontSeeTraffic", but "I.startRecordingTraffic" was never called before.');
2869
+ }
2870
+
2871
+ if (!name) {
2872
+ throw new Error('Missing required key "name" in object given to "I.dontSeeTraffic".');
2873
+ }
2874
+
2875
+ if (!url) {
2876
+ throw new Error('Missing required key "url" in object given to "I.dontSeeTraffic".');
2877
+ }
2878
+
2879
+ if (this._isInTraffic(url)) {
2880
+ assert.fail(`Traffic with name "${name}" (URL: "${url}') found, but was not expected to be found.`);
2881
+ }
2882
+ }
2883
+
2884
+ /**
2885
+ * Checks if URL with parameters is part of network traffic. Returns true or false. Internal method for this helper.
2886
+ *
2887
+ * @param url URL to look for.
2888
+ * @param [parameters] Parameters that this URL needs to contain
2889
+ * @return {boolean} Whether or not URL with parameters is part of network traffic.
2890
+ * @private
2891
+ */
2892
+ _isInTraffic(url, parameters) {
2893
+ let isInTraffic = false;
2894
+ this.requests.forEach((request) => {
2895
+ if (isInTraffic) {
2896
+ return; // We already found traffic. Continue with next request
2897
+ }
2898
+
2899
+ if (!request.url.match(new RegExp(url))) {
2900
+ return; // url not found in this request. continue with next request
2901
+ }
2902
+
2903
+ // URL has matched. Now we check the parameters
2904
+
2905
+ if (parameters) {
2906
+ const advancedReport = allParameterValuePairsMatchExtreme(extractQueryObjects(request.url), parameters);
2907
+ if (advancedReport === true) {
2908
+ isInTraffic = true;
2909
+ }
2910
+ } else {
2911
+ isInTraffic = true;
2912
+ }
2913
+ });
2914
+
2915
+ return isInTraffic;
2916
+ }
2917
+
2918
+ /**
2919
+ * Returns all URLs of all network requests recorded so far during execution of test scenario.
2920
+ *
2921
+ * @return {string} List of URLs recorded as a string, separated by new lines after each URL
2922
+ * @private
2923
+ */
2924
+ _getTrafficDump() {
2925
+ let dumpedTraffic = '';
2926
+ this.requests.forEach((request) => {
2927
+ dumpedTraffic += `${request.method} - ${request.url}\n`;
2928
+ });
2929
+ return dumpedTraffic;
2930
+ }
2670
2931
  }
2671
2932
 
2672
2933
  async function proceedSee(assertType, text, context, strict = false) {
@@ -0,0 +1,137 @@
1
+ const createAdvancedTestResults = (url, dataToCheck, requests) => {
2
+ // Creates advanced test results for a network traffic check.
3
+ // Advanced test results only applies when expected parameters are set
4
+ if (!dataToCheck) return '';
5
+
6
+ let urlFound = false;
7
+ let advancedResults;
8
+ requests.forEach((request) => {
9
+ // url not found in this request. continue with next request
10
+ if (urlFound || !request.url.match(new RegExp(url))) return;
11
+ urlFound = true;
12
+
13
+ // Url found. Now we create advanced test report for that URL and show which parameters failed
14
+ if (!request.requestPostData) {
15
+ advancedResults = allParameterValuePairsMatchExtreme(extractQueryObjects(request.url), dataToCheck);
16
+ } else if (request.requestPostData) {
17
+ advancedResults = allRequestPostDataValuePairsMatchExtreme(request.requestPostData, dataToCheck);
18
+ }
19
+ });
20
+ return advancedResults;
21
+ };
22
+
23
+ const extractQueryObjects = (queryString) => {
24
+ // Converts a string of GET parameters into an array of parameter objects. Each parameter object contains the properties "name" and "value".
25
+ if (queryString.indexOf('?') === -1) {
26
+ return [];
27
+ }
28
+ const queryObjects = [];
29
+
30
+ const queryPart = queryString.split('?')[1];
31
+
32
+ const queryParameters = queryPart.split('&');
33
+
34
+ queryParameters.forEach((queryParameter) => {
35
+ const keyValue = queryParameter.split('=');
36
+ const queryObject = {};
37
+ // eslint-disable-next-line prefer-destructuring
38
+ queryObject.name = keyValue[0];
39
+ queryObject.value = decodeURIComponent(keyValue[1]);
40
+ queryObjects.push(queryObject);
41
+ });
42
+
43
+ return queryObjects;
44
+ };
45
+
46
+ const allParameterValuePairsMatchExtreme = (queryStringObject, advancedExpectedParameterValuePairs) => {
47
+ // More advanced check if all request parameters match with the expectations
48
+ let littleReport = '\nQuery parameters:\n';
49
+ let success = true;
50
+
51
+ for (const expectedKey in advancedExpectedParameterValuePairs) {
52
+ if (!Object.prototype.hasOwnProperty.call(advancedExpectedParameterValuePairs, expectedKey)) {
53
+ continue;
54
+ }
55
+ let parameterFound = false;
56
+ const expectedValue = advancedExpectedParameterValuePairs[expectedKey];
57
+
58
+ for (const queryParameter of queryStringObject) {
59
+ if (queryParameter.name === expectedKey) {
60
+ parameterFound = true;
61
+ if (expectedValue === undefined) {
62
+ littleReport += ` ${expectedKey.padStart(10, ' ')}\n`;
63
+ } else if (typeof expectedValue === 'object' && expectedValue.base64) {
64
+ const decodedActualValue = Buffer.from(queryParameter.value, 'base64').toString('utf8');
65
+ if (decodedActualValue === expectedValue.base64) {
66
+ littleReport += ` ${expectedKey.padStart(10, ' ')} = base64(${expectedValue.base64})\n`;
67
+ } else {
68
+ littleReport += ` ✖ ${expectedKey.padStart(10, ' ')} = base64(${expectedValue.base64}) -> actual value: "base64(${decodedActualValue})"\n`;
69
+ success = false;
70
+ }
71
+ } else if (queryParameter.value === expectedValue) {
72
+ littleReport += ` ${expectedKey.padStart(10, ' ')} = ${expectedValue}\n`;
73
+ } else {
74
+ littleReport += ` ✖ ${expectedKey.padStart(10, ' ')} = ${expectedValue} -> actual value: "${queryParameter.value}"\n`;
75
+ success = false;
76
+ }
77
+ }
78
+ }
79
+
80
+ if (parameterFound === false) {
81
+ littleReport += ` ✖ ${expectedKey.padStart(10, ' ')}${expectedValue ? ` = ${JSON.stringify(expectedValue)}` : ''} -> parameter not found in request\n`;
82
+ success = false;
83
+ }
84
+ }
85
+
86
+ return success ? true : littleReport;
87
+ };
88
+
89
+ const allRequestPostDataValuePairsMatchExtreme = (RequestPostDataObject, advancedExpectedRequestPostValuePairs) => {
90
+ // More advanced check if all request post data match with the expectations
91
+ let littleReport = '\nRequest Post Data:\n';
92
+ let success = true;
93
+
94
+ for (const expectedKey in advancedExpectedRequestPostValuePairs) {
95
+ if (!Object.prototype.hasOwnProperty.call(advancedExpectedRequestPostValuePairs, expectedKey)) {
96
+ continue;
97
+ }
98
+ let keyFound = false;
99
+ const expectedValue = advancedExpectedRequestPostValuePairs[expectedKey];
100
+
101
+ for (const [key, value] of Object.entries(RequestPostDataObject)) {
102
+ if (key === expectedKey) {
103
+ keyFound = true;
104
+ if (expectedValue === undefined) {
105
+ littleReport += ` ${expectedKey.padStart(10, ' ')}\n`;
106
+ } else if (typeof expectedValue === 'object' && expectedValue.base64) {
107
+ const decodedActualValue = Buffer.from(value, 'base64').toString('utf8');
108
+ if (decodedActualValue === expectedValue.base64) {
109
+ littleReport += ` ${expectedKey.padStart(10, ' ')} = base64(${expectedValue.base64})\n`;
110
+ } else {
111
+ littleReport += ` ✖ ${expectedKey.padStart(10, ' ')} = base64(${expectedValue.base64}) -> actual value: "base64(${decodedActualValue})"\n`;
112
+ success = false;
113
+ }
114
+ } else if (value === expectedValue) {
115
+ littleReport += ` ${expectedKey.padStart(10, ' ')} = ${expectedValue}\n`;
116
+ } else {
117
+ littleReport += ` ✖ ${expectedKey.padStart(10, ' ')} = ${expectedValue} -> actual value: "${value}"\n`;
118
+ success = false;
119
+ }
120
+ }
121
+ }
122
+
123
+ if (keyFound === false) {
124
+ littleReport += ` ✖ ${expectedKey.padStart(10, ' ')}${expectedValue ? ` = ${JSON.stringify(expectedValue)}` : ''} -> key not found in request\n`;
125
+ success = false;
126
+ }
127
+ }
128
+
129
+ return success ? true : littleReport;
130
+ };
131
+
132
+ module.exports = {
133
+ createAdvancedTestResults,
134
+ extractQueryObjects,
135
+ allParameterValuePairsMatchExtreme,
136
+ allRequestPostDataValuePairsMatchExtreme,
137
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeceptjs",
3
- "version": "3.5.13-beta.1",
3
+ "version": "3.5.13-beta.3",
4
4
  "description": "Supercharged End 2 End Testing Framework for NodeJS",
5
5
  "keywords": [
6
6
  "acceptance",
@@ -25,7 +25,8 @@
25
25
  "bin",
26
26
  "lib",
27
27
  "translations",
28
- "typings/**/*.d.ts"
28
+ "typings/**/*.d.ts",
29
+ "docs/webapi/**"
29
30
  ],
30
31
  "main": "lib/index.js",
31
32
  "typings": "typings/index.d.ts",
@@ -133,7 +134,7 @@
133
134
  "contributor-faces": "1.1.0",
134
135
  "documentation": "12.3.0",
135
136
  "dtslint": "4.2.1",
136
- "electron": "28.1.4",
137
+ "electron": "28.2.1",
137
138
  "eslint": "8.56.0",
138
139
  "eslint-config-airbnb-base": "15.0.0",
139
140
  "eslint-plugin-import": "2.29.1",