Skip to content

Commit

Permalink
Merge pull request #496 from Synthetixio/dev
Browse files Browse the repository at this point in the history
promote dev to master
  • Loading branch information
drptbl authored Sep 13, 2022
2 parents 8a2b522 + f4030fb commit 3f828be
Show file tree
Hide file tree
Showing 12 changed files with 189 additions and 68 deletions.
45 changes: 26 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
</p>

#
[Synpress](https://github.com/Synthetixio/synpress) is e2e testing
framework based on [Cypress.io](https://github.com/cypress-io/cypress) and
[playwright](https://playwright.dev/) with support for [metamask](https://metamask.io/).

[Synpress](https://github.com/Synthetixio/synpress) is e2e testing framework
based on [Cypress.io](https://github.com/cypress-io/cypress) and
[playwright](https://playwright.dev/) with support for
[metamask](https://metamask.io/).

Synpress makes sure to always use latest version of metamask and puts a lot of
effort to make sure that dapp tests are stable and trustful.
Expand All @@ -37,8 +39,10 @@ To see in which direction Synpress is headed to, take a look at
## Features

- added support for metamask 🦊
- supports headless mode thanks to [docker 🐳](https://github.com/Synthetixio/synpress#-using-with-docker)
- recommended for local development and [CI](https://github.com/Synthetixio/synpress#ci-tips--tricks)
- supports headless mode thanks to
[docker 🐳](https://github.com/Synthetixio/synpress#-using-with-docker)
- recommended for local development and
[CI](https://github.com/Synthetixio/synpress#ci-tips--tricks)
- includes VNC and [noVNC](https://novnc.com/info.html)
- integrated video recoding 🎥 (full screen)
- exposes noVNC with [ngrok](https://ngrok.com/) (optional)
Expand All @@ -52,10 +56,13 @@ To see in which direction Synpress is headed to, take a look at
- extensible ⚙️ (add own custom commands and plugins)
- can be used in existing
[cypress setup](https://github.com/Synthetixio/synpress/issues/346#issuecomment-1060506096)
- supports dotenv
- loads all env vars from your `.env` file automatically (from project root folder)
- ability to use latest metamask or lock it's version to avoid unexpected
failures related to metamask updates
- supports multi-lang of metamask, it doesn't depend on any labels
- synpress is [fully tested](https://github.com/Synthetixio/synpress/tree/dev/tests/e2e/specs)
- synpress is
[fully tested](https://github.com/Synthetixio/synpress/tree/dev/tests/e2e/specs)
- waits for XHR requests, navigations and animations automatically
- ability to fail test run if there are any browser console errors found
- types support for all additional custom commands
Expand All @@ -67,8 +74,7 @@ To see in which direction Synpress is headed to, take a look at
- supports codespaces
- run your tests in docker
- get your feedback remotely thanks to ngrok
- use mpeg-4 preview plugin to watch videos from inside codespaces :)
...
- use mpeg-4 preview plugin to watch videos from inside codespaces :) ...

## 👷 Example setup for eslint and tsconfig

Expand Down Expand Up @@ -136,10 +142,9 @@ To change specific values in default config, you can use `--config` flag. For
example, to change path for `support.js` file, you can use
`synpress run --config "supportFile=__tests__/e2e/supportFile.js"`

If you would like to use custom paths for your tests and configs, feel free to
mirror
[default synpress config](https://github.com/Synthetixio/synpress/blob/dev/synpress.config.js)
and modify it for your needs. Then you can direct synpress to use it with
If you would like to use custom paths for your tests and configs, you should
[mirror (full) default synpress config](https://github.com/Synthetixio/synpress/blob/dev/synpress.config.js)
and then modify it for your needs. Then you can direct synpress to use it with
`--configFile` flag.

For example: `synpress run --configFile __tests__/e2e/customConfig.config.js`
Expand Down Expand Up @@ -207,9 +212,8 @@ key using `ETHERSCAN_KEY` enironmental variable.
To fail a test if there are any browser console errors, set `FAIL_ON_ERROR` to
`1` or `true`.

Automatic waiting for XHR requests to finish before tests start can be turned
on with `CYPRESS_RESOURCES_WAIT` environmental variable, set it to `1` or
`true`.
Automatic waiting for XHR requests to finish before tests start can be turned on
with `CYPRESS_RESOURCES_WAIT` environmental variable, set it to `1` or `true`.

If you want to skip metamask extension installation or metamask setup, you can
use `SKIP_METAMASK_INSTALL` and `SKIP_METAMASK_SETUP` separately. Both variables
Expand Down Expand Up @@ -255,20 +259,23 @@ Docker is awesome for CI and local development. Give it a try.
2. `cd synpress`
3. (optional) Fill env vars inside `.env` file
4. (without ngrok) `docker-compose up --build --exit-code-from synpress`
- (with ngrok) `docker-compose --profile ngrok up --build --exit-code-from synpress` or `./start-tests.sh`
- (with ngrok)
`docker-compose --profile ngrok up --build --exit-code-from synpress` or
`./start-tests.sh`

All examples of setup are present in this repository. Just take a look around.

**Warning: M2 is not supported with docker.**
As a workaround - you can use codespaces, they're fully supported! :)
**Warning: M2 is not supported with docker.** As a workaround - you can use
codespaces, they're fully supported! :)

## CI tips & tricks

- use [docker-e2e](https://github.com/Synthetixio/docker-e2e)
- stick to bigger resolutions (to make sure that whole extension is visible on
screen when opened)
- synpress is tested on 1920x1080
- take a look at this [example config](https://github.com/Synthetixio/synpress/blob/dev/.github/workflows/audit_and_lint.yml#L84)
- take a look at this
[example config](https://github.com/Synthetixio/synpress/blob/dev/.github/workflows/audit_and_lint.yml#L84)

## 🧪 Usage

Expand Down
19 changes: 13 additions & 6 deletions commands/metamask.js
Original file line number Diff line number Diff line change
Expand Up @@ -689,13 +689,20 @@ module.exports = {
);
return true;
},
allowToAddNetwork: async () => {
allowToAddNetwork: async ({ waitForEvent }) => {
const notificationPage = await playwright.switchToMetamaskNotification();
await playwright.waitAndClick(
confirmationPageElements.footer.approveButton,
notificationPage,
{ waitForEvent: 'close' },
);
if (waitForEvent) {
await playwright.waitAndClick(
confirmationPageElements.footer.approveButton,
notificationPage,
{ waitForEvent },
);
} else {
await playwright.waitAndClick(
confirmationPageElements.footer.approveButton,
notificationPage,
);
}
return true;
},
rejectToAddNetwork: async () => {
Expand Down
26 changes: 10 additions & 16 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ services:
container_name: synpress
build: .
environment:
- DISPLAY=novnc:0.0
- DISPLAY=display:0.0
- CYPRESS_PRIVATE_KEY_WITH_FUNDS=${CYPRESS_PRIVATE_KEY_WITH_FUNDS}
- GITHUB_TOKEN=${GITHUB_TOKEN}
depends_on:
- novnc
- display
- video
entrypoint: []
working_dir: /app
Expand All @@ -19,17 +19,15 @@ services:
command: >
bash -c 'echo -n "======> local noVNC URL:
http://localhost:8080/vnc.html?autoconnect=true " && npx wait-on
http://novnc:8080 && echo -n "======> remote noVNC URL: " && curl -s
http://display:8080 && echo -n "======> remote noVNC URL: " && curl -s
ngrok:4040/api/tunnels | jq -r .tunnels[0].public_url && yarn test:e2e'
networks:
- x11

novnc:
container_name: novnc
image: theasp/novnc@sha256:cd5210a86611bc2dc3ea6eb96a2bfe91237983f8fbc1ab02175142e63e461c40
display:
container_name: display
image: synthetixio/display:8c262e845add19dd78dfb446dddfb695858f1906-base
environment:
- DISPLAY_WIDTH=1920
- DISPLAY_HEIGHT=1080
- RUN_XTERM=no
ports:
- '8080:8080'
Expand All @@ -45,25 +43,21 @@ services:
- NGROK_DEBUG=1
ports:
- '4040:4040'
command: ['ngrok', 'http', 'novnc:8080', '--authtoken', '${NGROK_AUTH}']
command: ['ngrok', 'http', 'display:8080', '--authtoken', '${NGROK_AUTH}']
depends_on:
- novnc
- display
networks:
- x11

video:
container_name: video
image: selenium/video@sha256:bf3948fd78e160b21726293488e108de25d26d515ce02fbba6790f2a1a2acde6
image: synthetixio/video:8c262e845add19dd78dfb446dddfb695858f1906-base
volumes:
- ./docker/videos-ci:/videos
environment:
- SE_SCREEN_WIDTH=1920
- SE_SCREEN_HEIGHT=1080
- DISPLAY_CONTAINER_NAME=novnc
- DISPLAY_NUM=0
- FILE_NAME=CI-full-video.mp4
depends_on:
- novnc
- display
networks:
- x11

Expand Down
3 changes: 2 additions & 1 deletion helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const axios = require('axios');
const fs = require('fs');
const zip = require('cross-zip');
const path = require('path');
const packageJson = require('./package.json');

let networkName = 'mainnet';
let networkId = 1;
Expand Down Expand Up @@ -43,7 +44,7 @@ module.exports = {
if (process.env.SYNPRESS_LOCAL_TEST) {
return '.';
} else {
return path.dirname(require.resolve(`@synthetixio/synpress`));
return path.dirname(require.resolve(packageJson.name));
}
},
getMetamaskReleases: async version => {
Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@
"bytes32": "^0.0.3",
"commander": "^9.4.0",
"cross-zip": "^4.0.0",
"cypress": "^10.7.0",
"cypress": "^10.8.0",
"cypress-wait-until": "^1.7.2",
"dotenv": "^16.0.2",
"dotenv-parse-variables": "^2.0.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard": "^17.0.0",
Expand All @@ -74,10 +76,11 @@
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.0.1",
"eslint-plugin-standard": "^4.1.0",
"eslint-plugin-testing-library": "^5.6.1",
"eslint-plugin-testing-library": "^5.6.4",
"eslint-plugin-ui-testing": "^2.0.1",
"eslint-plugin-unicorn": "^43.0.2",
"etherscan-api": "^10.2.0",
"find-config": "^1.0.0",
"node-fetch": "^2.6.1",
"prettier": "^2.7.1",
"serve": "^14.0.1",
Expand All @@ -86,7 +89,7 @@
},
"devDependencies": {
"@microsoft/eslint-formatter-sarif": "^3.0.0",
"npm-check-updates": "^16.1.0",
"npm-check-updates": "^16.1.2",
"release-it": "^15.4.1"
},
"engines": {
Expand Down
4 changes: 2 additions & 2 deletions plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ module.exports = (on, config) => {
const rejected = await metamask.rejectTransaction();
return rejected;
},
allowMetamaskToAddNetwork: async () => {
const allowed = await metamask.allowToAddNetwork();
allowMetamaskToAddNetwork: async ({ waitForEvent }) => {
const allowed = await metamask.allowToAddNetwork({ waitForEvent });
return allowed;
},
rejectMetamaskToAddNetwork: async () => {
Expand Down
4 changes: 2 additions & 2 deletions support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ Cypress.Commands.add('rejectMetamaskTransaction', () => {
return cy.task('rejectMetamaskTransaction');
});

Cypress.Commands.add('allowMetamaskToAddNetwork', () => {
return cy.task('allowMetamaskToAddNetwork');
Cypress.Commands.add('allowMetamaskToAddNetwork', waitForEvent => {
return cy.task('allowMetamaskToAddNetwork', { waitForEvent });
});

Cypress.Commands.add('rejectMetamaskToAddNetwork', () => {
Expand Down
5 changes: 4 additions & 1 deletion support/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,11 @@ declare namespace Cypress {
* Allow site to add new network in metamask
* @example
* cy.allowMetamaskToAddNetwork()
* cy.allowMetamaskToAddNetwork('close') // (waitForEvent)
*/
allowMetamaskToAddNetwork(): Chainable<Subject>;
allowMetamaskToAddNetwork(
waitForEvent: string | undefined,
): Chainable<Subject>;
/**
* Reject site to add new network in metamask
* @example
Expand Down
16 changes: 12 additions & 4 deletions synpress.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const path = require('path');
const packageJson = require('./package.json');
const { defineConfig } = require('cypress');
const setupNodeEvents = require('./plugins/index');
const helpers = require('./helpers');

const fixturesFolder = `${helpers.getSynpressPath()}/fixtures`;
const setupNodeEvents = require(`${getSynpressPath()}/plugins/index`);
const fixturesFolder = `${getSynpressPath()}/fixtures`;
const supportFile = 'tests/e2e/support.js';

module.exports = defineConfig({
Expand Down Expand Up @@ -35,3 +35,11 @@ module.exports = defineConfig({
supportFile,
},
});

function getSynpressPath() {
if (process.env.SYNPRESS_LOCAL_TEST) {
return '.';
} else {
return path.dirname(require.resolve(packageJson.name));
}
}
6 changes: 6 additions & 0 deletions synpress.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ const program = require('commander');
const { run, open } = require('./launcher');
const { version } = require('./package.json');

if (process.env.SYNPRESS_LOCAL_TEST) {
require('dotenv').config();
} else {
require('dotenv').config({ path: require('find-config')('.env') });
}

if (process.env.SYNDEBUG) {
process.env.PWDEBUG = 1;
// process.env.DEBUG = 'cypress:*';
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/specs/metamask-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ describe('Metamask', () => {
});
it.skip(`allowMetamaskToAddNetwork should approve permission to add network`, () => {
cy.get('#addEthereumChain').click();
cy.allowMetamaskToAddNetwork().then(approved => {
cy.allowMetamaskToAddNetwork('close').then(approved => {
expect(approved).to.be.true;
});
});
Expand Down
Loading

0 comments on commit 3f828be

Please sign in to comment.