Skip to content

Commit

Permalink
Merge pull request #54 from NoriSte/feature/command-log
Browse files Browse the repository at this point in the history
Internal Cypress.log management
  • Loading branch information
NoriSte authored Oct 30, 2019
2 parents 2cfdb27 + 40a769a commit 2ea2765
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 141 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ script:
- fossa analyze
after_success:
- cd <SOURCE_DIR> && fossa test
- npm run semantic-release
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ Add the Cypress waiting power to virtually everything 🎉
[![NPM downloads](https://img.shields.io/npm/dw/cypress-wait-until?color=CB3836)](https://www.npmjs.com/package/cypress-wait-until)
<br />
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FNoriSte%2Fcypress-wait-until.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FNoriSte%2Fcypress-wait-until?ref=badge_shield)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FNoriSte%2Fcypress-wait-until.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FNoriSte%2Fcypress-wait-until?ref=badge_shield) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://badges.frapsoft.com/typescript/love/typescript.svg?v=101)](https://github.com/ellerbrock/typescript-badges/)
[![Open Source
Saturday](https://img.shields.io/badge/%E2%9D%A4%EF%B8%8F-open%20source%20saturday-F64060.svg)](https://www.meetup.com/it-IT/Open-Source-Saturday-Milano/)
Expand Down Expand Up @@ -128,11 +127,13 @@ A function that must return a truthy value when the wait is over.

Pass in an options object to change the default behavior of `cy.waitUntil()`.

Option | Default | Description
--- | --- | ---
`errorMsg` | `Timed out retrying` | The error message to write.
`timeout` | `5000` | Time to wait for the `checkFunction` to return a truthy value before throwing an error.
`interval` | `200` | Time to wait between the `checkFunction` invocations.
| Option | Default | Description |
| ------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `errorMsg` | `Timed out retrying` | The error message to write. |
| `timeout` | `5000` | Time to wait for the `checkFunction` to return a truthy value before throwing an error. |
| `interval` | `200` | Time to wait between the `checkFunction` invocations. |
| `description` | `waitUntil` | The name logged into the Cypress Test Runner. |
| `logger` | `Cypress.log` | A custom logger in place of the default [Cypress.log](https://docs.cypress.io/api/cypress-api/cypress-log.html). It's useful just for debugging purposes. |

<br />
<br />
Expand Down
255 changes: 162 additions & 93 deletions cypress/integration/plugin.spec.js
Original file line number Diff line number Diff line change
@@ -1,167 +1,236 @@
/// <reference types="Cypress" />

context('Actions', () => {
context("Cypress Wait Until", () => {
beforeEach(() => {
cy.visit('http://localhost:5000/')
})
cy.visit("http://localhost:5000/");
});

it('Should work with an immediately-satisfied condition', () => {
const COOKIE_NAME = 'immediate-cookie'
const EXPECTED_COOKIE_VALUE = 'Set'
cy.get('#' + COOKIE_NAME).click()
it("Should work with an immediately-satisfied condition", () => {
const COOKIE_NAME = "immediate-cookie";
const EXPECTED_COOKIE_VALUE = "Set";
cy.get("#" + COOKIE_NAME).click();

const checkFunction = () => cy.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE)
const checkFunction = () =>
cy
.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE);

cy.waitUntil(checkFunction)
cy.waitUntil(checkFunction);

cy.getCookie(COOKIE_NAME).then(cookieValue => expect(cookieValue.value).to.be.equal(EXPECTED_COOKIE_VALUE));
})
cy.getCookie(COOKIE_NAME).then(cookieValue =>
expect(cookieValue.value).to.be.equal(EXPECTED_COOKIE_VALUE)
);
});

it('Should work with a condition satisfied after a random delay', () => {
const COOKIE_NAME = 'after-a-while-cookie'
const EXPECTED_COOKIE_VALUE = 'Set'
cy.get('#' + COOKIE_NAME).click()
it("Should work with a condition satisfied after a random delay", () => {
const COOKIE_NAME = "after-a-while-cookie";
const EXPECTED_COOKIE_VALUE = "Set";
cy.get("#" + COOKIE_NAME).click();

const checkFunction = () => cy.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE)
const checkFunction = () =>
cy
.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE);

cy.waitUntil(checkFunction)
cy.waitUntil(checkFunction);

cy.getCookie(COOKIE_NAME).then(cookieValue => expect(cookieValue.value).to.be.equal(EXPECTED_COOKIE_VALUE));
})
cy.getCookie(COOKIE_NAME).then(cookieValue =>
expect(cookieValue.value).to.be.equal(EXPECTED_COOKIE_VALUE)
);
});

it('Should apply options correctly', () => {
const COOKIE_NAME = 'after-a-while-cookie'
const EXPECTED_COOKIE_VALUE = 'Set'
it("Should apply options correctly", () => {
const COOKIE_NAME = "after-a-while-cookie";
const EXPECTED_COOKIE_VALUE = "Set";

cy.once('fail', err => {
expect(err.message).to.be.equal('Timed out retrying')
})
cy.once("fail", err => {
expect(err.message).to.be.equal("Timed out retrying");
});

cy.get('#' + COOKIE_NAME).click()
cy.get("#" + COOKIE_NAME).click();

const checkFunction = () => cy.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE)
const checkFunction = () =>
cy
.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE);

cy.waitUntil(checkFunction, {
interval: 100,
timeout: 900
})
})
});
});

