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

Synpress Implementation #830

Merged
merged 17 commits into from May 5, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 4 additions & 12 deletions .github/workflows/integration-tests.yml
Expand Up @@ -10,8 +10,7 @@ on:
types: [opened, synchronize, reopened]

jobs:
cypress-run:
# TODO: Add some condition if we don't want to trigger this on every pr. (maybe some flag)
synpress-run:
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
Expand Down Expand Up @@ -44,13 +43,6 @@ jobs:
run: |
echo -e 'pcm.!default {\n type hw\n card 0\n}\n\nctl.!default {\n type hw\n card 0\n}' > ~/.asoundrc

- name: Cypress run
uses: cypress-io/github-action@v2
env:
NODE_ENV: 'development'
with:
browser: chrome
headless: true
start: yarn dev
wait-on: 'http://localhost:3000'
wait-on-timeout: 300
- name: Run Synpress
run: yarn run test:e2e

17 changes: 0 additions & 17 deletions cypress.json

This file was deleted.

5 changes: 0 additions & 5 deletions cypress/fixtures/example.json

This file was deleted.

43 changes: 37 additions & 6 deletions cypress/integration/Guilds/Guilds.spec.ts
@@ -1,17 +1,48 @@
/// <reference types="cypress" />
import Guilds from '../../support/pageObjects/Guilds';
import { clickAnywhereToClose } from '../../utils';

describe('Guilds', () => {
it('Should show Guild not available page', () => {
Guilds.goToGuildsPage('localhost', '0xbadAddress555555');
cy.contains('No guild exists on this address.');
it('Should show deployed guilds in LandingPage', () => {
Guilds.goToGuildsPage();
cy.findAllByTestId('guildCard').should(
'have.length',
Guilds.deployedGuildsAddresses.length
);
});

it('Should redirect to guild page', () => {
cy.findAllByTestId('guildCard')
.eq(1)
.invoke('attr', 'href')
.then(href => {
cy.findAllByTestId('guildCard').eq(1).click();
cy.url().should('include', href);
});
});

it('Should render proper components on Guild page', () => {
const guildAddress = Guilds.deployedGuildsAddresses[0];
expect(Guilds.deployedGuildsAddresses.length).to.be.equal(3);
Guilds.goToGuildsPage('localhost', guildAddress);
Guilds.shouldRenderProposalsList();
Guilds.shouldRenderSidebar();
});

it('Should be able to connect with metamask account', () => {
Guilds.clickOpenWalletModalBtn();
cy.findByTestId('wallet-option-MetaMask').eq(0).click();
cy.waitFor(null, 1000);
cy.acceptMetamaskAccess(true);
clickAnywhereToClose();
});

it('Should trigger Create Proposal', () => {
cy.findByTestId('create-proposal-button').should('be.visible').click();
cy.url().should('include', '/proposalType');
cy.findByTestId('proposal-type-continue-button')
.should('be.visible')
.click();
cy.url().should('include', '/create');
Guilds.fillCreateProposalForm();
cy.findByTestId('create-proposal-action-button').click();
});
});

1 change: 0 additions & 1 deletion cypress/plugins/index.ts
Expand Up @@ -8,7 +8,6 @@
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************

const fs = require('fs-extra');
const path = require('path');

Expand Down
13 changes: 13 additions & 0 deletions cypress/support/commands.ts
Expand Up @@ -9,3 +9,16 @@
// ***********************************************

import '@testing-library/cypress/add-commands';
// Synpress types -> https://github.com/Synthetixio/synpress/blob/master/support/index.d.ts
// Synpress commands -> https://github.com/Synthetixio/synpress/blob/master/plugins/index.js
declare global {
namespace Cypress {
interface Chainable<Subject> {
/**
* Include custom cy.command types
*/
// customCyCommandType(param?: string): Cypress.Chainable<Element>;
}
}
}

1 change: 1 addition & 0 deletions cypress/support/index.ts
Expand Up @@ -14,3 +14,4 @@
// ***********************************************************

import './commands';

31 changes: 26 additions & 5 deletions cypress/support/pageObjects/Guilds.ts
Expand Up @@ -11,12 +11,11 @@ class Guilds {
this.deployedGuildsAddresses = localhostConfigJSON.guilds;
}

goToGuildsPage(
network: string = 'localhost',
address: string = '0x9cdc16b5f95229b856cba5f38095fd8e00f8edef' // default rinkeby deployed address
) {
goToGuildsPage(network: string = 'localhost', address?: string) {
const baseUrl = Cypress.config('baseUrl');
cy.visit(`${baseUrl}/guilds/${network}/${address}`, { timeout: 120000 });
cy.visit(`${baseUrl}/guilds/${network}${address ? `/${address}` : ''}`, {
timeout: 120000,
});
}

shouldRenderProposalsList() {
Expand All @@ -26,8 +25,30 @@ class Guilds {
shouldRenderSidebar() {
cy.findByTestId(this.sidebarId).should('be.visible');
}

fillCreateProposalForm() {
cy.findByTestId('create-proposal-title')
.focus()
.type('Test automated proposal');
cy.findByTestId('create-proposal-link')
.focus()
.type(
'https://daotalk.org/t/test-synpress-proposal-07-02-2022-03-04-2022/4003'
);
cy.findByTestId('editor-content')
.find('div')
.type(
'Test Contributor proposal{enter}Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
{ force: true }
);
}

clickOpenWalletModalBtn() {
cy.findAllByTestId('connectWalletBtn').eq(0).click();
}
}

const guilds: Guilds = new Guilds();

export default guilds;

28 changes: 18 additions & 10 deletions cypress/tsconfig.json
@@ -1,11 +1,19 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
"types": ["node", "cypress", "@testing-library/cypress"],
"typeRoots": ["../node_modules/@types"],
"isolatedModules": false,
},
"include": ["**/*.ts"]
}
"extends": "../tsconfig.json",
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
"types": [
"node",
"cypress",
"@types/puppeteer-core",
"@synthetixio/synpress/support",
"cypress-wait-until",
"@testing-library/cypress"
],
"typeRoots": ["../node_modules/@types"],
"isolatedModules": false
},
"include": ["**/*.ts"]
}

