feat: add users page e2e test (#338)

Signed-off-by: zhaoxinxin <1186037180@qq.com>
This commit is contained in:
Zhaoxinxin 2023-12-13 15:35:15 +08:00 committed by GitHub
parent 99681b829a
commit 0f4db05321
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 926 additions and 40 deletions

View File

@ -88,18 +88,18 @@ describe('Profile', () => {
});
it('when data is loaded', () => {
cy.get('.css-70qvj9 > .MuiBox-root > .MuiTypography-body1').should('be.visible').and('have.text', 'lucy');
cy.get('.css-70qvj9 > .MuiBox-root > .MuiTypography-body1').should('be.visible').and('have.text', 'root');
cy.get('.MuiTypography-caption').should('be.visible').and('have.text', 'lucy@example.com');
cy.get('.MuiTypography-caption').should('be.visible').and('have.text', 'root@example.com');
// Show user name.
cy.get('.css-70qvj9 > .MuiBox-root > .MuiTypography-h5').should('be.visible').and('have.text', 'lucy');
cy.get('.css-70qvj9 > .MuiBox-root > .MuiTypography-h5').should('be.visible').and('have.text', 'root');
// Show user description.
cy.get('.MuiBox-root > .MuiTypography-subtitle1').should('be.visible').and('have.text', 'I am lucy');
cy.get('.MuiBox-root > .MuiTypography-subtitle1').should('be.visible').and('have.text', 'I am root');
cy.get('#id').should('be.visible').and('have.text', 1);
cy.get('#name').should('be.visible').and('have.text', 'lucy');
cy.get('#email').should('be.visible').and('have.text', 'lucy@example.com');
cy.get('#name').should('be.visible').and('have.text', 'root');
cy.get('#email').should('be.visible').and('have.text', 'root@example.com');
cy.get('#location').should('be.visible').and('have.text', 'Hangzhou');
cy.get('#phone').should('be.visible').and('have.text', 1234567890);
cy.get('#created_at').should('be.visible').and('have.text', '2023-11-06 06:09:04');
@ -107,10 +107,10 @@ describe('Profile', () => {
// Check Update Personal Information form.
cy.get('.MuiGrid-root > .MuiButtonBase-root').click();
cy.get('#bio').should('have.value', 'I am lucy');
cy.get('#bio').should('have.value', 'I am root');
cy.get('#phone').should('have.value', 1234567890);
cy.get('#location').should('have.value', 'Hangzhou');
cy.get('#email').should('have.value', 'lucy@example.com');
cy.get('#email').should('have.value', 'root@example.com');
});
it('when no data is loaded', () => {
@ -195,7 +195,7 @@ describe('Profile', () => {
// Update user name.
cy.get('#bio').clear();
cy.get('#bio').type('I am lucy, I will change the description');
cy.get('#bio').type('I am root, I will change the description');
// Update user phone.
cy.get('#phone').clear();
@ -207,7 +207,7 @@ describe('Profile', () => {
// Update user email.
cy.get('#email').clear();
cy.get('#email').type('lucy@gmail.com');
cy.get('#email').type('root@gmail.com');
cy.intercept(
{
@ -225,15 +225,15 @@ describe('Profile', () => {
cy.get('#save').click();
// Check whether the navigation bar email has changed.
cy.get('.MuiTypography-caption').should('have.text', 'lucy@gmail.com');
cy.get('.MuiTypography-caption').should('have.text', 'root@gmail.com');
// Check if profile description is updated.
cy.get('.MuiBox-root > .MuiTypography-subtitle1')
.should('be.visible')
.and('have.text', 'I am lucy, I will change the description');
.and('have.text', 'I am root, I will change the description');
// Check if profile email is updated.
cy.get('#email').should('be.visible').and('have.text', 'lucy@gmail.com');
cy.get('#email').should('be.visible').and('have.text', 'root@gmail.com');
// Check if profile location is updated.
cy.get('#location').should('be.visible').and('have.text', 'Shanghai');
@ -246,22 +246,22 @@ describe('Profile', () => {
// Click EDIT button.
cy.get('.MuiGrid-root > .MuiButtonBase-root').click();
cy.get('#bio').clear();
cy.get('#bio').type('I am lucy, I will change the description');
cy.get('#bio').type('I am root, I will change the description');
// Update user email.
cy.get('#email').clear();
cy.get('#email').type('lucy@gmail.com');
cy.get('#email').type('root@gmail.com');
cy.get('#cancel').click();
cy.get('.MuiBox-root > .MuiTypography-subtitle1').should('be.visible').and('have.text', 'I am lucy');
cy.get('.MuiBox-root > .MuiTypography-subtitle1').should('be.visible').and('have.text', 'I am root');
// Check whether the navigation bar email has changed.
cy.get('.MuiTypography-caption').should('have.text', 'lucy@example.com');
cy.get('#email').should('be.visible').and('have.text', 'lucy@example.com');
cy.get('.MuiTypography-caption').should('have.text', 'root@example.com');
cy.get('#email').should('be.visible').and('have.text', 'root@example.com');
// Click EDIT button.
cy.get('.MuiGrid-root > .MuiButtonBase-root').click();
cy.get('#bio').should('have.value', 'I am lucy');
cy.get('#email').should('have.value', 'lucy@example.com');
cy.get('#bio').should('have.value', 'I am root');
cy.get('#email').should('have.value', 'root@example.com');
});
it('try to update user with guest user', () => {
@ -353,7 +353,7 @@ describe('Profile', () => {
.and('have.text', 'Update Personal Information');
cy.get('#bio').clear();
cy.get('#bio').type('I am lucy');
cy.get('#bio').type('I am root');
// Verification passed.
cy.get('#bio-helper-text').should('not.exist');
@ -389,12 +389,12 @@ describe('Profile', () => {
// Should display message email the validation error.
cy.get('#email').clear();
cy.get('#email').type('lucy');
cy.get('#email').type('root');
// Show verification error message.
cy.get('#email-helper-text').should('be.visible').and('have.text', 'Email is invalid or already taken.');
cy.get('#email').clear();
cy.get('#email').type('lucy@example.com');
cy.get('#email').type('root@example.com');
cy.get('#email-helper-text').should('not.exist');
});
});

715
cypress/e2e/users.cy.ts Normal file
View File

@ -0,0 +1,715 @@
import root from '../fixtures/api/role-root.json';
import user from '../fixtures/api/user.json';
import users from '../fixtures/api/users.json';
import guestUser from '../fixtures/api/guest-user.json';
import guest from '../fixtures/api/role-guest.json';
describe('Users', () => {
beforeEach(() => {
cy.signin();
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.intercept(
{
method: 'GET',
url: '/api/v1/users?page=1&per_page=10000000',
},
(req) => {
req.reply({
statusCode: 200,
body: users,
});
},
);
cy.visit('/users');
cy.viewport(1440, 1080);
});
describe('when data is loaded', () => {
beforeEach(() => {
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/2',
},
(req) => {
req.reply({
statusCode: 200,
body: user,
});
},
);
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/3',
},
(req) => {
req.reply({
statusCode: 200,
body: guestUser,
});
},
);
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/2/roles',
},
(req) => {
req.reply({
statusCode: 200,
body: root,
});
},
);
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/3/roles',
},
(req) => {
req.reply({
statusCode: 200,
body: guest,
});
},
);
});
it('can display users table', () => {
// Show root user information.
cy.get('.MuiTableBody-root > :nth-child(1) > :nth-child(2)').should('be.visible').and('have.text', 'root');
// Show root user email.
cy.get('.MuiTableBody-root > :nth-child(1) > :nth-child(3)')
.should('be.visible')
.and('have.text', 'root@example.com');
// Show root user location.
cy.get('.MuiTableBody-root > :nth-child(1) > :nth-child(4)').should('be.visible').and('have.text', 'Shanghai');
// Show root user state.
cy.get('.MuiTableBody-root > :nth-child(1) > :nth-child(5)').should('be.visible').and('have.text', 'Enable');
// The update role button for the root user is not displayed.
cy.get('#edit-root > .MuiBox-root').should('not.exist');
// Show root user detail button.
cy.get('#detail-root > .MuiBox-root').should('exist');
// Show lucy user information.
cy.get('.MuiTableBody-root > :nth-child(2) > :nth-child(2)').should('be.visible').and('have.text', 'lucy');
cy.get('.MuiTableBody-root > :nth-child(2) > :nth-child(3)')
.should('be.visible')
.and('have.text', 'lucy@example.com');
cy.get('.MuiTableBody-root > :nth-child(2) > :nth-child(4)').should('be.visible').and('have.text', 'Hangzhou');
cy.get('.MuiTableBody-root > :nth-child(2) > :nth-child(5)').should('be.visible').and('have.text', 'Enable');
cy.get('#edit-lucy > .MuiBox-root').should('exist');
cy.get('#detail-lucy > .MuiBox-root').should('exist');
// Show jack user information.
cy.get('.MuiTableBody-root > :nth-child(3) > :nth-child(2)').should('be.visible').and('have.text', 'jack');
cy.get('.MuiTableBody-root > :nth-child(3) > :nth-child(3)')
.should('be.visible')
.and('have.text', 'jack@example.com');
cy.get('.MuiTableBody-root > :nth-child(3) > :nth-child(4)').should('be.visible').and('have.text', 'Shanghai');
cy.get('.MuiTableBody-root > :nth-child(3) > :nth-child(5)').should('be.visible').and('have.text', 'Enable');
cy.get('#edit-jack > .MuiBox-root').should('exist');
cy.get('#detail-jack > .MuiBox-root').should('exist');
});
it('can display user detail', () => {
// Click detail button.
cy.get('#detail-root > .MuiBox-root').click();
// Display user lucy details.
cy.get('.MuiDrawer-root > .MuiPaper-root').should('be.visible');
cy.get(':nth-child(3) > .css-e784if-MuiTypography-root').should('have.text', 1);
cy.get(':nth-child(5) > .css-e784if-MuiTypography-root').should('have.text', 'root');
cy.get('.css-e784if-MuiTypography-root > .MuiChip-root').should('have.text', 'root');
cy.get(':nth-child(9) > .css-e784if-MuiTypography-root').should('have.text', 'root@example.com');
cy.get(':nth-child(11) > .css-e784if-MuiTypography-root').should('have.text', '1234567890');
cy.get('.users_emailContent__jraG8 > .MuiTypography-root').should('have.text', 'Hangzhou');
cy.get('.MuiList-root > :nth-child(15)').should('contain', '2023-11-06 06:09:04');
cy.get('.MuiList-root > :nth-child(17)').should('contain', '2023-11-06 06:09:04');
// closure user details.
cy.get('.MuiListSubheader-root > .MuiButtonBase-root').click();
cy.get('#detail-jack').click();
// Display user jack details.
cy.get('.MuiDrawer-root > .MuiPaper-root').should('be.visible');
cy.get(':nth-child(3) > .css-e784if-MuiTypography-root').should('have.text', 2);
cy.get(':nth-child(5) > .css-e784if-MuiTypography-root').should('have.text', 'jack');
cy.get('.css-e784if-MuiTypography-root > .MuiChip-root').should('have.text', 'guest');
cy.get(':nth-child(9) > .css-e784if-MuiTypography-root').should('have.text', 'jack@example.com');
cy.get(':nth-child(11) > .css-e784if-MuiTypography-root').should('have.text', '1234567890');
cy.get('.users_emailContent__jraG8 > .MuiTypography-root').should('have.text', 'Shanghai');
cy.get('.MuiList-root > :nth-child(15)').should('contain', '2023-11-07 06:09:04');
cy.get('.MuiList-root > :nth-child(17)').should('contain', '2023-11-07 06:09:04');
});
it('can display update user', () => {
// Click update user button.
cy.get('#edit-lucy > .MuiBox-root').click();
// Check role.
cy.get('#role-root').should('be.checked').check({ force: true });
cy.get('#role-guest');
cy.get('body').click('topLeft');
cy.get('#edit-jack > .MuiBox-root').click();
cy.get('#role-root').should('not.be.checked');
cy.get('#role-guest').should('be.checked').check({ force: true });
});
});
describe('when no data is loaded', () => {
beforeEach(() => {
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.intercept(
{
method: 'GET',
url: '/api/v1/users?page=1&per_page=10000000',
},
(req) => {
req.reply({
statusCode: 200,
body: [],
});
},
);
cy.visit('/users');
cy.viewport(1440, 1080);
});
it('cannot display users table', () => {
cy.get('#user-table-row').should('not.exist');
});
});
it('try to show users page using guest user', () => {
cy.guestSignin();
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,
});
},
);
// The 404 page is displayed and the user page does not exist.
cy.get('.MuiTypography-h4').should('have.text', 'Something gone wrong!');
cy.get('.MuiTypography-body1').should('have.text', `The page you were looking for doesn't exist.`);
});
describe('get role API error response', () => {
it('cannot display users table', () => {
cy.intercept(
{
method: 'GET',
url: '/api/v1/users?page=1&per_page=10000000',
},
(req) => {
req.reply({
forceNetworkError: true,
});
},
);
cy.get('.MuiAlert-message').should('be.visible').and('have.text', 'Failed to fetch');
});
it('user detail should render empty', () => {
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/3',
},
(req) => {
req.reply({
forceNetworkError: true,
});
},
);
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/3/roles',
},
(req) => {
req.reply({
forceNetworkError: true,
});
},
);
cy.get('#detail-jack').click();
// Display user jack details.
cy.get(':nth-child(3) > .css-e784if-MuiTypography-root').should('have.text', 0);
cy.get(':nth-child(5) > .css-e784if-MuiTypography-root').should('have.text', '-');
cy.get('.MuiList-root > :nth-child(7)').should('contain', '-');
cy.get(':nth-child(9) > .css-e784if-MuiTypography-root').should('have.text', '-');
cy.get(':nth-child(11) > .css-e784if-MuiTypography-root').should('have.text', '-');
cy.get('.users_emailContent__jraG8 > .MuiTypography-root').should('have.text', '-');
cy.get('.MuiList-root > :nth-child(15)').should('contain', '-');
cy.get('.MuiList-root > :nth-child(17)').should('contain', '-');
});
});
describe('pagination', () => {
it('pagination updates results and page number', () => {
cy.get('#user-pagination').should('exist');
// Check number of pagination.
cy.get('#user-pagination > .MuiPagination-ul').children().should('have.length', 4);
cy.get('#user-pagination > .MuiPagination-ul .Mui-selected').should('have.text', '1');
});
it('when pagination changes, different page results are rendered', () => {
cy.get('.MuiTableBody-root > :nth-child(1) > :nth-child(2)').should('be.visible').and('have.text', 'root');
// There are ten users on the current page.
cy.get('#user-table-body').children().should('have.length', 10);
// Go to next page.
cy.get('.MuiPagination-ul > :nth-child(3) > .MuiButtonBase-root').click();
cy.get('#user-table-row > :nth-child(2)').should('be.visible').and('have.text', 'noah');
// There is only one user on the current page.
cy.get('#user-table-body').children().should('have.length', 1);
// Check the current page number.
cy.get('#user-pagination > .MuiPagination-ul .Mui-selected').should('have.text', '2');
});
it('pagination resets results and page number to first page when refresh is clicked', () => {
// Go to next page.
cy.get('.MuiPagination-ul > :nth-child(3) > .MuiButtonBase-root').click();
// There is only one user on the current page.
cy.get('#user-table-body').children().should('have.length', 1);
// Check the current page number.
cy.get('#user-pagination > .MuiPagination-ul .Mui-selected').should('have.text', '2');
// Refresh page.
cy.reload().then(() => {
cy.wait(2000);
});
// There are ten users on the current page.
cy.get('#user-table-body').children().should('have.length', 10);
// Check the current page number.
cy.get('#user-pagination > .MuiPagination-ul .Mui-selected').should('have.text', '1');
});
});
describe('update role', () => {
it('can change the root user to the guest user', () => {
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/2/roles',
},
(req) => {
req.reply({
statusCode: 200,
body: root,
});
},
);
cy.intercept(
{
method: 'PUT',
url: '/api/v1/users/2/roles/guest',
},
(req) => {
req.reply({
statusCode: 200,
});
},
);
cy.intercept(
{
method: 'DELETE',
url: '/api/v1/users/2/roles/root',
},
(req) => {
req.reply({
statusCode: 200,
});
},
);
cy.get('#edit-lucy > .MuiBox-root').click();
cy.get('#role-root').should('be.checked').check({ force: true });
cy.get('#role-guest').should('not.be.checked');
// Switch role to guest.
cy.get('#role-guest').click();
cy.get('#save').click();
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/2/roles',
},
(req) => {
req.reply({
statusCode: 200,
body: ['guest'],
});
},
);
cy.get('#edit-lucy > .MuiBox-root').click();
// Change success message.
cy.get('.MuiAlert-message').should('be.visible').and('have.text', 'Submission successful!');
cy.get('.MuiAlert-action > .MuiButtonBase-root').click();
cy.get('.MuiAlert-message').should('not.exist');
// Check role.
cy.get('#role-root').should('not.be.checked');
cy.get('#role-guest').should('be.checked').check({ force: true });
});
it('can change the guest user to the root user', () => {
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/3/roles',
},
(req) => {
req.reply({
statusCode: 200,
body: guest,
});
},
);
cy.intercept(
{
method: 'PUT',
url: '/api/v1/users/3/roles/root',
},
(req) => {
req.reply({
statusCode: 200,
});
},
);
cy.intercept(
{
method: 'DELETE',
url: '/api/v1/users/3/roles/guest',
},
(req) => {
req.reply({
statusCode: 200,
});
},
);
cy.get('#edit-jack > .MuiBox-root').click();
// Check if role is guest.
cy.get('#role-root').should('not.be.checked');
cy.get('#role-guest').should('be.checked').check({ force: true });
// Switch role to root.
cy.get('#role-root').click();
cy.get('#save').click();
cy.get('.MuiAlert-message').should('be.visible').and('have.text', 'Submission successful!');
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/3/roles',
},
(req) => {
req.reply({
statusCode: 200,
body: ['root'],
});
},
);
cy.get('#edit-jack > .MuiBox-root').click();
// Check if role is root.
cy.get('#role-root').should('be.checked').check({ force: true });
cy.get('#role-guest').should('not.be.checked');
});
it('try using root user to change to guest user and then update to root user', () => {
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/2/roles',
},
(req) => {
req.reply({
statusCode: 200,
body: root,
});
},
);
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/2',
},
(req) => {
req.reply({
statusCode: 200,
body: user,
});
},
);
cy.guestSignin();
cy.intercept(
{
method: 'PUT',
url: '/api/v1/users/2/roles/guest',
},
(req) => {
req.reply({
statusCode: 200,
});
},
);
cy.intercept(
{
method: 'DELETE',
url: '/api/v1/users/2/roles/root',
},
(req) => {
req.reply({
statusCode: 200,
});
},
);
// Click edit button.
cy.get('#edit-lucy > .MuiBox-root').click();
cy.get('#role-root').should('be.checked').check({ force: true });
cy.get('#role-guest').should('not.be.checked');
cy.get('#role-guest').click();
cy.get('#save').click();
// Change success message.
cy.get('.MuiAlert-message').should('be.visible').and('have.text', 'Submission successful!');
cy.get('.MuiAlert-action > .MuiButtonBase-root').click();
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/2/roles',
},
(req) => {
req.reply({
statusCode: 200,
body: ['guest'],
});
},
);
cy.get('#edit-lucy > .MuiBox-root').click();
// Check role.
cy.get('#role-root').should('not.be.checked');
cy.get('#role-guest').should('be.checked').check({ force: true });
// Switch role to guest.
cy.get('#role-root').click();
cy.intercept(
{
method: 'PUT',
url: '/api/v1/users/2/roles/root',
},
(req) => {
req.reply({
statusCode: 401,
body: { message: 'permission deny' },
});
},
);
cy.get('#save').click();
// Show error message.
cy.get('.MuiAlert-message').should('be.visible').and('have.text', 'permission deny');
// Refresh page.
cy.reload().then(() => {
cy.wait(2000);
});
// When the user role is guest, the user page will no longer be displayed.
cy.get('.MuiTypography-body1')
.should('be.visible')
.and('have.text', `The page you were looking for doesn't exist.`);
});
it('get role API error response', () => {
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/2/roles',
},
(req) => {
req.reply({
forceNetworkError: true,
});
},
);
cy.get('#edit-lucy > .MuiBox-root').click();
// Show error message.
cy.get('.MuiAlert-message').should('be.visible').and('have.text', 'Failed to fetch');
// Check role.
cy.get('#role-root').should('not.be.checked');
cy.get('#role-guest').should('not.be.checked');
});
it('change role API error response', () => {
cy.intercept(
{
method: 'GET',
url: '/api/v1/users/2/roles',
},
(req) => {
req.reply({
statusCode: 200,
body: root,
});
},
);
cy.intercept(
{
method: 'PUT',
url: '/api/v1/users/2/roles/guest',
},
(req) => {
req.reply({
forceNetworkError: true,
});
},
);
cy.intercept(
{
method: 'DELETE',
url: '/api/v1/users/2/roles/root',
},
(req) => {
req.reply({
forceNetworkError: true,
});
},
);
cy.get('#edit-lucy > .MuiBox-root').click();
// Check if role is root.
cy.get('#role-root').should('be.checked').check({ force: true });
cy.get('#role-guest').should('not.be.checked');
cy.get('#role-guest').click();
cy.get('#save').click();
// Show error message.
cy.get('.MuiAlert-message').should('be.visible').and('have.text', 'Failed to fetch');
});
});
});