it('Should check value equality check', () => {
const COOKIE_NAME = 'change-after-a-while-cookie'
const EXPECTED_COOKIE_VALUE = '7'
cy.get('#' + COOKIE_NAME).click()
it("Should log a custom logging description", () => {
const COOKIE_NAME = "after-a-while-cookie";
const EXPECTED_COOKIE_VALUE = "Set";

const checkFunction = () => cy.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE)
cy.once("fail", err => {
expect(err.message).to.be.equal("Timed out retrying");
});

cy.waitUntil(checkFunction)
cy.get("#" + COOKIE_NAME).click();

cy.getCookie(COOKIE_NAME).then(cookieValue => expect(cookieValue.value).to.be.equal(EXPECTED_COOKIE_VALUE));
})
const checkFunction = () =>
cy
.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE);

it('Should make the test fail with an unsatisfied condition', () => {
const COOKIE_NAME = 'unknwon-cookie'
const EXPECTED_COOKIE_VALUE = 'Set'
cy.waitUntil(checkFunction, {
interval: 100,
timeout: 900
});
});

it("Should check value equality check", () => {
const COOKIE_NAME = "change-after-a-while-cookie";
const EXPECTED_COOKIE_VALUE = "7";
cy.get("#" + COOKIE_NAME).click();

const checkFunction = () =>
cy
.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE);

cy.waitUntil(checkFunction);

cy.getCookie(COOKIE_NAME).then(cookieValue =>
expect(cookieValue.value).to.be.equal(EXPECTED_COOKIE_VALUE)
);
});

it("Should make the test fail with an unsatisfied condition", () => {
const COOKIE_NAME = "unknwon-cookie";
const EXPECTED_COOKIE_VALUE = "Set";

cy.once('fail', err => {
expect(err.message).to.be.equal('Timed out retrying')
})
cy.once("fail", err => {
expect(err.message).to.be.equal("Timed out retrying");
});

const checkFunction = () => cy.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE)
const checkFunction = () =>
cy
.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE);

cy.waitUntil(checkFunction)
})
cy.waitUntil(checkFunction);
});

it('Should work sync', () => {
const checkFunction = () => true
it("Should work sync", () => {
const checkFunction = () => true;

cy.waitUntil(checkFunction)
})
cy.waitUntil(checkFunction);
});

it('Should work sync with retries', () => {
it("Should work sync with retries", () => {
let n = 4;
const checkFunction = () => {
n--;
return n < 0;
}
};

cy.waitUntil(checkFunction)
})
cy.waitUntil(checkFunction);
});

it('`checkFunction` should be a function', () => {
const ERROR_MESSAGE = '`checkFunction` parameter should be a function. Found: true'
it("`checkFunction` should be a function", () => {
const ERROR_MESSAGE = "`checkFunction` parameter should be a function. Found: true";

cy.once('fail', err => expect(err.message).to.be.equal(ERROR_MESSAGE))
cy.waitUntil(true)
})
cy.once("fail", err => expect(err.message).to.be.equal(ERROR_MESSAGE));
cy.waitUntil(true);
});

it('Should accept a custom error message', () => {
const COOKIE_NAME = 'unknwon-cookie'
const EXPECTED_COOKIE_VALUE = 'Set'
it("Should accept a custom error message", () => {
const COOKIE_NAME = "unknwon-cookie";
const EXPECTED_COOKIE_VALUE = "Set";

cy.once('fail', err => {
expect(err.message).to.be.equal('Custom error message')
})
cy.once("fail", err => {
expect(err.message).to.be.equal("Custom error message");
});

const checkFunction = () => cy.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE)
const checkFunction = () =>
cy
.getCookie(COOKIE_NAME)
.then(cookieValue => cookieValue && cookieValue.value === EXPECTED_COOKIE_VALUE);

cy.waitUntil(checkFunction, {errorMsg: 'Custom error message'})
})
cy.waitUntil(checkFunction, { errorMsg: "Custom error message" });
});

it('Should pass the result to the next command', () => {
it("Should pass the result to the next command", () => {
const result = 10;

const checkFunction = () => result;
const asyncCheckFunction = () => Promise.resolve(result);
const chainableCheckFunction = () => cy.wrap(result).then(wrappedResult => wrappedResult);

cy.waitUntil(checkFunction).should('eq', result)
cy.waitUntil(asyncCheckFunction).should('eq', result)
cy.waitUntil(chainableCheckFunction).should('eq', result)
})
cy.waitUntil(checkFunction).should("eq", result);
cy.waitUntil(asyncCheckFunction).should("eq", result);
cy.waitUntil(chainableCheckFunction).should("eq", result);
});

it('Should wait between every check', () => {
it("Should wait between every check", () => {
const interval = 100;
let previousTimestamp;

const checkFunction = () => {
const previousTimestampBackup = previousTimestamp;
const newTimestamp = Date.now();
previousTimestamp = newTimestamp;
if(previousTimestampBackup) {
if (previousTimestampBackup) {
const diff = newTimestamp - previousTimestampBackup;
return diff >= interval;
}
return false
}
return false;
};

const asyncCheckFunction = () => Promise.resolve(checkFunction());
const chainableCheckFunction = () => cy.wrap().then(() => checkFunction());

cy.log("Sync function");
cy.waitUntil(checkFunction, {interval})
cy.waitUntil(checkFunction, { interval });
cy.log("Async function");
cy.waitUntil(asyncCheckFunction, {interval})
cy.waitUntil(asyncCheckFunction, { interval });
cy.log("Chainable function");
cy.waitUntil(chainableCheckFunction, {interval})
})
cy.waitUntil(chainableCheckFunction, { interval });
});

it('Should be chainable', () => {
it("Should be chainable", () => {
const result = 10;
const checkFunction = () => result;
const checkFunctionWithSubject = subject => subject;

cy.waitUntil(checkFunction)
.should('eq', result)
cy.waitUntil(checkFunction).should("eq", result);

cy.wrap(result)
.waitUntil(checkFunctionWithSubject)
.should('eq', result)
})
})
.should("eq", result);
});

it("Should leverage Cypress.log", () => {
const checkFunction = () => true;

const logger = {
log: (...params) => Cypress.log(...params)
};
const spy = cy.spy(logger, "log");

cy.waitUntil(checkFunction, { logger: logger.log }).then(() => {
expect(spy).to.have.been.called;
const lastCallArgs = spy.lastCall.args[0];
expect(lastCallArgs).deep.include({ name: "waitUntil" });
});
});

it("Should accept a custom log description", () => {
const checkFunction = () => true;
const description = "custom description";

const logger = {
log: (...params) => Cypress.log(...params)
};
const spy = cy.spy(logger, "log");

cy.waitUntil(checkFunction, { logger: logger.log, description }).then(() => {
expect(spy).to.have.been.called;
const lastCallArgs = spy.lastCall.args[0];
expect(lastCallArgs).deep.include({ name: description });
});
});
});
Loading

0 comments on commit 2ea2765

Please sign in to comment.