4 changes: 4 additions & 0 deletions cypress/utils/index.ts
@@ -0,0 +1,4 @@
export const clickAnywhereToClose = (nodeOrSelector: string = 'body') => {
return cy.get(nodeOrSelector).click(0, 0);
};

12 changes: 7 additions & 5 deletions package.json
Expand Up @@ -10,9 +10,8 @@
"lint": "eslint src/",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,md}\" \"scripts/*.{js,jsx,ts,tsx,json,md}\"",
"format-check": "prettier --check \"src/**/*.{js,jsx,ts,tsx,json,md}\" \"scripts/*.{js,jsx,ts,tsx,json,md}\"",
"cy:open": "cypress open",
"cy:run:development": "cypress run --env configFile=development --browser electron",
"test:e2e": "start-server-and-test 'yarn dev --no-browser' 3000 cy:run:development",
"cy:run": "./scripts/integration.sh",
"test:e2e": "start-server-and-test 'yarn dev --no-browser' 3000 cy:run",
"test": "react-app-rewired test --watchAll=false --coverage --verbose",
"updateBytecodes": "node scripts/updateDeployedBytecodes.js",
"postinstall": "yarn run updateBytecodes",
Expand Down Expand Up @@ -114,13 +113,17 @@
"workbox-webpack-plugin": "^5.1.4"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.2",
"@synthetixio/synpress": "^1.2.0",
"@testing-library/cypress": "^8.0.2",
"@testing-library/jest-dom": "^5.16.2",
"@types/jest": "^27.4.0",
"@types/jsonexport": "^3.0.2",
"@types/puppeteer-core": "^5.4.0",
"@types/react-router-dom": "^5.1.2",
"cra-bundle-analyzer": "^0.1.0",
"cypress": "^9.5.2",
"cypress-react-selector": "^2.3.17",
"cypress-wait-until": "^1.7.2",
"husky": "^6.0.0",
"prettier": "2.5.0",
"start-server-and-test": "^1.14.0",
Expand All @@ -145,4 +148,3 @@
"electron": "^17.1.2"
}
}

20 changes: 20 additions & 0 deletions scripts/integration.sh
@@ -0,0 +1,20 @@
#!/usr/bin/env bash

# Get record key from env
export $(cat .env | grep CYPRESS_RECORD_KEY | xargs)
RECORD_KEY="${CYPRESS_RECORD_KEY}"

