feat: add users page e2e test (#338)
Signed-off-by: zhaoxinxin <1186037180@qq.com>
This commit is contained in:
parent
99681b829a
commit
0f4db05321
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
]
|
|
@ -316,7 +316,7 @@ export default function NewPreheat() {
|
|||
filter: filters,
|
||||
headers: headerList,
|
||||
},
|
||||
cdn_cluster_ids: clusterID,
|
||||
scheduler_cluster_ids: clusterID,
|
||||
};
|
||||
|
||||
if (canSubmit) {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue