feat: cypress text (#317)
Signed-off-by: Gaius <gaius.qi@gmail.com> Co-authored-by: Gaius <gaius.qi@gmail.com>
This commit is contained in:
parent
cbfd04915a
commit
9dac701c8a
|
|
@ -0,0 +1,32 @@
|
|||
name: E2E Test
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
cypress-run:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '18.x'
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --force
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v6
|
||||
with:
|
||||
build: yarn build
|
||||
start: yarn start
|
||||
browser: chrome
|
||||
wait-on: 'http://localhost:3000'
|
||||
wait-on-timeout: 120
|
||||
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
|
@ -46,3 +46,6 @@ tsconfig.tsbuildinfo
|
|||
|
||||
# mock
|
||||
/mock
|
||||
|
||||
#nyc
|
||||
/.nyc_output
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ coverage:
|
|||
project:
|
||||
default:
|
||||
enabled: yes
|
||||
target: 80%
|
||||
target: 5%
|
||||
patch:
|
||||
default:
|
||||
enabled: yes
|
||||
target: 80%
|
||||
target: 5%
|
||||
comment:
|
||||
layout: 'reach, diff, flags, files'
|
||||
behavior: default
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
import { defineConfig } from 'cypress';
|
||||
|
||||
export default defineConfig({
|
||||
// setupNodeEvents can be defined in either
|
||||
// the e2e or component configuration
|
||||
e2e: {
|
||||
setupNodeEvents(on, config) {
|
||||
require('@cypress/code-coverage/task')(on, config);
|
||||
// include any other plugin code...
|
||||
|
||||
// It's IMPORTANT to return the config object
|
||||
// with any changed environment variables
|
||||
return config;
|
||||
},
|
||||
baseUrl: 'http://localhost:3000',
|
||||
},
|
||||
defaultCommandTimeout: 15000,
|
||||
responseTimeout: 60000,
|
||||
});
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
import signin from '../fixtures/api/signin.json';
|
||||
import root from '../fixtures/api/role-root.json';
|
||||
import user from '../fixtures/api/user.json';
|
||||
import _ from 'lodash';
|
||||
|
||||
describe('Signin', () => {
|
||||
beforeEach(() => {
|
||||
cy.intercept('POST', '/api/v1/users/signin', (req) => {
|
||||
const { name, password } = req.body;
|
||||
|
||||
if (name === 'root' && password === 'dragonfly') {
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: signin,
|
||||
});
|
||||
} else {
|
||||
req.reply({
|
||||
statusCode: 401,
|
||||
body: {
|
||||
message: 'Unauthorized',
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
cy.intercept(
|
||||
{
|
||||
method: 'GET',
|
||||
url: '/api/v1/users/1',
|
||||
},
|
||||
(req) => {
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: user,
|
||||
});
|
||||
},
|
||||
);
|
||||
cy.intercept(
|
||||
{
|
||||
method: 'GET',
|
||||
url: '/api/v1/users/1/roles',
|
||||
},
|
||||
(req) => {
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: root,
|
||||
});
|
||||
},
|
||||
);
|
||||
cy.visit('/signin');
|
||||
});
|
||||
|
||||
it('Signin failed', () => {
|
||||
cy.get('#account').type('root');
|
||||
cy.get('#password').type('rooot1');
|
||||
cy.get('form').submit();
|
||||
cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Unauthorized');
|
||||
cy.get('.MuiAlert-action > .MuiButtonBase-root').click();
|
||||
cy.get('.MuiSnackbar-root > .MuiPaper-root').should('not.exist');
|
||||
});
|
||||
|
||||
it('Signin suceesfully', () => {
|
||||
cy.get('#account').type('root');
|
||||
cy.get('#password').type(`dragonfly`);
|
||||
cy.signin();
|
||||
cy.get('form').submit();
|
||||
cy.location('pathname').should('eq', '/clusters');
|
||||
});
|
||||
|
||||
it('Switch to the signup page', () => {
|
||||
cy.get('.MuiTypography-inherit > .MuiTypography-root').click();
|
||||
cy.url().should('include', '/signup');
|
||||
cy.get('.MuiTypography-inherit > .MuiTypography-root').click();
|
||||
cy.url().should('include', '/signin');
|
||||
});
|
||||
|
||||
it('Password hidden function', () => {
|
||||
cy.get('#account').type('root');
|
||||
cy.get('#password').type(`dragonfly`);
|
||||
cy.get('.MuiInputBase-root > .MuiButtonBase-root').click();
|
||||
cy.get('#password').should('have.value', 'dragonfly');
|
||||
});
|
||||
|
||||
it('Validation error', () => {
|
||||
const NameNotLongEnough = _.times(2, () => _.sample('abcdefghijklmnopqrstuvwxyz')).join('');
|
||||
const nameLengthExceeds = _.times(11, () => _.sample('abcdefghijklmnopqrstuvwxyz')).join('');
|
||||
const passwordLengthExceeds = _.times(17, () => _.sample('abcdefghijklmnopqrstuvwxyz')).join('');
|
||||
|
||||
cy.get('#account').type(NameNotLongEnough);
|
||||
cy.get('#account-helper-text').should('be.visible').and('contain', 'Fill in the characters, the length is 3-10.');
|
||||
cy.get('#account').type(nameLengthExceeds);
|
||||
cy.get('#account-helper-text').should('be.visible').and('contain', 'Fill in the characters, the length is 3-10.');
|
||||
cy.get('#password').type(passwordLengthExceeds);
|
||||
cy.get('#password-helper-text')
|
||||
.should('be.visible')
|
||||
.and('contain', 'Fill in the characters, the maximum length is 16.');
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
[
|
||||
"root"
|
||||
]
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"expire": "2023-11-04T10:57:15+09:00",
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTkwNjY2MzUsImlkIjoxLCJvcmlnX2lhdCI6MTY5ODg5MzgzNX0.KH-3-Pu8BqVW1u5JDyiWooR1a_acyKFFE4BRbLB0bAg"
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"id": 1,
|
||||
"created_at": "2023-11-06T06:09:04Z",
|
||||
"updated_at": "2023-11-06T06:09:04Z",
|
||||
"is_del": 0,
|
||||
"email": "lucy@example.com",
|
||||
"name": "lucy",
|
||||
"avatar": "https://example.com/avatar.png",
|
||||
"phone": "1234567890",
|
||||
"state": "enable",
|
||||
"location": "Hangzhou",
|
||||
"bio": "I am lucy",
|
||||
"configs": null
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
declare namespace Cypress {
|
||||
interface Chainable<Subject> {
|
||||
signin(): void;
|
||||
}
|
||||
}
|
||||
|
||||
Cypress.Commands.add('signin', () => {
|
||||
const jwtToken =
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTkwNzMzNDcsImlkIjoxLCJvcmlnX2lhdCI6MTY5ODkwMDU0N30.mplV3_e5ZLKo9Y4YkMpsc8_2GIMj4AgSsw9W-z_qDRM';
|
||||
cy.setCookie('jwt', jwtToken);
|
||||
});
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// ***********************************************************
|
||||
// This example support/e2e.ts is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
import '@cypress/code-coverage/support'
|
||||
10
package.json
10
package.json
|
|
@ -10,11 +10,14 @@
|
|||
],
|
||||
"repository": "git@github.com:dragonflyoss/console.git",
|
||||
"scripts": {
|
||||
"start": "react-app-rewired start",
|
||||
"start": "react-app-rewired -r @cypress/instrument-cra start",
|
||||
"build": "BUILD_PATH='./dist' react-app-rewired build",
|
||||
"test": "react-app-rewired test",
|
||||
"eject": "react-scripts eject",
|
||||
"lint": "react-scripts lint"
|
||||
"lint": "react-scripts lint",
|
||||
"cy:open": "npx cypress open",
|
||||
"cy:run": "npx cypress run --browser chrome",
|
||||
"coverage:verify": "npx nyc report --check-coverage true --lines 10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.11.1",
|
||||
|
|
@ -58,8 +61,11 @@
|
|||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"@commitlint/cli": "^18.2.0",
|
||||
"@commitlint/config-conventional": "^18.0.0",
|
||||
"@cypress/code-coverage": "^3.12.6",
|
||||
"@cypress/instrument-cra": "^1.4.0",
|
||||
"@web3-storage/parse-link-header": "^3.1.0",
|
||||
"chart.js": "^4.4.0",
|
||||
"cypress": "^13.3.3",
|
||||
"eslint": "^8.0.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-config-react-app": "^7.0.1",
|
||||
|
|
|
|||
|
|
@ -710,6 +710,7 @@ export default function NewCluster() {
|
|||
size="small"
|
||||
variant="outlined"
|
||||
loadingPosition="end"
|
||||
id="cancle"
|
||||
sx={{
|
||||
'&.MuiLoadingButton-root': {
|
||||
color: 'var(--calcel-size-color)',
|
||||
|
|
|
|||
|
|
@ -804,6 +804,7 @@ export default function ShowCluster() {
|
|||
size="small"
|
||||
variant="outlined"
|
||||
loadingPosition="end"
|
||||
id="cancelDeleteScheduler"
|
||||
sx={{
|
||||
'&.MuiLoadingButton-root': {
|
||||
color: 'var(--calcel-size-color)',
|
||||
|
|
@ -1082,6 +1083,7 @@ export default function ShowCluster() {
|
|||
size="small"
|
||||
variant="outlined"
|
||||
loadingPosition="end"
|
||||
id="cancelDeleteSeedPeer"
|
||||
sx={{
|
||||
'&.MuiLoadingButton-root': {
|
||||
color: 'var(--calcel-size-color)',
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@
|
|||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"types": [
|
||||
"cypress",
|
||||
"node"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
|
|
@ -16,11 +20,12 @@
|
|||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"isolatedModules": false,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
"src",
|
||||
"**/*.ts"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue