chore: selector

This commit is contained in:
Nathan
2025-11-17 13:19:36 +08:00
parent 87c5c2f10e
commit eb7f7423aa
18 changed files with 289 additions and 255 deletions

View File

@@ -1,5 +1,5 @@
import { avatarTestUtils } from './avatar-test-utils';
import { byTestId } from '../../../support/selectors';
import { AccountSelectors, AvatarUiSelectors } from '../../../support/selectors';
import { testLog } from '../../../support/test-helpers';
const { generateRandomEmail, setupBeforeEach, imports } = avatarTestUtils;
@@ -39,7 +39,7 @@ describe('Avatar API', () => {
testLog.info( 'Step 5: Open Account Settings to verify avatar');
WorkspaceSelectors.dropdownTrigger().click();
cy.wait(1000);
cy.get(byTestId('account-settings-button')).click();
AccountSelectors.settingsButton().click();
AvatarSelectors.accountSettingsDialog().should('be.visible');
testLog.info( 'Step 6: Verify avatar image is displayed in Account Settings');
@@ -50,7 +50,7 @@ describe('Avatar API', () => {
// Wait for any avatar image to be present and loaded
// The AvatarImage component loads asynchronously and sets opacity to 0 while loading
cy.get(byTestId('avatar-image'), { timeout: 10000 })
AvatarUiSelectors.image()
.should('exist')
.should(($imgs) => {
// Find the first visible avatar image (opacity not 0)
@@ -68,7 +68,7 @@ describe('Avatar API', () => {
});
// Verify that the avatar image has loaded (check for non-empty src and visible state)
cy.get(byTestId('avatar-image')).then(($imgs) => {
AvatarUiSelectors.image().then(($imgs) => {
let foundLoaded = false;
$imgs.each((index, img) => {
const $img = Cypress.$(img);
@@ -160,7 +160,7 @@ describe('Avatar API', () => {
testLog.info( 'Step 5: Open Account Settings');
WorkspaceSelectors.dropdownTrigger().click();
cy.wait(1000);
cy.get(byTestId('account-settings-button')).click();
AccountSelectors.settingsButton().click();
AvatarSelectors.accountSettingsDialog().should('be.visible');
testLog.info( 'Step 6: Verify emoji is displayed in fallback');

View File

@@ -1,5 +1,5 @@
import { avatarTestUtils } from './avatar-test-utils';
import { byTestIdContains } from '../../../support/selectors';
import { PageSelectors } from '../../../support/selectors';
import { testLog } from '../../../support/test-helpers';
const { generateRandomEmail, setupBeforeEach, imports } = avatarTestUtils;
@@ -39,12 +39,15 @@ describe('Avatar Header Display', () => {
testLog.info( 'Step 4: Interact with editor to trigger collaborative user awareness');
// Click on a page to open editor
cy.get('body').then(($body) => {
// Try to find and click on a page in the sidebar
if ($body.find(byTestIdContains('page')).length > 0) {
cy.get(byTestIdContains('page')).first().click();
} else if ($body.text().includes('Getting started')) {
cy.contains('Getting started').click();
PageSelectors.items().then($pages => {
if ($pages.length > 0) {
cy.wrap($pages.first()).click();
} else {
cy.get('body').then($body => {
if ($body.text().includes('Getting started')) {
cy.contains('Getting started').click();
}
});
}
});
@@ -118,11 +121,15 @@ describe('Avatar Header Display', () => {
testLog.info( 'Step 4: Interact with editor to trigger collaborative user awareness');
// Click on a page to open editor
cy.get('body').then(($body) => {
if ($body.find(byTestIdContains('page')).length > 0) {
cy.get(byTestIdContains('page')).first().click();
} else if ($body.text().includes('Getting started')) {
cy.contains('Getting started').click();
PageSelectors.items().then($pages => {
if ($pages.length > 0) {
cy.wrap($pages.first()).click();
} else {
cy.get('body').then($body => {
if ($body.text().includes('Getting started')) {
cy.contains('Getting started').click();
}
});
}
});
@@ -214,11 +221,15 @@ describe('Avatar Header Display', () => {
testLog.info( 'Step 6: Interact with editor to trigger collaborative user awareness');
// Click on a page to open editor
cy.get('body').then(($body) => {
if ($body.find(byTestIdContains('page')).length > 0) {
cy.get(byTestIdContains('page')).first().click();
} else if ($body.text().includes('Getting started')) {
cy.contains('Getting started').click();
PageSelectors.items().then($pages => {
if ($pages.length > 0) {
cy.wrap($pages.first()).click();
} else {
cy.get('body').then($body => {
if ($body.text().includes('Getting started')) {
cy.contains('Getting started').click();
}
});
}
});

View File

@@ -1,5 +1,5 @@
import { avatarTestUtils } from './avatar-test-utils';
import { byTestId } from '../../../support/selectors';
import { AccountSelectors } from '../../../support/selectors';
import { testLog } from '../../../support/test-helpers';
const { generateRandomEmail, setupBeforeEach, imports } = avatarTestUtils;
@@ -63,7 +63,7 @@ describe('Avatar Notifications', () => {
testLog.info( 'Step 7: Open Account Settings to verify avatar');
WorkspaceSelectors.dropdownTrigger().click();
cy.wait(1000);
cy.get(byTestId('account-settings-button')).click();
AccountSelectors.settingsButton().click();
AvatarSelectors.accountSettingsDialog().should('be.visible');
testLog.info( 'Step 8: Verify avatar image uses updated URL');

View File

@@ -1,5 +1,5 @@
import { avatarTestUtils } from './avatar-test-utils';
import { byTestId } from '../../../support/selectors';
import { AccountSelectors } from '../../../support/selectors';
import { testLog } from '../../../support/test-helpers';
const { generateRandomEmail, setupBeforeEach, imports } = avatarTestUtils;
@@ -41,7 +41,7 @@ describe('Avatar Persistence', () => {
testLog.info( 'Step 5: Verify avatar persisted');
WorkspaceSelectors.dropdownTrigger().click();
cy.wait(1000);
cy.get(byTestId('account-settings-button')).click();
AccountSelectors.settingsButton().click();
AvatarSelectors.accountSettingsDialog().should('be.visible');
AvatarSelectors.avatarImage().should('exist').and('have.attr', 'src', testAvatarUrl);
@@ -52,7 +52,7 @@ describe('Avatar Persistence', () => {
WorkspaceSelectors.dropdownTrigger().click();
cy.wait(1000);
cy.get(byTestId('account-settings-button')).click();
AccountSelectors.settingsButton().click();
AvatarSelectors.accountSettingsDialog().should('be.visible');
AvatarSelectors.avatarImage().should('exist').and('have.attr', 'src', testAvatarUrl);

View File

@@ -1,5 +1,5 @@
import { avatarTestUtils } from './avatar-test-utils';
import { byTestId } from '../../../support/selectors';
import { AccountSelectors } from '../../../support/selectors';
import { testLog } from '../../../support/test-helpers';
const { generateRandomEmail, setupBeforeEach, imports } = avatarTestUtils;
@@ -47,7 +47,7 @@ describe('Avatar Priority', () => {
testLog.info( 'Step 5: Verify workspace avatar is displayed (priority)');
WorkspaceSelectors.dropdownTrigger().click();
cy.wait(1000);
cy.get(byTestId('account-settings-button')).click();
AccountSelectors.settingsButton().click();
AvatarSelectors.accountSettingsDialog().should('be.visible');
// Workspace avatar should be displayed, not user metadata avatar

View File

@@ -1,5 +1,5 @@
import { avatarTestUtils } from './avatar-test-utils';
import { byTestId } from '../../../support/selectors';
import { AccountSelectors } from '../../../support/selectors';
import { testLog } from '../../../support/test-helpers';
const { generateRandomEmail, setupBeforeEach, imports } = avatarTestUtils;
@@ -38,7 +38,7 @@ describe('Avatar Types', () => {
WorkspaceSelectors.dropdownTrigger().click();
cy.wait(1000);
cy.get(byTestId('account-settings-button')).click();
AccountSelectors.settingsButton().click();
AvatarSelectors.accountSettingsDialog().should('be.visible');
AvatarSelectors.avatarImage().should('exist').and('have.attr', 'src', httpsAvatar);
@@ -75,7 +75,7 @@ describe('Avatar Types', () => {
WorkspaceSelectors.dropdownTrigger().click();
cy.wait(1000);
cy.get(byTestId('account-settings-button')).click();
AccountSelectors.settingsButton().click();
AvatarSelectors.accountSettingsDialog().should('be.visible');
// Emoji should be displayed in fallback, not as image

View File

@@ -1,5 +1,5 @@
import { AuthTestUtils } from '../../support/auth-utils';
import { WorkspaceSelectors, byTestId } from '../../support/selectors';
import { WorkspaceSelectors, AccountSelectors } from '../../support/selectors';
import { generateRandomEmail } from '../../support/test-config';
describe('Update User Profile', () => {
@@ -40,61 +40,61 @@ describe('Update User Profile', () => {
// Click on Account Settings
cy.log('Step 4: Opening Account Settings');
cy.get(byTestId('account-settings-button')).should('be.visible').click();
AccountSelectors.settingsButton().should('be.visible').click();
// Add a wait to ensure the dialog has time to open
cy.wait(1000);
// Wait for Account Settings dialog to open
cy.log('Step 5: Verifying Account Settings dialog opened');
cy.get(byTestId('account-settings-dialog'), { timeout: 10000 }).should('be.visible');
AccountSelectors.settingsDialog().should('be.visible');
// Check initial date format (should be Month/Day/Year)
cy.log('Step 6: Checking initial date format');
cy.get(byTestId('date-format-dropdown')).should('be.visible');
AccountSelectors.dateFormatDropdown().should('be.visible');
// Test Date Format change - select Year/Month/Day
cy.log('Step 7: Testing Date Format change to Year/Month/Day');
cy.get(byTestId('date-format-dropdown')).click();
AccountSelectors.dateFormatDropdown().click();
cy.wait(500);
// Select US format (value 1) which is Year/Month/Day
cy.get(byTestId('date-format-1')).should('be.visible').click();
AccountSelectors.dateFormatOptionYearMonthDay().should('be.visible').click();
cy.wait(3000); // Wait for API call to complete
// Verify the dropdown now shows Year/Month/Day
cy.get(byTestId('date-format-dropdown')).should('contain.text', 'Year/Month/Day');
AccountSelectors.dateFormatDropdown().should('contain.text', 'Year/Month/Day');
// Test Time Format change
cy.log('Step 8: Testing Time Format change');
cy.get(byTestId('time-format-dropdown')).should('be.visible').click();
AccountSelectors.timeFormatDropdown().should('be.visible').click();
cy.wait(500);
// Select 24-hour format (value 1)
cy.get(byTestId('time-format-1')).should('be.visible').click();
AccountSelectors.timeFormatOption24().should('be.visible').click();
cy.wait(3000); // Wait for API call to complete
// Verify the dropdown now shows 24-hour format
cy.get(byTestId('time-format-dropdown')).should('contain.text', '24');
AccountSelectors.timeFormatDropdown().should('contain.text', '24');
// Test Start Week On change
cy.log('Step 9: Testing Start Week On change');
cy.get(byTestId('start-week-on-dropdown')).should('be.visible').click();
AccountSelectors.startWeekDropdown().should('be.visible').click();
cy.wait(500);
// Select Monday (value 1)
cy.get(byTestId('start-week-1')).should('be.visible').click();
AccountSelectors.startWeekMonday().should('be.visible').click();
cy.wait(3000); // Wait for API call to complete
cy.get(byTestId('start-week-on-dropdown')).should('contain.text', 'Monday');
AccountSelectors.startWeekDropdown().should('contain.text', 'Monday');
// The settings should remain selected in the current session
cy.log('Step 10: Verifying all settings are showing correctly');
// Verify all dropdowns still show the selected values
cy.get(byTestId('date-format-dropdown')).should('contain.text', 'Year/Month/Day');
cy.get(byTestId('time-format-dropdown')).should('contain.text', '24');
cy.get(byTestId('start-week-on-dropdown')).should('contain.text', 'Monday');
AccountSelectors.dateFormatDropdown().should('contain.text', 'Year/Month/Day');
AccountSelectors.timeFormatDropdown().should('contain.text', '24');
AccountSelectors.startWeekDropdown().should('contain.text', 'Monday');
cy.log('Test completed: User profile settings updated successfully');
});

View File

@@ -1,6 +1,6 @@
import { AuthTestUtils } from '../../support/auth-utils';
import { TestTool } from '../../support/page-utils';
import { AddPageSelectors, ModelSelectorSelectors, PageSelectors, SidebarSelectors, byTestId } from '../../support/selectors';
import { AddPageSelectors, ModelSelectorSelectors, PageSelectors, SidebarSelectors, ChatSelectors } from '../../support/selectors';
import { generateRandomEmail, logAppFlowyEnvironment } from '../../support/test-config';
describe('Chat Input Tests', () => {
@@ -55,18 +55,18 @@ describe('Chat Input Tests', () => {
// Test 1: Format toggle
cy.log('Testing format toggle');
cy.get('body').then($body => {
if ($body.find(byTestId('chat-format-group')).length > 0) {
cy.get(byTestId('chat-input-format-toggle')).click();
cy.get(byTestId('chat-format-group')).should('not.exist');
ChatSelectors.formatGroup().then($group => {
if ($group.length > 0) {
ChatSelectors.formatToggle().click();
ChatSelectors.formatGroup().should('not.exist');
}
});
cy.get(byTestId('chat-input-format-toggle')).should('be.visible').click();
cy.get(byTestId('chat-format-group')).should('exist');
cy.get(byTestId('chat-format-group')).find('button').should('have.length.at.least', 4);
cy.get(byTestId('chat-input-format-toggle')).click();
cy.get(byTestId('chat-format-group')).should('not.exist');
ChatSelectors.formatToggle().should('be.visible').click();
ChatSelectors.formatGroup().should('exist');
ChatSelectors.formatGroup().find('button').should('have.length.at.least', 4);
ChatSelectors.formatToggle().click();
ChatSelectors.formatGroup().should('not.exist');
// Test 2: Model selector
cy.log('Testing model selector');
@@ -76,7 +76,7 @@ describe('Chat Input Tests', () => {
// Test 3: Browse prompts
cy.log('Testing browse prompts');
cy.get(byTestId('chat-input-browse-prompts')).click();
ChatSelectors.browsePromptsButton().click();
cy.get('[role="dialog"]').should('exist');
cy.get('[role="dialog"]').contains('Browse prompts').should('be.visible');
cy.get('body').type('{esc}');
@@ -84,10 +84,10 @@ describe('Chat Input Tests', () => {
// Test 4: Related views
cy.log('Testing related views');
cy.get(byTestId('chat-input-related-views')).click();
cy.get(byTestId('chat-related-views-popover')).should('be.visible');
ChatSelectors.relatedViewsButton().click();
ChatSelectors.relatedViewsPopover().should('be.visible');
cy.get('body').type('{esc}');
cy.get(byTestId('chat-related-views-popover')).should('not.exist');
ChatSelectors.relatedViewsPopover().should('not.exist');
});
});
@@ -204,8 +204,8 @@ describe('Chat Input Tests', () => {
cy.wait(500);
// Check send button is disabled when empty
cy.get(byTestId('chat-input-send')).should('exist');
cy.get(byTestId('chat-input-send')).then($button => {
ChatSelectors.sendButton().should('exist');
ChatSelectors.sendButton().then($button => {
// Button might be disabled via attribute or opacity
const isDisabled = $button.prop('disabled') || $button.css('opacity') === '0.5';
expect(isDisabled).to.be.true;
@@ -215,7 +215,7 @@ describe('Chat Input Tests', () => {
getTextarea().type('Test message');
cy.wait(500);
cy.get(byTestId('chat-input-send')).then($button => {
ChatSelectors.sendButton().then($button => {
const isDisabled = $button.prop('disabled') || $button.css('opacity') === '0.5';
expect(isDisabled).to.be.false;
});
@@ -225,7 +225,7 @@ describe('Chat Input Tests', () => {
getTextarea().clear().type('Hello world');
cy.wait(500);
cy.get(byTestId('chat-input-send')).click();
ChatSelectors.sendButton().click();
cy.wait('@submitQuestion', { timeout: 10000 });
// Wait for textarea to be ready again

View File

@@ -1,6 +1,6 @@
import { AuthTestUtils } from '../../support/auth-utils';
import { TestTool } from '../../support/page-utils';
import { AddPageSelectors, PageSelectors, ModalSelectors, SidebarSelectors, byTestId, waitForReactUpdate } from '../../support/selectors';
import { AddPageSelectors, PageSelectors, ModalSelectors, SidebarSelectors, ChatSelectors, waitForReactUpdate } from '../../support/selectors';
import { generateRandomEmail, logAppFlowyEnvironment } from '../../support/test-config';
import { testLog } from '../../support/test-helpers';
@@ -125,8 +125,8 @@ describe('AI Chat Creation and Navigation Tests', () => {
testLog.info( '✓ Navigated to AI Chat page');
// Check if the AI Chat container exists (but don't fail if it doesn't load immediately)
cy.get('body').then($body => {
if ($body.find(byTestId('ai-chat-container')).length > 0) {
ChatSelectors.aiChatContainer().then($container => {
if ($container.length > 0) {
testLog.info( '✓ AI Chat container exists');
} else {
testLog.info( 'AI Chat container not immediately visible, checking for navigation success...');
@@ -139,15 +139,14 @@ describe('AI Chat Creation and Navigation Tests', () => {
// Check for AI Chat specific elements (the chat interface)
// The AI chat library loads its own components
cy.get('body').then($body => {
// Check if chat interface elements exist
const hasChatElements = $body.find('.ai-chat').length > 0 ||
$body.find(byTestId('ai-chat-container')).length > 0;
if (hasChatElements) {
testLog.info( ' AI Chat interface loaded');
} else {
testLog.info( 'Warning: AI Chat elements not immediately visible, but container exists');
}
ChatSelectors.aiChatContainer().then($container => {
const hasChatElements = $body.find('.ai-chat').length > 0 || $container.length > 0;
if (hasChatElements) {
testLog.info( '✓ AI Chat interface loaded');
} else {
testLog.info( 'Warning: AI Chat elements not immediately visible, but container exists');
}
});
});
// Verify no error messages are displayed

View File

@@ -2,8 +2,6 @@ import {
AddPageSelectors,
DatabaseGridSelectors,
CheckboxSelectors,
byTestId,
byTestIdPrefix,
waitForReactUpdate
} from '../../support/selectors';
import { AuthTestUtils } from '../../support/auth-utils';
@@ -59,18 +57,18 @@ describe('Checkbox Column Type', () => {
cy.log('[STEP 9] Looking for checkbox elements');
cy.get('body').then($body => {
// Check for checkbox cells with our data-testid
const checkboxCells = $body.find(byTestIdPrefix('checkbox-cell-'));
if (checkboxCells.length > 0) {
cy.log(`[STEP 10] Found ${checkboxCells.length} checkbox cells`);
CheckboxSelectors.allCheckboxCells().then($checkboxCells => {
if ($checkboxCells.length > 0) {
cy.log(`[STEP 10] Found ${$checkboxCells.length} checkbox cells`);
// Click first checkbox cell
CheckboxSelectors.allCheckboxCells().first().click();
waitForReactUpdate(500);
cy.log('[STEP 11] Clicked checkbox cell');
} else {
cy.log('[STEP 10] No checkbox cells found, cell interaction test completed');
}
});
// Click first checkbox cell
CheckboxSelectors.allCheckboxCells().first().click();
waitForReactUpdate(500);
cy.log('[STEP 11] Clicked checkbox cell');
} else {
cy.log('[STEP 10] No checkbox cells found, cell interaction test completed');
}
});
cy.log('[STEP 12] Test completed successfully');
});

View File

@@ -5,8 +5,6 @@ import {
PropertyMenuSelectors,
GridFieldSelectors,
FieldType,
byTestId,
byTestIdPrefix,
waitForReactUpdate
} from '../../support/selectors';
import { AuthTestUtils } from '../../support/auth-utils';
@@ -66,28 +64,23 @@ describe('DateTime Column Type', () => {
// The new column is created and the property menu should be open automatically
// Let's wait for property trigger to be available
cy.log('[STEP 8] Waiting for property menu to open');
cy.get('body').then($body => {
// Check if property type trigger exists
if ($body.find(byTestId('property-type-trigger')).length > 0) {
PropertyMenuSelectors.propertyTypeTrigger().then($trigger => {
if ($trigger.length > 0) {
cy.log('[STEP 9] Property type trigger found, changing to DateTime');
PropertyMenuSelectors.propertyTypeTrigger().first().click({ force: true });
cy.wrap($trigger.first()).click({ force: true });
waitForReactUpdate(1000);
// Select DateTime option
cy.log('[STEP 10] Selecting DateTime option');
PropertyMenuSelectors.propertyTypeOption(FieldType.DateTime).click({ force: true });
waitForReactUpdate(2000);
} else {
cy.log('[STEP 9] Property type trigger not found, looking for field header');
// Try clicking on the new field header first
GridFieldSelectors.allFieldHeaders().last().scrollIntoView().click({ force: true });
waitForReactUpdate(1000);
// Now try to find the property type trigger
PropertyMenuSelectors.propertyTypeTrigger().first().click({ force: true });
waitForReactUpdate(1000);
// Select DateTime option
cy.log('[STEP 10] Selecting DateTime option');
PropertyMenuSelectors.propertyTypeOption(FieldType.DateTime).click({ force: true });
waitForReactUpdate(2000);
@@ -101,21 +94,17 @@ describe('DateTime Column Type', () => {
// Verify datetime cells exist
cy.log('[STEP 12] Checking for datetime cells');
cy.get('body').then($body => {
const datetimeCells = $body.find(byTestIdPrefix('datetime-cell-'));
if (datetimeCells.length > 0) {
cy.log(`[STEP 13] Found ${datetimeCells.length} datetime cells`);
DateTimeSelectors.allDateTimeCells().then($cells => {
if ($cells.length > 0) {
cy.log(`[STEP 13] Found ${$cells.length} datetime cells`);
// Try to interact with the first datetime cell
DateTimeSelectors.allDateTimeCells().first().scrollIntoView().click({ force: true });
waitForReactUpdate(1000);
// Check if picker opens
cy.get('body').then($body => {
if ($body.find(byTestId('datetime-picker-popover')).length > 0) {
DateTimeSelectors.dateTimePickerPopover().then($popover => {
if ($popover.length > 0) {
cy.log('[STEP 14] DateTime picker opened successfully');
// Enter a date
const today = new Date();
const dateStr = `${(today.getMonth() + 1).toString().padStart(2, '0')}/${today.getDate().toString().padStart(2, '0')}/${today.getFullYear()}`;

View File

@@ -6,8 +6,6 @@ import {
SingleSelectSelectors,
PageSelectors,
FieldType,
byTestId,
byTestIdPrefix,
waitForReactUpdate
} from '../../support/selectors';
import { AuthTestUtils } from '../../support/auth-utils';
@@ -54,29 +52,24 @@ describe('Single Select Column Type', () => {
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(byTestId('inline-add-page')).length > 0;
const newPageExists = $body.find(byTestId('new-page-button')).length > 0;
if (inlineAddExists) {
cy.log('[STEP 4.2] Using inline add button');
return cy.wrap(null).then(() => {
AddPageSelectors.inlineAddButton().then($inlineAdd => {
const inlineAddExists = $inlineAdd.length > 0;
PageSelectors.newPageButton().then($newPage => {
const newPageExists = $newPage.length > 0;
if (inlineAddExists) {
cy.log('[STEP 4.2] Using inline add button');
AddPageSelectors.inlineAddButton().first().click({ force: true });
});
} else if (newPageExists) {
cy.log('[STEP 4.2] Using new page button instead');
return cy.wrap(null).then(() => {
} else if (newPageExists) {
cy.log('[STEP 4.2] Using new page button instead');
PageSelectors.newPageButton().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(() => {
} else {
cy.log('[STEP 4.2] Waiting for UI to stabilize');
cy.wait(3000);
AddPageSelectors.inlineAddButton().should('exist', { timeout: 15000 });
AddPageSelectors.inlineAddButton().first().click({ force: true });
});
}
}
});
});
waitForReactUpdate(1000);
@@ -166,14 +159,13 @@ describe('Single Select Column Type', () => {
// 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(byTestId('property-type-trigger')).length > 0) {
PropertyMenuSelectors.propertyTypeTrigger().first().click({ force: true });
PropertyMenuSelectors.propertyTypeTrigger().then($trigger => {
if ($trigger.length > 0) {
cy.wrap($trigger.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 });
@@ -191,20 +183,16 @@ describe('Single Select Column Type', () => {
cy.log('[STEP 8] Adding select options to cells');
// First try to find select cells
cy.get('body').then($body => {
const selectCells = $body.find(byTestIdPrefix('select-option-cell-'));
if (selectCells.length > 0) {
cy.log(`[STEP 9] Found ${selectCells.length} select cells`);
SingleSelectSelectors.allSelectOptionCells().then($cells => {
if ($cells.length > 0) {
cy.log(`[STEP 9] Found ${$cells.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) {
if ($cells.length > 1) {
SingleSelectSelectors.allSelectOptionCells().eq(1).click({ force: true });
waitForReactUpdate(500);
cy.focused().type('Option B{enter}');
@@ -213,18 +201,14 @@ describe('Single Select Column Type', () => {
} 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);
@@ -241,9 +225,9 @@ describe('Single Select Column Type', () => {
waitForReactUpdate(1000);
// Click edit property if available
cy.get('body').then($body => {
if ($body.find(byTestId('grid-field-edit-property')).length > 0) {
PropertyMenuSelectors.editPropertyMenuItem().click();
PropertyMenuSelectors.editPropertyMenuItem().then($edit => {
if ($edit.length > 0) {
cy.wrap($edit).click();
waitForReactUpdate(1000);
}
});
@@ -285,9 +269,9 @@ describe('Single Select Column Type', () => {
waitForReactUpdate(1000);
// Click edit property if available
cy.get('body').then($body => {
if ($body.find(byTestId('grid-field-edit-property')).length > 0) {
PropertyMenuSelectors.editPropertyMenuItem().click();
PropertyMenuSelectors.editPropertyMenuItem().then($edit => {
if ($edit.length > 0) {
cy.wrap($edit).click();
waitForReactUpdate(1000);
}
});
@@ -305,18 +289,15 @@ describe('Single Select Column Type', () => {
// 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(byTestIdPrefix('select-option-cell-'));
if (selectCells.length > 0) {
cy.log(`[STEP 17] Success! Found ${selectCells.length} select option cells after conversion`);
SingleSelectSelectors.allSelectOptionCells().then($cells => {
if ($cells.length > 0) {
cy.log(`[STEP 17] Success! Found ${$cells.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(byTestId('select-option-menu')).length > 0) {
SingleSelectSelectors.selectOptionMenu().then($menu => {
if ($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');

View File

@@ -1,12 +1,11 @@
import { AuthTestUtils } from '../../support/auth-utils';
import { TestTool } from '../../support/page-utils';
import {
import { testLog } from '../../support/test-helpers';
import {
PageSelectors,
SpaceSelectors,
SidebarSelectors,
byTestId,
byTestIdContains,
BreadcrumbSelectors,
waitForReactUpdate
} from '../../support/selectors';
import { generateRandomEmail, logAppFlowyEnvironment } from '../../support/test-config';
@@ -73,12 +72,10 @@ describe('Breadcrumb Navigation Complete Tests', () => {
// Step 4: Check for breadcrumb navigation
testLog.info( '=== Step 4: Checking for breadcrumb navigation ===');
cy.get('body').then($body => {
if ($body.find(byTestId('breadcrumb-navigation')).length > 0) {
BreadcrumbSelectors.navigation().then($nav => {
if ($nav.length > 0) {
testLog.info( '✓ Breadcrumb navigation found on this page');
// Count breadcrumb items
cy.get(byTestIdContains('breadcrumb-item-')).then($items => {
BreadcrumbSelectors.items().then($items => {
testLog.info( `✓ Found ${$items.length} breadcrumb items`);
});
} else {
@@ -135,19 +132,19 @@ describe('Breadcrumb Navigation Complete Tests', () => {
// Check for breadcrumb navigation
testLog.info( '=== Step 4: Testing breadcrumb navigation ===');
cy.get('body', { timeout: 5000 }).then($body => {
if ($body.find(byTestId('breadcrumb-navigation')).length > 0) {
BreadcrumbSelectors.navigation().then($nav => {
if ($nav.length > 0) {
testLog.info( '✓ Breadcrumb navigation is visible');
// Try to click breadcrumb to navigate back
if ($body.find(byTestIdContains('breadcrumb-item-')).length > 1) {
cy.get(byTestIdContains('breadcrumb-item-')).first().click({ force: true });
testLog.info( '✓ Clicked breadcrumb item to navigate back');
cy.wait(2000);
testLog.info( '✓ Successfully used breadcrumb navigation');
} else {
testLog.info( 'Only one breadcrumb item found');
}
BreadcrumbSelectors.items().then($items => {
if ($items.length > 1) {
cy.wrap($items).first().click({ force: true });
testLog.info( '✓ Clicked breadcrumb item to navigate back');
cy.wait(2000);
testLog.info( '✓ Successfully used breadcrumb navigation');
} else {
testLog.info( 'Only one breadcrumb item found');
}
});
} else {
testLog.info( 'No breadcrumb navigation on nested page');
}
@@ -253,22 +250,16 @@ describe('Breadcrumb Navigation Complete Tests', () => {
// Step 4: Test breadcrumb navigation
testLog.info( '=== Step 4: Testing breadcrumb navigation ===');
cy.get('body').then($body => {
if ($body.find(byTestId('breadcrumb-navigation')).length > 0) {
BreadcrumbSelectors.navigation().then($nav => {
if ($nav.length > 0) {
testLog.info( '✓ Breadcrumb navigation is visible');
// Check breadcrumb items with timeout
cy.get(byTestIdContains('breadcrumb-item-'), { timeout: 10000 }).then($items => {
BreadcrumbSelectors.items().then($items => {
testLog.info( `Found ${$items.length} breadcrumb items`);
if ($items.length > 1) {
// Click second-to-last breadcrumb (parent page)
const targetIndex = Math.max(0, $items.length - 2);
cy.wrap($items[targetIndex]).click({ force: true });
testLog.info( `✓ Clicked breadcrumb at index ${targetIndex} to go back`);
cy.wait(2000);
// Verify navigation worked
testLog.info( '✓ Successfully navigated back using breadcrumb');
}
});

View File

@@ -1,6 +1,6 @@
import { AuthTestUtils } from '../../support/auth-utils';
import { TestTool } from '../../support/page-utils';
import { PageSelectors, ModalSelectors, SidebarSelectors, byTestId, waitForReactUpdate } from '../../support/selectors';
import { PageSelectors, ModalSelectors, SidebarSelectors, TrashSelectors, waitForReactUpdate } from '../../support/selectors';
import { generateRandomEmail, logAppFlowyEnvironment } from '../../support/test-config';
import { testLog } from '../../support/test-helpers';
@@ -164,7 +164,7 @@ describe('Delete Page, Verify in Trash, and Restore Tests', () => {
testLog.info( '=== Step 5: Navigating to trash page ===');
// Click on the trash button in the sidebar
cy.get(byTestId('sidebar-trash-button')).click();
TrashSelectors.sidebarTrashButton().click();
// Wait for navigation
cy.wait(2000);
@@ -177,10 +177,10 @@ describe('Delete Page, Verify in Trash, and Restore Tests', () => {
testLog.info( '=== Step 6: Verifying deleted page exists in trash ===');
// Wait for trash table to load
cy.get(byTestId('trash-table'), { timeout: 10000 }).should('be.visible');
TrashSelectors.table().should('be.visible');
// Look for our deleted page in the trash table
cy.get(byTestId('trash-table-row')).then($rows => {
TrashSelectors.rows().then($rows => {
let foundPage = false;
// Check each row for our page name
@@ -206,13 +206,13 @@ describe('Delete Page, Verify in Trash, and Restore Tests', () => {
// Step 7: Verify restore and permanent delete buttons are present
testLog.info( '=== Step 7: Verifying trash actions are available ===');
cy.get(byTestId('trash-table-row')).first().within(() => {
TrashSelectors.rows().first().within(() => {
// Check for restore button
cy.get(byTestId('trash-restore-button')).should('exist');
TrashSelectors.restoreButton().should('exist');
testLog.info( '✓ Restore button found');
// Check for permanent delete button
cy.get(byTestId('trash-delete-button')).should('exist');
TrashSelectors.deleteButton().should('exist');
testLog.info( '✓ Permanent delete button found');
});
@@ -223,7 +223,7 @@ describe('Delete Page, Verify in Trash, and Restore Tests', () => {
let restoredPageName = 'Untitled'; // Default to Untitled since that's what usually gets created
// Click the restore button on the first row (our deleted page)
cy.get(byTestId('trash-table-row')).first().within(() => {
TrashSelectors.rows().first().within(() => {
// Get the page name before restoring
cy.get('td').first().invoke('text').then((text) => {
restoredPageName = text.trim() || 'Untitled';
@@ -231,7 +231,7 @@ describe('Delete Page, Verify in Trash, and Restore Tests', () => {
});
// Click restore button
cy.get(byTestId('trash-restore-button')).click();
TrashSelectors.restoreButton().click();
});
// Wait for restore to complete
@@ -242,30 +242,26 @@ describe('Delete Page, Verify in Trash, and Restore Tests', () => {
testLog.info( '=== Step 9: Verifying page is removed from trash ===');
// Check if trash is now empty or doesn't contain our page
cy.get('body').then(($body) => {
// Check if there are any rows left in trash
const rowsExist = $body.find(byTestId('trash-table-row')).length > 0;
TrashSelectors.rows().then($rows => {
const rowsExist = $rows.length > 0;
if (!rowsExist) {
testLog.info( '✓ Trash is now empty - page successfully removed from trash');
} else {
// If there are still rows, verify our page is not among them
cy.get(byTestId('trash-table-row')).then($rows => {
let pageStillInTrash = false;
$rows.each((index, row) => {
const rowText = Cypress.$(row).text();
if (rowText.includes(restoredPageName)) {
pageStillInTrash = true;
}
});
if (pageStillInTrash) {
throw new Error(`Page "${restoredPageName}" is still in trash after restore`);
} else {
testLog.info( `✓ Page "${restoredPageName}" successfully removed from trash`);
let pageStillInTrash = false;
$rows.each((index, row) => {
const rowText = Cypress.$(row).text();
if (rowText.includes(restoredPageName)) {
pageStillInTrash = true;
}
});
if (pageStillInTrash) {
throw new Error(`Page "${restoredPageName}" is still in trash after restore`);
} else {
testLog.info( `✓ Page "${restoredPageName}" successfully removed from trash`);
}
}
});

View File

@@ -1,6 +1,6 @@
import { AuthTestUtils } from '../../support/auth-utils';
import { TestTool } from '../../support/page-utils';
import { PageSelectors, byTestId, waitForReactUpdate } from '../../support/selectors';
import { PageSelectors, ModalSelectors, waitForReactUpdate } from '../../support/selectors';
import { generateRandomEmail } from '../../support/test-config';
import { testLog } from '../../support/test-helpers';
@@ -189,15 +189,15 @@ describe('More Page Actions', () => {
testLog.info( 'Clicked Rename option');
// Wait for the rename modal to appear
cy.get(byTestId('rename-modal-input'), { timeout: 5000 })
.should('be.visible')
ModalSelectors.renameInput()
.should('be.visible', { timeout: 5000 })
.clear()
.type(renamedPageName);
testLog.info( `Entered new page name: ${renamedPageName}`);
// Click the save button
cy.get(byTestId('rename-modal-save')).click();
ModalSelectors.renameSaveButton().click();
testLog.info( 'Clicked save button');

View File

@@ -1,6 +1,6 @@
import { AuthTestUtils } from '../../support/auth-utils';
import { TestTool } from '../../support/page-utils';
import { PageSelectors, ShareSelectors, SidebarSelectors, byTestId } from '../../support/selectors';
import { PageSelectors, ShareSelectors, SidebarSelectors } from '../../support/selectors';
import { generateRandomEmail, logAppFlowyEnvironment } from '../../support/test-config';
import { testLog } from '../../support/test-helpers';
@@ -71,7 +71,7 @@ describe('Publish Page Test', () => {
cy.wait(5000);
// Verify that the page is now published by checking for published UI elements
cy.get(byTestId('publish-namespace')).should('be.visible', { timeout: 10000 });
cy.get(ShareSelectors.publishNamespace()).should('be.visible', { timeout: 10000 });
testLog.info( 'Page published successfully, URL elements visible');
// 6. Get the published URL by constructing it from UI elements
@@ -79,8 +79,8 @@ describe('Publish Page Test', () => {
const origin = win.location.origin;
// Get namespace and publish name from the UI
cy.get(byTestId('publish-namespace')).should('be.visible').invoke('text').then((namespace) => {
cy.get(byTestId('publish-name-input')).should('be.visible').invoke('val').then((publishName) => {
cy.get(ShareSelectors.publishNamespace()).should('be.visible').invoke('text').then((namespace) => {
cy.get(ShareSelectors.publishNameInput()).should('be.visible').invoke('val').then((publishName) => {
const namespaceText = namespace.trim();
const publishNameText = String(publishName).trim();
const publishedUrl = `${origin}/${namespaceText}/${publishNameText}`;
@@ -91,7 +91,7 @@ describe('Publish Page Test', () => {
// Located in a div with class "p-1 text-text-primary" next to the URL container
ShareSelectors.sharePopover().within(() => {
// Find the parent container that holds both URL inputs and copy button
cy.get(byTestId('publish-name-input'))
cy.get(ShareSelectors.publishNameInput())
.closest('div.flex.w-full.items-center.overflow-hidden')
.find('div.p-1.text-text-primary')
.should('be.visible')
@@ -263,13 +263,13 @@ describe('Publish Page Test', () => {
cy.wait(5000);
// Verify published
cy.get(byTestId('publish-namespace')).should('be.visible', { timeout: 10000 });
cy.get(ShareSelectors.publishNamespace()).should('be.visible', { timeout: 10000 });
// Get the published URL
cy.window().then((win) => {
const origin = win.location.origin;
cy.get(byTestId('publish-namespace')).should('be.visible').invoke('text').then((namespace) => {
cy.get(byTestId('publish-name-input')).should('be.visible').invoke('val').then((publishName) => {
cy.get(ShareSelectors.publishNamespace()).should('be.visible').invoke('text').then((namespace) => {
cy.get(ShareSelectors.publishNameInput()).should('be.visible').invoke('val').then((publishName) => {
const publishedUrl = `${origin}/${namespace.trim()}/${String(publishName).trim()}`;
testLog.info( `Published URL: ${publishedUrl}`);
@@ -315,20 +315,20 @@ describe('Publish Page Test', () => {
ShareSelectors.publishConfirmButton().should('be.visible').click({ force: true });
cy.wait(5000);
cy.get(byTestId('publish-namespace')).should('be.visible', { timeout: 10000 });
cy.get(ShareSelectors.publishNamespace()).should('be.visible', { timeout: 10000 });
// Get original URL
cy.window().then((win) => {
const origin = win.location.origin;
cy.get(byTestId('publish-namespace')).invoke('text').then((namespace) => {
cy.get(byTestId('publish-name-input')).invoke('val').then((originalName) => {
cy.get(ShareSelectors.publishNamespace()).invoke('text').then((namespace) => {
cy.get(ShareSelectors.publishNameInput()).invoke('val').then((originalName) => {
const namespaceText = namespace.trim();
const originalNameText = String(originalName).trim();
testLog.info( `Original publish name: ${originalNameText}`);
// Edit the publish name directly in the input
const newPublishName = `custom-name-${Date.now()}`;
cy.get(byTestId('publish-name-input'))
cy.get(ShareSelectors.publishNameInput())
.clear()
.type(newPublishName)
.blur();
@@ -397,14 +397,14 @@ describe('Publish Page Test', () => {
ShareSelectors.publishConfirmButton().should('be.visible').click({ force: true });
cy.wait(5000);
cy.get(byTestId('publish-namespace')).should('be.visible', { timeout: 10000 });
cy.get(ShareSelectors.publishNamespace()).should('be.visible', { timeout: 10000 });
testLog.info( '✓ First publish successful');
// Get published URL
cy.window().then((win) => {
const origin = win.location.origin;
cy.get(byTestId('publish-namespace')).invoke('text').then((namespace) => {
cy.get(byTestId('publish-name-input')).invoke('val').then((publishName) => {
cy.get(ShareSelectors.publishNamespace()).invoke('text').then((namespace) => {
cy.get(ShareSelectors.publishNameInput()).invoke('val').then((publishName) => {
const publishedUrl = `${origin}/${namespace.trim()}/${String(publishName).trim()}`;
testLog.info( `Published URL: ${publishedUrl}`);
@@ -458,7 +458,7 @@ describe('Publish Page Test', () => {
// Republish with updated content
ShareSelectors.publishConfirmButton().should('be.visible').click({ force: true });
cy.wait(5000);
cy.get(byTestId('publish-namespace')).should('be.visible', { timeout: 10000 });
cy.get(ShareSelectors.publishNamespace()).should('be.visible', { timeout: 10000 });
testLog.info( '✓ Republished successfully');
// Verify updated content is published
@@ -501,14 +501,14 @@ describe('Publish Page Test', () => {
ShareSelectors.publishConfirmButton().should('be.visible').click({ force: true });
cy.wait(5000);
cy.get(byTestId('publish-namespace')).should('be.visible', { timeout: 10000 });
cy.get(ShareSelectors.publishNamespace()).should('be.visible', { timeout: 10000 });
// Try to set invalid publish name with spaces
cy.get(byTestId('publish-name-input')).invoke('val').then((originalName) => {
cy.get(ShareSelectors.publishNameInput()).invoke('val').then((originalName) => {
testLog.info( `Original name: ${originalName}`);
// Try to set name with space (should be rejected)
cy.get(byTestId('publish-name-input'))
cy.get(ShareSelectors.publishNameInput())
.clear()
.type('invalid name with spaces')
.blur();
@@ -519,7 +519,7 @@ describe('Publish Page Test', () => {
cy.get('body').then(($body) => {
const bodyText = $body.text();
// The name should either revert or show an error
cy.get(byTestId('publish-name-input')).invoke('val').then((currentName) => {
cy.get(ShareSelectors.publishNameInput()).invoke('val').then((currentName) => {
// Name should not contain spaces (validation should prevent it)
if (String(currentName).includes(' ')) {
testLog.info( '⚠ Warning: Invalid characters were not rejected');
@@ -558,7 +558,7 @@ describe('Publish Page Test', () => {
ShareSelectors.publishConfirmButton().should('be.visible').click({ force: true });
cy.wait(5000);
cy.get(byTestId('publish-namespace')).should('be.visible', { timeout: 10000 });
cy.get(ShareSelectors.publishNamespace()).should('be.visible', { timeout: 10000 });
// Test comments switch - find by looking for Switch components in the published panel
ShareSelectors.sharePopover().within(() => {
@@ -632,13 +632,13 @@ describe('Publish Page Test', () => {
ShareSelectors.publishConfirmButton().should('be.visible').click({ force: true });
cy.wait(5000);
cy.get(byTestId('publish-namespace')).should('be.visible', { timeout: 10000 });
cy.get(ShareSelectors.publishNamespace()).should('be.visible', { timeout: 10000 });
// Get first URL
cy.window().then((win) => {
const origin = win.location.origin;
cy.get(byTestId('publish-namespace')).invoke('text').then((namespace) => {
cy.get(byTestId('publish-name-input')).invoke('val').then((publishName) => {
cy.get(ShareSelectors.publishNamespace()).invoke('text').then((namespace) => {
cy.get(ShareSelectors.publishNameInput()).invoke('val').then((publishName) => {
firstPublishedUrl = `${origin}/${namespace.trim()}/${String(publishName).trim()}`;
testLog.info( `First published URL: ${firstPublishedUrl}`);
@@ -651,9 +651,9 @@ describe('Publish Page Test', () => {
cy.contains('Publish').should('exist').click({ force: true });
cy.wait(1000);
cy.get(byTestId('publish-namespace')).should('be.visible', { timeout: 10000 });
cy.get(byTestId('publish-namespace')).invoke('text').then((namespace2) => {
cy.get(byTestId('publish-name-input')).invoke('val').then((publishName2) => {
cy.get(ShareSelectors.publishNamespace()).should('be.visible', { timeout: 10000 });
cy.get(ShareSelectors.publishNamespace()).invoke('text').then((namespace2) => {
cy.get(ShareSelectors.publishNameInput()).invoke('val').then((publishName2) => {
const secondPublishedUrl = `${origin}/${namespace2.trim()}/${String(publishName2).trim()}`;
testLog.info( `Second check URL: ${secondPublishedUrl}`);
@@ -750,7 +750,7 @@ describe('Publish Page Test', () => {
cy.wait(5000);
// Verify that the database is now published by checking for published UI elements
cy.get(byTestId('publish-namespace')).should('be.visible', { timeout: 10000 });
cy.get(ShareSelectors.publishNamespace()).should('be.visible', { timeout: 10000 });
testLog.info( 'Database published successfully, URL elements visible');
// Get the published URL
@@ -758,8 +758,8 @@ describe('Publish Page Test', () => {
const origin = win.location.origin;
// Get namespace and publish name from the UI
cy.get(byTestId('publish-namespace')).should('be.visible').invoke('text').then((namespace) => {
cy.get(byTestId('publish-name-input')).should('be.visible').invoke('val').then((publishName) => {
cy.get(ShareSelectors.publishNamespace()).should('be.visible').invoke('text').then((namespace) => {
cy.get(ShareSelectors.publishNameInput()).should('be.visible').invoke('val').then((publishName) => {
const namespaceText = namespace.trim();
const publishNameText = String(publishName).trim();
const publishedUrl = `${origin}/${namespaceText}/${publishNameText}`;

View File

@@ -1,6 +1,6 @@
import { AuthTestUtils } from '../../support/auth-utils';
import { TestTool } from '../../support/page-utils';
import { PageSelectors, SpaceSelectors, SidebarSelectors, byTestId, waitForReactUpdate } from '../../support/selectors';
import { PageSelectors, SpaceSelectors, SidebarSelectors, ModalSelectors, waitForReactUpdate } from '../../support/selectors';
import { generateRandomEmail, logAppFlowyEnvironment } from '../../support/test-config';
import { testLog } from '../../support/test-helpers';
@@ -83,7 +83,7 @@ describe('Space Creation Tests', () => {
// Step 3: Click on "Create New Space" option
testLog.info( '=== Step 3: Clicking Create New Space option ===');
cy.get(byTestId('create-new-space-button'))
SpaceSelectors.createNewSpaceButton()
.should('be.visible')
.click();
@@ -96,13 +96,13 @@ describe('Space Creation Tests', () => {
testLog.info( '=== Step 4: Filling space creation form ===');
// Verify the modal is visible
cy.get(byTestId('create-space-modal'))
SpaceSelectors.createSpaceModal()
.should('be.visible');
testLog.info( 'Create Space modal is visible');
// Enter space name
cy.get(byTestId('space-name-input'))
SpaceSelectors.spaceNameInput()
.should('be.visible')
.clear()
.type(spaceName);
@@ -116,7 +116,7 @@ describe('Space Creation Tests', () => {
testLog.info( '=== Step 5: Saving new space ===');
// Click the Save button
cy.get(byTestId('modal-ok-button'))
ModalSelectors.okButton()
.should('be.visible')
.click();

View File

@@ -81,6 +81,19 @@ export const SpaceSelectors = {
// Get more actions button for spaces
moreActionsButton: () => cy.get(byTestId('inline-more-actions')),
// New space creation controls
createNewSpaceButton: () => cy.get(byTestId('create-new-space-button')),
createSpaceModal: () => cy.get(byTestId('create-space-modal')),
spaceNameInput: () => cy.get(byTestId('space-name-input')),
};
/**
* Breadcrumb selectors
*/
export const BreadcrumbSelectors = {
navigation: () => cy.get(byTestId('breadcrumb-navigation')),
items: () => cy.get(byTestIdContains('breadcrumb-item-')),
};
/**
@@ -124,6 +137,13 @@ export const ModalSelectors = {
// Get space item in modal
spaceItemInModal: () => cy.get(byTestId('space-item')),
// Generic modal accept/ok button
okButton: () => cy.get(byTestId('modal-ok-button')),
// Rename modal inputs
renameInput: () => cy.get(byTestId('rename-modal-input')),
renameSaveButton: () => cy.get(byTestId('rename-modal-save')),
};
/**
@@ -154,6 +174,10 @@ export const ShareSelectors = {
// Publish URL input
publishUrlInput: () => cy.get(byTestId('publish-url-input')),
// Publish namespace and name inputs
publishNamespace: () => cy.get(byTestId('publish-namespace')),
publishNameInput: () => cy.get(byTestId('publish-name-input')),
// Page settings button
pageSettingsButton: () => cy.get(byTestId('page-settings-button')),
@@ -201,6 +225,17 @@ export const SidebarSelectors = {
pageHeader: () => cy.get(byTestId('sidebar-page-header')),
};
/**
* Trash view selectors
*/
export const TrashSelectors = {
sidebarTrashButton: () => cy.get(byTestId('sidebar-trash-button')),
table: () => cy.get(byTestId('trash-table')),
rows: () => cy.get(byTestId('trash-table-row')),
restoreButton: () => cy.get(byTestId('trash-restore-button')),
deleteButton: () => cy.get(byTestId('trash-delete-button')),
};
/**
* Chat Model Selector-related selectors
* Used for testing AI model selection in chat interface
@@ -222,6 +257,19 @@ export const ModelSelectorSelectors = {
selectedOption: () => cy.get('[data-testid^="model-option-"]').filter('.bg-fill-content-select'),
};
/**
* Chat UI selectors
*/
export const ChatSelectors = {
aiChatContainer: () => cy.get(byTestId('ai-chat-container')),
formatToggle: () => cy.get(byTestId('chat-input-format-toggle')),
formatGroup: () => cy.get(byTestId('chat-format-group')),
browsePromptsButton: () => cy.get(byTestId('chat-input-browse-prompts')),
relatedViewsButton: () => cy.get(byTestId('chat-input-related-views')),
relatedViewsPopover: () => cy.get(byTestId('chat-related-views-popover')),
sendButton: () => cy.get(byTestId('chat-input-send')),
};
/**
* Database Grid-related selectors
*/
@@ -445,6 +493,27 @@ export const AuthSelectors = {
logoutConfirmButton: () => cy.get(byTestId('logout-confirm-button')),
};
/**
* Account settings selectors
*/
export const AccountSelectors = {
settingsButton: () => cy.get(byTestId('account-settings-button')),
settingsDialog: () => cy.get(byTestId('account-settings-dialog')),
dateFormatDropdown: () => cy.get(byTestId('date-format-dropdown')),
dateFormatOptionYearMonthDay: () => cy.get(byTestId('date-format-1')),
timeFormatDropdown: () => cy.get(byTestId('time-format-dropdown')),
timeFormatOption24: () => cy.get(byTestId('time-format-1')),
startWeekDropdown: () => cy.get(byTestId('start-week-on-dropdown')),
startWeekMonday: () => cy.get(byTestId('start-week-1')),
};
/**
* Avatar display selectors
*/
export const AvatarUiSelectors = {
image: () => cy.get(byTestId('avatar-image')),
};
export function waitForReactUpdate(ms: number = 500) {
return cy.wait(ms);
}