diff --git a/codecov.yml b/codecov.yml index 178fad2..1ce5c8a 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,16 +1,16 @@ coverage: precision: 2 round: down - range: '80...100' + range: '90...100' status: project: default: enabled: yes - target: 5% + target: 90% patch: default: enabled: yes - target: 5% + target: 90% comment: layout: 'reach, diff, flags, files' behavior: default diff --git a/cypress/e2e/insight/peers.cy.ts b/cypress/e2e/insight/peers.cy.ts new file mode 100644 index 0000000..d6c70ee --- /dev/null +++ b/cypress/e2e/insight/peers.cy.ts @@ -0,0 +1,316 @@ +import peers from '../../fixtures/peers/peers.json'; + +const path = require('path'); +declare const expect: Chai.ExpectStatic; + +describe('Peers', () => { + beforeEach(() => { + cy.signin(); + cy.intercept( + { + method: 'GET', + url: '/api/v1/peers?page=1&per_page=10000000', + }, + (req) => { + req.reply({ + statusCode: 200, + body: peers, + }); + }, + ); + + cy.visit('/insight/peers'); + cy.viewport(1440, 1080); + }); + + describe('when data is loaded', () => { + it('should display the total number of peers', () => { + cy.get(':nth-child(1) > .MuiPaper-root > .inde_navigationContent__kHaOF').should('exist'); + cy.get( + ':nth-child(1) > .MuiPaper-root > .inde_navigationContent__kHaOF > div.MuiBox-root > .MuiTypography-h5', + ).should('have.text', 7); + }); + + it('should display the total number of git version', () => { + cy.get(':nth-child(2) > .MuiPaper-root > .inde_navigationContent__kHaOF').should('exist'); + cy.get( + ':nth-child(2) > .MuiPaper-root > .inde_navigationContent__kHaOF > div.MuiBox-root > .MuiTypography-h5', + ).should('have.text', 4); + }); + + it('should display the total number of git commit', () => { + cy.get(':nth-child(3) > .MuiPaper-root > .inde_navigationContent__kHaOF').should('exist'); + cy.get( + ':nth-child(3) > .MuiPaper-root > .inde_navigationContent__kHaOF > div.MuiBox-root > .MuiTypography-h5', + ).should('have.text', 5); + }); + + it('should display the active ratio', () => { + // Show active ratio by cluster. + cy.get('#cluster-active').should('contain', '71.43%'); + + // Show active ratio by git version. + cy.get('#git-version-active').should('contain', '71.43%'); + + cy.get('.css-1tg4d9 > .MuiFormControl-root > .MuiInputBase-root > #states-select').click(); + + cy.get('[data-value="cluster-1"]').click(); + + cy.get('#git-version-active').should('contain', '66.67%'); + + // Show active ratio by git commit. + cy.get('#git-commit-active').should('contain', '71.43%'); + + cy.get('.css-1klrv8o-MuiFormControl-root > .MuiInputBase-root > #states-select').click(); + + cy.get('[data-value="cluster-1"]').click(); + + cy.get('#git-commit-active').should('contain', '66.67%'); + + cy.get( + '.css-1tg4d9 > .MuiBox-root > .css-1461v9t-MuiFormControl-root > .MuiInputBase-root > #states-select', + ).click(); + + cy.get('[data-value="git-version-1"]').click(); + + cy.get('#git-commit-active').should('contain', '50%'); + }); + + it('can export csv file', () => { + const downloadsFolder = Cypress.config('downloadsFolder'); + + // Click export csv. + cy.get('.css-1st7tpv > .MuiButtonBase-root').click(); + + // Click save button. + cy.get('#save').click(); + + // Wait two seconds to ensure the download is successful. + cy.wait(2000); + + // Get download file. + const all = path.join(downloadsFolder, 'Peer Data.csv'); + + // Check all quantity. + cy.readFile(all).then((fileContent) => { + const lines = fileContent.split('\n'); + const numEntries = lines.length - 2; + + expect(numEntries).to.be.closeTo(7, 0); + }); + + // Click export csv. + cy.get('.css-1st7tpv > .MuiButtonBase-root').click(); + + cy.get('.css-nvaly6-MuiFormControl-root > .MuiInputBase-root > #states-select').click(); + cy.get('[data-value="cluster-1"]').click(); + + cy.get('#save').click(); + + cy.wait(2000); + + const cluster = path.join(downloadsFolder, 'Peer Data.csv'); + + // Check whether the number of data exported based on cluster-1 is correct. + cy.readFile(cluster) + .should('exist') + .then((fileContent) => { + const numEntries = fileContent.split('\n').length - 2; + + expect(numEntries).to.be.closeTo(3, 0); + }); + + // Click export csv. + cy.get('.css-1st7tpv > .MuiButtonBase-root').click(); + + cy.get('.css-nvaly6-MuiFormControl-root > .MuiInputBase-root > #states-select').click(); + cy.get('[data-value="cluster-1"]').click(); + + cy.get('.css-g74ywa-MuiFormControl-root > .MuiInputBase-root > #states-select').click(); + cy.get('[data-value="git-version-1"]').click(); + + cy.get('#save').click(); + + cy.wait(2000); + + const gitVersion = path.join(downloadsFolder, 'Peer Data.csv'); + + // Check whether the number of data exported based on git-version-1 is correct. + cy.readFile(gitVersion) + .should('exist') + .then((fileContent) => { + const numEntries = fileContent.split('\n').length - 2; + + expect(numEntries).to.be.closeTo(2, 0); + }); + + // Click export csv. + cy.get('.css-1st7tpv > .MuiButtonBase-root').click(); + + cy.get('.css-nvaly6-MuiFormControl-root > .MuiInputBase-root > #states-select').click(); + cy.get('[data-value="cluster-1"]').click(); + + cy.get('.css-g74ywa-MuiFormControl-root > .MuiInputBase-root > #states-select').click(); + cy.get('[data-value="git-version-1"]').click(); + + cy.get('.css-70qsx4-MuiFormControl-root > .MuiInputBase-root > #states-select').click(); + cy.get('[data-value="git-commit-4"]').click(); + + cy.get('#save').click(); + + cy.wait(2000); + + const gitCommit = path.join(downloadsFolder, 'Peer Data.csv'); + + // Check whether the number of data exported based on git-commit-4 is correct. + cy.readFile(gitCommit) + .should('exist') + .then((fileContent) => { + const numEntries = fileContent.split('\n').length - 2; + + expect(numEntries).to.be.closeTo(1, 0); + }); + }); + + it('click cancel button', () => { + // Click export csv. + cy.get('.css-1st7tpv > .MuiButtonBase-root').click(); + cy.get('#alert-dialog-title').should('be.visible').and('have.text', 'Export'); + + // Select cluster-1 in the clusters selection box. + cy.get('.css-nvaly6-MuiFormControl-root > .MuiInputBase-root > #states-select').click(); + cy.get('[data-value="cluster-1"]').click(); + + // Select git-version-1 in the git version selection box. + cy.get('.css-g74ywa-MuiFormControl-root > .MuiInputBase-root > #states-select').click(); + cy.get('[data-value="git-version-1"]').click(); + + // Select git-commit-4 in the git commit selection box. + cy.get('.css-70qsx4-MuiFormControl-root > .MuiInputBase-root > #states-select').click(); + cy.get('[data-value="git-commit-4"]').click(); + + // Click cancel button. + cy.get('#cancel').click(); + + cy.get('.css-1st7tpv > .MuiButtonBase-root').click(); + + // Check whether the selected one is all. + cy.get('.css-nvaly6-MuiFormControl-root > .MuiInputBase-root > #states-select').should('have.text', 'All'); + cy.get('.css-g74ywa-MuiFormControl-root > .MuiInputBase-root > #states-select').should('have.text', 'All'); + cy.get('.css-70qsx4-MuiFormControl-root > .MuiInputBase-root > #states-select').should('have.text', 'All'); + }); + }); + + describe('when no data is loaded', () => { + beforeEach(() => { + cy.intercept( + { + method: 'GET', + url: '/api/v1/peers?page=1&per_page=10000000', + }, + (req) => { + req.reply({ + statusCode: 200, + body: [], + }); + }, + ); + }); + + it('should display the total number of peers', () => { + cy.get(':nth-child(1) > .MuiPaper-root > .inde_navigationContent__kHaOF').should('exist'); + cy.get( + ':nth-child(1) > .MuiPaper-root > .inde_navigationContent__kHaOF > div.MuiBox-root > .MuiTypography-h5', + ).should('have.text', 0); + }); + + it('should display the total number of git version', () => { + cy.get(':nth-child(2) > .MuiPaper-root > .inde_navigationContent__kHaOF').should('exist'); + cy.get( + ':nth-child(2) > .MuiPaper-root > .inde_navigationContent__kHaOF > div.MuiBox-root > .MuiTypography-h5', + ).should('have.text', 0); + }); + + it('should display the total number of git commit', () => { + cy.get(':nth-child(3) > .MuiPaper-root > .inde_navigationContent__kHaOF').should('exist'); + cy.get( + ':nth-child(3) > .MuiPaper-root > .inde_navigationContent__kHaOF > div.MuiBox-root > .MuiTypography-h5', + ).should('have.text', 0); + }); + + it('cannot display the active ratio', () => { + cy.get('#git-version-active').should('contain', '0'); + cy.get('#git-version-active').should('contain', '0'); + cy.get('#git-commit-active').should('contain', '0'); + }); + + it('cannot export csv file', () => { + cy.get('.css-1st7tpv > .MuiButtonBase-root').click(); + cy.get('#save').click(); + + // Show error message. + cy.get('.MuiAlert-message').should('have.text', 'Export failed'); + }); + }); + + describe('should handle API error response', () => { + beforeEach(() => { + cy.intercept( + { + method: 'GET', + url: '/api/v1/peers?page=1&per_page=10000000', + }, + (req) => { + req.reply({ + forceNetworkError: true, + }); + }, + ); + cy.visit('/insight/peers'); + }); + + it('should display the total number of peers', () => { + cy.get(':nth-child(1) > .MuiPaper-root > .inde_navigationContent__kHaOF').should('exist'); + cy.get( + ':nth-child(1) > .MuiPaper-root > .inde_navigationContent__kHaOF > div.MuiBox-root > .MuiTypography-h5', + ).should('have.text', 0); + }); + + it('should display the total number of git version', () => { + cy.get(':nth-child(2) > .MuiPaper-root > .inde_navigationContent__kHaOF').should('exist'); + cy.get( + ':nth-child(2) > .MuiPaper-root > .inde_navigationContent__kHaOF > div.MuiBox-root > .MuiTypography-h5', + ).should('have.text', 0); + }); + + it('should display the total number of git commit', () => { + cy.get(':nth-child(3) > .MuiPaper-root > .inde_navigationContent__kHaOF').should('exist'); + cy.get( + ':nth-child(3) > .MuiPaper-root > .inde_navigationContent__kHaOF > div.MuiBox-root > .MuiTypography-h5', + ).should('have.text', 0); + }); + + it('cannot display the active ratio', () => { + cy.get('#git-version-active').should('contain', '0'); + cy.get('#git-version-active').should('contain', '0'); + cy.get('#git-commit-active').should('contain', '0'); + }); + + it('show error message', () => { + // Show error message. + cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Failed to fetch'); + + // Close error message. + cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); + cy.get('.MuiAlert-message').should('not.exist'); + }); + + it('cannot export csv file', () => { + cy.get('.css-1st7tpv > .MuiButtonBase-root').click(); + cy.get('#save').click(); + + // Show error message. + cy.get('.MuiAlert-message').should('have.text', 'Export failed'); + }); + }); +}); diff --git a/cypress/fixtures/peers/peers.json b/cypress/fixtures/peers/peers.json new file mode 100644 index 0000000..cbc3c70 --- /dev/null +++ b/cypress/fixtures/peers/peers.json @@ -0,0 +1,324 @@ +[ + { + "id": 1, + "created_at": "2023-12-18T09:36:14Z", + "updated_at": "2023-12-18T09:36:14Z", + "is_del": 0, + "host_name": "peer-1", + "type": "super", + "idc": "sdfsd", + "location": "Hangzhou", + "ip": "30.44.96.255", + "port": 34001, + "download_port": 34201, + "object_storage_port": 0, + "state": "inactive", + "os": "linux", + "platform": "example", + "platform_family": "", + "platform_version": "7.2", + "kernel_version": "5.23.23", + "git_version": "git-version-1", + "git_commit": "commit-1", + "build_platform": "linux", + "scheduler_cluster_id": 1, + "scheduler_cluster": { + "id": 1, + "created_at": "2023-11-27T07:31:23Z", + "updated_at": "2023-11-27T07:31:23Z", + "is_del": 0, + "name": "cluster-1", + "bio": "", + "config": { + "candidate_parent_limit": 4, + "filter_parent_limit": 40 + }, + "client_config": { + "concurrent_piece_count": 4, + "load_limit": 50 + }, + "scopes": {}, + "is_default": true, + "seed_peer_clusters": null, + "schedulers": null, + "peers": null, + "jobs": null + } + }, + { + "id": 2, + "created_at": "2023-12-18T09:36:14Z", + "updated_at": "2023-12-18T09:36:14Z", + "is_del": 0, + "host_name": "peer-2", + "type": "super", + "idc": "sdfsd", + "location": "Hangzhou", + "ip": "30.44.96.255", + "port": 34001, + "download_port": 34201, + "object_storage_port": 0, + "state": "active", + "os": "linux", + "platform": "example", + "platform_family": "", + "platform_version": "7.2", + "kernel_version": "5.23.23", + "git_version": "git-version-2", + "git_commit": "git-commit-1", + "build_platform": "linux", + "scheduler_cluster_id": 1, + "scheduler_cluster": { + "id": 1, + "created_at": "2023-11-27T07:31:23Z", + "updated_at": "2023-11-27T07:31:23Z", + "is_del": 0, + "name": "cluster-1", + "bio": "", + "config": { + "candidate_parent_limit": 4, + "filter_parent_limit": 40 + }, + "client_config": { + "concurrent_piece_count": 4, + "load_limit": 50 + }, + "scopes": {}, + "is_default": true, + "seed_peer_clusters": null, + "schedulers": null, + "peers": null, + "jobs": null + } + }, + { + "id": 3, + "created_at": "2023-12-18T09:36:14Z", + "updated_at": "2023-12-18T09:36:14Z", + "is_del": 0, + "host_name": "peer-3", + "type": "super", + "idc": "sdfsd", + "location": "Hangzhou", + "ip": "30.44.96.255", + "port": 34001, + "download_port": 34201, + "object_storage_port": 0, + "state": "active", + "os": "linux", + "platform": "example", + "platform_family": "", + "platform_version": "7.2", + "kernel_version": "5.23.23", + "git_version": "git-version-2", + "git_commit": "git-commit-1", + "build_platform": "linux", + "scheduler_cluster_id": 1, + "scheduler_cluster": { + "id": 2, + "created_at": "2023-11-27T07:31:23Z", + "updated_at": "2023-11-27T07:31:23Z", + "is_del": 0, + "name": "cluster-2", + "bio": "", + "config": { + "candidate_parent_limit": 4, + "filter_parent_limit": 40 + }, + "client_config": { + "concurrent_piece_count": 4, + "load_limit": 50 + }, + "scopes": {}, + "is_default": true, + "seed_peer_clusters": null, + "schedulers": null, + "peers": null, + "jobs": null + } + }, + { + "id": 4, + "created_at": "2023-12-18T09:36:14Z", + "updated_at": "2023-12-18T09:36:14Z", + "is_del": 0, + "host_name": "peer-4", + "type": "super", + "idc": "sdfsd", + "location": "Hangzhou", + "ip": "30.44.96.255", + "port": 34001, + "download_port": 34201, + "object_storage_port": 0, + "state": "active", + "os": "linux", + "platform": "example", + "platform_family": "", + "platform_version": "7.2", + "kernel_version": "5.23.23", + "git_version": "git-version-3", + "git_commit": "git-commit-2", + "build_platform": "linux", + "scheduler_cluster_id": 1, + "scheduler_cluster": { + "id": 3, + "created_at": "2023-11-27T07:31:23Z", + "updated_at": "2023-11-27T07:31:23Z", + "is_del": 0, + "name": "cluster-3", + "bio": "", + "config": { + "candidate_parent_limit": 4, + "filter_parent_limit": 40 + }, + "client_config": { + "concurrent_piece_count": 4, + "load_limit": 50 + }, + "scopes": {}, + "is_default": true, + "seed_peer_clusters": null, + "schedulers": null, + "peers": null, + "jobs": null + } + }, + { + "id": 5, + "created_at": "2023-12-18T09:36:14Z", + "updated_at": "2023-12-18T09:36:14Z", + "is_del": 0, + "host_name": "peer-5", + "type": "super", + "idc": "sdfsd", + "location": "Hangzhou", + "ip": "30.44.96.255", + "port": 34001, + "download_port": 34201, + "object_storage_port": 0, + "state": "inactive", + "os": "linux", + "platform": "example", + "platform_family": "", + "platform_version": "7.2", + "kernel_version": "5.23.23", + "git_version": "git-version-3", + "git_commit": "git-commit-3", + "build_platform": "linux", + "scheduler_cluster_id": 1, + "scheduler_cluster": { + "id": 3, + "created_at": "2023-11-27T07:31:23Z", + "updated_at": "2023-11-27T07:31:23Z", + "is_del": 0, + "name": "cluster-3", + "bio": "", + "config": { + "candidate_parent_limit": 4, + "filter_parent_limit": 40 + }, + "client_config": { + "concurrent_piece_count": 4, + "load_limit": 50 + }, + "scopes": {}, + "is_default": true, + "seed_peer_clusters": null, + "schedulers": null, + "peers": null, + "jobs": null + } + }, + { + "id": 6, + "created_at": "2023-12-18T09:36:14Z", + "updated_at": "2023-12-18T09:36:14Z", + "is_del": 0, + "host_name": "peer-6", + "type": "super", + "idc": "sdfsd", + "location": "Hangzhou", + "ip": "30.44.96.255", + "port": 34001, + "download_port": 34201, + "object_storage_port": 0, + "state": "active", + "os": "linux", + "platform": "example", + "platform_family": "", + "platform_version": "7.2", + "kernel_version": "5.23.23", + "git_version": "git-version-4", + "git_commit": "git-commit-4", + "build_platform": "linux", + "scheduler_cluster_id": 1, + "scheduler_cluster": { + "id": 4, + "created_at": "2023-11-27T07:31:23Z", + "updated_at": "2023-11-27T07:31:23Z", + "is_del": 0, + "name": "cluster-4", + "bio": "", + "config": { + "candidate_parent_limit": 4, + "filter_parent_limit": 40 + }, + "client_config": { + "concurrent_piece_count": 4, + "load_limit": 50 + }, + "scopes": {}, + "is_default": true, + "seed_peer_clusters": null, + "schedulers": null, + "peers": null, + "jobs": null + } + }, + { + "id": 7, + "created_at": "2023-12-18T09:36:14Z", + "updated_at": "2023-12-18T09:36:14Z", + "is_del": 0, + "host_name": "peer-7", + "type": "super", + "idc": "sdfsd", + "location": "Hangzhou", + "ip": "30.44.96.255", + "port": 34001, + "download_port": 34201, + "object_storage_port": 0, + "state": "active", + "os": "linux", + "platform": "example", + "platform_family": "", + "platform_version": "7.2", + "kernel_version": "5.23.23", + "git_version": "git-version-1", + "git_commit": "git-commit-4", + "build_platform": "linux", + "scheduler_cluster_id": 1, + "scheduler_cluster": { + "id": 1, + "created_at": "2023-11-27T07:31:23Z", + "updated_at": "2023-11-27T07:31:23Z", + "is_del": 0, + "name": "cluster-1", + "bio": "", + "config": { + "candidate_parent_limit": 4, + "filter_parent_limit": 40 + }, + "client_config": { + "concurrent_piece_count": 4, + "load_limit": 50 + }, + "scopes": {}, + "is_default": true, + "seed_peer_clusters": null, + "schedulers": null, + "peers": null, + "jobs": null + } + } +] diff --git a/package.json b/package.json index 135c3f0..d83260e 100644 --- a/package.json +++ b/package.json @@ -110,5 +110,8 @@ "*.{css,sass}": [ "prettier --write" ] + }, + "nyc": { + "exclude": "src/reportWebVitals.ts" } } diff --git a/src/components/insight/peer/index.tsx b/src/components/insight/peer/index.tsx index 3cb3bae..e5494ed 100644 --- a/src/components/insight/peer/index.tsx +++ b/src/components/insight/peer/index.tsx @@ -20,7 +20,6 @@ import { Snackbar, Alert, Tooltip as MuiTooltip, - Chip, } from '@mui/material'; import { Chart as ChartJS, @@ -497,6 +496,10 @@ export default function Peer() { { key: 'scheduler_cluster.client_config.load_limit', label: 'schedulerCluster.clientConfig.loadLimit' }, ]; try { + if (peer.length === 0) { + throw Error; + } + if (exportSelectedVersion === 'All' && exportSelectedCommit === 'All' && exportSelectedCluster === 'All') { exportCSVFile(headers, peer, 'Peer Data'); setLoadingButton(false); @@ -692,7 +695,7 @@ export default function Peer() { Active - + {isLoading ? : clusterActive ? `${clusterActive}%` : '0'} @@ -790,7 +793,7 @@ export default function Peer() { Active - + {isLoading ? : gitVersionActive ? `${gitVersionActive}%` : '0'} @@ -914,7 +917,7 @@ export default function Peer() { Active - + {isLoading ? : gitCommitActive ? `${gitCommitActive}%` : '0'} @@ -1024,6 +1027,7 @@ export default function Peer() { size="small" variant="outlined" loadingPosition="end" + id="cancel" sx={{ '&.MuiLoadingButton-root': { color: 'var(--calcel-size-color)', @@ -1058,6 +1062,7 @@ export default function Peer() { variant="outlined" type="submit" loadingPosition="end" + id="save" sx={{ '&.MuiLoadingButton-root': { backgroundColor: 'var(--save-color)',