feat: add create cluster e2e test (#323)
This commit is contained in:
		
							parent
							
								
									28144ff820
								
							
						
					
					
						commit
						4ccfc9a03f
					
				|  | @ -40,7 +40,8 @@ describe('404', () => { | |||
|     cy.visit('/root'); | ||||
|     cy.get('.MuiTypography-h4').should('have.text', 'Something gone wrong!'); | ||||
|     cy.get('.MuiButtonBase-root').click(); | ||||
|     // Then I see that the current page is the clusters
 | ||||
|      | ||||
|     // Then I see that the current page is the clusters.
 | ||||
|     cy.url().should('include', '/clusters'); | ||||
|   }); | ||||
| }); | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ import root from '../fixtures/api/role-root.json'; | |||
| import user from '../fixtures/api/user.json'; | ||||
| import seedPeers from '../fixtures/api/clusters/seed-peers.json'; | ||||
| import schedulers from '../fixtures/api/clusters/schedulers.json'; | ||||
| import clusterSearch from '../fixtures/api/clusters/cluster-search.json'; | ||||
| import searchCluster from '../fixtures/api/clusters/search-cluster.json'; | ||||
| 
 | ||||
| describe('Clusters', () => { | ||||
|   beforeEach(() => { | ||||
|  | @ -117,21 +117,21 @@ describe('Clusters', () => { | |||
|     }); | ||||
| 
 | ||||
|     it('can display clusters card', () => { | ||||
|       // displays a card componen
 | ||||
|       // Display the card component.
 | ||||
|       cy.get('.MuiBackdrop-root > .MuiBox-root').should('exist'); | ||||
| 
 | ||||
|       // display Default background color
 | ||||
|       // Show Default background color.
 | ||||
|       cy.get(':nth-child(1) > .MuiPaper-root > .clusters_clusterListContent__UwWjF > #isDefault') | ||||
|         .should('be.visible') | ||||
|         .and('contain', 'Default') | ||||
|         .and('have.css', 'background-color', 'rgb(46, 143, 121)'); | ||||
| 
 | ||||
|       // display cluster name
 | ||||
|       // Show cluster name.
 | ||||
|       cy.get(':nth-child(1) > .MuiPaper-root > .clusters_clusterListContent__UwWjF > .MuiTypography-h6') | ||||
|         .should('be.visible') | ||||
|         .and('contain', 'cluster-1'); | ||||
| 
 | ||||
|       // display cluster description
 | ||||
|       // Show cluster description.
 | ||||
|       cy.get(':nth-child(1) > .MuiPaper-root > .clusters_clusterListContent__UwWjF > .css-m4gmz7 > .MuiTypography-root') | ||||
|         .should('be.visible') | ||||
|         .and( | ||||
|  | @ -139,12 +139,12 @@ describe('Clusters', () => { | |||
|           'Cluster-1 is a high-performance computing cluster located in China, specifically in Hangzhou and Beijing data centers.', | ||||
|         ); | ||||
| 
 | ||||
|       // display Non-Default cluster
 | ||||
|       // Show Non-Default cluster.
 | ||||
|       cy.get(':nth-child(8) > .MuiPaper-root > .clusters_clusterListContent__UwWjF > .MuiTypography-h6') | ||||
|         .should('be.visible') | ||||
|         .and('contain', 'cluster-2'); | ||||
| 
 | ||||
|       // display Non-Default background color
 | ||||
|       // Show Non-Default background color.
 | ||||
|       cy.get(':nth-child(8) > .MuiPaper-root > .clusters_clusterListContent__UwWjF > #isDefault') | ||||
|         .should('be.visible') | ||||
|         .and('contain', 'Non-Default') | ||||
|  | @ -239,7 +239,8 @@ describe('Clusters', () => { | |||
| 
 | ||||
|     it('cluster card should present an empty status', () => { | ||||
|       cy.get('#clusters').should('not.exist'); | ||||
|       // shouldn't render pagination buttons
 | ||||
| 
 | ||||
|       // Shouldn't render pagination buttons.
 | ||||
|       cy.get('#clusterPagination > .MuiPagination-ul').should('not.exist'); | ||||
|     }); | ||||
|   }); | ||||
|  | @ -248,10 +249,10 @@ describe('Clusters', () => { | |||
|     it('pagination updates results and page number', () => { | ||||
|       cy.get('.Mui-selected').invoke('text').should('eq', 'Cluster1'); | ||||
| 
 | ||||
|       //total number of pages
 | ||||
|       // Check number of pagination.
 | ||||
|       cy.get('#clusterPagination > .MuiPagination-ul').children().should('have.length', 4); | ||||
| 
 | ||||
|       // show cluster name
 | ||||
|       // Show cluster name.
 | ||||
|       cy.get(':nth-child(1) > .MuiPaper-root > .clusters_clusterListContent__UwWjF > .MuiTypography-h6') | ||||
|         .should('be.visible') | ||||
|         .and('contain', 'cluster-1'); | ||||
|  | @ -260,13 +261,13 @@ describe('Clusters', () => { | |||
|     it('when pagination changes, different page results are rendered', () => { | ||||
|       cy.get('.Mui-selected').invoke('text').should('eq', 'Cluster1'); | ||||
| 
 | ||||
|       // go to last page
 | ||||
|       // Go to last page.
 | ||||
|       cy.get('.MuiPagination-ul > :nth-child(3) > .MuiButtonBase-root').click(); | ||||
| 
 | ||||
|       // display last page cluster information
 | ||||
|       // Display last page cluster information.
 | ||||
|       cy.get('.clusters_clusterListContent__UwWjF > .css-k008qs').should('be.visible').and('contain', '8'); | ||||
| 
 | ||||
|       // display cluster information
 | ||||
|       // Display cluster information.
 | ||||
|       cy.get('#isDefault') | ||||
|         .should('be.visible') | ||||
|         .and('contain', 'Non-Default') | ||||
|  | @ -283,25 +284,27 @@ describe('Clusters', () => { | |||
|           'Cluster-8 is a high-performance computing cluster located in China, specifically in Jiangsu data centers.', | ||||
|         ); | ||||
| 
 | ||||
|       // current page number
 | ||||
|       // Check the current page number.
 | ||||
|       cy.get('#clusterPagination > .MuiPagination-ul .Mui-selected').should('have.text', '2'); | ||||
|     }); | ||||
| 
 | ||||
|     it('pagination resets results and page number to first page when refresh is clicked', () => { | ||||
|       // Go to last page
 | ||||
|       // Go to last page.
 | ||||
|       cy.get('.MuiPagination-ul > :nth-child(3) > .MuiButtonBase-root').click(); | ||||
| 
 | ||||
|       cy.get('.clusters_clusterListContent__UwWjF > .MuiTypography-h6') | ||||
|         .should('be.visible') | ||||
|         .and('contain', 'cluster-8'); | ||||
| 
 | ||||
|       // Check the current page number.
 | ||||
|       cy.get('#clusterPagination > .MuiPagination-ul .Mui-selected').should('have.text', '2'); | ||||
|       // refresh page
 | ||||
| 
 | ||||
|       // Refresh page.
 | ||||
|       cy.reload().then(() => { | ||||
|         cy.wait(2000); | ||||
|       }); | ||||
| 
 | ||||
|       // page numbers have been reset
 | ||||
|       // Check if the page number has been reset.
 | ||||
|       cy.get('#clusterPagination > .MuiPagination-ul .Mui-selected').should('have.text', '1'); | ||||
| 
 | ||||
|       cy.get(':nth-child(1) > .MuiPaper-root > .clusters_clusterListContent__UwWjF > .MuiTypography-h6') | ||||
|  | @ -338,12 +341,12 @@ describe('Clusters', () => { | |||
|     }); | ||||
| 
 | ||||
|     it('show error message', () => { | ||||
|       // show error message
 | ||||
|       // Show error message.
 | ||||
|       cy.get('.css-1rr4qq7 > .MuiSnackbar-root > .MuiPaper-root > .MuiAlert-message') | ||||
|         .should('be.visible') | ||||
|         .and('contain', 'Failed to fetch'); | ||||
| 
 | ||||
|       // close error message
 | ||||
|       // Close error message.
 | ||||
|       cy.get('.css-1rr4qq7 > .MuiSnackbar-root > .MuiPaper-root > .MuiAlert-action > .MuiButtonBase-root').click(); | ||||
|       cy.get('.css-1rr4qq7 > .MuiSnackbar-root > .MuiPaper-root > .MuiAlert-message').should('not.exist'); | ||||
|     }); | ||||
|  | @ -392,9 +395,10 @@ describe('Clusters', () => { | |||
|     }); | ||||
| 
 | ||||
|     it('cluster card should present an empty status', () => { | ||||
|       // no clusters
 | ||||
|       // No clusters.
 | ||||
|       cy.get('#clusters').should('not.exist'); | ||||
|       // no pagination
 | ||||
| 
 | ||||
|       // No pagination.
 | ||||
|       cy.get('#clusterPagination > .MuiPagination-ul').should('not.exist'); | ||||
|     }); | ||||
|   }); | ||||
|  | @ -409,20 +413,21 @@ describe('Clusters', () => { | |||
|         (req) => { | ||||
|           req.reply({ | ||||
|             statusCode: 200, | ||||
|             body: clusterSearch, | ||||
|             body: searchCluster, | ||||
|           }); | ||||
|         }, | ||||
|       ); | ||||
|       cy.get('#free-solo-demo').type('cluster-1{enter}'); | ||||
|       cy.get('#clusterPagination > .MuiPagination-ul').should('not.exist'); | ||||
| 
 | ||||
|       // clear search box
 | ||||
|       // Clear search box.
 | ||||
|       cy.get('#free-solo-demo').clear(); | ||||
|       //search all clusters
 | ||||
| 
 | ||||
|       // If the search is empty, all clusters will be displayed.
 | ||||
|       cy.get('#free-solo-demo').type('{enter}'); | ||||
|       cy.get('#clusterPagination > .MuiPagination-ul').should('exist'); | ||||
| 
 | ||||
|       // number of pagination
 | ||||
|       // Check number of pagination.
 | ||||
|       cy.get('#clusterPagination > .MuiPagination-ul').children().should('have.length', 4); | ||||
| 
 | ||||
|       cy.get(':nth-child(1) > .MuiPaper-root > .clusters_clusterListContent__UwWjF > .MuiTypography-h6') | ||||
|  | @ -449,9 +454,11 @@ describe('Clusters', () => { | |||
|       ); | ||||
| 
 | ||||
|       cy.get('#free-solo-demo').type('cluster-16{enter}'); | ||||
|       //no clusters card
 | ||||
| 
 | ||||
|       // No clusters card.
 | ||||
|       cy.get('#clusters').should('not.exist'); | ||||
|       // hidden pagination
 | ||||
| 
 | ||||
|       // Pagination has been hidden.
 | ||||
|       cy.get('#clusterPagination > .MuiPagination-ul').should('not.exist'); | ||||
|     }); | ||||
| 
 | ||||
|  | @ -470,7 +477,8 @@ describe('Clusters', () => { | |||
| 
 | ||||
|       cy.get('#free-solo-demo').clear(); | ||||
|       cy.get('#free-solo-demo').type('cluster-1{enter}'); | ||||
|       // error message
 | ||||
| 
 | ||||
|       // Show error message.
 | ||||
|       cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Failed to fetch'); | ||||
|     }); | ||||
|   }); | ||||
|  |  | |||
|  | @ -0,0 +1,465 @@ | |||
| import clusters from '../fixtures/api/clusters/clusters.json'; | ||||
| import root from '../fixtures/api/role-root.json'; | ||||
| import guest from '../fixtures/api/role-guest.json'; | ||||
| import user from '../fixtures/api/user.json'; | ||||
| import guestUser from '../fixtures/api/guest-user.json'; | ||||
| import seedPeers from '../fixtures/api/clusters/seed-peers.json'; | ||||
| import schedulers from '../fixtures/api/clusters/schedulers.json'; | ||||
| import createClustes from '../fixtures/api/clusters/create-cluster.json'; | ||||
| import _ from 'lodash'; | ||||
| 
 | ||||
| describe('Create cluster', () => { | ||||
|   beforeEach(() => { | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'GET', | ||||
|         url: '/api/v1/schedulers?page=1&per_page=10000000', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: schedulers, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'GET', | ||||
|         url: '/api/v1/clusters?page=1&per_page=10000000', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: clusters, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'GET', | ||||
|         url: '/api/v1/seed-peers?page=1&per_page=10000000', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: seedPeers, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
|     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.signin(); | ||||
|     cy.visit('/clusters/new'); | ||||
|     cy.viewport(1440, 1080); | ||||
|   }); | ||||
| 
 | ||||
|   it('can create cluster', () => { | ||||
|     cy.visit('/clusters'); | ||||
| 
 | ||||
|     // Show number of cluster.
 | ||||
|     cy.get( | ||||
|       ':nth-child(1) > .css-q5fqw0 > .clusters_clusterContentContainer__ZxKuh > .css-zm3ms > .css-70qvj9 > .MuiTypography-root', | ||||
|     ) | ||||
|       .should('be.visible') | ||||
|       .and('contain', '11'); | ||||
| 
 | ||||
|     // Show number of cluster default.
 | ||||
|     cy.get( | ||||
|       ':nth-child(1) > .css-q5fqw0 > .clusters_clusterContentContainer__ZxKuh > .css-zm3ms > .MuiGrid-root > .clusters_clusterBottomContentContainer__KII0M > .clusters_clusterBottomContent__k3P4u', | ||||
|     ) | ||||
|       .should('be.visible') | ||||
|       .and('contain', '7'); | ||||
| 
 | ||||
|     // Click the `ADD CLUSTER` button.
 | ||||
|     cy.get('.clusters_clusterTitle__5Lhnw > .MuiButtonBase-root').click(); | ||||
| 
 | ||||
|     cy.url().should('include', '/clusters/new'); | ||||
| 
 | ||||
|     // Add Information.
 | ||||
|     cy.get('.PrivateSwitchBase-input').click(); | ||||
|     cy.get('#name').type('cluster-12'); | ||||
|     cy.get('#description').type('Add new cluster case'); | ||||
|     cy.get('#location').type('China|Hang|Zhou'); | ||||
| 
 | ||||
|     // Add idc.
 | ||||
|     cy.get(':nth-child(2) > .MuiAutocomplete-root > .MuiFormControl-root > .MuiInputBase-root').type('hz{enter}'); | ||||
|     cy.get(':nth-child(2) > .MuiAutocomplete-root > .MuiFormControl-root > .MuiInputBase-root').type('sh{enter}'); | ||||
|     cy.get(':nth-child(3) > .MuiAutocomplete-root > .MuiFormControl-root > .MuiInputBase-root').click(); | ||||
| 
 | ||||
|     // Add cidrs.
 | ||||
|     cy.contains('li', '10.0.0.0/8').click(); | ||||
|     cy.get(':nth-child(3) > .MuiAutocomplete-root > .MuiFormControl-root > .MuiInputBase-root').click(); | ||||
|     cy.contains('li', '172.16.0.0/12').click(); | ||||
|     cy.get(':nth-child(3) > .MuiAutocomplete-root > .MuiFormControl-root > .MuiInputBase-root').click(); | ||||
|     cy.contains('li', '192.168.0.0/16').click(); | ||||
| 
 | ||||
|     // Add config.
 | ||||
|     cy.get(':nth-child(3) > .MuiInputBase-root').clear(); | ||||
|     cy.get(':nth-child(3) > .MuiInputBase-root').type('10'); | ||||
| 
 | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'POST', | ||||
|         url: '/api/v1/clusters', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.body = ''; | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: [], | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'GET', | ||||
|         url: '/api/v1/clusters?page=1&per_page=10000000', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: createClustes, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
| 
 | ||||
|     // Click the `save` button.
 | ||||
|     cy.get('#save').click(); | ||||
| 
 | ||||
|     // Then I see that the current page is the clusters.
 | ||||
|     cy.url().should('include', '/clusters'); | ||||
| 
 | ||||
|     // Displays successfully added clusters.
 | ||||
|     cy.get(':nth-child(8) > .MuiPaper-root > .clusters_clusterListContent__UwWjF > .MuiTypography-h6') | ||||
|       .should('be.visible') | ||||
|       .and('contain', 'cluster-12'); | ||||
| 
 | ||||
|     // The number of clusters has been increased.
 | ||||
|     cy.get( | ||||
|       ':nth-child(1) > .css-q5fqw0 > .clusters_clusterContentContainer__ZxKuh > .css-zm3ms > .css-70qvj9 > .MuiTypography-root', | ||||
|     ) | ||||
|       .should('be.visible') | ||||
|       .and('contain', '12'); | ||||
| 
 | ||||
|     // The default number of clusters has been increased.
 | ||||
|     cy.get( | ||||
|       ':nth-child(1) > .css-q5fqw0 > .clusters_clusterContentContainer__ZxKuh > .css-zm3ms > .MuiGrid-root > .clusters_clusterBottomContentContainer__KII0M > .clusters_clusterBottomContent__k3P4u', | ||||
|     ) | ||||
|       .should('be.visible') | ||||
|       .and('contain', '8'); | ||||
|   }); | ||||
| 
 | ||||
|   it('cannot create cluster with existing cluster', () => { | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'POST', | ||||
|         url: '/api/v1/clusters', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.body = { | ||||
|           name: 'cluster-1', | ||||
|           bio: '', | ||||
|           scopes: { | ||||
|             idc: '', | ||||
|             location: '', | ||||
|             cidrs: [], | ||||
|           }, | ||||
|           scheduler_cluster_config: { | ||||
|             filter_parent_limit: 4, | ||||
|             filter_parent_range_limit: 40, | ||||
|           }, | ||||
|           seed_peer_cluster_config: { | ||||
|             load_limit: 300, | ||||
|           }, | ||||
|           peer_cluster_config: { | ||||
|             load_limit: 50, | ||||
|             concurrent_piece_count: 4, | ||||
|           }, | ||||
|           is_default: true, | ||||
|         }; | ||||
|         req.reply({ | ||||
|           statusCode: 409, | ||||
|           body: { message: 'Conflict' }, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
| 
 | ||||
|     cy.get('#name').type('cluster-1{enter}'); | ||||
| 
 | ||||
|     // Show error message.
 | ||||
|     cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Conflict'); | ||||
|     cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); | ||||
|     cy.get('.MuiPaper-root').should('not.exist'); | ||||
|   }); | ||||
| 
 | ||||
|   it('click the `CANCEL button', () => { | ||||
|     cy.get('#cancel').click(); | ||||
| 
 | ||||
|     // Then I see that the current page is the clusters.
 | ||||
|     cy.url().should('include', '/clusters'); | ||||
|   }); | ||||
| 
 | ||||
|   it('cannot create cluster without required attributes', () => { | ||||
|     cy.get('#save').click(); | ||||
| 
 | ||||
|     cy.get('#name-helper-text').should('be.visible').and('contain', 'Fill in the characters, the length is 1-40.'); | ||||
|   }); | ||||
| 
 | ||||
|   it('try to create cluster with guest user', () => { | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'GET', | ||||
|         url: '/api/v1/users/2', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: guestUser, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'GET', | ||||
|         url: '/api/v1/users/2/roles', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: guest, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
| 
 | ||||
|     cy.guestSignin(); | ||||
| 
 | ||||
|     cy.intercept({ method: 'POST', url: '/api/v1/clusters' }, (req) => { | ||||
|       (req.body = ''), | ||||
|         req.reply({ | ||||
|           statusCode: 401, | ||||
|           body: { message: 'permission deny' }, | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|     cy.get('#name').type('cluster-12{enter}'); | ||||
| 
 | ||||
|     // Show error message.
 | ||||
|     cy.get('.MuiAlert-message').should('be.visible').and('contain', 'permission deny'); | ||||
| 
 | ||||
|     cy.get('#cancel').click(); | ||||
| 
 | ||||
|     cy.wait(1000); | ||||
| 
 | ||||
|     // Then I see that the current page is the clusters!
 | ||||
|     cy.url().should('include', '/clusters'); | ||||
|   }); | ||||
| 
 | ||||
|   it('should handle API error response', () => { | ||||
|     cy.intercept({ method: 'POST', url: '/api/v1/clusters' }, (req) => { | ||||
|       (req.body = ''), | ||||
|         req.reply({ | ||||
|           forceNetworkError: true, | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|     cy.get('#name').type('cluster-12'); | ||||
|     cy.get('#save').click(); | ||||
|     cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Failed to fetch'); | ||||
|   }); | ||||
| 
 | ||||
|   describe('cannot create cluster with invalid attributes', () => { | ||||
|     it('try to verify information', () => { | ||||
|       const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; | ||||
|       const name = _.times(41, () => _.sample(characters)).join(''); | ||||
|       const description = _.times(1001, () => _.sample(characters)).join(''); | ||||
| 
 | ||||
|       // Should display message name the validation error.
 | ||||
|       cy.get('#save').click(); | ||||
| 
 | ||||
|       // Name is a required attribute.
 | ||||
|       cy.get('#name-helper-text').should('be.visible').and('contain', 'Fill in the characters, the length is 1-40.'); | ||||
|       cy.get('#name').type(name); | ||||
| 
 | ||||
|       // Show verification error message.
 | ||||
|       cy.get('#name-helper-text').should('be.visible').and('contain', 'Fill in the characters, the length is 1-40.'); | ||||
| 
 | ||||
|       // Submit form when validation fails
 | ||||
|       cy.get('#save').click(); | ||||
| 
 | ||||
|       // Cluster creation failed, the page is still in cluster/new.
 | ||||
|       cy.url().should('include', '/clusters/new'); | ||||
|       cy.get('#name').clear(); | ||||
| 
 | ||||
|       // Enter the correct name。
 | ||||
|       cy.get('#name').type('cluster-12'); | ||||
|       cy.get('#name-helper-text').should('not.exist'); | ||||
| 
 | ||||
|       // Should display message describing the validation error.
 | ||||
|       cy.get('#description').type(description); | ||||
| 
 | ||||
|       // Show verification error message.
 | ||||
|       cy.get('#description-helper-text') | ||||
|         .should('be.visible') | ||||
|         .and('contain', 'Fill in the characters, the length is 0-1000.'); | ||||
|       cy.get('#save').click(); | ||||
|       cy.url().should('include', '/clusters/new'); | ||||
|       cy.get('#description').clear(); | ||||
|       cy.get('#description').type('cluster description'); | ||||
|       cy.get('#name-helper-text').should('not.exist'); | ||||
|     }); | ||||
| 
 | ||||
|     it('try to verify scopes', () => { | ||||
|       const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; | ||||
|       const location = _.times(101, () => _.sample(characters)).join(''); | ||||
| 
 | ||||
|       // Name is a required attribute.
 | ||||
|       cy.get('#name').type('cluster-12'); | ||||
| 
 | ||||
|       // Should display location the validation error message.
 | ||||
|       cy.get('#location').type(location); | ||||
| 
 | ||||
|       // Show verification error message.
 | ||||
|       cy.get('#location-helper-text') | ||||
|         .should('be.visible') | ||||
|         .and('contain', 'Fill in the characters, the length is 0-100.'); | ||||
|       cy.get('#save').click(); | ||||
|       cy.url().should('include', '/clusters/new'); | ||||
|       cy.get('#location').clear(); | ||||
| 
 | ||||
|       // Verification passed.
 | ||||
|       cy.get('#location').type('Beijing'); | ||||
|       cy.get('#location-helper-text').should('not.exist'); | ||||
| 
 | ||||
|       // Should display idc the validation error message.
 | ||||
|       cy.get(':nth-child(2) > .MuiAutocomplete-root > .MuiFormControl-root > .MuiInputBase-root').type('hz'); | ||||
|       cy.get('#save').click(); | ||||
|       cy.url().should('include', '/clusters/new'); | ||||
|       cy.get('#idc-helper-text').should('be.visible').and('contain', `Please press ENTER to end the IDC creation.`); | ||||
|       cy.get(':nth-child(2) > .MuiAutocomplete-root > .MuiFormControl-root > .MuiInputBase-root').type('hz{enter}'); | ||||
| 
 | ||||
|       // Verification passed.
 | ||||
|       cy.get('#idc-helper-text').should('not.exist'); | ||||
| 
 | ||||
|       // Should display cidrs the validation error message.
 | ||||
|       cy.get(':nth-child(3) > .MuiAutocomplete-root > .MuiFormControl-root > .MuiInputBase-root').type( | ||||
|         '192.168.40.0/24', | ||||
|       ); | ||||
|       cy.get('#save').click(); | ||||
|       cy.url().should('include', '/clusters/new'); | ||||
|       cy.get('#cidrs-helper-text').should('be.visible').and('contain', `Please press ENTER to end the CIDRs creation.`); | ||||
| 
 | ||||
|       cy.get(':nth-child(3) > .MuiAutocomplete-root > .MuiFormControl-root > .MuiInputBase-root').type( | ||||
|         '192.168.40.0/24{enter}', | ||||
|       ); | ||||
| 
 | ||||
|       // Verification passed.
 | ||||
|       cy.get('#cidrs-helper-text').should('not.exist'); | ||||
|     }); | ||||
| 
 | ||||
|     it('try to verify config', () => { | ||||
|       // Name is a required attribute.
 | ||||
|       cy.get('#name').type('cluster-12'); | ||||
| 
 | ||||
|       // Should display seed peer load limit the validation error message.
 | ||||
|       cy.get('#seedPeerLoadLimit').type('5000'); | ||||
|       cy.get('#seedPeerLoadLimit-helper-text') | ||||
|         .should('be.visible') | ||||
|         .and('contain', `Fill in the number, the length is 0-5000.`); | ||||
|       cy.get('#save').click(); | ||||
|       cy.url().should('include', '/clusters/new'); | ||||
|       cy.get('#seedPeerLoadLimit').clear(); | ||||
|       cy.get('#seedPeerLoadLimit').type('400'); | ||||
| 
 | ||||
|       // Verification passed.
 | ||||
|       cy.get('#seedPeerLoadLimit-helper-text').should('not.exist'); | ||||
| 
 | ||||
|       // Should display peer load limit the validation error message.
 | ||||
|       cy.get('#peerLoadLimit').clear(); | ||||
|       cy.get('#peerLoadLimit').type('2001'); | ||||
|       cy.get('#peerLoadLimit-helper-text') | ||||
|         .should('be.visible') | ||||
|         .and('contain', `Fill in the number, the length is 0-2000.`); | ||||
|       cy.get('#save').click(); | ||||
|       cy.url().should('include', '/clusters/new'); | ||||
|       cy.get('#peerLoadLimit').clear(); | ||||
|       cy.get('#peerLoadLimit').type('50'); | ||||
| 
 | ||||
|       // Verification passed.
 | ||||
|       cy.get('#peerLoadLimit-helper-text').should('not.exist'); | ||||
| 
 | ||||
|       // Should display number of concurrent download pieces the validation error message.
 | ||||
|       cy.get('#numberOfConcurrentDownloadPieces').clear(); | ||||
|       cy.get('#numberOfConcurrentDownloadPieces').type('51'); | ||||
|       cy.get('#numberOfConcurrentDownloadPieces-helper-text') | ||||
|         .should('be.visible') | ||||
|         .and('contain', `Fill in the number, the length is 0-50.`); | ||||
|       cy.get('#save').click(); | ||||
|       cy.url().should('include', '/clusters/new'); | ||||
|       cy.get('#numberOfConcurrentDownloadPieces').clear(); | ||||
|       cy.get('#numberOfConcurrentDownloadPieces').type('10'); | ||||
| 
 | ||||
|       // Verification passed.
 | ||||
|       cy.get('#numberOfConcurrentDownloadPieces-helper-text').should('not.exist'); | ||||
| 
 | ||||
|       // Should display candidate parent limit the validation error message.
 | ||||
|       cy.get('#candidateParentLimit').clear(); | ||||
|       cy.get('#candidateParentLimit').type('21'); | ||||
|       cy.get('#candidateParentLimit-helper-text') | ||||
|         .should('be.visible') | ||||
|         .and('contain', `Fill in the number, the length is 1-20.`); | ||||
|       cy.get('#save').click(); | ||||
|       cy.url().should('include', '/clusters/new'); | ||||
|       cy.get('#candidateParentLimit').clear(); | ||||
|       cy.get('#candidateParentLimit').type('5'); | ||||
|       cy.get('#candidateParentLimit-helper-text').should('not.exist'); | ||||
| 
 | ||||
|       // Should display filter parent limit the validation error message.
 | ||||
|       cy.get('#filterParentLimit').clear(); | ||||
| 
 | ||||
|       // Minimum validation range not reached.
 | ||||
|       cy.get('#filterParentLimit').type('9'); | ||||
|       cy.get('#filterParentLimit-helper-text') | ||||
|         .should('be.visible') | ||||
|         .and('contain', `Fill in the number, the length is 10-1000.`); | ||||
|       cy.get('#save').click(); | ||||
|       cy.url().should('include', '/clusters/new'); | ||||
|       cy.get('#filterParentLimit').clear(); | ||||
| 
 | ||||
|       // Maximum verification range exceeded.
 | ||||
|       cy.get('#filterParentLimit').type('1001'); | ||||
|       cy.get('#filterParentLimit-helper-text') | ||||
|         .should('be.visible') | ||||
|         .and('contain', `Fill in the number, the length is 10-1000.`); | ||||
|       cy.get('#save').click(); | ||||
|       cy.url().should('include', '/clusters/new'); | ||||
|       cy.get('#filterParentLimit').clear(); | ||||
|       cy.get('#filterParentLimit').type('100'); | ||||
| 
 | ||||
|       // Verification passed.
 | ||||
|       cy.get('#filterParentLimit-helper-text').should('not.exist'); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
|  | @ -94,16 +94,19 @@ describe('Signin', () => { | |||
| 
 | ||||
|     cy.signin(); | ||||
|     cy.get('form').submit(); | ||||
|     // Then I see that the current page is the clusters
 | ||||
| 
 | ||||
|     // Then I see that the current page is the clusters.
 | ||||
|     cy.url().should('include', '/clusters'); | ||||
|     cy.location('pathname').should('eq', '/clusters'); | ||||
|     //prompt message: Please change your password promptly when logging in for the first time!
 | ||||
|     cy.get('.MuiSnackbar-root > .MuiPaper-root').should('exist'); | ||||
|     // close prompt message
 | ||||
|     cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); | ||||
| 
 | ||||
|     // Prompt message: Please change your password promptly when logging in for the first time!
 | ||||
|     cy.get('.MuiSnackbar-root > .MuiPaper-root').should('exist'); | ||||
| 
 | ||||
|     // Close the prompt message.
 | ||||
|     cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); | ||||
|     cy.get('.MuiSnackbar-root > .MuiPaper-root').should('not.exist'); | ||||
|     // menu exists for users
 | ||||
| 
 | ||||
|     // Menu exists for users.
 | ||||
|     cy.get('[href="/users"]').should('exist'); | ||||
|   }); | ||||
| 
 | ||||
|  | @ -111,11 +114,10 @@ describe('Signin', () => { | |||
|     cy.get('#account').type('root'); | ||||
|     cy.get('#password').type('rooot1'); | ||||
|     cy.get('form').submit(); | ||||
|     // show error message
 | ||||
|     cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Unauthorized'); | ||||
|     // close error message
 | ||||
|     cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); | ||||
| 
 | ||||
|     // Show error message.
 | ||||
|     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'); | ||||
|   }); | ||||
| 
 | ||||
|  | @ -123,11 +125,10 @@ describe('Signin', () => { | |||
|     cy.get('#account').type('root-1'); | ||||
|     cy.get('#password').type('dragonfly'); | ||||
|     cy.get('form').submit(); | ||||
|     // show error message
 | ||||
|     cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Unauthorized'); | ||||
|     // close error message
 | ||||
|     cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); | ||||
| 
 | ||||
|     // Show error message.
 | ||||
|     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'); | ||||
|   }); | ||||
| 
 | ||||
|  | @ -166,29 +167,34 @@ describe('Signin', () => { | |||
| 
 | ||||
|     cy.get('#account').type('root-2'); | ||||
|     cy.get('#password').type(`dragonfly`); | ||||
|     // guest user
 | ||||
| 
 | ||||
|     cy.guestSignin(); | ||||
| 
 | ||||
|     cy.get('form').submit(); | ||||
|     // Then I see that the current page is the clusters
 | ||||
| 
 | ||||
|     // Then I see that the current page is the clusters!
 | ||||
|     cy.url().should('include', '/clusters'); | ||||
|     cy.location('pathname').should('eq', '/clusters'); | ||||
|     cy.get('.MuiSnackbar-root > .MuiPaper-root').should('exist'); | ||||
| 
 | ||||
|     cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); | ||||
|     // users menu does not exist
 | ||||
| 
 | ||||
|     // Users menu does not exist.
 | ||||
|     cy.get('.MuiSnackbar-root > .MuiPaper-root').should('not.exist'); | ||||
|     //menu not exists for users
 | ||||
| 
 | ||||
|     // Menu not exists for users.
 | ||||
|     cy.get('[href="/users"]').should('not.exist'); | ||||
|   }); | ||||
| 
 | ||||
|   it('click the `Create an account` button', () => { | ||||
|     cy.get('.MuiTypography-inherit > .MuiTypography-root').click(); | ||||
|     // Then I see that the current page is the signup
 | ||||
| 
 | ||||
|     // Then I see that the current page is the signup!
 | ||||
|     cy.url().should('include', '/signup'); | ||||
| 
 | ||||
|     cy.get('.MuiTypography-inherit > .MuiTypography-root').click(); | ||||
|     // Then I see that the current page is the signin
 | ||||
| 
 | ||||
|     // Then I see that the current page is the signin!
 | ||||
|     cy.url().should('include', '/signin'); | ||||
|   }); | ||||
| 
 | ||||
|  | @ -216,11 +222,9 @@ describe('Signin', () => { | |||
| 
 | ||||
|     cy.get('form').submit(); | ||||
| 
 | ||||
|     // 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('.MuiSnackbar-root > .MuiPaper-root').should('not.exist'); | ||||
|   }); | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,7 +27,8 @@ describe('Signup', () => { | |||
|     cy.get('#email').type('root@console.com'); | ||||
|     cy.get('#password').type('dragonfly1'); | ||||
|     cy.get('#confirmPassword').type(`dragonfly1{enter}`); | ||||
|     // then I see that the current page is the signin
 | ||||
| 
 | ||||
|     // Then I see that the current page is the signin!
 | ||||
|     cy.url().should('include', '/signin'); | ||||
|   }); | ||||
| 
 | ||||
|  | @ -36,11 +37,12 @@ describe('Signup', () => { | |||
|     cy.get('#email').type('lucy@example.com'); | ||||
|     cy.get('#password').type('dragonfly1'); | ||||
|     cy.get('#confirmPassword').type(`dragonfly1{enter}`); | ||||
|     // show error message
 | ||||
|     cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Conflict'); | ||||
|     // close error message
 | ||||
|     cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); | ||||
| 
 | ||||
|     // Show error message.
 | ||||
|     cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Conflict'); | ||||
| 
 | ||||
|     // Close error message.
 | ||||
|     cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); | ||||
|     cy.get('.MuiSnackbar-root > .MuiPaper-root').should('not.exist'); | ||||
|   }); | ||||
| 
 | ||||
|  | @ -49,11 +51,10 @@ describe('Signup', () => { | |||
|     cy.get('#email').type('root@console.co'); | ||||
|     cy.get('#password').type('dragonfly1'); | ||||
|     cy.get('#confirmPassword').type(`dragonfly1{enter}`); | ||||
|     // show error message
 | ||||
|     cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Conflict'); | ||||
|     // close error message
 | ||||
|     cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); | ||||
| 
 | ||||
|     // Show error message.
 | ||||
|     cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Conflict'); | ||||
|     cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); | ||||
|     cy.get('.MuiSnackbar-root > .MuiPaper-root').should('not.exist'); | ||||
|   }); | ||||
| 
 | ||||
|  | @ -90,21 +91,21 @@ describe('Signup', () => { | |||
|     cy.get('#password').type('dragonfly1'); | ||||
|     cy.get('#confirmPassword').type(`dragonfly1{enter}`); | ||||
| 
 | ||||
|     // 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('.MuiSnackbar-root > .MuiPaper-root').should('not.exist'); | ||||
|   }); | ||||
| 
 | ||||
|   it('click the `Sign in` button', () => { | ||||
|     cy.get('.MuiTypography-inherit > .MuiTypography-root').click(); | ||||
|     // Then I see that the current page is the signin
 | ||||
| 
 | ||||
|     // Then I see that the current page is the signin!
 | ||||
|     cy.url().should('include', '/signin'); | ||||
| 
 | ||||
|     cy.get('.MuiTypography-inherit > .MuiTypography-root').click(); | ||||
|     // Then I see that the current page is the signup
 | ||||
| 
 | ||||
|     // Then I see that the current page is the signup!
 | ||||
|     cy.url().should('include', '/signup'); | ||||
|   }); | ||||
| 
 | ||||
|  | @ -113,6 +114,7 @@ describe('Signup', () => { | |||
|     const nameLengthExceeds = _.times(11, () => _.sample('abcdefghijklmnopqrstuvwxyz')).join(''); | ||||
|     const passsword = _.times(8, () => _.sample('abcdefghijklmnopqrstuvwxyz')).join(''); | ||||
| 
 | ||||
|     // Should display message account the validation error.
 | ||||
|     cy.get('#account').type(nameNotLongEnough); | ||||
|     cy.get('#account-helper-text').should('be.visible').and('contain', 'Fill in the characters, the length is 3-10.'); | ||||
| 
 | ||||
|  | @ -122,20 +124,25 @@ describe('Signup', () => { | |||
|     cy.get('#account').clear(); | ||||
| 
 | ||||
|     cy.get('#account').type('root'); | ||||
|     // verification passed
 | ||||
| 
 | ||||
|     // Verification passed.
 | ||||
|     cy.get('#account-helper-text').should('not.exist'); | ||||
| 
 | ||||
|     // Should display message email the validation error.
 | ||||
|     cy.get('#email').type('root'); | ||||
|     cy.get('#email-helper-text').should('be.visible').and('contain', 'Email is invalid or already taken.'); | ||||
| 
 | ||||
|     cy.get('#email').clear(); | ||||
| 
 | ||||
|     cy.get('#email').type('root@console.com'); | ||||
|     // verification passed
 | ||||
| 
 | ||||
|     // Verification passed.
 | ||||
|     cy.get('#email-helper-text').should('not.exist'); | ||||
| 
 | ||||
|     // Should display message password the validation error.
 | ||||
|     cy.get('#password').type(passsword); | ||||
|     // missing number
 | ||||
| 
 | ||||
|     // Missing number.
 | ||||
|     cy.get('#password-helper-text') | ||||
|       .should('be.visible') | ||||
|       .and('contain', 'At least 8-16 characters, with at least 1 lowercase letter and 1 number.'); | ||||
|  | @ -143,17 +150,21 @@ describe('Signup', () => { | |||
|     cy.get('#password').clear(); | ||||
| 
 | ||||
|     cy.get('#password').type('dragonfly1'); | ||||
|     // verification passed
 | ||||
| 
 | ||||
|     // Verification passed.
 | ||||
|     cy.get('#password-helper-text').should('not.exist'); | ||||
| 
 | ||||
|     // Should display message confirm password the validation error.
 | ||||
|     cy.get('#confirmPassword').type(`dragonfly`); | ||||
|     // confirm password verification error when the two passwords are not the same
 | ||||
| 
 | ||||
|     // Confirm password verification error when the two passwords are not the same.
 | ||||
|     cy.get('#confirmPassword-helper-text').should('be.visible').and('contain', 'Please enter the same password.'); | ||||
| 
 | ||||
|     cy.get('#confirmPassword').clear(); | ||||
| 
 | ||||
|     cy.get('#confirmPassword').type('dragonfly1'); | ||||
|     // verification passed
 | ||||
|      | ||||
|     // verification passed.
 | ||||
|     cy.get('#confirmPassword-helper-text').should('not.exist'); | ||||
|   }); | ||||
| }); | ||||
|  |  | |||
|  | @ -0,0 +1,314 @@ | |||
| [ | ||||
|   { | ||||
|     "id": 1, | ||||
|     "name": "cluster-1", | ||||
|     "bio": "Cluster-1 is a high-performance computing cluster located in China, specifically in Hangzhou and Beijing data centers.", | ||||
|     "scopes": { | ||||
|       "idc": "Hangzhou|Shanghai|Beijing", | ||||
|       "location": "China|Hang|Zhou", | ||||
|       "cidrs": ["10.0.0.0/8", "192.168.0.0/16", "172.16.0.0/12"] | ||||
|     }, | ||||
|     "scheduler_cluster_id": 1, | ||||
|     "seed_peer_cluster_id": 1, | ||||
|     "scheduler_cluster_config": { | ||||
|       "candidate_parent_limit": 4, | ||||
|       "filter_parent_limit": 40 | ||||
|     }, | ||||
|     "seed_peer_cluster_config": { | ||||
|       "load_limit": 300 | ||||
|     }, | ||||
|     "peer_cluster_config": { | ||||
|       "load_limit": 51, | ||||
|       "concurrent_piece_count": 4 | ||||
|     }, | ||||
|     "created_at": "2023-10-31T07:48:35Z", | ||||
|     "updated_at": "2023-10-31T07:48:35Z", | ||||
|     "is_default": true | ||||
|   }, | ||||
|   { | ||||
|     "id": 2, | ||||
|     "name": "cluster-2", | ||||
|     "bio": "", | ||||
|     "scopes": { | ||||
|       "idc": "", | ||||
|       "location": "", | ||||
|       "cidrs": [] | ||||
|     }, | ||||
|     "scheduler_cluster_id": 2, | ||||
|     "seed_peer_cluster_id": 2, | ||||
|     "scheduler_cluster_config": { | ||||
|       "candidate_parent_limit": 4, | ||||
|       "filter_parent_limit": 40 | ||||
|     }, | ||||
|     "seed_peer_cluster_config": { | ||||
|       "load_limit": 300 | ||||
|     }, | ||||
|     "peer_cluster_config": { | ||||
|       "load_limit": 50, | ||||
|       "concurrent_piece_count": 4 | ||||
|     }, | ||||
|     "created_at": "2023-10-31T17:48:35Z", | ||||
|     "updated_at": "2023-10-31T17:48:35Z", | ||||
|     "is_default": false | ||||
|   }, | ||||
|   { | ||||
|     "id": 3, | ||||
|     "name": "cluster-3", | ||||
|     "bio": "Cluster-3 is a high-performance computing cluster located in Korea, specifically in Seoul data centers.", | ||||
|     "scopes": { | ||||
|       "idc": "Korea", | ||||
|       "location": "Seoul|Korea", | ||||
|       "cidrs": ["192.168.0.0/16", "172.16.0.0/12"] | ||||
|     }, | ||||
|     "scheduler_cluster_id": 3, | ||||
|     "seed_peer_cluster_id": 3, | ||||
|     "scheduler_cluster_config": { | ||||
|       "candidate_parent_limit": 4, | ||||
|       "filter_parent_limit": 40 | ||||
|     }, | ||||
|     "seed_peer_cluster_config": { | ||||
|       "load_limit": 300 | ||||
|     }, | ||||
|     "peer_cluster_config": { | ||||
|       "load_limit": 50, | ||||
|       "concurrent_piece_count": 4 | ||||
|     }, | ||||
|     "created_at": "2023-11-08T11:19:36Z", | ||||
|     "updated_at": "2023-11-08T11:19:36Z", | ||||
|     "is_default": true | ||||
|   }, | ||||
|   { | ||||
|     "id": 4, | ||||
|     "name": "cluster-4", | ||||
|     "bio": "Cluster-4 is a high-performance computing cluster located in China, specifically in Hangzhou data centers.", | ||||
|     "scopes": { | ||||
|       "idc": "hz|dl", | ||||
|       "location": "China|Hang|Zhou", | ||||
|       "cidrs": ["10.0.0.0/8", "192.168.0.0/16"] | ||||
|     }, | ||||
|     "scheduler_cluster_id": 4, | ||||
|     "seed_peer_cluster_id": 4, | ||||
|     "scheduler_cluster_config": { | ||||
|       "candidate_parent_limit": 5, | ||||
|       "filter_parent_limit": 40 | ||||
|     }, | ||||
|     "seed_peer_cluster_config": { | ||||
|       "load_limit": 300 | ||||
|     }, | ||||
|     "peer_cluster_config": { | ||||
|       "load_limit": 50, | ||||
|       "concurrent_piece_count": 5 | ||||
|     }, | ||||
|     "created_at": "2023-11-09T18:19:36Z", | ||||
|     "updated_at": "2023-11-09T18:19:36Z", | ||||
|     "is_default": true | ||||
|   }, | ||||
|   { | ||||
|     "id": 5, | ||||
|     "name": "cluster-5", | ||||
|     "bio": "Cluster-5 is a high-performance computing cluster located in China, specifically in Chongqing data centers.", | ||||
|     "scopes": { | ||||
|       "idc": "cq|cd", | ||||
|       "location": "China|Chong|Qing", | ||||
|       "cidrs": ["10.0.0.0/8", "192.168.0.0/16"] | ||||
|     }, | ||||
|     "scheduler_cluster_id": 5, | ||||
|     "seed_peer_cluster_id": 5, | ||||
|     "scheduler_cluster_config": { | ||||
|       "candidate_parent_limit": 4, | ||||
|       "filter_parent_limit": 40 | ||||
|     }, | ||||
|     "seed_peer_cluster_config": { | ||||
|       "load_limit": 300 | ||||
|     }, | ||||
|     "peer_cluster_config": { | ||||
|       "load_limit": 50, | ||||
|       "concurrent_piece_count": 4 | ||||
|     }, | ||||
|     "created_at": "2023-11-01T10:19:36Z", | ||||
|     "updated_at": "2023-11-01T10:19:36Z", | ||||
|     "is_default": false | ||||
|   }, | ||||
|   { | ||||
|     "id": 6, | ||||
|     "name": "cluster-6", | ||||
|     "bio": "Cluster-6 is a high-performance computing cluster located in China, specifically in Chongdu data centers.", | ||||
|     "scopes": { | ||||
|       "idc": "cq|cd", | ||||
|       "location": "China|Chong|Du", | ||||
|       "cidrs": ["10.0.0.0/8", "192.168.0.0/16"] | ||||
|     }, | ||||
|     "scheduler_cluster_id": 6, | ||||
|     "seed_peer_cluster_id": 6, | ||||
|     "scheduler_cluster_config": { | ||||
|       "candidate_parent_limit": 4, | ||||
|       "filter_parent_limit": 40 | ||||
|     }, | ||||
|     "seed_peer_cluster_config": { | ||||
|       "load_limit": 300 | ||||
|     }, | ||||
|     "peer_cluster_config": { | ||||
|       "load_limit": 50, | ||||
|       "concurrent_piece_count": 4 | ||||
|     }, | ||||
|     "created_at": "2023-11-09T20:12:36Z", | ||||
|     "updated_at": "2023-11-09T20:12:36Z", | ||||
|     "is_default": true | ||||
|   }, | ||||
|   { | ||||
|     "id": 7, | ||||
|     "name": "cluster-7", | ||||
|     "bio": "Cluster-7 is a high-performance computing cluster located in China, specifically in Chongdu data centers.", | ||||
|     "scopes": { | ||||
|       "idc": "cd", | ||||
|       "location": "China|Cheng|Du", | ||||
|       "cidrs": ["10.0.0.0/8", "172.16.0.0/19"] | ||||
|     }, | ||||
|     "scheduler_cluster_id": 7, | ||||
|     "seed_peer_cluster_id": 7, | ||||
|     "scheduler_cluster_config": { | ||||
|       "candidate_parent_limit": 4, | ||||
|       "filter_parent_limit": 40 | ||||
|     }, | ||||
|     "seed_peer_cluster_config": { | ||||
|       "load_limit": 300 | ||||
|     }, | ||||
|     "peer_cluster_config": { | ||||
|       "load_limit": 50, | ||||
|       "concurrent_piece_count": 4 | ||||
|     }, | ||||
|     "created_at": "2023-11-11T10:19:36Z", | ||||
|     "updated_at": "2023-11-11T10:19:36Z", | ||||
|     "is_default": true | ||||
|   }, | ||||
|   { | ||||
|     "id": 8, | ||||
|     "name": "cluster-8", | ||||
|     "bio": "Cluster-8 is a high-performance computing cluster located in China, specifically in Jiangsu data centers.", | ||||
|     "scopes": { | ||||
|       "idc": "js", | ||||
|       "location": "China|Jiang|Su", | ||||
|       "cidrs": ["10.0.0.0/5", "172.16.0.0/19"] | ||||
|     }, | ||||
|     "scheduler_cluster_id": 8, | ||||
|     "seed_peer_cluster_id": 8, | ||||
|     "scheduler_cluster_config": { | ||||
|       "candidate_parent_limit": 4, | ||||
|       "filter_parent_limit": 40 | ||||
|     }, | ||||
|     "seed_peer_cluster_config": { | ||||
|       "load_limit": 300 | ||||
|     }, | ||||
|     "peer_cluster_config": { | ||||
|       "load_limit": 50, | ||||
|       "concurrent_piece_count": 4 | ||||
|     }, | ||||
|     "created_at": "2023-11-11T13:19:36Z", | ||||
|     "updated_at": "2023-11-11T13:19:36Z", | ||||
|     "is_default": false | ||||
|   }, | ||||
|   { | ||||
|     "id": 9, | ||||
|     "name": "cluster-9", | ||||
|     "bio": "Cluster-9 is a high-performance computing cluster located in China, specifically in Hangzhou data centers.", | ||||
|     "scopes": { | ||||
|       "idc": "hz|hf", | ||||
|       "location": "China|Hang|Zhou", | ||||
|       "cidrs": ["10.0.0.0/8", "192.168.0.0/16"] | ||||
|     }, | ||||
|     "scheduler_cluster_id": 9, | ||||
|     "seed_peer_cluster_id": 9, | ||||
|     "scheduler_cluster_config": { | ||||
|       "candidate_parent_limit": 4, | ||||
|       "filter_parent_limit": 40 | ||||
|     }, | ||||
|     "seed_peer_cluster_config": { | ||||
|       "load_limit": 300 | ||||
|     }, | ||||
|     "peer_cluster_config": { | ||||
|       "load_limit": 50, | ||||
|       "concurrent_piece_count": 4 | ||||
|     }, | ||||
|     "created_at": "2023-11-11T10:29:36Z", | ||||
|     "updated_at": "2023-11-11T10:29:36Z", | ||||
|     "is_default": true | ||||
|   }, | ||||
|   { | ||||
|     "id": 10, | ||||
|     "name": "cluster-10", | ||||
|     "bio": "Cluster-10 is a high-performance computing cluster located in England, specifically in London data centers.", | ||||
|     "scopes": { | ||||
|       "idc": "London", | ||||
|       "location": "London|England", | ||||
|       "cidrs": ["192.168.255.255"] | ||||
|     }, | ||||
|     "scheduler_cluster_id": 10, | ||||
|     "seed_peer_cluster_id": 10, | ||||
|     "scheduler_cluster_config": { | ||||
|       "candidate_parent_limit": 4, | ||||
|       "filter_parent_limit": 40 | ||||
|     }, | ||||
|     "seed_peer_cluster_config": { | ||||
|       "load_limit": 300 | ||||
|     }, | ||||
|     "peer_cluster_config": { | ||||
|       "load_limit": 50, | ||||
|       "concurrent_piece_count": 4 | ||||
|     }, | ||||
|     "created_at": "2023-11-15T05:19:36Z", | ||||
|     "updated_at": "2023-11-15T05:19:36Z", | ||||
|     "is_default": true | ||||
|   }, | ||||
|   { | ||||
|     "id": 11, | ||||
|     "name": "cluster-11", | ||||
|     "bio": "Cluster-10 is a high-performance computing cluster located in France, specifically in Paris data centers.", | ||||
|     "scopes": { | ||||
|       "idc": "Paris", | ||||
|       "location": "Paris|France", | ||||
|       "cidrs": ["192.168.0.0", "10.0.0.0"] | ||||
|     }, | ||||
|     "scheduler_cluster_id": 11, | ||||
|     "seed_peer_cluster_id": 11, | ||||
|     "scheduler_cluster_config": { | ||||
|       "candidate_parent_limit": 4, | ||||
|       "filter_parent_limit": 40 | ||||
|     }, | ||||
|     "seed_peer_cluster_config": { | ||||
|       "load_limit": 300 | ||||
|     }, | ||||
|     "peer_cluster_config": { | ||||
|       "load_limit": 50, | ||||
|       "concurrent_piece_count": 4 | ||||
|     }, | ||||
|     "created_at": "2023-11-01T10:19:36Z", | ||||
|     "updated_at": "2023-11-01T10:19:36Z", | ||||
|     "is_default": false | ||||
|   }, | ||||
|   { | ||||
|     "id": 12, | ||||
|     "name": "cluster-12", | ||||
|     "bio": "Add new cluster case", | ||||
|     "scopes": { | ||||
|       "idc": "hz|sh", | ||||
|       "location": "China|Hang|Zhou", | ||||
|       "cidrs": ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"] | ||||
|     }, | ||||
|     "scheduler_cluster_id": 12, | ||||
|     "seed_peer_cluster_id": 12, | ||||
|     "scheduler_cluster_config": { | ||||
|       "candidate_parent_limit": 4, | ||||
|       "filter_parent_limit": 40 | ||||
|     }, | ||||
|     "seed_peer_cluster_config": { | ||||
|       "load_limit": 300 | ||||
|     }, | ||||
|     "peer_cluster_config": { | ||||
|       "load_limit": 50, | ||||
|       "concurrent_piece_count": 10 | ||||
|     }, | ||||
|     "created_at": "2023-11-21T06:49:41Z", | ||||
|     "updated_at": "2023-11-21T06:49:41Z", | ||||
|     "is_default": true | ||||
|   } | ||||
| ] | ||||
|  | @ -62,7 +62,7 @@ export default function Clusters() { | |||
|   const [clusterIsLoading, setClusterIsLoading] = useState(true); | ||||
|   const [clusterPage, setClusterPage] = useState(1); | ||||
|   const [totalPages, setTotalPages] = useState<number>(1); | ||||
|   const [clustersSearch, setClustersSearch] = useState(''); | ||||
|   const [searchClusters, setSearchClusters] = useState(''); | ||||
|   const [clusterCount, setClusterCount] = useState<getClustersResponse[]>([]); | ||||
|   const [cluster, setCluster] = useState<getClustersResponse[]>([]); | ||||
|   const [scheduler, setScheduler] = useState<getSchedulersResponse[]>([]); | ||||
|  | @ -134,11 +134,11 @@ export default function Clusters() { | |||
|   const numberOfActiveSeedPeers = | ||||
|     Array.isArray(seedPeer) && seedPeer?.filter((item: any) => item?.state === 'active').length; | ||||
| 
 | ||||
|   const clusterSearch = async () => { | ||||
|   const searchCluster = async () => { | ||||
|     try { | ||||
|       setClusterIsLoading(true); | ||||
|       const cluster = clustersSearch | ||||
|         ? await getClusters({ page: 1, per_page: MAX_PAGE_SIZE, name: clustersSearch }) | ||||
|       const cluster = searchClusters | ||||
|         ? await getClusters({ page: 1, per_page: MAX_PAGE_SIZE, name: searchClusters }) | ||||
|         : await getClusters({ page: 1, per_page: MAX_PAGE_SIZE }); | ||||
| 
 | ||||
|       setCluster(cluster); | ||||
|  | @ -153,7 +153,7 @@ export default function Clusters() { | |||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   const clusterSearchKeyDown = (event: any) => { | ||||
|   const searchClusterKeyDown = (event: any) => { | ||||
|     if (event.key === 'Enter') { | ||||
|       event.preventDefault(); | ||||
|       const submitButton = document.getElementById('submit-button'); | ||||
|  | @ -311,10 +311,10 @@ export default function Clusters() { | |||
|               color="secondary" | ||||
|               id="free-solo-demo" | ||||
|               freeSolo | ||||
|               onKeyDown={clusterSearchKeyDown} | ||||
|               inputValue={clustersSearch} | ||||
|               onKeyDown={searchClusterKeyDown} | ||||
|               inputValue={searchClusters} | ||||
|               onInputChange={(_event, newInputValue) => { | ||||
|                 setClustersSearch(newInputValue); | ||||
|                 setSearchClusters(newInputValue); | ||||
|               }} | ||||
|               options={(Array.isArray(clusterCount) && clusterCount.map((option) => option?.name)) || ['']} | ||||
|               renderInput={(params) => <TextField {...params} label="Search" />} | ||||
|  | @ -325,7 +325,7 @@ export default function Clusters() { | |||
|             aria-label="search" | ||||
|             id="submit-button" | ||||
|             size="small" | ||||
|             onClick={clusterSearch} | ||||
|             onClick={searchCluster} | ||||
|             sx={{ width: '3rem' }} | ||||
|           > | ||||
|             <SearchIcon sx={{ color: 'rgba(0,0,0,0.6)' }} /> | ||||
|  |  | |||
|  | @ -223,7 +223,7 @@ export default function NewCluster() { | |||
|   const configForm = [ | ||||
|     { | ||||
|       formProps: { | ||||
|         id: 'seed peer load limit', | ||||
|         id: 'seedPeerLoadLimit', | ||||
|         label: 'Seed Peer load limit', | ||||
|         name: 'seedPeerLoadLimit', | ||||
|         type: 'number', | ||||
|  | @ -258,7 +258,7 @@ export default function NewCluster() { | |||
|     }, | ||||
|     { | ||||
|       formProps: { | ||||
|         id: 'peer load limit', | ||||
|         id: 'peerLoadLimit', | ||||
|         label: 'Peer load limit', | ||||
|         name: 'peerLoadLimit', | ||||
|         type: 'number', | ||||
|  | @ -295,7 +295,7 @@ export default function NewCluster() { | |||
|     }, | ||||
|     { | ||||
|       formProps: { | ||||
|         id: 'number of concurrent download pieces', | ||||
|         id: 'numberOfConcurrentDownloadPieces', | ||||
|         label: 'Number of concurrent download pieces', | ||||
|         name: 'numberOfConcurrentDownloadPieces', | ||||
|         type: 'number', | ||||
|  | @ -330,7 +330,7 @@ export default function NewCluster() { | |||
|     }, | ||||
|     { | ||||
|       formProps: { | ||||
|         id: 'candidate parent limit', | ||||
|         id: 'candidateParentLimit', | ||||
|         label: 'Candidate parent limit', | ||||
|         name: 'candidateParentLimit', | ||||
|         type: 'number', | ||||
|  | @ -365,7 +365,7 @@ export default function NewCluster() { | |||
|     }, | ||||
|     { | ||||
|       formProps: { | ||||
|         id: 'filter parent limit', | ||||
|         id: 'filterParentLimit', | ||||
|         label: 'Filter parent limit', | ||||
|         name: 'filterParentLimit', | ||||
|         type: 'number', | ||||
|  | @ -420,7 +420,7 @@ export default function NewCluster() { | |||
|     const cidrsText = event.currentTarget.elements.cidrs.value; | ||||
| 
 | ||||
|     if (idcText) { | ||||
|       setIDCHelperText('Please press ENTER to end the IDC creation'); | ||||
|       setIDCHelperText('Please press ENTER to end the IDC creation.'); | ||||
|       setIDCError(true); | ||||
|     } else { | ||||
|       setIDCError(false); | ||||
|  | @ -428,7 +428,7 @@ export default function NewCluster() { | |||
|     } | ||||
| 
 | ||||
|     if (cidrsText) { | ||||
|       setCIDRsHelperText('Please press ENTER to end the CIDRs creation'); | ||||
|       setCIDRsHelperText('Please press ENTER to end the CIDRs creation.'); | ||||
|       setCIDRsError(true); | ||||
|     } else { | ||||
|       setCIDRsError(false); | ||||
|  | @ -710,7 +710,7 @@ export default function NewCluster() { | |||
|             size="small" | ||||
|             variant="outlined" | ||||
|             loadingPosition="end" | ||||
|             id="cancle" | ||||
|             id="cancel" | ||||
|             sx={{ | ||||
|               '&.MuiLoadingButton-root': { | ||||
|                 color: 'var(--calcel-size-color)', | ||||
|  | @ -743,6 +743,7 @@ export default function NewCluster() { | |||
|             variant="outlined" | ||||
|             type="submit" | ||||
|             loadingPosition="end" | ||||
|             id="save" | ||||
|             sx={{ | ||||
|               '&.MuiLoadingButton-root': { | ||||
|                 backgroundColor: 'var(--save-color)', | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue