refactor: added Mailosaur to manage sms
This commit is contained in:
parent
bc6e1bc12e
commit
e2a59a566f
@ -1,3 +1,6 @@
|
||||
{
|
||||
"baseUrl": "https://app.post-prod.lifen.fr"
|
||||
"baseUrl": "https://app.post-prod.lifen.fr",
|
||||
"env": {
|
||||
"MAILOSAUR_API_KEY": "your-key-here"
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
/// <reference types="cypress" />
|
||||
context('The login page', () => {
|
||||
|
||||
describe('Test the login page', () => {
|
||||
describe.skip('Test the login page', () => {
|
||||
|
||||
it('Access the webpage', function() {
|
||||
cy.visit('/');
|
||||
cy.visit('/login');
|
||||
cy.get('#email').should("have.attr", "type", "email");
|
||||
cy.get('#password').should("have.attr", "type", "password");
|
||||
//cy.get('#password').type(mdp);
|
||||
});
|
||||
|
||||
it('Log an invalid email', function() {
|
||||
cy.visit('/');
|
||||
cy.visit('/login');
|
||||
cy.get('#email').type("not an email");
|
||||
cy.get('#password').type("somepasseword {enter}");
|
||||
cy.url().should('include', 'login?');
|
||||
});
|
||||
|
||||
it('Log an unexisting user', function() {
|
||||
cy.visit('/');
|
||||
cy.visit('/login');
|
||||
cy.get('#email').type("toto@yopmail.com");
|
||||
cy.get('#password').type("somepasseword {enter}");
|
||||
cy.get('#error-message').should("have.class", "alert alert-danger").should("be.visible");
|
||||
@ -28,9 +28,17 @@ context('The login page', () => {
|
||||
|
||||
describe("It send an SMS", function() {
|
||||
it('Log the candidate user', function(){
|
||||
cy.visit('/login');
|
||||
cy.visit('/');
|
||||
cy.get('#email').type("candidature-qa@example.org");
|
||||
cy.get('#password').type("kHwWawhH5ADNuFb");
|
||||
cy.get('#continueButton').click();
|
||||
|
||||
cy.mailosaurGetMessage(serverId, {
|
||||
sentTo: smsNumber
|
||||
}).as('sms');
|
||||
|
||||
cy.get('#challenge_mfa_form_candidate_otp').type('@sms');
|
||||
cy.get('#validateButton').click();
|
||||
|
||||
});
|
||||
});
|
||||
|
@ -23,3 +23,4 @@
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
import 'cypress-mailosaur';
|
21
node_modules/cypress-mailosaur/LICENSE
generated
vendored
Normal file
21
node_modules/cypress-mailosaur/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Mailosaur Ltd (https://mailosaur.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
162
node_modules/cypress-mailosaur/README.md
generated
vendored
Normal file
162
node_modules/cypress-mailosaur/README.md
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
# Mailosaur Cypress Commands
|
||||
|
||||
[](https://github.com/mailosaur/cypress-mailosaur/actions)
|
||||
|
||||
## Test email and SMS messages with Cypress
|
||||
|
||||
Using Cypress and Mailosaur together you can:
|
||||
- Test email, with unlimited test email addresses
|
||||
- Test SMS messages
|
||||
- Capture emails with your very own fake SMTP servers
|
||||
|
||||
## What is Mailosaur?
|
||||
|
||||
[Mailosaur](https://mailosaur.com) is a service that lets you automate email testing (e.g. email verification, password resets, etc.) and SMS testing (e.g. one-time passwords).
|
||||
|
||||
Mailosaur also provides dummy SMTP servers to test with; allowing you to catch email in staging environments - preventing email being sent to customers by mistake.
|
||||
|
||||
## How do I test email with Cypress?
|
||||
|
||||
Follow these steps to start testing email with Cypress:
|
||||
|
||||
### Step 1 - Installation
|
||||
|
||||
Install the Mailosaur commands via `npm`:
|
||||
|
||||
```sh
|
||||
npm install cypress-mailosaur --save-dev
|
||||
```
|
||||
|
||||
Once downloaded, add the following line to `cypress/support/index.js` to import the commands into your Cypress project:
|
||||
|
||||
```js
|
||||
require('cypress-mailosaur');
|
||||
```
|
||||
|
||||
### Step 2 - API Authentication
|
||||
|
||||
Mailosaur commands need your Mailosaur API key to work. You can learn about [managing API keys here](https://mailosaur.com/docs/managing-your-account/api-keys/).
|
||||
|
||||
#### Option 1: Add API key to `cypress.json`
|
||||
|
||||
```
|
||||
{
|
||||
"env": {
|
||||
"MAILOSAUR_API_KEY": "your-key-here"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Option 2: Add API key to a `cypress.env.json` file
|
||||
|
||||
You can create your own `cypress.env.json` file that Cypress will automatically check. This is useful because if you add `cypress.env.json` to your `.gitignore` file, the values in here can be different for each developer machine.
|
||||
|
||||
```
|
||||
{
|
||||
"MAILOSAUR_API_KEY": "your-key-here"
|
||||
}
|
||||
```
|
||||
|
||||
#### Option 3: Set API key via a system environment variable
|
||||
|
||||
To set the environment variable on your machine, it needs to be prefixed with either `CYPRESS_` or `cypress_`.
|
||||
|
||||
```sh
|
||||
export CYPRESS_MAILOSAUR_API_KEY=your-key-here
|
||||
```
|
||||
|
||||
### Step 3 - Write your email test
|
||||
|
||||
For this example, we'll navigate to a password reset page, request a new password link (sent via email), and get that email.
|
||||
|
||||
Create a new test spec:
|
||||
|
||||
```sh
|
||||
touch cypress/integration/password-reset.spec.js
|
||||
```
|
||||
|
||||
Now edit the file to something like this:
|
||||
|
||||
```js
|
||||
describe('Password reset', () => {
|
||||
const serverId = 'abcd1234'
|
||||
const serverDomain = 'abcd1234.mailosaur.net'
|
||||
const emailAddress = 'password-reset@' + serverDomain
|
||||
|
||||
it('Makes a Password Reset request', () => {
|
||||
cy.visit('https://github.com/password_reset')
|
||||
cy.title().should('equal', 'Forgot your password?')
|
||||
cy.get('#email_field').type(emailAddress)
|
||||
})
|
||||
|
||||
it('Gets Password Reset email from Mailosaur', () => {
|
||||
cy.mailosaurGetMessage(serverId, {
|
||||
sentTo: emailAddress
|
||||
}).then(email => {
|
||||
expect(email.subject).to.equal('Reset your password');
|
||||
passwordResetLink = email.text.links[0].href;
|
||||
})
|
||||
})
|
||||
|
||||
it('Follows the link from the email', () => {
|
||||
const validPassword = 'delighted cheese jolly cloud'
|
||||
|
||||
cy.visit(passwordResetLink)
|
||||
cy.title().should('contain', 'Change your password')
|
||||
cy.get('#password').type(validPassword)
|
||||
cy.get('#password_confirmation').type(validPassword)
|
||||
cy.get('form').submit()
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Step 4 - Write further test cases
|
||||
|
||||
You can test pretty much anything with Mailosaur and Cypress, including:
|
||||
|
||||
- [Test the text content of an email](https://mailosaur.com/docs/test-cases/text-content/)
|
||||
- [Test links within an email](https://mailosaur.com/docs/test-cases/links/)
|
||||
- [Working with email attachments](https://mailosaur.com/docs/test-cases/attachments/)
|
||||
- [Handling images and web beacons](https://mailosaur.com/docs/test-cases/images/)
|
||||
- [Perform a spam test](https://mailosaur.com/docs/test-cases/spam/)
|
||||
|
||||
For more information, check out the full [Mailosaur docs](https://mailosaur.com/docs/frameworks-and-tools/cypress/) for the most up-to-date guides and troubleshooting tips.
|
||||
|
||||
## How do I test SMS with Cypress?
|
||||
|
||||
Mailosaur Team, Premium, and Ultimate customers can perform SMS tests with Cypress, whilst Trial account users can just ask support to enable this feature to try it out!
|
||||
|
||||
SMS testing works in just the same way as email testing above. However rather than dealing with email addresses, you search using phone numbers instead. For example:
|
||||
|
||||
```js
|
||||
cy.mailosaurGetMessage(serverId, {
|
||||
sentTo: '447555111222'
|
||||
}).then(sms => {
|
||||
expect(sms.text.body).to.equal('Your OTP code is: 123456')
|
||||
})
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
Install all development dependencies:
|
||||
|
||||
```sh
|
||||
npm i
|
||||
```
|
||||
|
||||
The test suite requires the following environment variables to be set:
|
||||
|
||||
```sh
|
||||
export CYPRESS_MAILOSAUR_API_KEY=your_api_key
|
||||
export CYPRESS_MAILOSAUR_SERVER=server_id
|
||||
```
|
||||
|
||||
Run all tests:
|
||||
|
||||
```sh
|
||||
npm test
|
||||
```
|
||||
|
||||
## Contacting us
|
||||
|
||||
You can get us at [support@mailosaur.com](mailto:support@mailosaur.com)
|
5
node_modules/cypress-mailosaur/index.js
generated
vendored
Normal file
5
node_modules/cypress-mailosaur/index.js
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/* global Cypress */
|
||||
|
||||
const { register } = require("./src/register");
|
||||
|
||||
register(Cypress);
|
118
node_modules/cypress-mailosaur/package.json
generated
vendored
Normal file
118
node_modules/cypress-mailosaur/package.json
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
{
|
||||
"_from": "cypress-mailosaur",
|
||||
"_id": "cypress-mailosaur@2.3.3",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-Xo3NqXm0kxdozwAdpCgv2bRLgZyMuGaQS7CK7+e8oFQWFaG/e+zamg8KSbi/n2ROSjm5CXh0WFNMHgBYZ8wZjg==",
|
||||
"_location": "/cypress-mailosaur",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"registry": true,
|
||||
"raw": "cypress-mailosaur",
|
||||
"name": "cypress-mailosaur",
|
||||
"escapedName": "cypress-mailosaur",
|
||||
"rawSpec": "",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#DEV:/",
|
||||
"#USER"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/cypress-mailosaur/-/cypress-mailosaur-2.3.3.tgz",
|
||||
"_shasum": "f7d40905e29f042416e3f504e449b8a320405018",
|
||||
"_spec": "cypress-mailosaur",
|
||||
"_where": "/home/simon/Documents/lifen-autotest",
|
||||
"author": {
|
||||
"name": "Mailosaur Ltd"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/mailosaur/mailosaur-node/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "Extends Cypress' cy commands that let you integrate email and SMS testing into your continuous integration process.",
|
||||
"devDependencies": {
|
||||
"@types/node": "^15.0.3",
|
||||
"babel-eslint": "10.1.0",
|
||||
"coveralls": "3.0.9",
|
||||
"eslint": "6.8.0",
|
||||
"eslint-config-airbnb-base": "^14.1.0",
|
||||
"eslint-plugin-import": "^2.20.1",
|
||||
"eslint-plugin-react": "^7.20.0",
|
||||
"jest": "25.4.0",
|
||||
"sinon": "9.0.2",
|
||||
"typescript": "^4.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= v10.0.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"airbnb-base"
|
||||
],
|
||||
"env": {
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"globals": {
|
||||
"Cypress": true,
|
||||
"cy": true,
|
||||
"assert": true
|
||||
},
|
||||
"rules": {
|
||||
"quotes": [
|
||||
2,
|
||||
"single",
|
||||
{
|
||||
"allowTemplateLiterals": true
|
||||
}
|
||||
],
|
||||
"consistent-return": 0,
|
||||
"comma-dangle": 0,
|
||||
"max-len": 0,
|
||||
"no-shadow": 0,
|
||||
"class-methods-use-this": 0,
|
||||
"linebreak-style": 0,
|
||||
"arrow-parens": 0,
|
||||
"operator-linebreak": 0,
|
||||
"object-curly-newline": 0,
|
||||
"implicit-arrow-linebreak": 0,
|
||||
"no-else-return": 0,
|
||||
"indent": 0,
|
||||
"lines-between-class-members": 0
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"homepage": "https://github.com/mailosaur/cypress-mailosaur#readme",
|
||||
"keywords": [
|
||||
"cypress",
|
||||
"mailosaur",
|
||||
"email",
|
||||
"sms",
|
||||
"testing",
|
||||
"automation",
|
||||
"testing-tools"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"name": "cypress-mailosaur",
|
||||
"peerDependencies": {
|
||||
"cypress": ">= 2.1.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mailosaur/cypress-mailosaur.git"
|
||||
},
|
||||
"scripts": {
|
||||
"coveralls": "cat ./coverage/lcov.info | coveralls",
|
||||
"lint": "eslint src test/react-app/src test/react-app/cypress",
|
||||
"test": "npm run tsc && cd test/react-app && npm run test:ci",
|
||||
"test:ci": "cd test/react-app && npm i && npm run test:ci",
|
||||
"tsc": "tsc src/mailosaurCommands.d.ts --types node"
|
||||
},
|
||||
"types": "src/mailosaurCommands.d.ts",
|
||||
"version": "2.3.3"
|
||||
}
|
408
node_modules/cypress-mailosaur/src/mailosaurCommands.d.ts
generated
vendored
Normal file
408
node_modules/cypress-mailosaur/src/mailosaurCommands.d.ts
generated
vendored
Normal file
@ -0,0 +1,408 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the SpamAssassinRule class.
|
||||
* @constructor
|
||||
* @member {number} [score]
|
||||
* @member {string} [rule]
|
||||
* @member {string} [description]
|
||||
*/
|
||||
export interface SpamAssassinRule {
|
||||
score?: number;
|
||||
rule?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the SpamFilterResults class.
|
||||
* @constructor
|
||||
* @member {array} [spamAssassin]
|
||||
*/
|
||||
export interface SpamFilterResults {
|
||||
spamAssassin?: SpamAssassinRule[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the SpamAnalysisResult class.
|
||||
* @constructor
|
||||
* @member {object} [spamFilterResults]
|
||||
* @member {array} [spamFilterResults.spamAssassin]
|
||||
* @member {number} [score]
|
||||
*/
|
||||
export interface SpamAnalysisResult {
|
||||
spamFilterResults?: SpamFilterResults;
|
||||
score?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the MessageAddress class.
|
||||
* @constructor
|
||||
* @member {string} [name] Display name, if one is specified.
|
||||
* @member {string} [email] Email address (applicable to email messages).
|
||||
* @member {string} [phone] Phone number (applicable to SMS messages).
|
||||
*/
|
||||
export interface MessageAddress {
|
||||
name?: string;
|
||||
email?: string;
|
||||
phone?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the Link class.
|
||||
* @constructor
|
||||
* @member {string} [href]
|
||||
* @member {string} [text]
|
||||
*/
|
||||
export interface Link {
|
||||
href?: string;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the Image class.
|
||||
* @constructor
|
||||
* @member {string} [src]
|
||||
* @member {string} [alt]
|
||||
*/
|
||||
export interface Image {
|
||||
src?: string;
|
||||
alt?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the MessageContent class.
|
||||
* @constructor
|
||||
* @member {array} [links]
|
||||
* @member {array} [images]
|
||||
* @member {string} [body]
|
||||
*/
|
||||
export interface MessageContent {
|
||||
links?: Link[];
|
||||
images?: Image[];
|
||||
body?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the Attachment class.
|
||||
* @constructor
|
||||
* @member {uuid} id
|
||||
* @member {string} [contentType]
|
||||
* @member {string} [fileName]
|
||||
* @member {string} [contentId]
|
||||
* @member {number} [length]
|
||||
* @member {string} [url]
|
||||
*/
|
||||
export interface Attachment {
|
||||
id: string;
|
||||
contentType?: string;
|
||||
fileName?: string;
|
||||
contentId?: string;
|
||||
length?: number;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the MessageHeader class.
|
||||
* @constructor
|
||||
* @member {string} [field] Header key.
|
||||
* @member {string} [value] Header value.
|
||||
*/
|
||||
export interface MessageHeader {
|
||||
field?: string;
|
||||
value?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the Metadata class.
|
||||
* @constructor
|
||||
* Advanced use case content related to the message.
|
||||
*
|
||||
* @member {array} [headers] Email headers.
|
||||
*/
|
||||
export interface Metadata {
|
||||
headers?: MessageHeader[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the Message class.
|
||||
* @constructor
|
||||
* @member {uuid} [id] Unique identifier for the message.
|
||||
* @member {array} [from] The sender of the message.
|
||||
* @member {array} [to] The message’s recipient.
|
||||
* @member {array} [cc] Carbon-copied recipients for email messages.
|
||||
* @member {array} [bcc] Blind carbon-copied recipients for email messages.
|
||||
* @member {date} [received] The datetime that this message was received by
|
||||
* Mailosaur.
|
||||
* @member {string} [subject] The message’s subject.
|
||||
* @member {object} [html] Message content that was sent in HTML format.
|
||||
* @member {array} [html.links]
|
||||
* @member {array} [html.images]
|
||||
* @member {string} [html.body]
|
||||
* @member {object} [text] Message content that was sent in plain text format.
|
||||
* @member {array} [text.links]
|
||||
* @member {array} [text.images]
|
||||
* @member {string} [text.body]
|
||||
* @member {array} [attachments] An array of attachment metadata for any
|
||||
* attached files.
|
||||
* @member {object} [metadata]
|
||||
* @member {array} [metadata.headers] Email headers.
|
||||
* @member {string} [server] Identifier for the server in which the message is
|
||||
* located.
|
||||
*/
|
||||
export interface Message {
|
||||
id?: string;
|
||||
from?: MessageAddress[];
|
||||
to?: MessageAddress[];
|
||||
cc?: MessageAddress[];
|
||||
bcc?: MessageAddress[];
|
||||
received?: Date;
|
||||
subject?: string;
|
||||
html?: MessageContent;
|
||||
text?: MessageContent;
|
||||
attachments?: Attachment[];
|
||||
metadata?: Metadata;
|
||||
server?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the MessageSummary class.
|
||||
* @constructor
|
||||
* @member {uuid} id
|
||||
* @member {string} [server]
|
||||
* @member {array} [rcpt]
|
||||
* @member {array} [from]
|
||||
* @member {array} [to]
|
||||
* @member {array} [cc]
|
||||
* @member {array} [bcc]
|
||||
* @member {date} [received]
|
||||
* @member {string} [subject]
|
||||
* @member {string} [summary]
|
||||
* @member {number} [attachments]
|
||||
*/
|
||||
export interface MessageSummary {
|
||||
id: string;
|
||||
server?: string;
|
||||
rcpt?: MessageAddress[];
|
||||
from?: MessageAddress[];
|
||||
to?: MessageAddress[];
|
||||
cc?: MessageAddress[];
|
||||
bcc?: MessageAddress[];
|
||||
received?: Date;
|
||||
subject?: string;
|
||||
summary?: string;
|
||||
attachments?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the MessageListResult class.
|
||||
* @constructor
|
||||
* The result of a message listing request.
|
||||
*
|
||||
* @member {array} [items] The individual summaries of each message forming the
|
||||
* result. Summaries are returned sorted by received date, with the most
|
||||
* recently-received messages appearing first.
|
||||
*/
|
||||
export interface MessageListResult {
|
||||
items?: MessageSummary[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the SearchCriteria class.
|
||||
* @constructor
|
||||
* @member {string} [sentFrom] The full email address from which the target email
|
||||
* was sent.
|
||||
* @member {string} [sentTo] The full email address to which the target email
|
||||
* was sent.
|
||||
* @member {string} [subject] The value to seek within the target email's
|
||||
* subject line.
|
||||
* @member {string} [body] The value to seek within the target email's HTML or
|
||||
* text body.
|
||||
* @member {string} [match] If set to ALL (default), then only results that match all
|
||||
* specified criteria will be returned. If set to ANY, results that match any of the
|
||||
* specified criteria will be returned.
|
||||
*/
|
||||
export interface SearchCriteria {
|
||||
sentFrom?: string;
|
||||
sentTo?: string;
|
||||
subject?: string;
|
||||
body?: string;
|
||||
match?: "ALL" | "ANY";
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the Server class.
|
||||
* @constructor
|
||||
* @member {string} [id] Unique identifier for the server. Used as username for
|
||||
* SMTP/POP3 authentication.
|
||||
* @member {string} [name] A name used to identify the server.
|
||||
* @member {array} [users] Users (excluding administrators) who have access to
|
||||
* the server.
|
||||
* @member {number} [messages] The number of messages currently in the server.
|
||||
*/
|
||||
export interface Server {
|
||||
id?: string;
|
||||
name?: string;
|
||||
users?: string[];
|
||||
messages?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the ServerListResult class.
|
||||
* @constructor
|
||||
* The result of a server listing request.
|
||||
*
|
||||
* @member {array} [items] The individual servers forming the result. Servers
|
||||
* are returned sorted by creation date, with the most recently-created server
|
||||
* appearing first.
|
||||
*/
|
||||
export interface ServerListResult {
|
||||
items?: Server[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the ServerCreateOptions class.
|
||||
* @constructor
|
||||
* @member {string} [name] A name used to identify the server.
|
||||
*/
|
||||
export interface ServerCreateOptions {
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface SearchOptions {
|
||||
timeout?: number,
|
||||
receivedAfter?: Date,
|
||||
page?: number,
|
||||
itemsPerPage?: number,
|
||||
suppressError?: boolean
|
||||
}
|
||||
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
/**
|
||||
* @summary List all servers
|
||||
*
|
||||
* Returns a list of your virtual SMTP servers. Servers are returned sorted in
|
||||
* alphabetical order.
|
||||
*
|
||||
*/
|
||||
mailosaurListServers(
|
||||
): Cypress.Chainable<ServerListResult>;
|
||||
|
||||
mailosaurCreateServer(
|
||||
options: ServerCreateOptions
|
||||
): Cypress.Chainable<Server>;
|
||||
|
||||
mailosaurGetServer(
|
||||
serverId: string
|
||||
): Cypress.Chainable<Server>;
|
||||
|
||||
mailosaurGetServerPassword(
|
||||
serverId: string
|
||||
): Cypress.Chainable<string>;
|
||||
|
||||
mailosaurUpdateServer(
|
||||
server: Server
|
||||
): Cypress.Chainable<Server>;
|
||||
|
||||
mailosaurDeleteServer(
|
||||
serverId: string
|
||||
): Cypress.Chainable<null>;
|
||||
|
||||
mailosaurDeleteAllMessages(
|
||||
serverId: string
|
||||
): Cypress.Chainable<null>;
|
||||
|
||||
mailosaurListMessages(
|
||||
serverId: string
|
||||
): Cypress.Chainable<MessageListResult>;
|
||||
|
||||
mailosaurCreateMessage(
|
||||
serverId: string
|
||||
): Cypress.Chainable<Message>;
|
||||
|
||||
mailosaurGetMessage(
|
||||
serverId: string,
|
||||
criteria: SearchCriteria,
|
||||
options?: SearchOptions
|
||||
): Cypress.Chainable<Message>;
|
||||
|
||||
mailosaurGetMessageById(
|
||||
messageId: string
|
||||
): Cypress.Chainable<Message>;
|
||||
|
||||
mailosaurSearchMessages(
|
||||
serverId: string,
|
||||
criteria: SearchCriteria,
|
||||
options?: SearchOptions
|
||||
): Cypress.Chainable<MessageListResult>;
|
||||
|
||||
mailosaurGetMessagesBySubject(
|
||||
serverId: string,
|
||||
subject: string
|
||||
): Cypress.Chainable<MessageListResult>;
|
||||
|
||||
mailosaurGetMessagesByBody(
|
||||
serverId: string,
|
||||
body: string
|
||||
): Cypress.Chainable<MessageListResult>;
|
||||
|
||||
mailosaurGetMessagesBySentFrom(
|
||||
serverId: string,
|
||||
sentFrom: string
|
||||
): Cypress.Chainable<MessageListResult>;
|
||||
|
||||
mailosaurGetMessagesBySentTo(
|
||||
serverId: string,
|
||||
sentTo: string
|
||||
): Cypress.Chainable<MessageListResult>;
|
||||
|
||||
mailosaurDownloadAttachment(
|
||||
attachmentId: string
|
||||
): Cypress.Chainable<Attachment>;
|
||||
|
||||
mailosaurDownloadMessage(
|
||||
messageId: string
|
||||
): Cypress.Chainable<string>;
|
||||
|
||||
mailosaurDeleteMessage(
|
||||
messageId: string
|
||||
): Cypress.Chainable<null>;
|
||||
|
||||
/**
|
||||
* @summary Perform a spam test
|
||||
*
|
||||
* Perform spam testing on the specified email
|
||||
*
|
||||
* @param {string} messageId The identifier of the email to be analyzed.
|
||||
*
|
||||
* @returns {Chainable<SpamAnalysisResult>}
|
||||
*/
|
||||
mailosaurGetSpamAnalysis(
|
||||
messageId: string
|
||||
): Chainable<SpamAnalysisResult>;
|
||||
|
||||
mailosaurGenerateEmailAddress(
|
||||
serverId: string
|
||||
): Cypress.Chainable<string>;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
210
node_modules/cypress-mailosaur/src/mailosaurCommands.js
generated
vendored
Normal file
210
node_modules/cypress-mailosaur/src/mailosaurCommands.js
generated
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
const Request = require('./request');
|
||||
|
||||
class MailosaurCommands {
|
||||
static get cypressCommands() {
|
||||
return [
|
||||
'mailosaurSetApiKey',
|
||||
'mailosaurListServers',
|
||||
'mailosaurCreateServer',
|
||||
'mailosaurGetServer',
|
||||
'mailosaurGetServerPassword',
|
||||
'mailosaurUpdateServer',
|
||||
'mailosaurDeleteServer',
|
||||
'mailosaurListMessages',
|
||||
'mailosaurCreateMessage',
|
||||
'mailosaurGetMessage',
|
||||
'mailosaurGetMessageById',
|
||||
'mailosaurSearchMessages',
|
||||
'mailosaurGetMessagesBySubject',
|
||||
'mailosaurGetMessagesByBody',
|
||||
'mailosaurGetMessagesBySentFrom',
|
||||
'mailosaurGetMessagesBySentTo',
|
||||
'mailosaurDeleteMessage',
|
||||
'mailosaurDeleteAllMessages',
|
||||
'mailosaurDownloadAttachment',
|
||||
'mailosaurDownloadMessage',
|
||||
'mailosaurGetSpamAnalysis',
|
||||
'mailosaurGenerateEmailAddress'
|
||||
];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
const defaultApiKey = Cypress.env('MAILOSAUR_API_KEY');
|
||||
this.mailosaurSetApiKey(defaultApiKey);
|
||||
}
|
||||
|
||||
mailosaurSetApiKey(apiKey) {
|
||||
this.request = new Request({ apiKey, baseUrl: Cypress.env('MAILOSAUR_BASE_URL') });
|
||||
}
|
||||
|
||||
mailosaurListServers() {
|
||||
return this.request.get(`api/servers`);
|
||||
}
|
||||
|
||||
mailosaurCreateServer(params) {
|
||||
return this.request.post(`api/servers`, params);
|
||||
}
|
||||
|
||||
mailosaurGetServer(serverId) {
|
||||
return this.request.get(`api/servers/${serverId}`);
|
||||
}
|
||||
|
||||
mailosaurGetServerPassword(serverId) {
|
||||
return this.request.get(`api/servers/${serverId}/password`)
|
||||
.then((result) => (result.value));
|
||||
}
|
||||
|
||||
mailosaurUpdateServer(server) {
|
||||
return this.request.put(`api/servers/${server.id}`, server);
|
||||
}
|
||||
|
||||
mailosaurDeleteServer(serverId) {
|
||||
return this.request.del(`api/servers/${serverId}`);
|
||||
}
|
||||
|
||||
mailosaurDeleteAllMessages(serverId) {
|
||||
return this.request.del(`api/messages?server=${serverId}`);
|
||||
}
|
||||
|
||||
mailosaurListMessages(serverId) {
|
||||
return this.request.get(`api/messages?server=${serverId}`);
|
||||
}
|
||||
|
||||
mailosaurCreateMessage(serverId) {
|
||||
return this.request.post(`api/messages?server=${serverId}`, {});
|
||||
}
|
||||
|
||||
mailosaurGetMessage(server, criteria, options = {}) {
|
||||
// Only return 1 result
|
||||
options.page = 0;
|
||||
options.itemsPerPage = 1;
|
||||
|
||||
// Default timeout to 10s
|
||||
options.timeout = options.timeout || 10000; // eslint-disable-line no-param-reassign
|
||||
|
||||
// Default receivedAfter to 1h
|
||||
options.receivedAfter = options.receivedAfter || new Date(Date.now() - 3600000); // eslint-disable-line no-param-reassign
|
||||
|
||||
return cy.mailosaurSearchMessages(server, criteria, options)
|
||||
.then((result) => (
|
||||
cy.mailosaurGetMessageById(result.items[0].id)
|
||||
));
|
||||
}
|
||||
|
||||
mailosaurGetMessageById(messageId) {
|
||||
return this.request.get(`api/messages/${messageId}`);
|
||||
}
|
||||
|
||||
mailosaurSearchMessages(serverId, searchCriteria, options = {}) {
|
||||
let pollCount = 0;
|
||||
const startTime = Date.now();
|
||||
|
||||
const qs = {
|
||||
server: serverId,
|
||||
page: options.page,
|
||||
itemsPerPage: options.itemsPerPage,
|
||||
receivedAfter: options.receivedAfter
|
||||
};
|
||||
|
||||
if (!Number.isInteger(options.timeout)) {
|
||||
options.timeout = 0; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
if (typeof options.errorOnTimeout !== 'boolean') {
|
||||
options.errorOnTimeout = true; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
const fn = (resolve, reject) => () => {
|
||||
const reqOptions = this.request.buildOptions('POST', `api/messages/search`);
|
||||
reqOptions.qs = qs;
|
||||
reqOptions.json = searchCriteria;
|
||||
|
||||
return Cypress.backend('http:request', reqOptions)
|
||||
.timeout(10000)
|
||||
.then((result) => {
|
||||
const { body, status, headers } = result;
|
||||
|
||||
switch (status) {
|
||||
case 200:
|
||||
break;
|
||||
case 400:
|
||||
return reject(new Error(JSON.stringify(result.body)));
|
||||
case 401:
|
||||
return reject(new Error('Cannot authenticate with Mailosaur (401). Please check your API key.'));
|
||||
default:
|
||||
return reject(new Error(`Status: ${status}, Result: ${JSON.stringify(result)}`));
|
||||
}
|
||||
|
||||
if (options.timeout && !body.items.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) {
|
||||
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).'));
|
||||
}
|
||||
|
||||
return setTimeout(fn(resolve, reject), delay);
|
||||
}
|
||||
|
||||
resolve(body);
|
||||
});
|
||||
};
|
||||
|
||||
cy.wrap(new Cypress.Promise((resolve, reject) => {
|
||||
fn(resolve, reject)();
|
||||
}), {
|
||||
log: false,
|
||||
timeout: options.timeout + 10000
|
||||
});
|
||||
}
|
||||
|
||||
mailosaurGetMessagesBySubject(serverId, subject) {
|
||||
return cy.mailosaurSearchMessages(serverId, { subject });
|
||||
}
|
||||
|
||||
mailosaurGetMessagesByBody(serverId, body) {
|
||||
return cy.mailosaurSearchMessages(serverId, { body });
|
||||
}
|
||||
|
||||
mailosaurGetMessagesBySentFrom(serverId, sentFrom) {
|
||||
return cy.mailosaurSearchMessages(serverId, { sentFrom });
|
||||
}
|
||||
|
||||
mailosaurGetMessagesBySentTo(serverId, sentTo) {
|
||||
return cy.mailosaurSearchMessages(serverId, { sentTo });
|
||||
}
|
||||
|
||||
mailosaurDownloadAttachment(attachmentId) {
|
||||
return this.request.get(`api/files/attachments/${attachmentId}`);
|
||||
}
|
||||
|
||||
mailosaurDownloadMessage(messageId) {
|
||||
return this.request.get(`api/files/email/${messageId}`);
|
||||
}
|
||||
|
||||
mailosaurDeleteMessage(messageId) {
|
||||
return this.request.del(`api/messages/${messageId}`);
|
||||
}
|
||||
|
||||
mailosaurGetSpamAnalysis(messageId) {
|
||||
return this.request.get(`api/analysis/spam/${messageId}`);
|
||||
}
|
||||
|
||||
mailosaurGenerateEmailAddress(serverId) {
|
||||
const host = Cypress.env('MAILOSAUR_SMTP_HOST') || 'mailosaur.net';
|
||||
const random = (Math.random() + 1).toString(36).substring(7);
|
||||
return cy.wrap(`${random}@${serverId}.${host}`);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MailosaurCommands;
|
15
node_modules/cypress-mailosaur/src/register.js
generated
vendored
Normal file
15
node_modules/cypress-mailosaur/src/register.js
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
const MailosaurCommands = require('./mailosaurCommands');
|
||||
|
||||
const register = (Cypress) => {
|
||||
const mailosaurCommands = new MailosaurCommands();
|
||||
MailosaurCommands.cypressCommands.forEach((commandName) => {
|
||||
Cypress.Commands.add(
|
||||
commandName,
|
||||
mailosaurCommands[commandName].bind(mailosaurCommands)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
register,
|
||||
};
|
56
node_modules/cypress-mailosaur/src/request.js
generated
vendored
Normal file
56
node_modules/cypress-mailosaur/src/request.js
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
const pkg = require('../package.json');
|
||||
|
||||
/* eslint-disable max-classes-per-file */
|
||||
class Request {
|
||||
constructor(options) {
|
||||
this.baseUrl = options.baseUrl || 'https://mailosaur.com/';
|
||||
this.apiKey = options.apiKey;
|
||||
const encodedKey = Buffer.from(`${this.apiKey}:`).toString('base64');
|
||||
this.headers = {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Basic ${encodedKey}`,
|
||||
'User-Agent': `cypress-mailosaur/${pkg.version}`
|
||||
};
|
||||
}
|
||||
|
||||
buildOptions(method, path) {
|
||||
if (!this.apiKey) {
|
||||
// CYPRESS_ prefix necessary per https://docs.cypress.io/guides/guides/environment-variables.html#Option-3-CYPRESS
|
||||
throw new Error('You must set the CYPRESS_MAILOSAUR_API_KEY environment variable to use the Mailosaur plugin.');
|
||||
}
|
||||
|
||||
return {
|
||||
method,
|
||||
url: `${this.baseUrl}${path}`,
|
||||
headers: {
|
||||
Accept: this.headers.Accept,
|
||||
Authorization: this.headers.Authorization,
|
||||
'User-Agent': this.headers['User-Agent']
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
request(method, path, body) {
|
||||
const options = this.buildOptions(method, path);
|
||||
options.body = body || undefined;
|
||||
return cy.request(options).its('body');
|
||||
}
|
||||
|
||||
get(path) {
|
||||
return this.request('GET', path);
|
||||
}
|
||||
|
||||
post(path, body) {
|
||||
return this.request('POST', path, body);
|
||||
}
|
||||
|
||||
put(path, body) {
|
||||
return this.request('PUT', path, body);
|
||||
}
|
||||
|
||||
del(path) {
|
||||
return this.request('DELETE', path);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Request;
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -2514,6 +2514,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"cypress-mailosaur": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/cypress-mailosaur/-/cypress-mailosaur-2.3.3.tgz",
|
||||
"integrity": "sha512-Xo3NqXm0kxdozwAdpCgv2bRLgZyMuGaQS7CK7+e8oFQWFaG/e+zamg8KSbi/n2ROSjm5CXh0WFNMHgBYZ8wZjg==",
|
||||
"dev": true
|
||||
},
|
||||
"d": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
|
||||
|
@ -7,7 +7,8 @@
|
||||
"cypress": "^8.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cypress-cucumber-preprocessor": "^4.2.0"
|
||||
"cypress-cucumber-preprocessor": "^4.2.0",
|
||||
"cypress-mailosaur": "^2.3.3"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "cypress open"
|
||||
|
Loading…
x
Reference in New Issue
Block a user