Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/playwright-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,15 @@ jobs:
name: playwright-report
path: playwright-report/
retention-days: 30

- name: Comment PR with Report Link
if: github.event_name == 'pull_request'
uses: thollander/actions-comment-pull-request@v2
with:
message: |
✅ Playwright tests completed.

📄 [Download HTML report](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1 change: 1 addition & 0 deletions src/components/UndoModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ export const UndoModal: React.FC<UndoModalProps> = ({
dataSource={undoHistory}
renderItem={(item, index) => (
<List.Item
className="undo-item"
onClick={() => {
if (index === selectedUndoIndex) {
// If clicking the same item again, treat it as deselection
Expand Down
111 changes: 111 additions & 0 deletions tests/flows/feature-edit-undo-flow.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { test, expect } from '@playwright/test'

test('Feature editing should update properties panel and undo system', async ({ page }) => {
const plotName = 'Feature Edit Flow Test'

// Setup: Create a sample plot
await page.goto('/')
await page.waitForSelector('button:has-text("Sample plot")')
await page.click('button:has-text("Sample plot")')
await page.waitForSelector('div.ant-modal-content')
await page.locator('input.ant-input').fill(plotName)
await page.locator('button:has-text("OK")').click()
await page.waitForSelector('.flexlayout__tab_button_content')

// Step 1: Select a feature in the layer panel
const featureName = 'VAN GALEN'
const featureInTree = page.locator(`span:has-text("${featureName}")`).first()
await expect(featureInTree).toBeVisible()
await featureInTree.click()

// Step 2: Verify the Properties panel updates to show the selected feature
const propertiesPanel = page.locator('.core-form-animated')
await expect(propertiesPanel).toBeVisible()

// Verify the name field in properties panel shows the selected feature name
const nameField = propertiesPanel.locator('input[id="trackPropertiesForm_name"]')
await expect(nameField).toHaveValue(featureName)

// Check Save button is currently disabled
await expect(propertiesPanel.locator('button:has-text("Save")')).toBeDisabled()

// Check Reset button is currently disabled
await expect(propertiesPanel.locator('button:has-text("Reset")')).toBeDisabled()

// Step 3: Edit the feature's name in the property panel
const newName = 'RENAMED FEATURE'
await nameField.clear()
await nameField.fill(newName)
await page.keyboard.press('Enter')

// Wait for the UI to update
await page.waitForTimeout(200)

// Check Save and Reset buttons are enabled
await expect(propertiesPanel.locator('button:has-text("Save")')).not.toBeDisabled()
await expect(propertiesPanel.locator('button:has-text("Reset")')).not.toBeDisabled()

// Press Save on the form
await propertiesPanel.locator('button:has-text("Save")').click()

// Wait for the UI to update
await page.waitForTimeout(200)

// Check Save and Reset buttons are disabled
await expect(propertiesPanel.locator('button:has-text("Save")')).toBeDisabled()
await expect(propertiesPanel.locator('button:has-text("Reset")')).toBeDisabled()

// Step 4: Verify the feature name is updated in the layer panel
const updatedFeature = page.locator(`span:has-text("${newName}")`).first()
await expect(updatedFeature).toBeVisible()

// Step 5: Verify the undo button is enabled after the edit
const undoRedoButton = page.locator('.undo-redo-button')
await expect(undoRedoButton).not.toBeDisabled()

// Step 6: Open the undo modal
await undoRedoButton.click()

// Step 7: Verify the undo modal appears with the correct description
const undoModal = page.locator('.ant-modal-content').filter({ hasText: 'Select a version' })
await expect(undoModal).toBeVisible()

// Check that the undo description mentions the name attribute
const undoDescription = undoModal.locator('.undo-item').first()
await expect(undoDescription).toContainText('name')

// Step 8: Perform the undo and verify the feature name reverts
await undoModal.locator('.ant-list-items').locator('.ant-list-item').first().click()
await page.locator('button:has-text("Restore Version")').click()

// Wait for the UI to update
await page.waitForTimeout(200)

// Step 9: Verify original name is restored in both the layer panel and properties panel
await expect(featureInTree).toBeVisible()
await expect(updatedFeature).not.toBeVisible()

// Verify the name field in properties panel shows the original name
await expect(nameField).toHaveValue(featureName)

// Step 10: Open the undo modal again to perform a Redo operation
await undoRedoButton.click()
await expect(undoModal).toBeVisible()

// Step 11: Select the second item in the list (which would be the Redo operation)
const redoItem = undoModal.locator('.ant-list-items').locator('.ant-list-item').first()
await redoItem.click()

// Step 12: Perform the Redo by clicking Restore Version
await page.locator('button:has-text("Restore Version")').click()

// Wait for the UI to update
await page.waitForTimeout(200)

// Step 13: Verify the feature name is changed back to the new name
await expect(updatedFeature).toBeVisible()
await expect(featureInTree).not.toBeVisible()

// Verify the name field in properties panel shows the new name again
await expect(nameField).toHaveValue(newName)
})
12 changes: 11 additions & 1 deletion tests/layers/paste-features.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ test('Pasting features in Layers component', async ({ browser }) => {

// Select a reference point
const referencePoint = page.locator('.ant-tree-title:has-text("NEW SONO")').first()
if (!await referencePoint.isVisible()) {
await pointsNode.click()
await page.waitForTimeout(100)
}
await referencePoint.click()

await copyButton.click()
Expand Down Expand Up @@ -96,7 +100,13 @@ test('Pasting features in Layers component', async ({ browser }) => {
// // Wait for the points to be visible
await page.waitForTimeout(100)

// // Verify that there's at least one point visible after pasting
// if points is collapsed
const pointsAfterPaste = page.locator('span:has-text("NEW SONO")').first()
if (!await pointsNode.isVisible()) {
await pointsNode.click()
await page.waitForTimeout(100)
}

// // Verify that there's at least one point visible after pasting
await expect(pointsAfterPaste).toBeVisible()
})