Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cypress Testing on CI #9478

Merged
merged 4 commits into from
Sep 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,7 @@ src/
_build/
**/.vs
**/dist/*

# cypress artifacts
cypress/videos
cypress/screenshots
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ services:
- docker
- postgresql
- redis
- xvfb

addons:
chrome: stable

cache:
npm: false
Expand Down Expand Up @@ -48,6 +52,8 @@ jobs:
- npm run stylelint
- (cd app; python3 ./manage.py collectstatic --noinput --disable-collectfast)
- pytest -p no:ethereum -p no:warnings
# Run cypress tests
- bin/ci/cypress-run
# Generate Markdown documentation and static docs page.
- pydocmd build
env:
Expand Down
17 changes: 15 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ ENV DEBIAN_FRONTEND=noninteractive

ARG PACKAGES="libpq-dev libxml2 libxslt1-dev libfreetype6 libjpeg-dev libmaxminddb-dev bash git tar gzip inkscape libmagic-dev"
ARG BUILD_DEPS="gcc g++ curl postgresql libxml2-dev libxslt-dev libfreetype6 libffi-dev libjpeg-dev autoconf automake libtool make dos2unix libvips libvips-dev"
WORKDIR /code
ARG CHROME_DEPS="fonts-liberation libasound2 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 libcairo2 libcups2 libcurl3-gnutls libdrm2 libexpat1 libgbm1 libglib2.0-0 libnspr4 libgtk-3-0 libpango-1.0-0 libx11-6 libxcb1 libxcomposite1 libxdamage1 libxext6 libxfixes3 libxkbcommon0 libxrandr2 libxshmfence1 xdg-utils"
ARG CYPRESS_DEPS="libgtk2.0-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libxtst6 xauth xvfb"

# Inkscape
RUN apt-get update
Expand All @@ -19,13 +20,24 @@ RUN apt-get install -y $PACKAGES
RUN apt-get update
RUN apt-get install -y $BUILD_DEPS

RUN apt-get install -y wget
# Install google chrome for cypress testing
WORKDIR /usr/src
RUN apt-get update && apt-get install -y wget
RUN wget "https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb"
RUN apt-get install -y $CHROME_DEPS
RUN dpkg -i google-chrome-stable_current_amd64.deb

# Install cypress dependencies
RUN apt-get install -y $CYPRESS_DEPS

RUN apt-get install -y libsodium-dev

RUN add-apt-repository universe
RUN apt-get update
RUN apt-get install -y python3-pip

WORKDIR /code

COPY dist/* ./

# GeoIP2 Data Files
Expand Down Expand Up @@ -58,6 +70,7 @@ RUN apt-get install -y yarn
RUN yarn global add n
RUN n stable

EXPOSE 9222
ENTRYPOINT ["/usr/local/bin/dumb-init", "--"]
CMD ["bash", "/bin/docker-command.bash"]

Expand Down
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ logs: ## Print and actively tail the docker compose logs.
cypress: ## Open cypress testing UI
@npx cypress open

cypress-local: ## Run the cypress tests locally - the application MUST already be running for these to pass
@source "./app/app/.env"
@npx cypress install
@npx cypress run --headed --browser chrome

pytest: ## Run pytest (Backend)
@docker-compose exec -e PYTHONPATH=/code/app/ -e DJANGO_SETTINGS_MODULE="app.settings" web pytest -p no:ethereum

Expand Down
6 changes: 6 additions & 0 deletions app/app/local.env
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,9 @@ PREMAILER_CACHE_MAXSIZE=4096

GTC_DIST_API_URL=
GTC_DIST_KEY=

# CYPRESS METAMASK VARIABLES
NETWORK_NAME=localhost
SECRET_WORDS=
PASSWORD=
CYPRESS_REMOTE_DEBUGGING_PORT=9222
36 changes: 36 additions & 0 deletions bin/ci/cypress-run
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#! /bin/bash
set -eou pipefail

# start ganache and send to background
# using published ganache mnemonic - known globally and not a secret
export SECRET_WORDS="chief loud snack trend chief net field husband vote message decide replace"
node_modules/.bin/ganache-cli -m "${SECRET_WORDS}" -h 0.0.0.0 &

# build assets
mkdir -p app/assets/{static,media}
export STATICFILES_DIRS="${TRAVIS_BUILD_DIR}/app/assets/"
python3 app/manage.py bundle
yarn run build

python3 app/manage.py collectstatic --noinput --disable-collectfast

# set up database
python3 app/manage.py migrate
python3 app/manage.py loaddata "${TRAVIS_BUILD_DIR}/app/app/fixtures/users.json"
python3 app/manage.py loaddata "${TRAVIS_BUILD_DIR}/app/app/fixtures/profiles.json"

# run app server
python3 app/manage.py runserver 0.0.0.0:8000 &

# set required env vars and run cypress tests
export NETWORK_NAME=localhost
export PASSWORD="g1tc01nc0" # used in readme for root user account
export CYPRESS_REMOTE_DEBUGGING_PORT=9222
export VERBOSE=1
node_modules/.bin/cypress install
node_modules/.bin/wait-on http://0.0.0.0:8000
node_modules/.bin/cypress run \
--browser chrome \
--headed \
--record \
--key 23c824d9-b9eb-4aea-88fd-d0bb06a9eb51
1 change: 1 addition & 0 deletions bin/docker-command.bash
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ then
then
yarn run build
else
yarn cypress install
yarn run webpack &
fi
fi
Expand Down
6 changes: 5 additions & 1 deletion cypress.json
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
{}
{
"chromeWebSecurity": true,
"baseUrl": "http://localhost:8000",
"projectId": "e7rv3w"
ksolo marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
describe('connect wallet: metamask', () => {
before(() => {
cy.setupMetamask();
cy.changeMetamaskNetwork('localhost');
});

after(() => {
cy.disconnectMetamaskWallet();
cy.clearWindows();
});

it('pulls address from metamask accounts', () => {
cy.impersonateUser();

cy.get('#navbarDropdownWallet').as('wallet').click();
cy.contains('Connect Wallet').click();
cy.contains('MetaMask').click();

cy.acceptMetamaskAccess();

cy.get('@wallet').click();
cy.get('#wallet-btn').should('contain.text', 'Change Wallet');
});
});
14 changes: 0 additions & 14 deletions cypress/integration/test_visit.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,12 @@ describe('Visit Tests', function() {
it('Visits the Kudos Marketplace', function() {
cy.visit('http://localhost:8000/kudos/marketplace');
});
/*
it('Visits the Kudos Sender', function() {
cy.visit('http://localhost:8000/kudos/send');
cy.url().should('contain', 'github.com');
});
*/
it('Visits the Labs Page', function() {
cy.visit('http://localhost:8000/explorer');
});
it('Visits the About Page', function() {
cy.visit('http://localhost:8000/about');
});
it('Visits the Mission Page', function() {
cy.visit('http://localhost:8000/mission');
});
/*
it('Visits the Results Page', function() {
cy.visit('http://localhost:8000/results');
});
*/
it('Visits the Activity Page', function() {
cy.visit('http://localhost:8000/activity');
});
Expand Down
1 change: 1 addition & 0 deletions cypress/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
require('cypress-metamask/plugins')(on);
};
81 changes: 81 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,84 @@
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })

