mirror of
https://github.com/AppFlowy-IO/AppFlowy-Web.git
synced 2026-03-13 10:00:26 +08:00
Merge pull request #81 from AppFlowy-IO/databaes_row_test
Databaes row test
This commit is contained in:
171
cypress/e2e/database/row-deletion.cy.ts
Normal file
171
cypress/e2e/database/row-deletion.cy.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { AuthTestUtils } from '../../support/auth-utils';
|
||||
import {
|
||||
AddPageSelectors,
|
||||
DatabaseGridSelectors,
|
||||
RowControlsSelectors,
|
||||
waitForReactUpdate
|
||||
} from '../../support/selectors';
|
||||
|
||||
describe('Database Row Deletion', () => {
|
||||
const generateRandomEmail = () => `${uuidv4()}@appflowy.io`;
|
||||
|
||||
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 delete a row from the grid', () => {
|
||||
const testEmail = generateRandomEmail();
|
||||
const testContent = `Test Row ${Date.now()}`;
|
||||
|
||||
cy.log(`[TEST START] Testing row deletion - Test email: ${testEmail}`);
|
||||
|
||||
// Login
|
||||
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(3000);
|
||||
|
||||
// Create a new grid
|
||||
cy.log('[STEP 4] Creating new grid');
|
||||
AddPageSelectors.inlineAddButton().first().should('be.visible').click();
|
||||
waitForReactUpdate(1000);
|
||||
AddPageSelectors.addGridButton().should('be.visible').click();
|
||||
cy.wait(8000);
|
||||
|
||||
// Verify grid exists
|
||||
cy.log('[STEP 5] Verifying grid exists');
|
||||
DatabaseGridSelectors.grid().should('exist');
|
||||
|
||||
// Get cells and edit the first one
|
||||
cy.log('[STEP 6] Getting cells and editing first cell');
|
||||
DatabaseGridSelectors.cells().should('exist');
|
||||
|
||||
DatabaseGridSelectors.cells().then($cells => {
|
||||
cy.log(`[STEP 7] Found ${$cells.length} cells`);
|
||||
|
||||
// Click first cell and type content
|
||||
cy.wrap($cells.first()).click();
|
||||
waitForReactUpdate(500);
|
||||
cy.focused().type(testContent);
|
||||
cy.focused().type('{enter}');
|
||||
waitForReactUpdate(1000);
|
||||
|
||||
// Verify data was entered
|
||||
cy.log('[STEP 8] Verifying content was added');
|
||||
cy.wrap($cells.first()).should('contain.text', testContent);
|
||||
});
|
||||
|
||||
// Get initial row count
|
||||
cy.log('[STEP 9] Getting initial row count');
|
||||
DatabaseGridSelectors.rows().then($rows => {
|
||||
const initialRowCount = $rows.length;
|
||||
cy.log(`[STEP 9.1] Initial row count: ${initialRowCount}`);
|
||||
|
||||
// Now hover over the first row to show controls
|
||||
cy.log('[STEP 10] Hovering over first row to show controls');
|
||||
|
||||
// Get the first row and hover over it
|
||||
DatabaseGridSelectors.firstRow()
|
||||
.parent()
|
||||
.parent()
|
||||
.trigger('mouseenter', { force: true })
|
||||
.trigger('mouseover', { force: true });
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
// Click on the drag icon/row accessory button
|
||||
cy.log('[STEP 11] Looking for and clicking row accessory button');
|
||||
|
||||
RowControlsSelectors.rowAccessoryButton().then($button => {
|
||||
if ($button.length > 0) {
|
||||
cy.log('[STEP 11.1] Found row accessory button with data-testid');
|
||||
cy.wrap($button.first()).click({ force: true });
|
||||
} else {
|
||||
cy.log('[STEP 11.1] Looking for drag icon by class');
|
||||
cy.get('div[class*="cursor-pointer"]').first().click({ force: true });
|
||||
}
|
||||
});
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
// Now the dropdown menu should be open
|
||||
cy.log('[STEP 12] Looking for delete option in dropdown menu');
|
||||
|
||||
// Wait for the dropdown menu to be visible
|
||||
cy.get('[role="menu"], [data-slot="dropdown-menu-content"]').should('be.visible');
|
||||
|
||||
// Click on the delete option
|
||||
RowControlsSelectors.rowMenuDelete().then($delete => {
|
||||
if ($delete.length > 0) {
|
||||
cy.log('[STEP 12.1] Found delete menu item by data-testid');
|
||||
cy.wrap($delete).click();
|
||||
} else {
|
||||
cy.log('[STEP 12.1] Looking for delete by text');
|
||||
// Look for delete option by text
|
||||
cy.get('[role="menuitem"]').contains(/delete/i).click();
|
||||
}
|
||||
});
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
// Handle the confirmation dialog
|
||||
cy.log('[STEP 13] Handling deletion confirmation dialog');
|
||||
|
||||
// Click the confirm button
|
||||
RowControlsSelectors.deleteRowConfirmButton().then($confirm => {
|
||||
if ($confirm.length > 0) {
|
||||
cy.log('[STEP 13.1] Found delete confirmation button by data-testid');
|
||||
cy.wrap($confirm).click();
|
||||
} else {
|
||||
cy.log('[STEP 13.1] Looking for delete confirmation by button text');
|
||||
// Look for a button with text "Delete" or similar
|
||||
cy.get('button').contains(/delete/i).click();
|
||||
}
|
||||
});
|
||||
|
||||
cy.wait(2000);
|
||||
|
||||
// Verify the row was deleted
|
||||
cy.log('[STEP 14] Verifying row was deleted');
|
||||
|
||||
// Check that we now have fewer rows
|
||||
DatabaseGridSelectors.rows().should('have.length', initialRowCount - 1);
|
||||
|
||||
// Verify the content is gone
|
||||
cy.log('[STEP 15] Verifying deleted content is gone');
|
||||
DatabaseGridSelectors.cells().then($allCells => {
|
||||
let foundContent = false;
|
||||
|
||||
$allCells.each((index, cell) => {
|
||||
const text = Cypress.$(cell).text();
|
||||
if (text.includes(testContent)) {
|
||||
foundContent = true;
|
||||
cy.log(`[STEP 15.1] ERROR: Found deleted content at index ${index}`);
|
||||
}
|
||||
});
|
||||
|
||||
// The content should be gone
|
||||
expect(foundContent).to.be.false;
|
||||
});
|
||||
|
||||
cy.log('[STEP 16] Row deletion test completed successfully');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
164
cypress/e2e/database/row-duplication.cy.ts
Normal file
164
cypress/e2e/database/row-duplication.cy.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { AuthTestUtils } from '../../support/auth-utils';
|
||||
import {
|
||||
AddPageSelectors,
|
||||
DatabaseGridSelectors,
|
||||
RowControlsSelectors,
|
||||
waitForReactUpdate
|
||||
} from '../../support/selectors';
|
||||
|
||||
describe('Database Row Duplication', () => {
|
||||
const generateRandomEmail = () => `${uuidv4()}@appflowy.io`;
|
||||
|
||||
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 a new grid, add content to first row, and duplicate it', () => {
|
||||
const testEmail = generateRandomEmail();
|
||||
const testContent = `Test Content ${Date.now()}`;
|
||||
|
||||
cy.log(`[TEST START] Testing row duplication - Test email: ${testEmail}`);
|
||||
|
||||
// Login
|
||||
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(3000);
|
||||
|
||||
// Create a new grid
|
||||
cy.log('[STEP 4] Creating new grid');
|
||||
AddPageSelectors.inlineAddButton().first().should('be.visible').click();
|
||||
waitForReactUpdate(1000);
|
||||
AddPageSelectors.addGridButton().should('be.visible').click();
|
||||
cy.wait(8000);
|
||||
|
||||
// Verify grid exists
|
||||
cy.log('[STEP 5] Verifying grid exists');
|
||||
DatabaseGridSelectors.grid().should('exist');
|
||||
|
||||
// Get cells and edit the first one
|
||||
cy.log('[STEP 6] Getting cells and editing first cell');
|
||||
DatabaseGridSelectors.cells().should('exist');
|
||||
|
||||
DatabaseGridSelectors.cells().then($cells => {
|
||||
cy.log(`[STEP 7] Found ${$cells.length} cells`);
|
||||
|
||||
// Click first cell and type content
|
||||
cy.wrap($cells.first()).click();
|
||||
waitForReactUpdate(500);
|
||||
cy.focused().type(testContent);
|
||||
cy.focused().type('{enter}');
|
||||
waitForReactUpdate(1000);
|
||||
|
||||
// Verify data was entered
|
||||
cy.log('[STEP 8] Verifying content was added');
|
||||
cy.wrap($cells.first()).should('contain.text', testContent);
|
||||
});
|
||||
|
||||
// Now hover over the first row to show controls
|
||||
cy.log('[STEP 9] Hovering over first row to show controls');
|
||||
|
||||
// Get the first row and hover over it
|
||||
DatabaseGridSelectors.firstRow()
|
||||
.parent()
|
||||
.parent()
|
||||
.trigger('mouseenter', { force: true })
|
||||
.trigger('mouseover', { force: true });
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
// Click on the drag icon/row accessory button
|
||||
cy.log('[STEP 10] Looking for and clicking row accessory button');
|
||||
|
||||
// The drag icon should be visible after hovering
|
||||
// Try to find it by the data-testid we added or by its class
|
||||
RowControlsSelectors.rowAccessoryButton().then($button => {
|
||||
if ($button.length > 0) {
|
||||
cy.log('[STEP 10.1] Found row accessory button with data-testid');
|
||||
cy.wrap($button.first()).click({ force: true });
|
||||
} else {
|
||||
cy.log('[STEP 10.1] Looking for drag icon by class');
|
||||
// Try to find the drag icon button
|
||||
cy.get('div[class*="cursor-pointer"]').first().click({ force: true });
|
||||
}
|
||||
});
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
// Now the dropdown menu should be open
|
||||
cy.log('[STEP 11] Looking for duplicate option in dropdown menu');
|
||||
|
||||
// Wait for the dropdown menu to be visible
|
||||
cy.get('[role="menu"], [data-slot="dropdown-menu-content"]').should('be.visible');
|
||||
|
||||
// Click on the duplicate option
|
||||
cy.get('[role="menuitem"]').then($items => {
|
||||
let found = false;
|
||||
$items.each((index, item) => {
|
||||
const text = Cypress.$(item).text();
|
||||
if (text.includes('Duplicate') || text.includes('duplicate')) {
|
||||
cy.log('[STEP 11.1] Found duplicate menu item by text');
|
||||
cy.wrap(item).click();
|
||||
found = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!found) {
|
||||
// Try clicking by the data-testid we added
|
||||
RowControlsSelectors.rowMenuDuplicate().then($duplicate => {
|
||||
if ($duplicate.length > 0) {
|
||||
cy.log('[STEP 11.2] Found duplicate menu item by data-testid');
|
||||
cy.wrap($duplicate).click();
|
||||
} else {
|
||||
// Fallback: click the third menu item (typically duplicate is after insert above/below)
|
||||
cy.log('[STEP 11.3] Clicking third menu item as fallback');
|
||||
cy.get('[role="menuitem"]').eq(2).click();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
cy.wait(2000);
|
||||
|
||||
// Verify the row was duplicated
|
||||
cy.log('[STEP 12] Verifying row was duplicated');
|
||||
DatabaseGridSelectors.rows().should('have.length.at.least', 2);
|
||||
|
||||
// Get all cells again and verify the duplicated content
|
||||
cy.log('[STEP 13] Verifying duplicated content');
|
||||
DatabaseGridSelectors.cells().then($allCells => {
|
||||
// The duplicated row should have the same content
|
||||
// Find cells that contain our test content
|
||||
let contentCount = 0;
|
||||
$allCells.each((index, cell) => {
|
||||
if (Cypress.$(cell).text().includes(testContent)) {
|
||||
contentCount++;
|
||||
}
|
||||
});
|
||||
|
||||
cy.log(`[STEP 14] Found ${contentCount} cells with test content`);
|
||||
// We should have at least 2 cells with the same content (original and duplicate)
|
||||
expect(contentCount).to.be.at.least(2);
|
||||
});
|
||||
|
||||
cy.log('[STEP 15] Row duplication test completed successfully');
|
||||
});
|
||||
});
|
||||
});
|
||||
238
cypress/e2e/database/row-insertion.cy.ts
Normal file
238
cypress/e2e/database/row-insertion.cy.ts
Normal file
@@ -0,0 +1,238 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { AuthTestUtils } from '../../support/auth-utils';
|
||||
import {
|
||||
AddPageSelectors,
|
||||
DatabaseGridSelectors,
|
||||
RowControlsSelectors,
|
||||
waitForReactUpdate
|
||||
} from '../../support/selectors';
|
||||
|
||||
describe('Database Row Insertion', () => {
|
||||
const generateRandomEmail = () => `${uuidv4()}@appflowy.io`;
|
||||
|
||||
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 insert rows above and below existing row', () => {
|
||||
const testEmail = generateRandomEmail();
|
||||
const originalContent = `Original Row ${Date.now()}`;
|
||||
const aboveContent = `Above Row ${Date.now()}`;
|
||||
const belowContent = `Below Row ${Date.now()}`;
|
||||
|
||||
cy.log(`[TEST START] Testing row insertion above and below - Test email: ${testEmail}`);
|
||||
|
||||
// Login
|
||||
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(3000);
|
||||
|
||||
// Create a new grid
|
||||
cy.log('[STEP 4] Creating new grid');
|
||||
AddPageSelectors.inlineAddButton().first().should('be.visible').click();
|
||||
waitForReactUpdate(1000);
|
||||
AddPageSelectors.addGridButton().should('be.visible').click();
|
||||
cy.wait(8000);
|
||||
|
||||
// Verify grid exists
|
||||
cy.log('[STEP 5] Verifying grid exists');
|
||||
DatabaseGridSelectors.grid().should('exist');
|
||||
|
||||
// Get cells and edit the first one
|
||||
cy.log('[STEP 6] Getting cells and editing first cell');
|
||||
DatabaseGridSelectors.cells().should('exist');
|
||||
|
||||
DatabaseGridSelectors.cells().then($cells => {
|
||||
cy.log(`[STEP 7] Found ${$cells.length} cells`);
|
||||
|
||||
// Click first cell and type content
|
||||
cy.wrap($cells.first()).click();
|
||||
waitForReactUpdate(500);
|
||||
cy.focused().type(originalContent);
|
||||
cy.focused().type('{enter}');
|
||||
waitForReactUpdate(1000);
|
||||
|
||||
// Verify data was entered
|
||||
cy.log('[STEP 8] Verifying content was added');
|
||||
cy.wrap($cells.first()).should('contain.text', originalContent);
|
||||
});
|
||||
|
||||
// Get initial row count
|
||||
cy.log('[STEP 9] Getting initial row count');
|
||||
DatabaseGridSelectors.rows().then($rows => {
|
||||
const initialRowCount = $rows.length;
|
||||
cy.log(`[STEP 9.1] Initial row count: ${initialRowCount}`);
|
||||
|
||||
// Insert a row above
|
||||
cy.log('[STEP 10] Inserting row above');
|
||||
|
||||
// Get the first row and hover over it
|
||||
DatabaseGridSelectors.firstRow()
|
||||
.parent()
|
||||
.parent()
|
||||
.trigger('mouseenter', { force: true })
|
||||
.trigger('mouseover', { force: true });
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
// Click on the drag icon/row accessory button
|
||||
cy.log('[STEP 11] Looking for and clicking row accessory button');
|
||||
|
||||
RowControlsSelectors.rowAccessoryButton().then($button => {
|
||||
if ($button.length > 0) {
|
||||
cy.log('[STEP 11.1] Found row accessory button with data-testid');
|
||||
cy.wrap($button.first()).click({ force: true });
|
||||
} else {
|
||||
cy.log('[STEP 11.1] Looking for drag icon by class');
|
||||
cy.get('div[class*="cursor-pointer"]').first().click({ force: true });
|
||||
}
|
||||
});
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
// Now the dropdown menu should be open
|
||||
cy.log('[STEP 12] Looking for insert above option in dropdown menu');
|
||||
|
||||
// Wait for the dropdown menu to be visible
|
||||
cy.get('[role="menu"], [data-slot="dropdown-menu-content"]').should('be.visible');
|
||||
|
||||
// Click on the insert above option - using data-testid first
|
||||
RowControlsSelectors.rowMenuInsertAbove().then($insertAbove => {
|
||||
if ($insertAbove.length > 0) {
|
||||
cy.log('[STEP 12.1] Found insert above menu item by data-testid');
|
||||
cy.wrap($insertAbove).click();
|
||||
} else {
|
||||
cy.log('[STEP 12.1] Looking for insert above by position');
|
||||
// First menu item is typically insert above
|
||||
cy.get('[role="menuitem"]').first().click();
|
||||
}
|
||||
});
|
||||
|
||||
cy.wait(2000);
|
||||
|
||||
// Verify a new row was added
|
||||
cy.log('[STEP 13] Verifying row was inserted above');
|
||||
DatabaseGridSelectors.rows().should('have.length', initialRowCount + 1);
|
||||
|
||||
// Add content to the newly inserted row (which should be the first row now)
|
||||
cy.log('[STEP 14] Adding content to newly inserted row above');
|
||||
DatabaseGridSelectors.cells().first().click();
|
||||
waitForReactUpdate(500);
|
||||
cy.focused().type(aboveContent);
|
||||
cy.focused().type('{enter}');
|
||||
waitForReactUpdate(1000);
|
||||
|
||||
// Now insert a row below the original row (which is now the second row)
|
||||
cy.log('[STEP 15] Inserting row below original row');
|
||||
|
||||
// Get the second row and hover over it
|
||||
DatabaseGridSelectors.rows().eq(1)
|
||||
.parent()
|
||||
.parent()
|
||||
.trigger('mouseenter', { force: true })
|
||||
.trigger('mouseover', { force: true });
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
// Click on the drag icon/row accessory button again
|
||||
cy.log('[STEP 16] Looking for and clicking row accessory button for second row');
|
||||
|
||||
// The row controls should appear for the second row after hovering
|
||||
RowControlsSelectors.rowAccessoryButton().then($buttons => {
|
||||
if ($buttons.length > 0) {
|
||||
cy.log('[STEP 16.1] Found row accessory button');
|
||||
// Click the last visible button (should be for the hovered row)
|
||||
cy.wrap($buttons.last()).click({ force: true });
|
||||
} else {
|
||||
cy.log('[STEP 16.1] Looking for drag icon by class');
|
||||
cy.get('div[class*="cursor-pointer"]').last().click({ force: true });
|
||||
}
|
||||
});
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
// Now the dropdown menu should be open
|
||||
cy.log('[STEP 17] Looking for insert below option in dropdown menu');
|
||||
|
||||
// Wait for the dropdown menu to be visible
|
||||
cy.get('[role="menu"], [data-slot="dropdown-menu-content"]').should('be.visible');
|
||||
|
||||
// Click on the insert below option - using data-testid first
|
||||
RowControlsSelectors.rowMenuInsertBelow().then($insertBelow => {
|
||||
if ($insertBelow.length > 0) {
|
||||
cy.log('[STEP 17.1] Found insert below menu item by data-testid');
|
||||
cy.wrap($insertBelow).click();
|
||||
} else {
|
||||
cy.log('[STEP 17.1] Looking for insert below by position');
|
||||
// Second menu item is typically insert below
|
||||
cy.get('[role="menuitem"]').eq(1).click();
|
||||
}
|
||||
});
|
||||
|
||||
cy.wait(2000);
|
||||
|
||||
// Verify another new row was added
|
||||
cy.log('[STEP 18] Verifying row was inserted below');
|
||||
DatabaseGridSelectors.rows().should('have.length', initialRowCount + 2);
|
||||
|
||||
// Add content to the newly inserted row below (should be the third row)
|
||||
cy.log('[STEP 19] Adding content to newly inserted row below');
|
||||
DatabaseGridSelectors.rows().eq(2).within(() => {
|
||||
DatabaseGridSelectors.cells().first().click();
|
||||
});
|
||||
waitForReactUpdate(500);
|
||||
cy.focused().type(belowContent);
|
||||
cy.focused().type('{enter}');
|
||||
waitForReactUpdate(1000);
|
||||
|
||||
// Final verification - check all cells have the correct content
|
||||
cy.log('[STEP 20] Final verification of content');
|
||||
DatabaseGridSelectors.cells().then($allCells => {
|
||||
// Find cells that contain our test content
|
||||
let foundAbove = false;
|
||||
let foundOriginal = false;
|
||||
let foundBelow = false;
|
||||
|
||||
$allCells.each((index, cell) => {
|
||||
const text = Cypress.$(cell).text();
|
||||
if (text.includes(aboveContent)) {
|
||||
foundAbove = true;
|
||||
cy.log(`[STEP 20.1] Found above content at index ${index}`);
|
||||
}
|
||||
if (text.includes(originalContent)) {
|
||||
foundOriginal = true;
|
||||
cy.log(`[STEP 20.2] Found original content at index ${index}`);
|
||||
}
|
||||
if (text.includes(belowContent)) {
|
||||
foundBelow = true;
|
||||
cy.log(`[STEP 20.3] Found below content at index ${index}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Verify all content was found
|
||||
expect(foundAbove).to.be.true;
|
||||
expect(foundOriginal).to.be.true;
|
||||
expect(foundBelow).to.be.true;
|
||||
});
|
||||
|
||||
cy.log('[STEP 21] Row insertion test completed successfully');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -363,6 +363,23 @@ export const FieldType = {
|
||||
FileMedia: 14
|
||||
};
|
||||
|
||||
/**
|
||||
* Database Row Controls selectors
|
||||
*/
|
||||
export const RowControlsSelectors = {
|
||||
// Row accessory button (appears on hover)
|
||||
rowAccessoryButton: () => cy.get(byTestId('row-accessory-button')),
|
||||
|
||||
// Row menu items
|
||||
rowMenuDuplicate: () => cy.get(byTestId('row-menu-duplicate')),
|
||||
rowMenuInsertAbove: () => cy.get(byTestId('row-menu-insert-above')),
|
||||
rowMenuInsertBelow: () => cy.get(byTestId('row-menu-insert-below')),
|
||||
rowMenuDelete: () => cy.get(byTestId('row-menu-delete')),
|
||||
|
||||
// Delete confirmation
|
||||
deleteRowConfirmButton: () => cy.get(byTestId('delete-row-confirm-button')),
|
||||
};
|
||||
|
||||
export function waitForReactUpdate(ms: number = 500) {
|
||||
return cy.wait(ms);
|
||||
}
|
||||
@@ -68,7 +68,7 @@ export function DeleteRowConfirm({
|
||||
<Button variant={'outline'} onClick={onClose}>
|
||||
{t('button.cancel')}
|
||||
</Button>
|
||||
<Button variant={'destructive'} onClick={handleDelete}>
|
||||
<Button variant={'destructive'} onClick={handleDelete} data-testid="delete-row-confirm-button">
|
||||
{t('button.delete')}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -98,6 +98,7 @@ export function HoverControls ({ rowId, dragHandleRef }: {
|
||||
<TooltipTrigger asChild>
|
||||
<div
|
||||
ref={dragHandleRef}
|
||||
data-testid="row-accessory-button"
|
||||
onClick={() => {
|
||||
setMenuOpen(true);
|
||||
}}
|
||||
|
||||
@@ -77,6 +77,13 @@ function RowMenu({ rowId, onClose }: { rowId: string; onClose: () => void }) {
|
||||
{actions.map((item) => (
|
||||
<DropdownMenuItem
|
||||
key={item.label}
|
||||
data-testid={
|
||||
item.label === t('grid.row.duplicate') ? 'row-menu-duplicate' :
|
||||
item.label === t('grid.row.insertRecordAbove') ? 'row-menu-insert-above' :
|
||||
item.label === t('grid.row.insertRecordBelow') ? 'row-menu-insert-below' :
|
||||
item.label === t('grid.row.delete') ? 'row-menu-delete' :
|
||||
undefined
|
||||
}
|
||||
onSelect={async (e) => {
|
||||
e.preventDefault();
|
||||
item.onSelect();
|
||||
|
||||
Reference in New Issue
Block a user