View File

@ -3,12 +3,12 @@
"created_at": "2023-11-06T06:09:04Z",
"updated_at": "2023-11-06T06:09:04Z",
"is_del": 0,
"email": "lucy@gmail.com",
"name": "lucy",
"email": "root@gmail.com",
"name": "root",
"avatar": "https://example.com/avatar.png",
"phone": "15123456789",
"state": "enable",
"location": "Shanghai",
"bio": "I am lucy, I will change the description",
"bio": "I am root, I will change the description",
"configs": null
}

View File

@ -3,12 +3,12 @@
"created_at": "2023-11-06T06:09:04Z",
"updated_at": "2023-11-06T06:09:04Z",
"is_del": 0,
"email": "lucy@example.com",
"name": "lucy",
"email": "root@example.com",
"name": "root",
"avatar": "https://example.com/avatar.png",
"phone": "1234567890",
"state": "enable",
"location": "Hangzhou",
"bio": "I am lucy",
"bio": "I am root",
"configs": null
}

View File

@ -0,0 +1,156 @@
[
{
"id": 1,
"created_at": "2023-12-07T12:26:52Z",
"updated_at": "2023-12-07T12:26:52Z",
"is_del": 0,
"email": "root@example.com",
"name": "root",
"avatar": "",
"phone": "",
"state": "enable",
"location": "Shanghai",
"bio": "",
"configs": null
},
{
"id": 2,
"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
},
{
"id": 3,
"created_at": "2023-11-07T06:09:04Z",
"updated_at": "2023-11-07T06:09:04Z",
"is_del": 0,
"email": "jack@example.com",
"name": "jack",
"avatar": "https://example.com/avatar.png",
"phone": "1234567890",
"state": "enable",
"location": "Shanghai",
"bio": "I am jack",
"configs": null
},
{
"id": 4,
"created_at": "2023-12-05T07:17:47Z",
"updated_at": "2023-12-12T06:37:49Z",
"is_del": 0,
"email": "mary@example.com",
"name": "mary",
"avatar": "",
"phone": "15170017449",
"state": "enable",
"location": "shanghaiHongqiao",
"bio": "I am mary",
"configs": null
},
{
"id": 5,
"created_at": "2023-12-05T07:17:47Z",
"updated_at": "2023-12-12T06:37:49Z",
"is_del": 0,
"email": "lip@example.com",
"name": "lip",
"avatar": "",
"phone": "15170017449",
"state": "enable",
"location": "Chengdu",
"bio": "I am lip",
"configs": null
},
{
"id": 6,
"created_at": "2023-12-05T07:17:47Z",
"updated_at": "2023-12-12T06:37:49Z",
"is_del": 0,
"email": "carl@example.com",
"name": "carl",
"avatar": "",
"phone": "15170017449",
"state": "enable",
"location": "shanghaiHuangpu",
"bio": "I am carl",
"configs": null
},
{
"id": 7,
"created_at": "2023-12-05T07:17:47Z",
"updated_at": "2023-12-12T06:37:49Z",
"is_del": 0,
"email": "david@example.com",
"name": "david",
"avatar": "",
"phone": "15170017449",
"state": "enable",
"location": "Hangzhou",
"bio": "I am david",
"configs": null
},
{
"id": 8,
"created_at": "2023-12-05T07:17:47Z",
"updated_at": "2023-12-12T06:37:49Z",
"is_del": 0,
"email": "debbie@example.com",
"name": "debbie",
"avatar": "",
"phone": "15170017449",
"state": "enable",
"location": "Tianjing",
"bio": "I am debbie",
"configs": null
},
{
"id": 9,
"created_at": "2023-12-05T07:17:47Z",
"updated_at": "2023-12-12T06:37:49Z",
"is_del": 0,
"email": "allen@example.com",
"name": "allen",
"avatar": "",
"phone": "15170017449",
"state": "enable",
"location": "Fuzhou",
"bio": "I am allen",
"configs": null
},
{
"id": 10,
"created_at": "2023-12-05T07:17:47Z",
"updated_at": "2023-12-12T06:37:49Z",
"is_del": 0,
"email": "liam@example.com",
"name": "liam",
"avatar": "",
"phone": "18170017449",
"state": "enable",
"location": "Nanjing",
"bio": "I am liam",
"configs": null
},
{
"id": 11,
"created_at": "2023-12-05T07:17:47Z",
"updated_at": "2023-12-12T06:37:49Z",
"is_del": 0,
"email": "noah@example.com",
"name": "noah",
"avatar": "",
"phone": "15170017449",
"state": "enable",
"location": "Shengyang",
"bio": "I am noah",
"configs": null
}
]