export PRIVATE_KEY=0x0054b824c2083e7db09f36edb2ab24eb31f8276fa6cd62e30b42e3a185b37179
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id put a quick comment here about where this private key is from

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is localhost hardhat account. Extracted from dev.sh

# Account #0: 0x79706c8e413cdaee9e63f282507287b9ea9c0928 (10000 ETH)

export PASSWORD="TestMetaMask"
export NETWORK_NAME=localhost
export RPC_URL=http://127.0.0.1:8545/
export CHAIN_ID=1337
export IS_TESTNET=true


if test -z "$RECORD_KEY"
then
synpress run --configFile synpress.json --record false
else
synpress run --configFile synpress.json --record --key $RECORD_KEY
fi
5 changes: 4 additions & 1 deletion src/components/Guilds/GuildCard/index.tsx
Expand Up @@ -34,7 +34,10 @@ interface GuildCardProps extends CardProps {

const GuildCard: React.FC<GuildCardProps> = ({ children, guildAddress }) => {
return (
<StyledLink to={location => `${location.pathname}/${guildAddress}`}>
<StyledLink
data-testId="guildCard"
to={location => `${location.pathname}/${guildAddress}`}
>
<Card customStyles={cardWrapperStyles}>{children}</Card>
</StyledLink>
);
Expand Down
6 changes: 5 additions & 1 deletion src/components/Guilds/Header/WalletButton.tsx
Expand Up @@ -71,7 +71,11 @@ const Web3Status = () => {
/>
);
} else {
return <Button onClick={toggleWalletModal}>Connect Wallet</Button>;
return (
<Button data-testId="connectWalletBtn" onClick={toggleWalletModal}>
Connect Wallet
</Button>
);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/components/Guilds/Web3Modals/WalletModal.tsx
Expand Up @@ -182,6 +182,7 @@ const WalletModal: React.FC<WalletModalProps> = ({ isOpen, onClose }) => {
icon={option.icon}
link={option.href}
header={option.name}
dataTestId={`wallet-option-${option.name}`}
/>
)
);
Expand Down Expand Up @@ -277,6 +278,7 @@ const WalletModal: React.FC<WalletModalProps> = ({ isOpen, onClose }) => {

return (
<Modal
dataTestId="wallet-modal"
header={getHeader()}
isOpen={isOpen}
onDismiss={onClose}
Expand Down
2 changes: 2 additions & 0 deletions src/components/Guilds/Web3Modals/components/Option.tsx
Expand Up @@ -58,13 +58,15 @@ export default function Option({
icon,
header,
active = false,
dataTestId = '',
}) {
const content = (
<OptionButton
variant="secondary"
onClick={onClick}
clickable={clickable && !active}
active={active}
data-testId={dataTestId}
>
<OptionButtonText>
{active && <LiveIndicator />}
Expand Down
4 changes: 3 additions & 1 deletion src/components/Guilds/common/Modal/index.tsx
Expand Up @@ -136,6 +136,7 @@ export interface ModalProps {
backnCross?: boolean;
prevContent?: () => void;
leftIcon?: boolean;
dataTestId?: string;
}

export const ModalButton = styled(Button)`
Expand Down Expand Up @@ -169,9 +170,10 @@ export const Modal: React.FC<ModalProps> = ({
backnCross,
prevContent,
leftIcon = true,
dataTestId,
}) => {
const modal = (
<div>
<div data-testId={dataTestId}>
<Backdrop onClick={onDismiss} zIndex={zIndex} />
<Wrapper maxWidth={maxWidth} zIndex={zIndex + 1}>
<StyledModal>
Expand Down
24 changes: 24 additions & 0 deletions synpress.json
@@ -0,0 +1,24 @@
{
"projectId": "bocbgz",
"experimentalStudio": true,
"viewportWidth": 1920,
"viewportHeight": 1080,
"baseUrl": "http://localhost:3000/#",
"userAgent": "synpress",
"retries": { "runMode": 0, "openMode": 0 },
"integrationFolder": "./cypress/integration",
"screenshotsFolder": "./cypress/screenshots",
"videosFolder": "cypress/videos",
"chromeWebSecurity": true,
"component": {
"componentFolder": "src",
"testFiles": "**/*spec.{js,jsx,ts,tsx}"
},
"env": {
"coverage": false
},
"defaultCommandTimeout": 60000,
"pageLoadTimeout": 60000,
"requestTimeout": 60000
}