Files
AppFlowy-Web/cypress/e2e/database/single-select-column.cy.ts
2025-09-10 20:49:41 +08:00

332 lines
13 KiB
TypeScript

import { v4 as uuidv4 } from 'uuid';
import { AuthTestUtils } from '../../support/auth-utils';
import {
AddPageSelectors,
DatabaseGridSelectors,
PropertyMenuSelectors,
GridFieldSelectors,
SingleSelectSelectors,
FieldType,
waitForReactUpdate
} from '../../support/selectors';
describe('Single Select Column Type', () => {
const generateRandomEmail = () => `${uuidv4()}@appflowy.io`;
const SINGLE_SELECT_FIELD_TYPE = 3; // From FieldType enum
beforeEach(() => {
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);
});
it('should create and edit basic grid cells', () => {
const testEmail = generateRandomEmail();
cy.log(`[TEST START] Third test - Test email: ${testEmail}`);
cy.log('[STEP 1] Visiting login page');
cy.visit('/login', { failOnStatusCode: false });
cy.wait(2000);
const authUtils = new AuthTestUtils();
cy.log('[STEP 2] Starting authentication');
authUtils.signInWithTestUrl(testEmail).then(() => {
cy.log('[STEP 3] Authentication successful');
cy.url({ timeout: 30000 }).should('include', '/app');
cy.wait(5000); // Increased wait for CI environment
// Ensure we're on the right page before proceeding
cy.log('[STEP 3.1] Verifying workspace loaded');
cy.get('body').should('exist');
cy.wait(2000);
// Create a new grid
cy.log('[STEP 4] Creating new grid');
cy.log('[STEP 4.1] Waiting for inline add button or new page button');
// Try to find either inline add button or new page button
cy.get('body').then($body => {
const inlineAddExists = $body.find('[data-testid="inline-add-page"]').length > 0;
const newPageExists = $body.find('[data-testid="new-page-button"]').length > 0;
if (inlineAddExists) {
cy.log('[STEP 4.2] Using inline add button');
return cy.wrap(null).then(() => {
AddPageSelectors.inlineAddButton().first().click({ force: true });
});
} else if (newPageExists) {
cy.log('[STEP 4.2] Using new page button instead');
return cy.wrap(null).then(() => {
cy.get('[data-testid="new-page-button"]').first().click({ force: true });
});
} else {
// Wait a bit more and try inline add button
cy.log('[STEP 4.2] Waiting for UI to stabilize');
return cy.wrap(null).then(() => {
cy.wait(3000);
AddPageSelectors.inlineAddButton().should('exist', { timeout: 15000 });
AddPageSelectors.inlineAddButton().first().click({ force: true });
});
}
});
waitForReactUpdate(1000);
cy.log('[STEP 4.3] Clicking add grid button');
AddPageSelectors.addGridButton().should('exist', { timeout: 10000 });
AddPageSelectors.addGridButton().click({ force: true });
cy.wait(8000);
// Verify cells exist
DatabaseGridSelectors.cells().should('exist');
// Get all cells and verify interaction
DatabaseGridSelectors.cells().then($cells => {
cy.log(`[STEP 8] Found ${$cells.length} cells`);
// Click first cell
cy.wrap($cells.first()).click();
waitForReactUpdate(500);
cy.focused().type('Cell 1 Data');
cy.focused().type('{enter}');
waitForReactUpdate(500);
// Verify data was entered
cy.wrap($cells.first()).should('contain.text', 'Cell 1 Data');
// Click second cell if exists
if ($cells.length > 1) {
cy.wrap($cells.eq(1)).click();
waitForReactUpdate(500);
cy.focused().type('Option One');
cy.focused().type('{enter}');
waitForReactUpdate(500);
// Verify the new option 'Option One' exists in the cell
cy.wrap($cells.eq(1)).should('contain.text', 'Option One');
}
cy.log('[STEP 9] Cell interaction completed successfully');
});
});
});
it('should convert SingleSelect to RichText and back preserving options', () => {
const testEmail = generateRandomEmail();
cy.log(`[TEST START] Testing field type conversion - Test email: ${testEmail}`);
cy.log('[STEP 1] Visiting login page');
cy.visit('/login', { failOnStatusCode: false });
cy.wait(2000);
const authUtils = new AuthTestUtils();
cy.log('[STEP 2] Starting authentication');
authUtils.signInWithTestUrl(testEmail).then(() => {
cy.log('[STEP 3] Authentication successful');
cy.url({ timeout: 30000 }).should('include', '/app');
cy.wait(5000); // Increased wait for CI environment
// Ensure we're on the right page before proceeding
cy.log('[STEP 3.1] Verifying workspace loaded');
cy.get('body').should('exist');
cy.wait(2000);
// Create a new grid
cy.log('[STEP 4] Creating new grid');
cy.log('[STEP 4.1] Waiting for inline add button');
AddPageSelectors.inlineAddButton().should('exist', { timeout: 15000 });
AddPageSelectors.inlineAddButton().first().scrollIntoView().click({ force: true });
waitForReactUpdate(1000);
cy.log('[STEP 4.2] Clicking add grid button');
AddPageSelectors.addGridButton().should('exist', { timeout: 10000 });
AddPageSelectors.addGridButton().click({ force: true });
cy.wait(8000);
// Verify grid exists with better error handling
cy.log('[STEP 5] Verifying grid exists');
DatabaseGridSelectors.grid().should('exist', { timeout: 15000 });
// Wait for cells to appear
cy.log('[STEP 5.1] Waiting for cells to appear');
DatabaseGridSelectors.cells().should('have.length.at.least', 1);
// Add new column as SingleSelect
cy.log('[STEP 6] Adding new SingleSelect column');
PropertyMenuSelectors.newPropertyButton().first().scrollIntoView().click({ force: true });
waitForReactUpdate(3000);
// Check if property menu is open and change to SingleSelect
cy.log('[STEP 7] Changing column type to SingleSelect');
cy.get('body').then($body => {
if ($body.find('[data-testid="property-type-trigger"]').length > 0) {
PropertyMenuSelectors.propertyTypeTrigger().first().click({ force: true });
waitForReactUpdate(1000);
PropertyMenuSelectors.propertyTypeOption(FieldType.SingleSelect).click({ force: true });
waitForReactUpdate(2000);
} else {
// Try clicking on the field header first
GridFieldSelectors.allFieldHeaders().last().scrollIntoView().click({ force: true });
waitForReactUpdate(1000);
PropertyMenuSelectors.propertyTypeTrigger().first().click({ force: true });
waitForReactUpdate(1000);
PropertyMenuSelectors.propertyTypeOption(FieldType.SingleSelect).click({ force: true });
waitForReactUpdate(2000);
}
});
// Close menu
cy.get('body').type('{esc}{esc}');
waitForReactUpdate(1000);
// Add some select options by clicking on cells
cy.log('[STEP 8] Adding select options to cells');
// First try to find select cells
cy.get('body').then($body => {
const selectCells = $body.find('[data-testid^="select-option-cell-"]');
if (selectCells.length > 0) {
cy.log(`[STEP 9] Found ${selectCells.length} select cells`);
// Click first cell with force and add option
SingleSelectSelectors.allSelectOptionCells().first().click({ force: true });
waitForReactUpdate(500);
cy.focused().type('Option A{enter}');
waitForReactUpdate(1000);
// Add second option if possible
if (selectCells.length > 1) {
SingleSelectSelectors.allSelectOptionCells().eq(1).click({ force: true });
waitForReactUpdate(500);
cy.focused().type('Option B{enter}');
waitForReactUpdate(1000);
}
} else {
cy.log('[STEP 9] No select cells found, using regular cells');
// Get all rows and find cells in the newly added column
DatabaseGridSelectors.rows().first().within(() => {
// Click the last cell in this row (should be the new column)
DatabaseGridSelectors.cells().last().click({ force: true });
waitForReactUpdate(500);
});
// Type option A
cy.focused().type('Option A{enter}');
waitForReactUpdate(1000);
// Try second row
DatabaseGridSelectors.rows().eq(1).within(() => {
DatabaseGridSelectors.cells().last().click({ force: true });
waitForReactUpdate(500);
});
cy.focused().type('Option B{enter}');
waitForReactUpdate(1000);
}
});
// Now open the field header menu to convert to RichText
cy.log('[STEP 10] Opening field menu to convert to RichText');
GridFieldSelectors.allFieldHeaders().last().click({ force: true });
waitForReactUpdate(1000);
// Click edit property if available
cy.get('body').then($body => {
if ($body.find('[data-testid="grid-field-edit-property"]').length > 0) {
PropertyMenuSelectors.editPropertyMenuItem().click();
waitForReactUpdate(1000);
}
});
// Change type to RichText
cy.log('[STEP 11] Converting SingleSelect to RichText');
PropertyMenuSelectors.propertyTypeTrigger().click({ force: true });
waitForReactUpdate(500);
PropertyMenuSelectors.propertyTypeOption(FieldType.RichText).click({ force: true });
waitForReactUpdate(2000);
// Close menu
cy.get('body').type('{esc}{esc}');
waitForReactUpdate(1000);
// Verify the cells now show text representation
cy.log('[STEP 12] Verifying text representation of select options');
DatabaseGridSelectors.cells().then($cells => {
// Check if any cell contains "Option A" or "Option B" as text
let foundOptionA = false;
let foundOptionB = false;
$cells.each((_, cell) => {
const text = cell.textContent || '';
if (text.includes('Option A')) foundOptionA = true;
if (text.includes('Option B')) foundOptionB = true;
});
if (foundOptionA || foundOptionB) {
cy.log('[STEP 13] Text representation confirmed - found option text');
} else {
cy.log('[STEP 13] Text representation may be empty or different');
}
});
// Convert back to SingleSelect
cy.log('[STEP 14] Converting back to SingleSelect');
GridFieldSelectors.allFieldHeaders().last().click({ force: true });
waitForReactUpdate(1000);
// Click edit property if available
cy.get('body').then($body => {
if ($body.find('[data-testid="grid-field-edit-property"]').length > 0) {
PropertyMenuSelectors.editPropertyMenuItem().click();
waitForReactUpdate(1000);
}
});
// Change type back to SingleSelect
cy.log('[STEP 15] Changing type back to SingleSelect');
PropertyMenuSelectors.propertyTypeTrigger().click({ force: true });
waitForReactUpdate(500);
PropertyMenuSelectors.propertyTypeOption(FieldType.SingleSelect).click({ force: true });
waitForReactUpdate(2000);
// Close menu
cy.get('body').type('{esc}{esc}');
waitForReactUpdate(1000);
// Verify select options are displayed again
cy.log('[STEP 16] Verifying select options are displayed again');
cy.get('body').then($body => {
const selectCells = $body.find('[data-testid^="select-option-cell-"]');
if (selectCells.length > 0) {
cy.log(`[STEP 17] Success! Found ${selectCells.length} select option cells after conversion`);
// Click on a cell to verify options are still available
SingleSelectSelectors.allSelectOptionCells().first().click();
waitForReactUpdate(500);
// Check if select menu appears
cy.get('body').then($body => {
if ($body.find('[data-testid="select-option-menu"]').length > 0) {
cy.log('[STEP 18] Select option menu opened - options preserved!');
} else {
cy.log('[STEP 18] Select cells exist but menu behavior may differ');
}
});
} else {
cy.log('[STEP 17] Select cells may be using different testid or rendering differently');
}
});
cy.log('[STEP 19] Field type conversion test completed');
});
});
});