// authentication
Cypress.Commands.add('loginRootUser', () => {
const url = '_administrationlogin/';

cy.request({url, method: 'GET', log: true}).then((response) => {
const body = Cypress.$(response.body);
const csrfmiddlewaretoken = body.find('input[name=csrfmiddlewaretoken]').val();

cy.request({
url,
method: 'POST',
body: {
csrfmiddlewaretoken,
username: 'root',
password: 'gitcoinco'
},
form: true
});
});
});

Cypress.Commands.add('impersonateUser', () => {
cy.loginRootUser();
cy.visit('impersonate/4/');
});

Cypress.Commands.add('logout', () => {
cy.request('logout/?next=/');
});

// grants
Cypress.Commands.add('createGrantSubmission', (options = {}) => {
cy.logout();
cy.impersonateUser();

const url = 'grants/new/';

return cy.request(url)
.then((response) => {
const body = Cypress.$(response.body);
const csrfmiddlewaretoken = body.find('input[name=csrfmiddlewaretoken]').val();

return cy.request({
url,
method: 'POST',
body: {
csrfmiddlewaretoken,
grant_type: options.grant_type || 'media',
title: options.title || 'Test Grant Submission',
description: options.description || 'Describing grant submission',
description_rich: options.description_rich || "{'ops':[{'insert':'The mission of the grant is to...},{'insert':'\n'}]}'",
has_external_funding: options.has_exeternal_funding || 'no',
eth_payout_address: options.eth_payout_address || '0xB81C935D01e734b3D8bb233F5c4E1D72DBC30f6c',
handle1: options.handle1 || '@gitcoin',
handle2: options.handle2 || '@kbw',
region: options.region || 'north_america',
reference_url: options.reference_url || 'https://gitcoin.co',
github_project_url: options.github_project_url || 'https://github.com/gitcoinco/web',
'team_members[]': options.team_members || '',
'categories[]': options.categories || 4
},
form: true
});
});
});

