proxymail-qa 0.1.1 → 0.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/dist/index.d.ts CHANGED
@@ -101,6 +101,32 @@ export interface WaitOptions {
101
101
  since?: Date | string;
102
102
  }
103
103
  export type LinkType = 'verify' | 'magic_signin' | 'invite' | 'reset' | 'any';
104
+ export interface EmailSummary {
105
+ received_at: string;
106
+ service: string | null;
107
+ service_domain: string | null;
108
+ type: 'code' | 'link' | null;
109
+ subtype: string | null;
110
+ email_id: string;
111
+ }
112
+ export interface EmailCount {
113
+ address: string;
114
+ since: string | null;
115
+ count: number;
116
+ emails: EmailSummary[];
117
+ }
118
+ export interface CountOptions {
119
+ since?: Date | string;
120
+ service?: string;
121
+ type?: 'code' | 'link';
122
+ subtype?: CountSubtype | CountSubtype[];
123
+ }
124
+ export type CountSubtype = 'otp' | 'coupon' | 'verify' | 'magic_signin' | 'invite' | 'reset' | 'other' | 'any';
125
+ export interface NoEmail {
126
+ address: string;
127
+ since: string;
128
+ until: string;
129
+ }
104
130
  export declare class ProxyMailQAError extends Error {
105
131
  readonly status: number;
106
132
  readonly code: string;
@@ -137,6 +163,10 @@ export declare class ProxyMailQA {
137
163
  includeHtml?: boolean;
138
164
  limit?: number;
139
165
  }): Promise<Record<string, unknown>[]>;
166
+ countEmails(address: string, options?: CountOptions): Promise<EmailCount>;
167
+ expectNoEmail(address: string, options?: CountOptions & {
168
+ timeout?: number;
169
+ }): Promise<NoEmail>;
140
170
  checkDelivery(address: string): Promise<DeliveryStatus>;
141
171
  variants(address: string): Promise<Variants>;
142
172
  setPassword(address: string, options: {
package/dist/index.js CHANGED
@@ -22,6 +22,19 @@ export class ProxyMailQAError extends Error {
22
22
  }
23
23
  }
24
24
  const TIMED_OUT = /^No (code|link) arrived/;
25
+ function countQuery(options, extra = {}) {
26
+ const query = new URLSearchParams(extra);
27
+ if (options.since !== undefined)
28
+ query.set('since', new Date(options.since).toISOString());
29
+ if (options.service)
30
+ query.set('service', options.service);
31
+ if (options.type)
32
+ query.set('type', options.type);
33
+ const subtype = [options.subtype ?? []].flat().join(',');
34
+ if (subtype)
35
+ query.set('subtype', subtype);
36
+ return query.size ? `?${query}` : '';
37
+ }
25
38
  const MAX_WAIT_SECONDS = 30;
26
39
  export class ProxyMailQA {
27
40
  apiKey;
@@ -107,6 +120,32 @@ export class ProxyMailQA {
107
120
  query.set('limit', String(options.limit));
108
121
  return this.request('GET', `/addresses/${encodeURIComponent(address)}/messages${query.size ? `?${query}` : ''}`);
109
122
  }
123
+ // How many emails reached the address (since a time, from a service, with a
124
+ // code or link), each summarised without its content. Doesn't wait: count
125
+ // after the wait for the first email returns, so a duplicate has had time
126
+ // to arrive. Without since, every email the address has received.
127
+ countEmails(address, options = {}) {
128
+ return this.request('GET', `/addresses/${encodeURIComponent(address)}/count${countQuery(options)}`);
129
+ }
130
+ // Resolves when no matching email arrives within timeout seconds (default
131
+ // 30; longer repeats the request), for checks such as "an unsubscribed user
132
+ // gets nothing". Throws ProxyMailQAError (status 409, code email_arrived)
133
+ // as soon as one does. Pass since as the time of the action, so an email
134
+ // that came before the call still counts; without it, from now.
135
+ async expectNoEmail(address, options = {}) {
136
+ const deadline = Date.now() + (options.timeout ?? MAX_WAIT_SECONDS) * 1000;
137
+ let since = options.since;
138
+ for (;;) {
139
+ const left = Math.max(0, Math.min(MAX_WAIT_SECONDS, Math.ceil((deadline - Date.now()) / 1000)));
140
+ const query = countQuery({ ...options, since }, { timeout: String(left) });
141
+ const result = await this.request('GET', `/addresses/${encodeURIComponent(address)}/none${query}`);
142
+ // The server's since, so later requests watch from the same moment
143
+ // whatever this machine's clock says.
144
+ since = result.since;
145
+ if (Date.now() >= deadline - 500)
146
+ return { address: result.address, since: result.since, until: result.until };
147
+ }
148
+ }
110
149
  // What reached the address and what was refused, without waiting: for when
111
150
  // a wait comes back empty.
112
151
  checkDelivery(address) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "proxymail-qa",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Disposable test inboxes for Playwright, Cypress and scripts: create an address, then wait for its verification code or link.",
5
5
  "license": "MIT",
6
6
  "author": "Proxy Mail QA <hello@proxymail.qa> (https://proxymail.qa)",