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 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
- sharedSecret: 'JBSWY3DPEHPK3PXP',
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
- base32SecretKey: 'JBSWY3DPEHPK3PXP',
243
+ base32_secret_key: 'JBSWY3DPEHPK3PXP',
244
244
  issuer: 'GitHub',
245
245
  });
246
246
 
247
247
  cy.mailiskDeviceCreateFromOtpAuthUrl({
248
- otpAuthUrl: 'otpauth://totp/GitHub:qa@example.com?secret=JBSWY3DPEHPK3PXP&issuer=GitHub',
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cypress-mailisk",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "description": "Mailisk library for Cypress",
5
5
  "keywords": [
6
6
  "mailisk",
@@ -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
- expiresAt?: string | null;
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
- sharedSecret: string;
274
+ shared_secret: string;
275
275
  /** Optional device display name. */
276
276
  name?: string;
277
277
  /** Optional future ISO expiration timestamp. */
278
- expiresAt?: string;
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
- expiresAt?: string;
297
+ expires_at?: string;
298
298
  }
299
299
 
300
300
  export interface CreateBase32SecretKeyTotpDeviceParams {
301
301
  /** Base32 secret key. */
302
- base32SecretKey: string;
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
- expiresAt?: string;
316
+ expires_at?: string;
317
317
  }
318
318
 
319
319
  export interface CreateOtpAuthUrlTotpDeviceParams {
320
320
  /** otpauth://totp URL with a secret query parameter. */
321
- otpAuthUrl: string;
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
- expiresAt?: string;
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.
@@ -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
- return this._withRequest((request) => request.get(`api/devices/${encodedDeviceId}/otp`, options));
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
- return this._withRequest((request) => request.post('api/devices/otp', { sharedSecret: normalizedSharedSecret }, options));
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 = {}) {