cypress-mailisk 3.1.0 → 3.2.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 +13 -3
- package/package.json +1 -1
- package/src/mailiskCommands.d.ts +52 -8
- package/src/mailiskCommands.js +37 -4
package/README.md
CHANGED
|
@@ -223,7 +223,7 @@ cy.mailiskDeviceList({ issuer: 'GitHub', username: 'qa@example.com' }).then((res
|
|
|
223
223
|
|
|
224
224
|
cy.mailiskDeviceCreate({
|
|
225
225
|
name: 'GitHub staging',
|
|
226
|
-
|
|
226
|
+
shared_secret: 'JBSWY3DPEHPK3PXP',
|
|
227
227
|
}).then((device) => {
|
|
228
228
|
cy.mailiskDeviceOtpByDeviceId(device.id).then((otp) => {
|
|
229
229
|
expect(otp.code).to.match(/^\d{6}$/);
|
|
@@ -240,18 +240,28 @@ cy.mailiskDeviceCreateCustom({
|
|
|
240
240
|
});
|
|
241
241
|
|
|
242
242
|
cy.mailiskDeviceCreateFromBase32SecretKey({
|
|
243
|
-
|
|
243
|
+
base32_secret_key: 'JBSWY3DPEHPK3PXP',
|
|
244
244
|
issuer: 'GitHub',
|
|
245
245
|
});
|
|
246
246
|
|
|
247
247
|
cy.mailiskDeviceCreateFromOtpAuthUrl({
|
|
248
|
-
|
|
248
|
+
otp_auth_url: 'otpauth://totp/GitHub:qa@example.com?secret=JBSWY3DPEHPK3PXP&issuer=GitHub',
|
|
249
249
|
});
|
|
250
250
|
|
|
251
251
|
cy.mailiskDeviceOtpBySharedSecret('JBSWY3DPEHPK3PXP'); // one-off code without saving a device
|
|
252
252
|
cy.mailiskDeviceDelete('9b1f6ec0-b90d-4bd8-8dd0-f6b2d5138273');
|
|
253
253
|
```
|
|
254
254
|
|
|
255
|
+
To avoid receiving a TOTP code right before it expires, pass min_seconds_until_expire. If the current code has fewer seconds remaining, Mailisk waits for the next code before returning.
|
|
256
|
+
|
|
257
|
+
```js
|
|
258
|
+
cy.mailiskDeviceOtpByDeviceId(device.id, { min_seconds_until_expire: 10 }).then((otp) => {
|
|
259
|
+
cy.get('#code').type(otp.code);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
cy.mailiskDeviceOtpBySharedSecret('JBSWY3DPEHPK3PXP', { min_seconds_until_expire: 10 });
|
|
263
|
+
```
|
|
264
|
+
|
|
255
265
|
## Common test cases
|
|
256
266
|
|
|
257
267
|
### Working with email attachments
|
package/package.json
CHANGED
package/src/mailiskCommands.d.ts
CHANGED
|
@@ -245,7 +245,7 @@ export interface TotpDevice {
|
|
|
245
245
|
/** Source used to create the saved device */
|
|
246
246
|
source: TotpDeviceSource;
|
|
247
247
|
/** Optional expiration timestamp */
|
|
248
|
-
|
|
248
|
+
expires_at?: string | null;
|
|
249
249
|
/** Date and time the device was created */
|
|
250
250
|
created_at: string;
|
|
251
251
|
/** Date and time the device was updated */
|
|
@@ -271,11 +271,11 @@ export interface TotpDeviceListResponse {
|
|
|
271
271
|
|
|
272
272
|
export interface CreateTotpDeviceParams {
|
|
273
273
|
/** Base32 shared secret. */
|
|
274
|
-
|
|
274
|
+
shared_secret: string;
|
|
275
275
|
/** Optional device display name. */
|
|
276
276
|
name?: string;
|
|
277
277
|
/** Optional future ISO expiration timestamp. */
|
|
278
|
-
|
|
278
|
+
expires_at?: string;
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
export interface CreateCustomTotpDeviceParams {
|
|
@@ -294,12 +294,12 @@ export interface CreateCustomTotpDeviceParams {
|
|
|
294
294
|
/** TOTP hash algorithm. */
|
|
295
295
|
algorithm?: TotpAlgorithm;
|
|
296
296
|
/** Optional future ISO expiration timestamp. */
|
|
297
|
-
|
|
297
|
+
expires_at?: string;
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
export interface CreateBase32SecretKeyTotpDeviceParams {
|
|
301
301
|
/** Base32 secret key. */
|
|
302
|
-
|
|
302
|
+
base32_secret_key: string;
|
|
303
303
|
/** Optional device display name. */
|
|
304
304
|
name?: string;
|
|
305
305
|
/** Optional account label. */
|
|
@@ -313,12 +313,12 @@ export interface CreateBase32SecretKeyTotpDeviceParams {
|
|
|
313
313
|
/** TOTP hash algorithm. */
|
|
314
314
|
algorithm?: TotpAlgorithm;
|
|
315
315
|
/** Optional future ISO expiration timestamp. */
|
|
316
|
-
|
|
316
|
+
expires_at?: string;
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
export interface CreateOtpAuthUrlTotpDeviceParams {
|
|
320
320
|
/** otpauth://totp URL with a secret query parameter. */
|
|
321
|
-
|
|
321
|
+
otp_auth_url: string;
|
|
322
322
|
/** Optional device display name override. */
|
|
323
323
|
name?: string;
|
|
324
324
|
/** Optional account label fallback. */
|
|
@@ -332,7 +332,7 @@ export interface CreateOtpAuthUrlTotpDeviceParams {
|
|
|
332
332
|
/** TOTP hash algorithm, used only if missing from the URL. */
|
|
333
333
|
algorithm?: TotpAlgorithm;
|
|
334
334
|
/** Optional future ISO expiration timestamp. */
|
|
335
|
-
|
|
335
|
+
expires_at?: string;
|
|
336
336
|
}
|
|
337
337
|
|
|
338
338
|
export interface TotpOtpResponse {
|
|
@@ -342,6 +342,16 @@ export interface TotpOtpResponse {
|
|
|
342
342
|
expires: string;
|
|
343
343
|
}
|
|
344
344
|
|
|
345
|
+
export interface TotpOtpParams {
|
|
346
|
+
/**
|
|
347
|
+
* Minimum number of seconds the generated code must remain valid.
|
|
348
|
+
*
|
|
349
|
+
* When the current TOTP code expires sooner than this value, the API waits
|
|
350
|
+
* for the next code before responding.
|
|
351
|
+
*/
|
|
352
|
+
min_seconds_until_expire?: number;
|
|
353
|
+
}
|
|
354
|
+
|
|
345
355
|
declare global {
|
|
346
356
|
namespace Cypress {
|
|
347
357
|
interface Chainable {
|
|
@@ -494,6 +504,23 @@ declare global {
|
|
|
494
504
|
options?: Partial<Cypress.RequestOptions>,
|
|
495
505
|
): Cypress.Chainable<TotpOtpResponse>;
|
|
496
506
|
|
|
507
|
+
mailiskDeviceOtpByDeviceId(
|
|
508
|
+
/**
|
|
509
|
+
* Saved device ID.
|
|
510
|
+
*/
|
|
511
|
+
deviceId: string,
|
|
512
|
+
/**
|
|
513
|
+
* OTP generation parameters.
|
|
514
|
+
*/
|
|
515
|
+
params?: TotpOtpParams,
|
|
516
|
+
/**
|
|
517
|
+
* Request options.
|
|
518
|
+
*
|
|
519
|
+
* See https://docs.cypress.io/api/commands/request#Arguments
|
|
520
|
+
*/
|
|
521
|
+
options?: Partial<Cypress.RequestOptions>,
|
|
522
|
+
): Cypress.Chainable<TotpOtpResponse>;
|
|
523
|
+
|
|
497
524
|
mailiskDeviceOtpBySharedSecret(
|
|
498
525
|
/**
|
|
499
526
|
* Shared secret for one-off OTP generation.
|
|
@@ -507,6 +534,23 @@ declare global {
|
|
|
507
534
|
options?: Partial<Cypress.RequestOptions>,
|
|
508
535
|
): Cypress.Chainable<TotpOtpResponse>;
|
|
509
536
|
|
|
537
|
+
mailiskDeviceOtpBySharedSecret(
|
|
538
|
+
/**
|
|
539
|
+
* Shared secret for one-off OTP generation.
|
|
540
|
+
*/
|
|
541
|
+
sharedSecret: string,
|
|
542
|
+
/**
|
|
543
|
+
* OTP generation parameters.
|
|
544
|
+
*/
|
|
545
|
+
params?: TotpOtpParams,
|
|
546
|
+
/**
|
|
547
|
+
* Request options.
|
|
548
|
+
*
|
|
549
|
+
* See https://docs.cypress.io/api/commands/request#Arguments
|
|
550
|
+
*/
|
|
551
|
+
options?: Partial<Cypress.RequestOptions>,
|
|
552
|
+
): Cypress.Chainable<TotpOtpResponse>;
|
|
553
|
+
|
|
510
554
|
mailiskDeviceDelete(
|
|
511
555
|
/**
|
|
512
556
|
* Saved device ID.
|
package/src/mailiskCommands.js
CHANGED
|
@@ -216,6 +216,33 @@ class MailiskCommands {
|
|
|
216
216
|
return value.trim();
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
_hasTotpOtpParam(value) {
|
|
220
|
+
return (
|
|
221
|
+
value &&
|
|
222
|
+
typeof value === 'object' &&
|
|
223
|
+
Object.prototype.hasOwnProperty.call(value, 'min_seconds_until_expire')
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
_getTotpOtpArgs(paramsOrOptions = {}, options = {}, hasRequestOptions = false) {
|
|
228
|
+
if (hasRequestOptions || this._hasTotpOtpParam(paramsOrOptions)) {
|
|
229
|
+
return [{ ...(paramsOrOptions || {}) }, options];
|
|
230
|
+
}
|
|
231
|
+
return [{}, paramsOrOptions];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
_buildTotpOtpUrlParams(params = {}) {
|
|
235
|
+
return this._buildUrlParams(params);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
_buildTotpOtpBody(params = {}) {
|
|
239
|
+
const body = {};
|
|
240
|
+
if (params.min_seconds_until_expire != null) {
|
|
241
|
+
body.min_seconds_until_expire = params.min_seconds_until_expire;
|
|
242
|
+
}
|
|
243
|
+
return body;
|
|
244
|
+
}
|
|
245
|
+
|
|
219
246
|
mailiskDeviceList(params = {}, options = {}) {
|
|
220
247
|
const urlParams = this._buildUrlParams(params);
|
|
221
248
|
const query = urlParams.toString();
|
|
@@ -239,14 +266,20 @@ class MailiskCommands {
|
|
|
239
266
|
return this._withRequest((request) => request.post('api/devices/otpauth-url', input, options));
|
|
240
267
|
}
|
|
241
268
|
|
|
242
|
-
mailiskDeviceOtpByDeviceId(deviceId, options = {}) {
|
|
269
|
+
mailiskDeviceOtpByDeviceId(deviceId, paramsOrOptions = {}, options = {}) {
|
|
270
|
+
const [params, requestOptions] = this._getTotpOtpArgs(paramsOrOptions, options, arguments.length >= 3);
|
|
243
271
|
const encodedDeviceId = encodeURIComponent(this._requireNonEmptyString(deviceId, 'deviceId'));
|
|
244
|
-
|
|
272
|
+
const urlParams = this._buildTotpOtpUrlParams(params);
|
|
273
|
+
const query = urlParams.toString();
|
|
274
|
+
const path = query ? `api/devices/${encodedDeviceId}/otp?${query}` : `api/devices/${encodedDeviceId}/otp`;
|
|
275
|
+
return this._withRequest((request) => request.get(path, requestOptions));
|
|
245
276
|
}
|
|
246
277
|
|
|
247
|
-
mailiskDeviceOtpBySharedSecret(sharedSecret, options = {}) {
|
|
278
|
+
mailiskDeviceOtpBySharedSecret(sharedSecret, paramsOrOptions = {}, options = {}) {
|
|
279
|
+
const [params, requestOptions] = this._getTotpOtpArgs(paramsOrOptions, options, arguments.length >= 3);
|
|
248
280
|
const normalizedSharedSecret = this._requireNonEmptyString(sharedSecret, 'sharedSecret');
|
|
249
|
-
|
|
281
|
+
const body = { shared_secret: normalizedSharedSecret, ...this._buildTotpOtpBody(params) };
|
|
282
|
+
return this._withRequest((request) => request.post('api/devices/otp', body, requestOptions));
|
|
250
283
|
}
|
|
251
284
|
|
|
252
285
|
mailiskDeviceDelete(deviceId, options = {}) {
|