@telefonica/acceptance-testing 2.9.1 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -0
- package/dist/acceptance-testing.cjs.development.js +128 -29
- package/dist/acceptance-testing.cjs.development.js.map +1 -1
- package/dist/acceptance-testing.cjs.production.min.js +1 -1
- package/dist/acceptance-testing.cjs.production.min.js.map +1 -1
- package/dist/acceptance-testing.esm.js +127 -30
- package/dist/acceptance-testing.esm.js.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js.flow +5 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -106,3 +106,52 @@ you need a different jest config file name you can manually setup some scripts i
|
|
|
106
106
|
|
|
107
107
|
Just take into account that the `jest-environment-puppeteer` must always be configured in your jest config
|
|
108
108
|
file. Also note that tests run in UI mode by default, unless you set the `HEADLESS=1` env var.
|
|
109
|
+
|
|
110
|
+
## Intercepting requests
|
|
111
|
+
|
|
112
|
+
If you can intercept and mock requests in your acceptance tests you can use the `interceptRequest` function:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import {openPage, screen, interceptRequest} from '@telefonica/acceptance-testing';
|
|
116
|
+
|
|
117
|
+
test('example screenshot test', async () => {
|
|
118
|
+
const imageSpy = interceptRequest((req) => req.url().endsWith('.jpg'));
|
|
119
|
+
|
|
120
|
+
imageSpy.mockReturnValue({
|
|
121
|
+
status: 200,
|
|
122
|
+
contentType: 'image/jpeg',
|
|
123
|
+
body: myMockedJpeg,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const page = await openPage({path: '/foo'});
|
|
127
|
+
|
|
128
|
+
expect(imageSpy).toHaveBeenCalled();
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
To mock JSON api endpoints you can use `interceptRequest` too, but we also provide a more conveninent api
|
|
133
|
+
wrapper over `interceptRequest`: `createApiEndpointMock`
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
import {openPage, screen, createApiEndpointMock} from '@telefonica/acceptance-testing';
|
|
137
|
+
|
|
138
|
+
test('example screenshot test', async () => {
|
|
139
|
+
const api = createApiEndpointMock({basePath: 'https://my-api-endpoint.com'});
|
|
140
|
+
|
|
141
|
+
const getSpy = api.spyOn('/some-path').mockReturnValue({a: 1, b: 2});
|
|
142
|
+
const postSpy = api.spyOn('/other-path', 'POST').mockReturnValue({c: 3});
|
|
143
|
+
|
|
144
|
+
const page = await openPage({path: '/foo'});
|
|
145
|
+
|
|
146
|
+
expect(getSpy).toHaveBeenCalled();
|
|
147
|
+
|
|
148
|
+
await page.click(await screen.findByRole('button', {name: 'Send'}));
|
|
149
|
+
|
|
150
|
+
expect(postSpy).toHaveBeenCalled();
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`createApiEndpointMock` automatically mocks CORS response headers and preflight (`OPTIONS`) requests for you.
|
|
155
|
+
|
|
156
|
+
You can also use globs for paths if you need: `api.spyOn('/some/*/path')`. We use the
|
|
157
|
+
[`glob-to-regexp`](https://www.npmjs.com/package/glob-to-regexp) lib internally.
|
|
@@ -9,6 +9,7 @@ var fs = _interopDefault(require('fs'));
|
|
|
9
9
|
var findRoot = _interopDefault(require('find-root'));
|
|
10
10
|
var pptrTestingLibrary = require('pptr-testing-library');
|
|
11
11
|
var jestImageSnapshot = require('jest-image-snapshot');
|
|
12
|
+
var globToRegExp = _interopDefault(require('glob-to-regexp'));
|
|
12
13
|
|
|
13
14
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
14
15
|
try {
|
|
@@ -1115,14 +1116,88 @@ var getPageApi = function getPageApi(page) {
|
|
|
1115
1116
|
|
|
1116
1117
|
return api;
|
|
1117
1118
|
};
|
|
1119
|
+
var needsRequestInterception = false;
|
|
1120
|
+
var requestHandlers = [];
|
|
1121
|
+
|
|
1122
|
+
var requestInterceptor = function requestInterceptor(req) {
|
|
1123
|
+
var _requestHandlers$find;
|
|
1124
|
+
|
|
1125
|
+
var _ref11 = (_requestHandlers$find = requestHandlers.find(function (_ref12) {
|
|
1126
|
+
var matcher = _ref12.matcher;
|
|
1127
|
+
return matcher(req);
|
|
1128
|
+
})) != null ? _requestHandlers$find : {
|
|
1129
|
+
handler: null
|
|
1130
|
+
},
|
|
1131
|
+
handler = _ref11.handler;
|
|
1132
|
+
|
|
1133
|
+
if (!handler) {
|
|
1134
|
+
req["continue"]();
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
var response = handler(req);
|
|
1139
|
+
req.respond(response);
|
|
1140
|
+
};
|
|
1141
|
+
|
|
1142
|
+
var interceptRequest = function interceptRequest(matcher) {
|
|
1143
|
+
needsRequestInterception = true;
|
|
1144
|
+
var spy = jest.fn();
|
|
1145
|
+
requestHandlers.push({
|
|
1146
|
+
matcher: matcher,
|
|
1147
|
+
handler: spy
|
|
1148
|
+
});
|
|
1149
|
+
return spy;
|
|
1150
|
+
};
|
|
1151
|
+
var createApiEndpointMock = function createApiEndpointMock(_ref13) {
|
|
1152
|
+
var baseUrl = _ref13.baseUrl;
|
|
1153
|
+
interceptRequest(function (req) {
|
|
1154
|
+
return req.method() === 'OPTIONS' && req.url().startsWith(baseUrl);
|
|
1155
|
+
}).mockImplementation(function () {
|
|
1156
|
+
return {
|
|
1157
|
+
status: 204,
|
|
1158
|
+
headers: {
|
|
1159
|
+
'Access-Control-Allow-Origin': '*',
|
|
1160
|
+
'Access-Control-Allow-Methods': 'POST,PATCH,PUT,GET,OPTIONS',
|
|
1161
|
+
'Access-Control-Allow-Headers': 'Content-Type,Authorization'
|
|
1162
|
+
}
|
|
1163
|
+
};
|
|
1164
|
+
});
|
|
1165
|
+
return {
|
|
1166
|
+
spyOn: function spyOn(path, method) {
|
|
1167
|
+
if (method === void 0) {
|
|
1168
|
+
method = 'GET';
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
var matcher = function matcher(req) {
|
|
1172
|
+
var url = req.url();
|
|
1173
|
+
var urlPath = url.substring(baseUrl.length);
|
|
1174
|
+
return req.method() === method && url.startsWith(baseUrl) && !!urlPath.match(globToRegExp(path));
|
|
1175
|
+
};
|
|
1176
|
+
|
|
1177
|
+
var spy = jest.fn();
|
|
1178
|
+
interceptRequest(matcher).mockImplementation(function (req) {
|
|
1179
|
+
var resBody = spy(req);
|
|
1180
|
+
return {
|
|
1181
|
+
status: 200,
|
|
1182
|
+
headers: {
|
|
1183
|
+
'Access-Control-Allow-Origin': '*'
|
|
1184
|
+
},
|
|
1185
|
+
contentType: 'application/json',
|
|
1186
|
+
body: JSON.stringify(resBody)
|
|
1187
|
+
};
|
|
1188
|
+
});
|
|
1189
|
+
return spy;
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
1192
|
+
};
|
|
1118
1193
|
var openPage = /*#__PURE__*/function () {
|
|
1119
|
-
var
|
|
1194
|
+
var _ref15 = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee7(_ref14) {
|
|
1120
1195
|
var userAgent, isDarkMode, viewport, cookies, urlConfig, url, currentUserAgent, page, connectionError;
|
|
1121
1196
|
return runtime_1.wrap(function _callee7$(_context7) {
|
|
1122
1197
|
while (1) {
|
|
1123
1198
|
switch (_context7.prev = _context7.next) {
|
|
1124
1199
|
case 0:
|
|
1125
|
-
userAgent =
|
|
1200
|
+
userAgent = _ref14.userAgent, isDarkMode = _ref14.isDarkMode, viewport = _ref14.viewport, cookies = _ref14.cookies, urlConfig = /*#__PURE__*/_objectWithoutPropertiesLoose(_ref14, _excluded2);
|
|
1126
1201
|
|
|
1127
1202
|
url = function () {
|
|
1128
1203
|
if (urlConfig.url !== undefined) {
|
|
@@ -1206,20 +1281,32 @@ var openPage = /*#__PURE__*/function () {
|
|
|
1206
1281
|
});
|
|
1207
1282
|
|
|
1208
1283
|
case 23:
|
|
1209
|
-
|
|
1284
|
+
if (!needsRequestInterception) {
|
|
1285
|
+
_context7.next = 27;
|
|
1286
|
+
break;
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1210
1289
|
_context7.next = 26;
|
|
1211
|
-
return page
|
|
1290
|
+
return page.setRequestInterception(true);
|
|
1212
1291
|
|
|
1213
1292
|
case 26:
|
|
1214
|
-
|
|
1293
|
+
page.on('request', requestInterceptor);
|
|
1294
|
+
|
|
1295
|
+
case 27:
|
|
1296
|
+
_context7.prev = 27;
|
|
1297
|
+
_context7.next = 30;
|
|
1298
|
+
return page["goto"](url);
|
|
1299
|
+
|
|
1300
|
+
case 30:
|
|
1301
|
+
_context7.next = 41;
|
|
1215
1302
|
break;
|
|
1216
1303
|
|
|
1217
|
-
case
|
|
1218
|
-
_context7.prev =
|
|
1219
|
-
_context7.t1 = _context7["catch"](
|
|
1304
|
+
case 32:
|
|
1305
|
+
_context7.prev = 32;
|
|
1306
|
+
_context7.t1 = _context7["catch"](27);
|
|
1220
1307
|
|
|
1221
1308
|
if (!_context7.t1.message.includes('net::ERR_CONNECTION_REFUSED')) {
|
|
1222
|
-
_context7.next =
|
|
1309
|
+
_context7.next = 40;
|
|
1223
1310
|
break;
|
|
1224
1311
|
}
|
|
1225
1312
|
|
|
@@ -1227,33 +1314,33 @@ var openPage = /*#__PURE__*/function () {
|
|
|
1227
1314
|
Error.captureStackTrace(connectionError, openPage);
|
|
1228
1315
|
throw connectionError;
|
|
1229
1316
|
|
|
1230
|
-
case
|
|
1317
|
+
case 40:
|
|
1231
1318
|
throw _context7.t1;
|
|
1232
1319
|
|
|
1233
|
-
case
|
|
1234
|
-
_context7.next =
|
|
1320
|
+
case 41:
|
|
1321
|
+
_context7.next = 43;
|
|
1235
1322
|
return page.waitForFunction('document.fonts.status === "loaded"');
|
|
1236
1323
|
|
|
1237
|
-
case
|
|
1324
|
+
case 43:
|
|
1238
1325
|
return _context7.abrupt("return", getPageApi(page));
|
|
1239
1326
|
|
|
1240
|
-
case
|
|
1327
|
+
case 44:
|
|
1241
1328
|
case "end":
|
|
1242
1329
|
return _context7.stop();
|
|
1243
1330
|
}
|
|
1244
1331
|
}
|
|
1245
|
-
}, _callee7, null, [[
|
|
1332
|
+
}, _callee7, null, [[27, 32]]);
|
|
1246
1333
|
}));
|
|
1247
1334
|
|
|
1248
1335
|
return function openPage(_x11) {
|
|
1249
|
-
return
|
|
1336
|
+
return _ref15.apply(this, arguments);
|
|
1250
1337
|
};
|
|
1251
1338
|
}();
|
|
1252
1339
|
|
|
1253
1340
|
var buildQueryMethods = function buildQueryMethods(_temp3) {
|
|
1254
|
-
var
|
|
1255
|
-
page =
|
|
1256
|
-
element =
|
|
1341
|
+
var _ref16 = _temp3 === void 0 ? {} : _temp3,
|
|
1342
|
+
page = _ref16.page,
|
|
1343
|
+
element = _ref16.element;
|
|
1257
1344
|
|
|
1258
1345
|
var boundQueries = {};
|
|
1259
1346
|
|
|
@@ -1311,7 +1398,7 @@ var buildQueryMethods = function buildQueryMethods(_temp3) {
|
|
|
1311
1398
|
newElementHandle = Object.create(elementHandle);
|
|
1312
1399
|
|
|
1313
1400
|
newElementHandle.screenshot = /*#__PURE__*/function () {
|
|
1314
|
-
var
|
|
1401
|
+
var _ref18 = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee8(options) {
|
|
1315
1402
|
return runtime_1.wrap(function _callee8$(_context8) {
|
|
1316
1403
|
while (1) {
|
|
1317
1404
|
switch (_context8.prev = _context8.next) {
|
|
@@ -1342,7 +1429,7 @@ var buildQueryMethods = function buildQueryMethods(_temp3) {
|
|
|
1342
1429
|
}));
|
|
1343
1430
|
|
|
1344
1431
|
return function (_x12) {
|
|
1345
|
-
return
|
|
1432
|
+
return _ref18.apply(this, arguments);
|
|
1346
1433
|
};
|
|
1347
1434
|
}();
|
|
1348
1435
|
|
|
@@ -1381,9 +1468,13 @@ beforeEach( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function
|
|
|
1381
1468
|
switch (_context10.prev = _context10.next) {
|
|
1382
1469
|
case 0:
|
|
1383
1470
|
_context10.next = 2;
|
|
1384
|
-
return
|
|
1471
|
+
return getGlobalPage().setRequestInterception(false);
|
|
1385
1472
|
|
|
1386
1473
|
case 2:
|
|
1474
|
+
_context10.next = 4;
|
|
1475
|
+
return global.jestPuppeteer.resetPage();
|
|
1476
|
+
|
|
1477
|
+
case 4:
|
|
1387
1478
|
case "end":
|
|
1388
1479
|
return _context10.stop();
|
|
1389
1480
|
}
|
|
@@ -1391,34 +1482,42 @@ beforeEach( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function
|
|
|
1391
1482
|
}, _callee10);
|
|
1392
1483
|
})));
|
|
1393
1484
|
afterEach( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee11() {
|
|
1485
|
+
var page;
|
|
1394
1486
|
return runtime_1.wrap(function _callee11$(_context11) {
|
|
1395
1487
|
while (1) {
|
|
1396
1488
|
switch (_context11.prev = _context11.next) {
|
|
1397
1489
|
case 0:
|
|
1398
1490
|
_context11.prev = 0;
|
|
1399
|
-
|
|
1400
|
-
|
|
1491
|
+
page = getGlobalPage();
|
|
1492
|
+
requestHandlers = [];
|
|
1493
|
+
needsRequestInterception = false;
|
|
1494
|
+
page.off('request', requestInterceptor); // clear tab, this way we clear the DOM and stop js execution or pending requests
|
|
1401
1495
|
|
|
1402
|
-
case 3:
|
|
1403
1496
|
_context11.next = 7;
|
|
1497
|
+
return page["goto"]('about:blank');
|
|
1498
|
+
|
|
1499
|
+
case 7:
|
|
1500
|
+
_context11.next = 11;
|
|
1404
1501
|
break;
|
|
1405
1502
|
|
|
1406
|
-
case
|
|
1407
|
-
_context11.prev =
|
|
1503
|
+
case 9:
|
|
1504
|
+
_context11.prev = 9;
|
|
1408
1505
|
_context11.t0 = _context11["catch"](0);
|
|
1409
1506
|
|
|
1410
|
-
case
|
|
1507
|
+
case 11:
|
|
1411
1508
|
case "end":
|
|
1412
1509
|
return _context11.stop();
|
|
1413
1510
|
}
|
|
1414
1511
|
}
|
|
1415
|
-
}, _callee11, null, [[0,
|
|
1512
|
+
}, _callee11, null, [[0, 9]]);
|
|
1416
1513
|
})));
|
|
1417
1514
|
|
|
1515
|
+
exports.createApiEndpointMock = createApiEndpointMock;
|
|
1418
1516
|
exports.getGlobalBrowser = getGlobalBrowser;
|
|
1419
1517
|
exports.getGlobalPage = getGlobalPage;
|
|
1420
1518
|
exports.getPageApi = getPageApi;
|
|
1421
1519
|
exports.getScreen = getScreen;
|
|
1520
|
+
exports.interceptRequest = interceptRequest;
|
|
1422
1521
|
exports.openPage = openPage;
|
|
1423
1522
|
exports.screen = screen;
|
|
1424
1523
|
exports.serverHostName = serverHostName;
|