codeceptjs 3.5.12-beta.6 → 3.5.12-beta.8

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,221 @@
1
+ const { mock, settings } = require('pactum');
2
+
3
+ /**
4
+ * ## Configuration
5
+ *
6
+ * This helper should be configured in codecept.conf.(js|ts)
7
+ *
8
+ * @typedef MockServerConfig
9
+ * @type {object}
10
+ * @prop {number} [port=9393] - Mock server port
11
+ * @prop {string} [host="0.0.0.0"] - Mock server host
12
+ * @prop {object} [httpsOpts] - key & cert values are the paths to .key and .crt files
13
+ */
14
+ let config = {
15
+ port: 9393,
16
+ host: '0.0.0.0',
17
+ httpsOpts: {
18
+ key: '',
19
+ cert: '',
20
+ },
21
+ };
22
+
23
+ /**
24
+ * MockServer
25
+ *
26
+ * The MockServer Helper in CodeceptJS empowers you to mock any server or service via HTTP or HTTPS, making it an excellent tool for simulating REST endpoints and other HTTP-based APIs.
27
+ *
28
+ * <!-- configuration -->
29
+ *
30
+ * #### Examples
31
+ *
32
+ * You can seamlessly integrate MockServer with other helpers like REST or Playwright. Here's a configuration example inside the `codecept.conf.js` file:
33
+ *
34
+ * ```javascript
35
+ * {
36
+ * helpers: {
37
+ * REST: {...},
38
+ * MockServer: {
39
+ * // default mock server config
40
+ * port: 9393,
41
+ * host: '0.0.0.0',
42
+ * httpsOpts: {
43
+ * key: '',
44
+ * cert: '',
45
+ * },
46
+ * },
47
+ * }
48
+ * }
49
+ * ```
50
+ *
51
+ * #### Adding Interactions
52
+ *
53
+ * Interactions add behavior to the mock server. Use the `I.addInteractionToMockServer()` method to include interactions. It takes an interaction object as an argument, containing request and response details.
54
+ *
55
+ * ```javascript
56
+ * I.addInteractionToMockServer({
57
+ * request: {
58
+ * method: 'GET',
59
+ * path: '/api/hello'
60
+ * },
61
+ * response: {
62
+ * status: 200,
63
+ * body: {
64
+ * 'say': 'hello to mock server'
65
+ * }
66
+ * }
67
+ * });
68
+ * ```
69
+ *
70
+ * #### Request Matching
71
+ *
72
+ * When a real request is sent to the mock server, it matches the received request with the interactions. If a match is found, it returns the specified response; otherwise, a 404 status code is returned.
73
+ *
74
+ * - Strong match on HTTP Method, Path, Query Params & JSON body.
75
+ * - Loose match on Headers.
76
+ *
77
+ * ##### Strong Match on Query Params
78
+ *
79
+ * You can send different responses based on query parameters:
80
+ *
81
+ * ```javascript
82
+ * I.addInteractionToMockServer({
83
+ * request: {
84
+ * method: 'GET',
85
+ * path: '/api/users',
86
+ * queryParams: {
87
+ * id: 1
88
+ * }
89
+ * },
90
+ * response: {
91
+ * status: 200,
92
+ * body: 'user 1'
93
+ * }
94
+ * });
95
+ *
96
+ * I.addInteractionToMockServer({
97
+ * request: {
98
+ * method: 'GET',
99
+ * path: '/api/users',
100
+ * queryParams: {
101
+ * id: 2
102
+ * }
103
+ * },
104
+ * response: {
105
+ * status: 200,
106
+ * body: 'user 2'
107
+ * }
108
+ * });
109
+ * ```
110
+ *
111
+ * - GET to `/api/users?id=1` will return 'user 1'.
112
+ * - GET to `/api/users?id=2` will return 'user 2'.
113
+ * - For all other requests, it returns a 404 status code.
114
+ *
115
+ * ##### Loose Match on Body
116
+ *
117
+ * When `strict` is set to false, it performs a loose match on query params and response body:
118
+ *
119
+ * ```javascript
120
+ * I.addInteractionToMockServer({
121
+ * strict: false,
122
+ * request: {
123
+ * method: 'POST',
124
+ * path: '/api/users',
125
+ * body: {
126
+ * name: 'john'
127
+ * }
128
+ * },
129
+ * response: {
130
+ * status: 200
131
+ * }
132
+ * });
133
+ * ```
134
+ *
135
+ * - POST to `/api/users` with the body containing `name` as 'john' will return a 200 status code.
136
+ * - POST to `/api/users` without the `name` property in the body will return a 404 status code.
137
+ *
138
+ * Happy testing with MockServer in CodeceptJS! 🚀
139
+ *
140
+ * ## Methods
141
+ */
142
+ class MockServer {
143
+ constructor(passedConfig) {
144
+ settings.setLogLevel('SILENT');
145
+ config = { ...passedConfig };
146
+ if (global.debugMode) {
147
+ settings.setLogLevel('VERBOSE');
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Start the mock server
153
+ * @param {number} [port] start the mock server with given port
154
+ *
155
+ * @returns Promise<void>
156
+ */
157
+ async startMockServer(port) {
158
+ const _config = { ...config };
159
+ if (port) _config.port = port;
160
+ await mock.setDefaults(_config);
161
+ await mock.start();
162
+ }
163
+
164
+ /**
165
+ * Stop the mock server
166
+ *
167
+ * @returns Promise<void>
168
+ *
169
+ */
170
+ async stopMockServer() {
171
+ await mock.stop();
172
+ }
173
+
174
+ /**
175
+ * An interaction adds behavior to the mock server
176
+ *
177
+ *
178
+ * ```js
179
+ * I.addInteractionToMockServer({
180
+ * request: {
181
+ * method: 'GET',
182
+ * path: '/api/hello'
183
+ * },
184
+ * response: {
185
+ * status: 200,
186
+ * body: {
187
+ * 'say': 'hello to mock server'
188
+ * }
189
+ * }
190
+ * });
191
+ * ```
192
+ * ```js
193
+ * // with query params
194
+ * I.addInteractionToMockServer({
195
+ * request: {
196
+ * method: 'GET',
197
+ * path: '/api/hello',
198
+ * queryParams: {
199
+ * id: 2
200
+ * }
201
+ * },
202
+ * response: {
203
+ * status: 200,
204
+ * body: {
205
+ * 'say': 'hello to mock server'
206
+ * }
207
+ * }
208
+ * });
209
+ * ```
210
+ *
211
+ * @param {CodeceptJS.MockInteraction|object} interaction add behavior to the mock server
212
+ *
213
+ * @returns Promise<void>
214
+ *
215
+ */
216
+ async addInteractionToMockServer(interaction) {
217
+ await mock.addInteraction(interaction);
218
+ }
219
+ }
220
+
221
+ module.exports = MockServer;
@@ -2188,6 +2188,8 @@ class Playwright extends Helper {
2188
2188
  let chunked = chunkArray(attrs, values.length);
2189
2189
  chunked = chunked.filter((val) => {
2190
2190
  for (let i = 0; i < val.length; ++i) {
2191
+ // the attribute could be a boolean
2192
+ if (typeof val[i] === 'boolean') return val[i] === values[i];
2191
2193
  // if the attribute doesn't exist, returns false as well
2192
2194
  if (!val[i] || !val[i].includes(values[i])) return false;
2193
2195
  }
@@ -1842,6 +1842,8 @@ class Puppeteer extends Helper {
1842
1842
  for (let i = 0; i < val.length; ++i) {
1843
1843
  const _actual = Number.isNaN(val[i]) || (typeof values[i]) === 'string' ? val[i] : Number.parseInt(values[i], 10);
1844
1844
  const _expected = Number.isNaN(values[i]) || (typeof values[i]) === 'string' ? values[i] : Number.parseInt(values[i], 10);
1845
+ // the attribute could be a boolean
1846
+ if (typeof _actual === 'boolean') return _actual === _expected;
1845
1847
  // if the attribute doesn't exist, returns false as well
1846
1848
  if (!_actual || !_actual.includes(_expected)) return false;
1847
1849
  }
@@ -1631,6 +1631,8 @@ class WebDriver extends Helper {
1631
1631
  for (let i = 0; i < val.length; ++i) {
1632
1632
  const _actual = Number.isNaN(val[i]) || (typeof values[i]) === 'string' ? val[i] : Number.parseInt(val[i], 10);
1633
1633
  const _expected = Number.isNaN(values[i]) || (typeof values[i]) === 'string' ? values[i] : Number.parseInt(values[i], 10);
1634
+ // the attribute could be a boolean
1635
+ if (typeof _actual === 'boolean') return _actual === _expected;
1634
1636
  if (_actual !== _expected) return false;
1635
1637
  }
1636
1638
  return true;
package/lib/locator.js CHANGED
@@ -1,4 +1,4 @@
1
- const cssToXPath = require('csstoxpath');
1
+ let cssToXPath;
2
2
  const { sprintf } = require('sprintf-js');
3
3
 
4
4
  const { xpathLocator } = require('./utils');
@@ -162,8 +162,17 @@ class Locator {
162
162
  * @returns {string}
163
163
  */
164
164
  toXPath(pseudoSelector = '') {
165
+ const locator = `${this.value}${pseudoSelector}`;
166
+ const limitation = [':nth-of-type', ':first-of-type', ':last-of-type', ':nth-last-child', ':nth-last-of-type', ':checked', ':disabled', ':enabled', ':required', ':lang'];
167
+
168
+ if (limitation.some(item => locator.includes(item))) {
169
+ cssToXPath = require('css-to-xpath');
170
+ } else {
171
+ cssToXPath = require('csstoxpath');
172
+ }
173
+
165
174
  if (this.isXPath()) return this.value;
166
- if (this.isCSS()) return cssToXPath(`${this.value}${pseudoSelector}`);
175
+ if (this.isCSS()) return cssToXPath(locator);
167
176
 
168
177
  throw new Error('Can\'t be converted to XPath');
169
178
  }
@@ -250,7 +259,7 @@ class Locator {
250
259
  */
251
260
  withText(text) {
252
261
  text = xpathLocator.literal(text);
253
- const xpath = this.toXPath(`:text-contains-case(${text})`);
262
+ const xpath = sprintf('%s[%s]', this.toXPath(), `contains(., ${text})`);
254
263
  return new Locator({ xpath });
255
264
  }
256
265
 
@@ -261,7 +270,7 @@ class Locator {
261
270
  */
262
271
  withTextEquals(text) {
263
272
  text = xpathLocator.literal(text);
264
- const xpath = this.toXPath(`:text-case(${text})`);
273
+ const xpath = sprintf('%s[%s]', this.toXPath(), `.= ${text}`);
265
274
  return new Locator({ xpath });
266
275
  }
267
276
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeceptjs",
3
- "version": "3.5.12-beta.6",
3
+ "version": "3.5.12-beta.8",
4
4
  "description": "Supercharged End 2 End Testing Framework for NodeJS",
5
5
  "keywords": [
6
6
  "acceptance",
@@ -55,6 +55,7 @@
55
55
  "test:unit:webbapi:webDriver:devtools": "mocha test/helper/WebDriver_devtools_test.js --exit",
56
56
  "test:unit:webbapi:testCafe": "mocha test/helper/TestCafe_test.js",
57
57
  "test:unit:expect": "mocha test/helper/Expect_test.js",
58
+ "test:unit:mockServer": "mocha test/helper/MockServer_test.js",
58
59
  "test:plugin": "mocha test/plugin/plugin_test.js",
59
60
  "def": "./runok.js def",
60
61
  "dev:graphql": "node test/data/graphql/index.js",
@@ -76,14 +77,15 @@
76
77
  "axios": "1.6.3",
77
78
  "chai": "4.3.8",
78
79
  "chai-deep-match": "1.2.1",
79
- "chai-exclude": "^2.1.0",
80
- "chai-json-schema": "^1.5.1",
81
- "chai-json-schema-ajv": "^5.2.4",
82
- "chai-match-pattern": "^1.3.0",
83
- "chai-string": "^1.5.0",
80
+ "chai-exclude": "2.1.0",
81
+ "chai-json-schema": "1.5.1",
82
+ "chai-json-schema-ajv": "5.2.4",
83
+ "chai-match-pattern": "1.3.0",
84
+ "chai-string": "1.5.0",
84
85
  "chalk": "4.1.2",
85
86
  "commander": "11.1.0",
86
87
  "cross-spawn": "7.0.3",
88
+ "css-to-xpath": "0.1.0",
87
89
  "csstoxpath": "1.6.0",
88
90
  "devtools": "8.27.2",
89
91
  "envinfo": "7.11.0",
@@ -92,7 +94,7 @@
92
94
  "fn-args": "4.0.0",
93
95
  "fs-extra": "11.2.0",
94
96
  "glob": "6.0.1",
95
- "html-minifier-terser": "^7.2.0",
97
+ "html-minifier-terser": "7.2.0",
96
98
  "inquirer": "6.5.2",
97
99
  "joi": "17.11.0",
98
100
  "js-beautify": "1.14.11",
@@ -103,6 +105,7 @@
103
105
  "ms": "2.1.3",
104
106
  "openai": "3.2.1",
105
107
  "ora-classic": "5.4.2",
108
+ "pactum": "3.6.0",
106
109
  "parse-function": "5.6.4",
107
110
  "parse5": "7.1.2",
108
111
  "promise-retry": "1.1.1",
@@ -118,7 +121,7 @@
118
121
  "@faker-js/faker": "7.6.0",
119
122
  "@pollyjs/adapter-puppeteer": "6.0.6",
120
123
  "@pollyjs/core": "5.1.0",
121
- "@types/chai": "^4.3.7",
124
+ "@types/chai": "4.3.7",
122
125
  "@types/inquirer": "9.0.3",
123
126
  "@types/node": "20.10.7",
124
127
  "@wdio/sauce-service": "8.27.0",
@@ -131,7 +134,7 @@
131
134
  "contributor-faces": "1.1.0",
132
135
  "documentation": "12.3.0",
133
136
  "dtslint": "4.2.1",
134
- "electron": "28.0.0",
137
+ "electron": "28.1.4",
135
138
  "eslint": "8.56.0",
136
139
  "eslint-config-airbnb-base": "15.0.0",
137
140
  "eslint-plugin-import": "2.29.1",
@@ -144,7 +147,7 @@
144
147
  "jsdoc": "3.6.11",
145
148
  "jsdoc-typeof-plugin": "1.0.0",
146
149
  "json-server": "0.10.1",
147
- "playwright": "1.40.1",
150
+ "playwright": "1.41.1",
148
151
  "puppeteer": "21.1.1",
149
152
  "qrcode-terminal": "0.12.0",
150
153
  "rosie": "2.1.1",
@@ -159,7 +162,7 @@
159
162
  "typedoc-plugin-markdown": "3.17.1",
160
163
  "typescript": "5.3.3",
161
164
  "wdio-docker-service": "1.5.0",
162
- "webdriverio": "8.27.2",
165
+ "webdriverio": "8.28.8",
163
166
  "xml2js": "0.6.2",
164
167
  "xpath": "0.0.34"
165
168
  },
@@ -382,6 +382,22 @@ declare namespace CodeceptJS {
382
382
  [key: string]: any;
383
383
  };
384
384
 
385
+ type MockRequest = {
386
+ method: 'GET'|'PUT'|'POST'|'PATCH'|'DELETE'|string;
387
+ path: string;
388
+ queryParams?: object;
389
+ }
390
+
391
+ type MockResponse = {
392
+ status: number;
393
+ body?: object;
394
+ }
395
+
396
+ type MockInteraction = {
397
+ request: MockRequest;
398
+ response: MockResponse;
399
+ }
400
+
385
401
  interface PageScrollPosition {
386
402
  x: number;
387
403
  y: number;
@@ -1732,6 +1732,188 @@ declare namespace CodeceptJS {
1732
1732
  */
1733
1733
  seeResponseMatchesJsonSchema(fnOrSchema: any): Promise<any>;
1734
1734
  }
1735
+ /**
1736
+ * ## Configuration
1737
+ *
1738
+ * This helper should be configured in codecept.conf.(js|ts)
1739
+ * @property [port = 9393] - Mock server port
1740
+ * @property [host = "0.0.0.0"] - Mock server host
1741
+ * @property [httpsOpts] - key & cert values are the paths to .key and .crt files
1742
+ */
1743
+ type MockServerConfig = {
1744
+ port?: number;
1745
+ host?: string;
1746
+ httpsOpts?: any;
1747
+ };
1748
+ /**
1749
+ * MockServer
1750
+ *
1751
+ * The MockServer Helper in CodeceptJS empowers you to mock any server or service via HTTP or HTTPS, making it an excellent tool for simulating REST endpoints and other HTTP-based APIs.
1752
+ *
1753
+ * <!-- configuration -->
1754
+ *
1755
+ * #### Examples
1756
+ *
1757
+ * You can seamlessly integrate MockServer with other helpers like REST or Playwright. Here's a configuration example inside the `codecept.conf.js` file:
1758
+ *
1759
+ * ```javascript
1760
+ * {
1761
+ * helpers: {
1762
+ * REST: {...},
1763
+ * MockServer: {
1764
+ * // default mock server config
1765
+ * port: 9393,
1766
+ * host: '0.0.0.0',
1767
+ * httpsOpts: {
1768
+ * key: '',
1769
+ * cert: '',
1770
+ * },
1771
+ * },
1772
+ * }
1773
+ * }
1774
+ * ```
1775
+ *
1776
+ * #### Adding Interactions
1777
+ *
1778
+ * Interactions add behavior to the mock server. Use the `I.addInteractionToMockServer()` method to include interactions. It takes an interaction object as an argument, containing request and response details.
1779
+ *
1780
+ * ```javascript
1781
+ * I.addInteractionToMockServer({
1782
+ * request: {
1783
+ * method: 'GET',
1784
+ * path: '/api/hello'
1785
+ * },
1786
+ * response: {
1787
+ * status: 200,
1788
+ * body: {
1789
+ * 'say': 'hello to mock server'
1790
+ * }
1791
+ * }
1792
+ * });
1793
+ * ```
1794
+ *
1795
+ * #### Request Matching
1796
+ *
1797
+ * When a real request is sent to the mock server, it matches the received request with the interactions. If a match is found, it returns the specified response; otherwise, a 404 status code is returned.
1798
+ *
1799
+ * - Strong match on HTTP Method, Path, Query Params & JSON body.
1800
+ * - Loose match on Headers.
1801
+ *
1802
+ * ##### Strong Match on Query Params
1803
+ *
1804
+ * You can send different responses based on query parameters:
1805
+ *
1806
+ * ```javascript
1807
+ * I.addInteractionToMockServer({
1808
+ * request: {
1809
+ * method: 'GET',
1810
+ * path: '/api/users',
1811
+ * queryParams: {
1812
+ * id: 1
1813
+ * }
1814
+ * },
1815
+ * response: {
1816
+ * status: 200,
1817
+ * body: 'user 1'
1818
+ * }
1819
+ * });
1820
+ *
1821
+ * I.addInteractionToMockServer({
1822
+ * request: {
1823
+ * method: 'GET',
1824
+ * path: '/api/users',
1825
+ * queryParams: {
1826
+ * id: 2
1827
+ * }
1828
+ * },
1829
+ * response: {
1830
+ * status: 200,
1831
+ * body: 'user 2'
1832
+ * }
1833
+ * });
1834
+ * ```
1835
+ *
1836
+ * - GET to `/api/users?id=1` will return 'user 1'.
1837
+ * - GET to `/api/users?id=2` will return 'user 2'.
1838
+ * - For all other requests, it returns a 404 status code.
1839
+ *
1840
+ * ##### Loose Match on Body
1841
+ *
1842
+ * When `strict` is set to false, it performs a loose match on query params and response body:
1843
+ *
1844
+ * ```javascript
1845
+ * I.addInteractionToMockServer({
1846
+ * strict: false,
1847
+ * request: {
1848
+ * method: 'POST',
1849
+ * path: '/api/users',
1850
+ * body: {
1851
+ * name: 'john'
1852
+ * }
1853
+ * },
1854
+ * response: {
1855
+ * status: 200
1856
+ * }
1857
+ * });
1858
+ * ```
1859
+ *
1860
+ * - POST to `/api/users` with the body containing `name` as 'john' will return a 200 status code.
1861
+ * - POST to `/api/users` without the `name` property in the body will return a 404 status code.
1862
+ *
1863
+ * Happy testing with MockServer in CodeceptJS! 🚀
1864
+ *
1865
+ * ## Methods
1866
+ */
1867
+ class MockServer {
1868
+ /**
1869
+ * Start the mock server
1870
+ * @param [port] - start the mock server with given port
1871
+ */
1872
+ startMockServer(port?: number): Promise<any>;
1873
+ /**
1874
+ * Stop the mock server
1875
+ */
1876
+ stopMockServer(): Promise<any>;
1877
+ /**
1878
+ * An interaction adds behavior to the mock server
1879
+ *
1880
+ *
1881
+ * ```js
1882
+ * I.addInteractionToMockServer({
1883
+ * request: {
1884
+ * method: 'GET',
1885
+ * path: '/api/hello'
1886
+ * },
1887
+ * response: {
1888
+ * status: 200,
1889
+ * body: {
1890
+ * 'say': 'hello to mock server'
1891
+ * }
1892
+ * }
1893
+ * });
1894
+ * ```
1895
+ * ```js
1896
+ * // with query params
1897
+ * I.addInteractionToMockServer({
1898
+ * request: {
1899
+ * method: 'GET',
1900
+ * path: '/api/hello',
1901
+ * queryParams: {
1902
+ * id: 2
1903
+ * }
1904
+ * },
1905
+ * response: {
1906
+ * status: 200,
1907
+ * body: {
1908
+ * 'say': 'hello to mock server'
1909
+ * }
1910
+ * }
1911
+ * });
1912
+ * ```
1913
+ * @param interaction - add behavior to the mock server
1914
+ */
1915
+ addInteractionToMockServer(interaction: CodeceptJS.MockInteraction | any): Promise<any>;
1916
+ }
1735
1917
  /**
1736
1918
  * Nightmare helper wraps [Nightmare](https://github.com/segmentio/nightmare) library to provide
1737
1919
  * fastest headless testing using Electron engine. Unlike Selenium-based drivers this uses
@@ -1759,6 +1759,191 @@ declare namespace CodeceptJS {
1759
1759
  */
1760
1760
  seeResponseMatchesJsonSchema(fnOrSchema: any): void;
1761
1761
  }
1762
+ /**
1763
+ * ## Configuration
1764
+ *
1765
+ * This helper should be configured in codecept.conf.(js|ts)
1766
+ * @property [port = 9393] - Mock server port
1767
+ * @property [host = "0.0.0.0"] - Mock server host
1768
+ * @property [httpsOpts] - key & cert values are the paths to .key and .crt files
1769
+ */
1770
+ type MockServerConfig = {
1771
+ port?: number;
1772
+ host?: string;
1773
+ httpsOpts?: any;
1774
+ };
1775
+ /**
1776
+ * MockServer
1777
+ *
1778
+ * The MockServer Helper in CodeceptJS empowers you to mock any server or service via HTTP or HTTPS, making it an excellent tool for simulating REST endpoints and other HTTP-based APIs.
1779
+ *
1780
+ * <!-- configuration -->
1781
+ *
1782
+ * #### Examples
1783
+ *
1784
+ * You can seamlessly integrate MockServer with other helpers like REST or Playwright. Here's a configuration example inside the `codecept.conf.js` file:
1785
+ *
1786
+ * ```javascript
1787
+ * {
1788
+ * helpers: {
1789
+ * REST: {...},
1790
+ * MockServer: {
1791
+ * // default mock server config
1792
+ * port: 9393,
1793
+ * host: '0.0.0.0',
1794
+ * httpsOpts: {
1795
+ * key: '',
1796
+ * cert: '',
1797
+ * },
1798
+ * },
1799
+ * }
1800
+ * }
1801
+ * ```
1802
+ *
1803
+ * #### Adding Interactions
1804
+ *
1805
+ * Interactions add behavior to the mock server. Use the `I.addInteractionToMockServer()` method to include interactions. It takes an interaction object as an argument, containing request and response details.
1806
+ *
1807
+ * ```javascript
1808
+ * I.addInteractionToMockServer({
1809
+ * request: {
1810
+ * method: 'GET',
1811
+ * path: '/api/hello'
1812
+ * },
1813
+ * response: {
1814
+ * status: 200,
1815
+ * body: {
1816
+ * 'say': 'hello to mock server'
1817
+ * }
1818
+ * }
1819
+ * });
1820
+ * ```
1821
+ *
1822
+ * #### Request Matching
1823
+ *
1824
+ * When a real request is sent to the mock server, it matches the received request with the interactions. If a match is found, it returns the specified response; otherwise, a 404 status code is returned.
1825
+ *
1826
+ * - Strong match on HTTP Method, Path, Query Params & JSON body.
1827
+ * - Loose match on Headers.
1828
+ *
1829
+ * ##### Strong Match on Query Params
1830
+ *
1831
+ * You can send different responses based on query parameters:
1832
+ *
1833
+ * ```javascript
1834
+ * I.addInteractionToMockServer({
1835
+ * request: {
1836
+ * method: 'GET',
1837
+ * path: '/api/users',
1838
+ * queryParams: {
1839
+ * id: 1
1840
+ * }
1841
+ * },
1842
+ * response: {
1843
+ * status: 200,
1844
+ * body: 'user 1'
1845
+ * }
1846
+ * });
1847
+ *
1848
+ * I.addInteractionToMockServer({
1849
+ * request: {
1850
+ * method: 'GET',
1851
+ * path: '/api/users',
1852
+ * queryParams: {
1853
+ * id: 2
1854
+ * }
1855
+ * },
1856
+ * response: {
1857
+ * status: 200,
1858
+ * body: 'user 2'
1859
+ * }
1860
+ * });
1861
+ * ```
1862
+ *
1863
+ * - GET to `/api/users?id=1` will return 'user 1'.
1864
+ * - GET to `/api/users?id=2` will return 'user 2'.
1865
+ * - For all other requests, it returns a 404 status code.
1866
+ *
1867
+ * ##### Loose Match on Body
1868
+ *
1869
+ * When `strict` is set to false, it performs a loose match on query params and response body:
1870
+ *
1871
+ * ```javascript
1872
+ * I.addInteractionToMockServer({
1873
+ * strict: false,
1874
+ * request: {
1875
+ * method: 'POST',
1876
+ * path: '/api/users',
1877
+ * body: {
1878
+ * name: 'john'
1879
+ * }
1880
+ * },
1881
+ * response: {
1882
+ * status: 200
1883
+ * }
1884
+ * });
1885
+ * ```
1886
+ *
1887
+ * - POST to `/api/users` with the body containing `name` as 'john' will return a 200 status code.
1888
+ * - POST to `/api/users` without the `name` property in the body will return a 404 status code.
1889
+ *
1890
+ * Happy testing with MockServer in CodeceptJS! 🚀
1891
+ *
1892
+ * ## Methods
1893
+ */
1894
+ class MockServer {
1895
+ /**
1896
+ * Start the mock server
1897
+ * @param [port] - start the mock server with given port
1898
+ * @returns Promise<void>
1899
+ */
1900
+ startMockServer(port?: number): any;
1901
+ /**
1902
+ * Stop the mock server
1903
+ * @returns Promise<void>
1904
+ */
1905
+ stopMockServer(): any;
1906
+ /**
1907
+ * An interaction adds behavior to the mock server
1908
+ *
1909
+ *
1910
+ * ```js
1911
+ * I.addInteractionToMockServer({
1912
+ * request: {
1913
+ * method: 'GET',
1914
+ * path: '/api/hello'
1915
+ * },
1916
+ * response: {
1917
+ * status: 200,
1918
+ * body: {
1919
+ * 'say': 'hello to mock server'
1920
+ * }
1921
+ * }
1922
+ * });
1923
+ * ```
1924
+ * ```js
1925
+ * // with query params
1926
+ * I.addInteractionToMockServer({
1927
+ * request: {
1928
+ * method: 'GET',
1929
+ * path: '/api/hello',
1930
+ * queryParams: {
1931
+ * id: 2
1932
+ * }
1933
+ * },
1934
+ * response: {
1935
+ * status: 200,
1936
+ * body: {
1937
+ * 'say': 'hello to mock server'
1938
+ * }
1939
+ * }
1940
+ * });
1941
+ * ```
1942
+ * @param interaction - add behavior to the mock server
1943
+ * @returns Promise<void>
1944
+ */
1945
+ addInteractionToMockServer(interaction: CodeceptJS.MockInteraction | any): any;
1946
+ }
1762
1947
  /**
1763
1948
  * Nightmare helper wraps [Nightmare](https://github.com/segmentio/nightmare) library to provide
1764
1949
  * fastest headless testing using Electron engine. Unlike Selenium-based drivers this uses