View File

@ -316,7 +316,7 @@ export default function NewPreheat() {
filter: filters,
headers: headerList,
},
cdn_cluster_ids: clusterID,
scheduler_cluster_ids: clusterID,
};
if (canSubmit) {

View File

@ -35,7 +35,7 @@ import {
createTheme,
} from '@mui/material';
import { useEffect, useState } from 'react';
import { getUserRoles, getUsers, getUser, deleteUserRole, putUserRole } from '../../lib/api';
import { getUserRoles, getUsers, getUser, deleteUserRole, putUserRole, getUsersResponse } from '../../lib/api';
import { makeStyles } from '@mui/styles';
import { getDatetime, getPaginatedList } from '../../lib/utils';
import { LoadingButton } from '@mui/lab';
@ -85,8 +85,8 @@ export default function Users() {
const [loadingButton, setLoadingButton] = useState(false);
const [userPage, setUserPage] = useState(1);
const [userTotalPages, setUserTotalPages] = useState<number>(1);
const [users, setUsers] = useState([{ avatar: '', id: 0, email: '', name: '', state: '', location: '' }]);
const [allUsers, setAllUsers] = useState([{ avatar: '', id: 0, email: '', name: '', state: '', location: '' }]);
const [users, setUsers] = useState<getUsersResponse[]>([]);
const [allUsers, setAllUsers] = useState<getUsersResponse[]>([]);
const [user, setUser] = useState({
id: 0,
email: '',
@ -285,10 +285,11 @@ export default function Users() {
</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableBody id="user-table-body">
{Array.isArray(allUsers) &&
allUsers.map((item) => (
<TableRow
id="user-table-row"
sx={{
'&.MuiTableRow-root': {
':hover': {
@ -371,6 +372,7 @@ export default function Users() {
color: '#fff',
},
}}
id={`detail-${item.name}`}
onClick={() => {
handleChange(item);
}}
@ -388,6 +390,7 @@ export default function Users() {
color: '#fff',
},
}}
id={`edit-${item.name}`}
onClick={() => {
openSwitchUser(item);
}}
@ -403,6 +406,7 @@ export default function Users() {
color: '#fff',
},
}}
id={`detail-${item.name}`}
onClick={() => {
handleChange(item);
}}
@ -420,6 +424,7 @@ export default function Users() {
{userTotalPages > 1 ? (
<Box display="flex" justifyContent="flex-end" sx={{ marginTop: theme.spacing(2) }}>
<Pagination
id="user-pagination"
count={userTotalPages}
page={userPage}
onChange={(_event: any, newPage: number) => {
@ -458,6 +463,7 @@ export default function Users() {
value="root"
control={
<Radio
id="role-root"
sx={{
'&.MuiRadio-root': {
color: 'var(--button-color)',
@ -471,6 +477,7 @@ export default function Users() {
value="guest"
control={
<Radio
id="role-guest"
sx={{
'&.MuiRadio-root': {
color: 'var(--button-color)',
@ -491,6 +498,7 @@ export default function Users() {
size="small"
variant="outlined"
loadingPosition="end"
id="cancel"
sx={{
'&.MuiLoadingButton-root': {
color: 'var(--calcel-size-color)',
@ -520,6 +528,7 @@ export default function Users() {
variant="outlined"
type="submit"
loadingPosition="end"
id="save"
sx={{
'&.MuiLoadingButton-root': {
backgroundColor: 'var(--save-color)',
@ -583,7 +592,7 @@ export default function Users() {
</Typography>
</ListItemAvatar>
<Typography variant="body2">
{detailIsLoading ? <Skeleton sx={{ width: '8rem' }} /> : user?.name}
{detailIsLoading ? <Skeleton sx={{ width: '8rem' }} /> : user?.name || '-'}
</Typography>
</ListItem>
<Divider />
@ -597,7 +606,7 @@ export default function Users() {
<Typography variant="body2" component="div">
{detailIsLoading ? (
<Skeleton sx={{ width: '8rem' }} />
) : (
) : detailRole ? (
<Chip
label={detailRole}
size="small"
@ -611,6 +620,8 @@ export default function Users() {
fontWeight: 'bold',
}}
/>
) : (
'-'
)}
</Typography>
</ListItem>
@ -666,13 +677,15 @@ export default function Users() {
</ListItemAvatar>
{detailIsLoading ? (
<Skeleton sx={{ width: '8rem' }} />
) : (
) : user.created_at ? (
<Chip
avatar={<Box component="img" src="/icons/user/created-at.svg" />}
label={getDatetime(user.created_at || '-')}
variant="outlined"
size="small"
/>
) : (
'-'
)}
</ListItem>
<Divider />
@ -685,13 +698,15 @@ export default function Users() {
</ListItemAvatar>
{detailIsLoading ? (
<Skeleton sx={{ width: '8rem' }} />
) : (
) : user.updated_at ? (
<Chip
avatar={<Box component="img" src="/icons/user/updated-at.svg" />}
label={getDatetime(user.updated_at || '-')}
variant="outlined"
size="small"
/>
) : (
'-'
)}
</ListItem>
</List>

View File

@ -446,7 +446,7 @@ interface getUserParams {
per_page?: number;
}
interface getUsersResponse {
export interface getUsersResponse {
avatar: string;
id: number;
email: string;
@ -760,7 +760,7 @@ interface createJobRequest {
filter: string;
headers?: { [key: string]: string };
};
cdn_cluster_ids: Array<number>;
scheduler_cluster_ids: Array<number>;
}
interface cerateJobResponse {