Task/Updated tests to pass when there are no transactions (#145)

* Updated tests to pass when there are no txs

* Add slack command to send messages to slack

* Re add library for Cypress

* Resolved PR comments

* Added TODOs for clarity

* Increase wait for block to update

* Increase to 3 seconds

Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
This commit is contained in:
Joe Tsang 2022-04-04 18:20:33 +01:00 committed by GitHub
parent 49f97a3097
commit a459793f09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 224 additions and 117 deletions

View File

@ -54,7 +54,7 @@ jobs:
run: ./vegawallet service run --network fairground &
- name: Run Cypress tests
run: npx nx affected:e2e --parallel=5 --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --env.tradingWalletPassphrase=${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }} --browser chrome
run: npx nx affected:e2e --parallel=5 --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --env.tradingWalletPassphrase=${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }} --env.slackWebhook=${{ secrets.CYPRESS_SLACK_WEBHOOK }} --browser chrome
pr:
name: Run end-to-end tests - PR
runs-on: ubuntu-latest
@ -99,4 +99,4 @@ jobs:
run: ./vegawallet service run --network fairground &
- name: Run Cypress tests
run: npx nx affected:e2e --parallel=5 --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --env.tradingWalletPassphrase=${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }} --browser chrome
run: npx nx affected:e2e --parallel=5 --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --env.tradingWalletPassphrase=${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }} --env.slackWebhook=${{ secrets.CYPRESS_SLACK_WEBHOOK }} --browser chrome

View File

@ -1 +0,0 @@
export const getGreeting = () => cy.get('h1');

View File

@ -1,37 +0,0 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
// eslint-disable-next-line @typescript-eslint/no-namespace
declare namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
login(email: string, password: string): void;
getByTestId(selector: string): Chainable<JQuery<HTMLElement>>;
}
}
//
// -- This is a parent command --
Cypress.Commands.add('login', (email, password) => {
console.log('Custom command example: Login', email, password);
});
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
Cypress.Commands.add('getByTestId', (selector, ...args) => {
return cy.get(`[data-testid=${selector}]`, ...args);
});

View File

@ -13,5 +13,4 @@
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands';
import '@vegaprotocol/cypress';

View File

@ -25,10 +25,17 @@ export default class BlocksPage extends BasePage {
validateBlockValidatorPage() {
cy.getByTestId(this.minedByValidator).should('not.be.empty');
cy.getByTestId(this.blockTime).should('not.be.empty');
cy.get(`[data-testid=${this.transactionsRow}] > td`)
.should('have.length.above', 0)
.each(($cell) => {
cy.wrap($cell).should('not.be.empty');
});
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(1000); // Wait for transactions to load if there are any
cy.get('body').then(($body) => {
if ($body.find(`[data-testid=${this.transactionsRow}] > td`).length) {
cy.get(`[data-testid=${this.transactionsRow}] > td`).each(($cell) => {
cy.wrap($cell).should('not.be.empty');
});
} else {
cy.slack('Unable to find any transactions on page');
cy.screenshot();
}
});
}
}

View File

@ -22,18 +22,12 @@ export default class TransactionsPage extends BasePage {
cy.getByTestId(this.blockTime).first().should('not.be.empty');
}
verifyAllBlockRowsAreNotEmpty() {
cy.get(`[data-testid=${this.transactionRow}] > td`).each(($cell) => {
cy.wrap($cell).should('not.be.empty');
});
}
validateRefreshBtn() {
cy.getByTestId(this.blockHeight)
.first()
.invoke('text')
.then((blockHeightTxt) => {
cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.wait(3000); // eslint-disable-line cypress/no-unnecessary-waiting
//Wait needed to allow blocks to change
cy.getByTestId(this.refreshBtn).click();
@ -48,35 +42,55 @@ export default class TransactionsPage extends BasePage {
}
validateTxDetailsAreDisplayed() {
cy.getByTestId(this.txHash).invoke('text').should('have.length', 64);
cy.getByTestId(this.txSubmittedBy)
.find('a')
.then(($address) => {
cy.wrap($address).should('have.attr', 'href');
cy.wrap($address).invoke('text').should('have.length', 66);
});
cy.getByTestId(this.txBlock).should('not.be.empty');
cy.getByTestId(this.txEncodedTnx).should('not.be.empty');
cy.getByTestId(this.txType)
.should('not.be.empty')
.invoke('text')
.then((txTypeTxt) => {
if (txTypeTxt == 'Order Submission') {
cy.get('.hljs-attr')
.should('have.length.at.least', 8)
.each(($propertyName) => {
cy.wrap($propertyName).should('not.be.empty');
});
cy.get('span[style*="color"]')
.should('have.length.at.least', 8)
.each(($propertyValue) => {
cy.wrap($propertyValue).should('not.be.empty');
});
}
});
// TODO fail test when there are no txs once running with Capsule
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(1000); // Wait for transactions to load if there are any
cy.get('body').then(($body) => {
if ($body.find(`[data-testid=${this.txHash}]`).length) {
cy.getByTestId(this.txHash).invoke('text').should('have.length', 64);
cy.getByTestId(this.txSubmittedBy)
.find('a')
.then(($address) => {
cy.wrap($address).should('have.attr', 'href');
cy.wrap($address).invoke('text').should('have.length', 66);
});
cy.getByTestId(this.txBlock).should('not.be.empty');
cy.getByTestId(this.txEncodedTnx).should('not.be.empty');
cy.getByTestId(this.txType)
.should('not.be.empty')
.invoke('text')
.then((txTypeTxt) => {
if (txTypeTxt == 'Order Submission') {
cy.get('.hljs-attr')
.should('have.length.at.least', 8)
.each(($propertyName) => {
cy.wrap($propertyName).should('not.be.empty');
});
cy.get('span[style*="color"]')
.should('have.length.at.least', 8)
.each(($propertyValue) => {
cy.wrap($propertyValue).should('not.be.empty');
});
}
});
} else {
cy.slack('Unable to find any transactions on page');
cy.screenshot();
}
});
}
clickOnTopTransaction() {
cy.getByTestId(this.transactionRow).first().find('a').first().click();
// TODO fail test when there are no txs once running with Capsule
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(1000); // Wait for transactions to load if there are any
cy.get('body').then(($body) => {
if ($body.find(`[data-testid=${this.transactionRow}]`).length) {
cy.getByTestId(this.transactionRow).first().find('a').first().click();
} else {
cy.slack('Unable to find any transactions on page');
cy.screenshot();
}
});
}
}

View File

@ -17,7 +17,6 @@ When('I click on the top transaction', () => {
Then('transactions page is correctly displayed', () => {
transactionsPage.validateTransactionsPagedisplayed();
transactionsPage.verifyAllBlockRowsAreNotEmpty();
transactionsPage.validateRefreshBtn();
});

View File

@ -1,33 +0,0 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
// eslint-disable-next-line @typescript-eslint/no-namespace
declare namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
login(email: string, password: string): void;
}
}
//
// -- This is a parent command --
Cypress.Commands.add('login', (email, password) => {
console.log('Custom command example: Login', email, password);
});
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })

View File

@ -13,5 +13,4 @@
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands';
import '@vegaprotocol/cypress';

3
libs/cypress/.babelrc Normal file
View File

@ -0,0 +1,3 @@
{
"presets": [["@nrwl/web/babel", { "useBuiltIns": "usage" }]]
}

View File

@ -0,0 +1,18 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

7
libs/cypress/README.md Normal file
View File

@ -0,0 +1,7 @@
# cypress
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test cypress` to execute the unit tests via [Jest](https://jestjs.io).

View File

@ -0,0 +1,14 @@
module.exports = {
displayName: 'cypress',
preset: '../../jest.preset.js',
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json',
},
},
transform: {
'^.+\\.[tj]sx?$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../coverage/libs/cypress',
};

23
libs/cypress/project.json Normal file
View File

@ -0,0 +1,23 @@
{
"root": "libs/cypress",
"sourceRoot": "libs/cypress/src",
"projectType": "library",
"targets": {
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/cypress/**/*.ts"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/libs/cypress"],
"options": {
"jestConfig": "libs/cypress/jest.config.js",
"passWithNoTests": true
}
}
},
"tags": []
}

View File

@ -0,0 +1,5 @@
import { addGetTestIdcommand } from './lib/commands/get-by-test-id';
import { addSlackCommand } from './lib/commands/slack';
addGetTestIdcommand();
addSlackCommand();

View File

@ -0,0 +1,14 @@
// eslint-disable-next-line @typescript-eslint/no-namespace
declare namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
getByTestId(selector: string): Chainable<JQuery<HTMLElement>>;
}
}
export function addGetTestIdcommand() {
// @ts-ignore - ignoring Cypress type error which gets resolved when Cypress uses the command
Cypress.Commands.add('getByTestId', (selector, ...args) => {
return cy.get(`[data-testid=${selector}]`, ...args);
});
}

View File

@ -0,0 +1,26 @@
// eslint-disable-next-line @typescript-eslint/no-namespace
declare namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
slack(message: string): void;
}
}
export function addSlackCommand() {
// @ts-ignore - ignoring Cypress type error which gets resolved when Cypress uses the command
Cypress.Commands.add('slack', (message) => {
const text = `${message}: ${JSON.stringify(Cypress.spec)}`;
cy.log('NOTIFYING SLACK');
const webhook = Cypress.env('slackWebhook');
if (!webhook) {
return;
}
cy.request('POST', webhook, {
text,
});
});
}

View File

@ -0,0 +1,19 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"compilerOptions": {
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
}
}

View File

@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"declaration": true,
"types": ["cypress", "node"]
},
"include": ["**/*.ts"],
"exclude": ["**/*.spec.ts"]
}

View File

@ -0,0 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"**/*.test.ts",
"**/*.spec.ts",
"**/*.test.tsx",
"**/*.spec.tsx",
"**/*.test.js",
"**/*.spec.js",
"**/*.test.jsx",
"**/*.spec.jsx",
"**/*.d.ts"
]
}

View File

@ -15,6 +15,7 @@
"skipDefaultLibCheck": true,
"baseUrl": ".",
"paths": {
"@vegaprotocol/cypress": ["libs/cypress/src/index.ts"],
"@vegaprotocol/deal-ticket": ["libs/deal-ticket/src/index.ts"],
"@vegaprotocol/market-list": ["libs/market-list/src/index.ts"],
"@vegaprotocol/network-stats": ["libs/network-stats/src/index.ts"],

View File

@ -1,6 +1,7 @@
{
"version": 2,
"projects": {
"cypress": "libs/cypress",
"deal-ticket": "libs/deal-ticket",
"explorer": "apps/explorer",
"explorer-e2e": "apps/explorer-e2e",