UNPKG

cypress-mailosaur

Version:

Extends Cypress' cy commands that let you integrate email and SMS testing into your continuous integration process.

478 lines (477 loc) 20.5 kB
"use strict"; /* eslint-disable class-methods-use-this */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ResultEnum = void 0; const request_1 = __importDefault(require("./request")); /** * The result of a deliverability check */ var ResultEnum; (function (ResultEnum) { /** * The check had a positive result */ ResultEnum[ResultEnum["Pass"] = 0] = "Pass"; /** * The check was acceptable but could be improved */ ResultEnum[ResultEnum["Warning"] = 1] = "Warning"; /** * The check had a negative result */ ResultEnum[ResultEnum["Fail"] = 2] = "Fail"; /** * The check was inconclusive due to a timeout */ ResultEnum[ResultEnum["Timeout"] = 3] = "Timeout"; })(ResultEnum || (exports.ResultEnum = ResultEnum = {})); class MailosaurCommands { static get cypressCommands() { return [ 'mailosaurSetApiKey', 'mailosaurListServers', 'mailosaurCreateServer', 'mailosaurGetServer', 'mailosaurGetServerPassword', 'mailosaurUpdateServer', 'mailosaurDeleteServer', 'mailosaurListMessages', 'mailosaurCreateMessage', 'mailosaurForwardMessage', 'mailosaurReplyToMessage', 'mailosaurGetMessage', 'mailosaurGetMessageById', 'mailosaurSearchMessages', 'mailosaurGetMessagesBySubject', 'mailosaurGetMessagesByBody', 'mailosaurGetMessagesBySentFrom', 'mailosaurGetMessagesBySentTo', 'mailosaurDeleteMessage', 'mailosaurDeleteAllMessages', 'mailosaurDownloadAttachment', 'mailosaurDownloadMessage', 'mailosaurGetSpamAnalysis', 'mailosaurGetDeliverabilityReport', 'mailosaurGenerateEmailAddress', 'mailosaurGetUsageLimits', 'mailosaurGetUsageTransactions', 'mailosaurListDevices', 'mailosaurCreateDevice', 'mailosaurGetDeviceOtp', 'mailosaurDeleteDevice', 'mailosaurListPreviewEmailClients', 'mailosaurGenerateEmailPreviews', 'mailosaurDownloadPreview', ]; } constructor() { this._request = null; } init() { if (this._request) { return cy.wrap(this._request); } return cy .env(['MAILOSAUR_API_KEY', 'MAILOSAUR_BASE_URL']) .then(({ MAILOSAUR_API_KEY: apiKey, MAILOSAUR_BASE_URL: baseUrl, }) => { this._request = new request_1.default({ apiKey, baseUrl }); return this._request; }); } mailosaurSetApiKey(apiKey) { return cy .env(['MAILOSAUR_BASE_URL']) .then(({ MAILOSAUR_BASE_URL: baseUrl }) => { this._request = new request_1.default({ apiKey, baseUrl }); }); } /** * Returns a list of your virtual servers. Servers are returned sorted in alphabetical order. */ mailosaurListServers() { return this.init().then((req) => req.get('api/servers')); } /** * Creates a new virtual server. * @param options Options used to create a new Mailosaur server. */ mailosaurCreateServer(options) { return this.init().then((req) => req.post('api/servers', options)); } /** * Retrieves the detail for a single server. * @param serverId The unique identifier of the server. */ mailosaurGetServer(serverId) { return this.init().then((req) => req.get(`api/servers/${serverId}`)); } /** * Retrieves the password for a server. This password can be used for SMTP, POP3, and IMAP connectivity. * @param serverId The unique identifier of the server. */ mailosaurGetServerPassword(serverId) { return this.init().then((req) => req .get(`api/servers/${serverId}/password`) .then((result) => result.value)); } /** * Updates the attributes of a server. * @param server The updated server. */ mailosaurUpdateServer(server = {}) { return this.init().then((req) => req.put(`api/servers/${server.id}`, server)); } /** * Permanently delete a server. This will also delete all messages, associated attachments, etc. within the server. This operation cannot be undone. * @param serverId The unique identifier of the server. */ mailosaurDeleteServer(serverId) { return this.init().then((req) => req.del(`api/servers/${serverId}`)); } /** * Permenantly delete all messages within a server. * @param serverId The unique identifier of the server. */ mailosaurDeleteAllMessages(serverId) { return this.init().then((req) => req.del(`api/messages?server=${serverId}`)); } /** * Returns a list of your messages in summary form. The summaries are returned sorted by received date, with the most recently-received messages appearing first. * @param serverId The unique identifier of the required server. * @param options Message listing options. */ mailosaurListMessages(serverId, options = {}) { return this.init().then((req) => { const qs = { server: serverId, page: options.page, itemsPerPage: options.itemsPerPage, receivedAfter: options.receivedAfter, dir: options.dir, }; return req.get('api/messages', { qs }); }); } /** * Creates a new message that can be sent to a verified email address. This is useful * in scenarios where you want an email to trigger a workflow in your product. * @param serverId The unique identifier of the required server. * @param options Options to use when creating a new message. */ mailosaurCreateMessage(serverId, options) { return this.init().then((req) => req.post(`api/messages?server=${serverId}`, options)); } /** * Forwards the specified email to a verified email address. * @param messageId The unique identifier of the message to be forwarded. * @param options Options to use when forwarding a message. */ mailosaurForwardMessage(messageId, options) { return this.init().then((req) => req.post(`api/messages/${messageId}/forward`, options)); } /** * Sends a reply to the specified message. This is useful for when simulating a user replying to one of your email or SMS messages. * @param messageId The unique identifier of the message to be forwarded. * @param options Options to use when replying to a message. */ mailosaurReplyToMessage(messageId, options) { return this.init().then((req) => req.post(`api/messages/${messageId}/reply`, options)); } /** * Waits for a message to be found. Returns as soon as a message matching the specified search criteria is found. * **Recommended:** This is the most efficient method of looking up a message, therefore we recommend using it wherever possible. * @param serverId The unique identifier of the containing server. * @param criteria The criteria with which to find messages during a search. * @param options Search options. */ mailosaurGetMessage(serverId, criteria = {}, options = {}) { // Only return 1 result options.page = 0; options.itemsPerPage = 1; // Default timeout to 10s options.timeout = options.timeout || 10000; // Default receivedAfter to 1h options.receivedAfter = options.receivedAfter || new Date(Date.now() - 3600000); return cy .mailosaurSearchMessages(serverId, criteria, options) .then((result) => { var _a; return cy.mailosaurGetMessageById((_a = result.items) === null || _a === void 0 ? void 0 : _a[0].id); }); } /** * Retrieves the detail for a single message. Must be used in conjunction with either list or * search in order to get the unique identifier for the required message. * @param messageId The unique identifier of the message to be retrieved. */ mailosaurGetMessageById(messageId) { return this.init().then((req) => req.get(`api/messages/${messageId}`)); } /** * Returns a list of messages matching the specified search criteria, in summary form. * The messages are returned sorted by received date, with the most recently-received messages appearing first. * @param serverId The unique identifier of the server to search. * @param searchCriteria The criteria with which to find messages during a search. * @param options Search options. */ mailosaurSearchMessages(serverId, searchCriteria = {}, options = {}) { return this.init().then((req) => { let pollCount = 0; const startTime = Date.now(); const qs = { server: serverId, page: options.page, itemsPerPage: options.itemsPerPage, receivedAfter: options.receivedAfter, dir: options.dir, }; if (!Number.isInteger(options.timeout)) { options.timeout = 0; } if (typeof options.errorOnTimeout !== 'boolean') { options.errorOnTimeout = true; } const fn = (resolve, reject) => () => { const reqOptions = req.buildOptions('POST', 'api/messages/search'); reqOptions.qs = qs; reqOptions.json = searchCriteria; return Cypress.backend('http:request', reqOptions) .timeout(10000) .then(req.getResponseHandler(true)) .then((result) => { var _a; const { body, headers } = result; if (options.timeout && !((_a = body.items) === null || _a === void 0 ? void 0 : _a.length)) { const delayPattern = (headers['x-ms-delay'] || '1000') .split(',') .map((x) => parseInt(x, 10)); const delay = pollCount >= delayPattern.length ? delayPattern[delayPattern.length - 1] : delayPattern[pollCount]; pollCount += 1; // Stop if timeout will be exceeded if (Date.now() - startTime + delay > (options.timeout || 0)) { return options.errorOnTimeout === false ? resolve(body) : reject(new Error('No matching messages found in time. By default, only messages received in the last hour are checked ' + `(use receivedAfter to override this). The search criteria used for this query was ` + `[${JSON.stringify(searchCriteria)}] which timed out after ${options.timeout}ms`)); } return setTimeout(fn(resolve, reject), delay); } return resolve(body); }); }; return cy.wrap(new Cypress.Promise((resolve, reject) => { fn(resolve, reject)(); }), { log: false, timeout: (options.timeout || 0) + 10000, }); }); } /** * Returns a list of messages matching the specified subject, in summary form. * The messages are returned sorted by received date, with the most recently-received messages appearing first. * @param serverId The unique identifier of the server to search. * @param subject The value to seek within the subject line of a target email. */ mailosaurGetMessagesBySubject(serverId, subject) { return cy.mailosaurSearchMessages(serverId, { subject, }); } /** * Returns a list of messages matching the specified body, in summary form. * The messages are returned sorted by received date, with the most recently-received messages appearing first. * @param serverId The unique identifier of the server to search. * @param body The value to seek within the body of the target message. */ mailosaurGetMessagesByBody(serverId, body) { return cy.mailosaurSearchMessages(serverId, { body, }); } /** * Returns a list of messages matching the specified sender, in summary form. * The messages are returned sorted by received date, with the most recently-received messages appearing first. * @param serverId The unique identifier of the server to search. * @param sentFrom The full email address (or phone number for SMS) from which the target message was sent. */ mailosaurGetMessagesBySentFrom(serverId, sentFrom) { return cy.mailosaurSearchMessages(serverId, { sentFrom, }); } /** * Returns a list of messages matching the specified recipient, in summary form. * The messages are returned sorted by received date, with the most recently-received messages appearing first. * @param serverId The unique identifier of the server to search. * @param sentTo The full email address (or phone number for SMS) to which the target message was sent. */ mailosaurGetMessagesBySentTo(serverId, sentTo) { return cy.mailosaurSearchMessages(serverId, { sentTo, }); } /** * Downloads a single attachment. * @param attachmentId The identifier for the required attachment. */ mailosaurDownloadAttachment(attachmentId) { return this.init().then((req) => req.get(`api/files/attachments/${attachmentId}`, { encoding: 'binary' })); } /** * Downloads an EML file representing the specified email. * @param messageId The identifier for the required message. */ mailosaurDownloadMessage(messageId) { return this.init().then((req) => req.get(`api/files/email/${messageId}`)); } /** * Permanently deletes a message. Also deletes any attachments related to the message. This operation cannot be undone. * @param messageId The identifier for the message. */ mailosaurDeleteMessage(messageId) { return this.init().then((req) => req.del(`api/messages/${messageId}`)); } /** * Perform a spam analysis of an email. * @param messageId The identifier of the message to be analyzed. */ mailosaurGetSpamAnalysis(messageId) { return this.init().then((req) => req.get(`api/analysis/spam/${messageId}`)); } /** * Perform a deliverability report of an email. * @param messageId The identifier of the message to be analyzed. */ mailosaurGetDeliverabilityReport(messageId) { return this.init().then((req) => req.get(`api/analysis/deliverability/${messageId}`)); } /** * Generates a random email address by appending a random string in front of the server's * domain name. * @param serverId The identifier of the server. */ mailosaurGenerateEmailAddress(serverId) { return cy .env(['MAILOSAUR_SMTP_HOST']) .then(({ MAILOSAUR_SMTP_HOST: host }) => { const actualHost = host || 'mailosaur.net'; const random = (Math.random() + 1).toString(36).substring(7); return cy.wrap(`${random}@${serverId}.${actualHost}`); }); } /** * Retrieve account usage limits. Details the current limits and usage for your account. * This endpoint requires authentication with an account-level API key. */ mailosaurGetUsageLimits() { return this.init().then((req) => req.get('api/usage/limits')); } /** * Retrieves the last 31 days of transactional usage. * This endpoint requires authentication with an account-level API key. */ mailosaurGetUsageTransactions() { return this.init().then((req) => req.get('api/usage/transactions')); } /** * Returns a list of your virtual security devices. */ mailosaurListDevices() { return this.init().then((req) => req.get('api/devices')); } /** * Creates a new virtual security device. * @param options Options used to create a new Mailosaur virtual security device. */ mailosaurCreateDevice(options) { return this.init().then((req) => req.post('api/devices', options)); } /** * Retrieves the current one-time password for a saved device, or given base32-encoded shared secret. * @param query Either the unique identifier of the device, or a base32-encoded shared secret. */ mailosaurGetDeviceOtp(query) { return this.init().then((req) => { if (!query || query.indexOf('-') > -1) { return req.get(`api/devices/${query}/otp`); } return req.post('api/devices/otp', { sharedSecret: query, }); }); } /** * Permanently delete a device. This operation cannot be undone. * @param deviceId The unique identifier of the device. */ mailosaurDeleteDevice(deviceId) { return this.init().then((req) => req.del(`api/devices/${deviceId}`)); } /** * List all email clients that can be used to generate email previews. */ mailosaurListPreviewEmailClients() { return this.init().then((req) => req.get('api/screenshots/clients')); } /** * Generates screenshots of an email rendered in the specified email clients. * @param messageId The identifier of the email to preview. * @param options The options with which to generate previews. */ mailosaurGenerateEmailPreviews(messageId, options) { return this.init().then((req) => req.post(`api/messages/${messageId}/screenshots`, options)); } /** * Downloads a screenshot of your email rendered in a real email client. Simply supply * the unique identifier for the required preview. * @param previewId The identifier of the email preview to be downloaded. */ mailosaurDownloadPreview(previewId) { return this.init().then((req) => { const timeout = 120000; let pollCount = 0; const startTime = Date.now(); const fn = (resolve, reject) => () => { const reqOptions = req.buildOptions('GET', `api/files/screenshots/${previewId}`); reqOptions.encoding = 'binary'; return Cypress.backend('http:request', reqOptions) .timeout(timeout) .then(req.getResponseHandler(true)) .then((result) => { const { body, headers, status } = result; if (status === 200) { return resolve(body); } if (status !== 202) { return reject(new Error(`Failed to download preview. Status code: ${status}`)); } const delayPattern = (headers['x-ms-delay'] || '1000') .split(',') .map((x) => parseInt(x, 10)); const delay = pollCount >= delayPattern.length ? delayPattern[delayPattern.length - 1] : delayPattern[pollCount]; pollCount += 1; // Stop if timeout will be exceeded if (Date.now() - startTime + delay > timeout) { return reject(new Error(`An email preview was not generated in time. The email client may not be available, or the preview ID ` + `[${previewId}] may be incorrect.`)); } return setTimeout(fn(resolve, reject), delay); }); }; return cy.wrap(new Cypress.Promise((resolve, reject) => { fn(resolve, reject)(); }), { log: false, timeout: timeout + 10000, }); }); } } exports.default = MailosaurCommands;