Cypress.Commands.add('approveGrant', (grantSlug) => {
cy.logout();
cy.loginRootUser();

const pk = grantSlug.match(/\/grants\/(\d*)\//)[1];
const changePath = `_administrationgrants/grant/${pk}/change/`;

cy.visit(changePath);
cy.get('[name=active]').check();
cy.get('[name=defer_clr_to]').select(pk);
cy.get('[name=_save]').click();

cy.logout();
});
2 changes: 2 additions & 0 deletions cypress/support/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

// Import commands.js using ES2015 syntax:
import './commands';
import 'cypress-metamask';

// Alternatively you can use CommonJS syntax:
// require('./commands')
Expand All @@ -24,3 +25,4 @@ Cypress.on('uncaught:exception', (err, runnable) => {
// failing the test
return false;
});

5 changes: 4 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ services:

web:
restart: unless-stopped
ipc: host
shm_size: '4gb'
environment:
- PYTHONUNBUFFERED=1
- PYTHONIOENCODING=utf8
Expand All @@ -63,6 +65,7 @@ services:
- "3030:3030"
- "8001:8001"
- "35729:35729"
- "9222:9222"
depends_on:
- db
stdin_open: true
Expand All @@ -79,7 +82,7 @@ services:
image: trufflesuite/ganache-cli
ports:
- "8545:8545"
command: '-a 1 --seed 2 --host 0.0.0.0 --mnemonic "${TEST_MNEMONIC}"'
command: '--host 0.0.0.0 --mnemonic "${TEST_MNEMONIC}"'
deploy:
replicas: 1
resources:
Expand Down
1 change: 1 addition & 0 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ To keep the style of the Javascript code consistent we have a basic linting conf
* 1 tab = 4 spaces for everything else
* Use `rem` for CSS when applicable
* Add relevant unit tests for all new Python logic and update existing tests to accommodate new logic. You can run tests via: `make pytest`
* Gitcoin uses Cypress for system tests. To run those locally you will first need to launch the application, and then use the `make cypress-local` target
* If you introduce new backend methods or classes, you must include docstrings that conform to PEP-257 and follow the existing patterns throughout the codebase. See `app/avatar/(models|views|utils).py` - If you introduce a new django module, like: `avatar` or `marketing`, you must update `pydocmd.yaml` to include relevant python modules from the newly introduced app.

### Step 4: Commit
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,19 @@
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.2",
"css-loader": "^5.2.4",
"cypress": "^3.4.1",
"cypress": "^8.3.1",
"eslint": "^7.14.0",
"file-loader": "^6.2.0",
"filemanager-webpack-plugin": "^4.0.0",
"ganache-cli": "^6.12.2",
"glob": "^7.1.6",
"sass": "^1.32.11",
"sass-loader": "^11.0.1",
"stylelint": "^9.10.1",
"stylelint-config-recommended": "^2.2.0",
"stylelint-scss": "^3.19.0",
"uglify-js": "^3.13.4",
"wait-on": "^6.0.0",
"webpack": "^5.36.0",
"webpack-cli": "^4.6.0",
"webpack-watched-glob-entries-plugin": "^2.1.9"
Expand All @@ -47,6 +49,7 @@
"@joeattardi/emoji-button": "^3.1.1",
"bootstrap": "4.6.0",
"bootstrap-vue": "2.18.0",
"cypress-metamask": "https://github.com/gitcoinco/cypress-metamask",
"daterangepicker": "3.0.5",
"dompurify": "^2.2.9",
"gsap": "3.6.0",
Expand Down
Loading