mirror of
https://github.com/AppFlowy-IO/AppFlowy-Web.git
synced 2025-11-30 03:18:02 +08:00
chore: add login logout test
This commit is contained in:
241
cypress/e2e/auth/login-logout.cy.ts
Normal file
241
cypress/e2e/auth/login-logout.cy.ts
Normal file
@@ -0,0 +1,241 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { AuthTestUtils } from '../../support/auth-utils';
|
||||
import { TestTool } from '../../support/page-utils';
|
||||
import {
|
||||
WorkspaceSelectors,
|
||||
AuthSelectors,
|
||||
waitForReactUpdate
|
||||
} from '../../support/selectors';
|
||||
|
||||
describe('Login and Logout Flow', () => {
|
||||
const baseUrl = Cypress.config('baseUrl') || 'http://localhost:3000';
|
||||
const gotrueUrl = Cypress.env('APPFLOWY_GOTRUE_BASE_URL') || 'http://localhost/gotrue';
|
||||
const apiUrl = Cypress.env('APPFLOWY_BASE_URL') || 'http://localhost';
|
||||
|
||||
beforeEach(() => {
|
||||
// Handle uncaught exceptions
|
||||
cy.on('uncaught:exception', (err) => {
|
||||
if (err.message.includes('Minified React error') ||
|
||||
err.message.includes('View not found') ||
|
||||
err.message.includes('No workspace or service found')) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
cy.viewport(1280, 720);
|
||||
});
|
||||
|
||||
describe('Test Case 1: Complete Login and Logout Flow', () => {
|
||||
it('should login and successfully logout with detailed verification', () => {
|
||||
const testEmail = `test-${uuidv4()}@appflowy.io`;
|
||||
|
||||
cy.log(`[TEST START] Complete Login and Logout Flow - Email: ${testEmail}`);
|
||||
|
||||
// Step 1: Navigate to login page
|
||||
cy.log('[STEP 1] Visiting login page');
|
||||
cy.visit('/login', { failOnStatusCode: false });
|
||||
cy.wait(2000);
|
||||
|
||||
// Step 2: Verify login page elements before authentication
|
||||
cy.log('[STEP 2] Verifying login page loaded with all elements');
|
||||
cy.contains('Welcome to AppFlowy').should('be.visible');
|
||||
AuthSelectors.emailInput().should('be.visible');
|
||||
AuthSelectors.passwordSignInButton().should('be.visible');
|
||||
|
||||
// Step 3: Use AuthTestUtils for authentication (more reliable than manual password entry)
|
||||
cy.log('[STEP 3] Starting authentication process');
|
||||
const authUtils = new AuthTestUtils();
|
||||
authUtils.signInWithTestUrl(testEmail).then(() => {
|
||||
cy.log('[STEP 4] Authentication successful');
|
||||
|
||||
// Step 4: Verify successful navigation to app page
|
||||
cy.url({ timeout: 30000 }).should('include', '/app');
|
||||
cy.wait(3000); // Allow app to fully load
|
||||
|
||||
// Step 5: Verify workspace is loaded by checking dropdown trigger
|
||||
cy.log('[STEP 5] Verifying workspace loaded');
|
||||
WorkspaceSelectors.dropdownTrigger({ timeout: 15000 })
|
||||
.should('be.visible');
|
||||
|
||||
// Step 6: Open workspace dropdown
|
||||
cy.log('[STEP 6] Opening workspace dropdown');
|
||||
TestTool.openWorkspaceDropdown();
|
||||
|
||||
// Step 7: Verify dropdown content and user email
|
||||
cy.log('[STEP 7] Verifying dropdown content and user email');
|
||||
WorkspaceSelectors.dropdownContent()
|
||||
.should('be.visible');
|
||||
cy.contains(testEmail).should('be.visible');
|
||||
|
||||
// Step 8: Click logout menu item
|
||||
cy.log('[STEP 8] Clicking logout menu item');
|
||||
AuthSelectors.logoutMenuItem()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
waitForReactUpdate(1000);
|
||||
|
||||
// Step 9: Verify logout confirmation dialog appears
|
||||
cy.log('[STEP 9] Verifying logout confirmation dialog');
|
||||
AuthSelectors.logoutConfirmButton()
|
||||
.should('be.visible');
|
||||
|
||||
// Step 10: Confirm logout
|
||||
cy.log('[STEP 10] Confirming logout');
|
||||
AuthSelectors.logoutConfirmButton().click();
|
||||
|
||||
waitForReactUpdate(2000);
|
||||
|
||||
// Step 11: Verify redirect to login page
|
||||
cy.log('[STEP 11] Verifying redirect to login page');
|
||||
cy.url({ timeout: 10000 }).should('include', '/login');
|
||||
|
||||
// Step 12: Verify login page elements are visible after logout
|
||||
cy.log('[STEP 12] Verifying login page elements after logout');
|
||||
cy.contains('Welcome to AppFlowy').should('be.visible');
|
||||
AuthSelectors.emailInput().should('be.visible');
|
||||
AuthSelectors.passwordSignInButton().should('be.visible');
|
||||
|
||||
cy.log('[STEP 13] Test completed successfully - Full login and logout flow verified');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test Case 2: Quick Login and Logout using Test URL', () => {
|
||||
it('should login with test URL and successfully logout', () => {
|
||||
const testEmail = `test-${uuidv4()}@appflowy.io`;
|
||||
|
||||
cy.log(`[TEST START] Quick Login and Logout using Test URL - Email: ${testEmail}`);
|
||||
|
||||
// Step 1: Visit login page
|
||||
cy.log('[STEP 1] Visiting login page');
|
||||
cy.visit('/login', { failOnStatusCode: false });
|
||||
cy.wait(2000);
|
||||
|
||||
// Step 2: Use AuthTestUtils for quick authentication
|
||||
cy.log('[STEP 2] Starting quick authentication with test URL');
|
||||
const authUtils = new AuthTestUtils();
|
||||
authUtils.signInWithTestUrl(testEmail).then(() => {
|
||||
cy.log('[STEP 3] Authentication successful');
|
||||
|
||||
// Verify navigation to app page
|
||||
cy.url({ timeout: 30000 }).should('include', '/app');
|
||||
cy.wait(3000); // Allow app to fully load
|
||||
|
||||
// Step 4: Verify user is logged in
|
||||
cy.log('[STEP 4] Verifying user is logged in');
|
||||
WorkspaceSelectors.dropdownTrigger({ timeout: 15000 })
|
||||
.should('be.visible');
|
||||
|
||||
// Step 5: Open workspace dropdown
|
||||
cy.log('[STEP 5] Opening workspace dropdown');
|
||||
TestTool.openWorkspaceDropdown();
|
||||
|
||||
// Verify dropdown is open and user email is visible
|
||||
WorkspaceSelectors.dropdownContent()
|
||||
.should('be.visible');
|
||||
cy.contains(testEmail).should('be.visible');
|
||||
|
||||
// Step 6: Click logout menu item
|
||||
cy.log('[STEP 6] Clicking logout menu item');
|
||||
AuthSelectors.logoutMenuItem()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
waitForReactUpdate(1000);
|
||||
|
||||
// Step 7: Confirm logout
|
||||
cy.log('[STEP 7] Confirming logout');
|
||||
AuthSelectors.logoutConfirmButton()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
waitForReactUpdate(2000);
|
||||
|
||||
// Step 8: Verify redirect to login page
|
||||
cy.log('[STEP 8] Verifying redirect to login page');
|
||||
cy.url({ timeout: 10000 }).should('include', '/login');
|
||||
|
||||
// Verify login page elements are visible
|
||||
cy.contains('Welcome to AppFlowy').should('be.visible');
|
||||
AuthSelectors.emailInput().should('be.visible');
|
||||
|
||||
cy.log('[STEP 9] Test completed successfully - Quick login and logout verified');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test Case 3: Cancel Logout Confirmation', () => {
|
||||
it('should cancel logout when clicking cancel button', () => {
|
||||
const testEmail = `test-${uuidv4()}@appflowy.io`;
|
||||
|
||||
cy.log(`[TEST START] Cancel Logout Confirmation - Email: ${testEmail}`);
|
||||
|
||||
// Step 1: Visit login page
|
||||
cy.log('[STEP 1] Visiting login page');
|
||||
cy.visit('/login', { failOnStatusCode: false });
|
||||
cy.wait(2000);
|
||||
|
||||
// Step 2: Use AuthTestUtils for quick authentication
|
||||
cy.log('[STEP 2] Starting authentication');
|
||||
const authUtils = new AuthTestUtils();
|
||||
authUtils.signInWithTestUrl(testEmail).then(() => {
|
||||
cy.log('[STEP 3] Authentication successful');
|
||||
|
||||
// Verify navigation to app page
|
||||
cy.url({ timeout: 30000 }).should('include', '/app');
|
||||
cy.wait(3000); // Allow app to fully load
|
||||
|
||||
// Step 4: Open workspace dropdown
|
||||
cy.log('[STEP 4] Opening workspace dropdown');
|
||||
WorkspaceSelectors.dropdownTrigger({ timeout: 15000 })
|
||||
.should('be.visible');
|
||||
TestTool.openWorkspaceDropdown();
|
||||
|
||||
// Verify dropdown is open
|
||||
WorkspaceSelectors.dropdownContent()
|
||||
.should('be.visible');
|
||||
|
||||
// Step 5: Click logout menu item
|
||||
cy.log('[STEP 5] Clicking logout menu item');
|
||||
AuthSelectors.logoutMenuItem()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
waitForReactUpdate(1000);
|
||||
|
||||
// Step 6: Click Cancel button in logout confirmation dialog
|
||||
cy.log('[STEP 6] Clicking Cancel button in logout confirmation');
|
||||
|
||||
// Find and click the Cancel button using text content
|
||||
cy.contains('button', 'Cancel')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
waitForReactUpdate(1000);
|
||||
|
||||
// Step 7: Verify user remains logged in
|
||||
cy.log('[STEP 7] Verifying user remains logged in');
|
||||
|
||||
// Should still be on /app page
|
||||
cy.url().should('include', '/app');
|
||||
|
||||
// Workspace dropdown should still be accessible
|
||||
WorkspaceSelectors.dropdownTrigger()
|
||||
.should('be.visible');
|
||||
|
||||
// Open dropdown again to verify user is still logged in
|
||||
TestTool.openWorkspaceDropdown();
|
||||
WorkspaceSelectors.dropdownContent()
|
||||
.should('be.visible');
|
||||
cy.contains(testEmail).should('be.visible');
|
||||
|
||||
// Close dropdown
|
||||
cy.get('body').click(0, 0); // Click outside to close dropdown
|
||||
waitForReactUpdate(500);
|
||||
|
||||
cy.log('[STEP 8] Test completed successfully - Logout cancellation verified');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -404,6 +404,26 @@ export const RowControlsSelectors = {
|
||||
deleteRowConfirmButton: () => cy.get(byTestId('delete-row-confirm-button')),
|
||||
};
|
||||
|
||||
/**
|
||||
* Authentication-related selectors
|
||||
* Used for login/logout flow testing
|
||||
*/
|
||||
export const AuthSelectors = {
|
||||
// Login page elements
|
||||
emailInput: () => cy.get(byTestId('login-email-input')),
|
||||
|
||||
// Password sign-in button
|
||||
passwordSignInButton: () => cy.get(byTestId('login-password-button')),
|
||||
|
||||
// Password page elements
|
||||
passwordInput: () => cy.get(byTestId('password-input')),
|
||||
passwordSubmitButton: () => cy.get(byTestId('password-submit-button')),
|
||||
|
||||
// Logout elements
|
||||
logoutMenuItem: () => cy.get(byTestId('logout-menu-item')),
|
||||
logoutConfirmButton: () => cy.get(byTestId('logout-confirm-button')),
|
||||
};
|
||||
|
||||
export function waitForReactUpdate(ms: number = 500) {
|
||||
return cy.wait(ms);
|
||||
}
|
||||
@@ -231,7 +231,7 @@ export function Workspaces() {
|
||||
<div className={'flex-1 text-left'}>{t('web.accountSettings')}</div>
|
||||
</DropdownMenuItem>
|
||||
</AccountSettings>
|
||||
<DropdownMenuItem onSelect={() => setOpenLogoutConfirm(true)}>
|
||||
<DropdownMenuItem data-testid="logout-menu-item" onSelect={() => setOpenLogoutConfirm(true)}>
|
||||
<LogoutIcon />
|
||||
{t('button.logout')}
|
||||
</DropdownMenuItem>
|
||||
|
||||
Reference in New Issue
Block a user