Skip to content

Conversation

@domhhv
Copy link
Contributor

@domhhv domhhv commented Oct 2, 2025

  • Add 10 new e2e test cases covering SDL builder deployment flow
  • Extend BuildTemplatePage with helper methods for form interactions
  • Tests cover: image input, preview, multi-service, validation, reset

Tests verify:

  • Basic SDL creation and preview functionality
  • Deployment flow up to wallet connection
  • Multi-service configuration
  • Form validation and reset behavior
  • YAML structure generation

Summary by CodeRabbit

  • Tests
    • Added end-to-end UI tests covering the SDL Builder deployment flow: navigation, image input, preview rendering, deploy initiation, multiple services, reset/validation, YAML structure checks, and wallet-connection prompts.
    • Added reusable UI test helpers for the Build Template interface to drive and assert interactions (fill inputs, preview/deploy/reset, add services) for more reliable coverage.
    • No user-facing functionality changed.

- Add 10 new e2e test cases covering SDL builder deployment flow
- Extend BuildTemplatePage with helper methods for form interactions
- Tests cover: image input, preview, multi-service, validation, reset

Tests verify:
- Basic SDL creation and preview functionality
- Deployment flow up to wallet connection
- Multi-service configuration
- Form validation and reset behavior
- YAML structure generation
@domhhv domhhv requested a review from a team as a code owner October 2, 2025 12:43
@coderabbitai
Copy link

coderabbitai bot commented Oct 2, 2025

Walkthrough

Adds Playwright page-object methods and locators to BuildTemplatePage for interacting with the Build Template UI and introduces a new UI test suite exercising preview, deploy, add-service, reset, and YAML/preview validations.

Changes

Cohort / File(s) Summary of changes
BuildTemplate page object
apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx
Added interaction and locator methods: fillImageName(imageName: string), addService(), clickDeploy(), clickPreview(), clickReset(), closePreview(), getPreviewTextLocator(text: string), getImageNameInput(), getDeployButton(), getPreviewButton(), getAddServiceButton(), getServiceLocator(serviceName: string), getServiceNameInput(serviceName: string), and waitForServiceAdded(serviceName: string, timeout = 10000) (default timeout updated to 10000). Maintains navigation to the interactive builder.
SDL Builder UI tests
apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts
New Playwright E2E test suite "SDL Builder Deployment Flow" covering: visibility/navigation checks, filling image names, preview open/close and content assertions (image and SDL structure), deploy flow (wallet connect), adding services and waiting for them, iterating previews for multiple images, YAML structure checks (version, services, profiles, deployment), reset and validation behaviors.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Tester
  participant Playwright
  participant BuildTemplatePage
  participant SDL_UI
  participant PreviewModal
  participant WalletDialog

  Tester->>Playwright: run sdl-builder-deployment.spec
  Playwright->>SDL_UI: navigate to /sdl-builder
  Playwright->>BuildTemplatePage: new BuildTemplatePage(page)

  Note right of BuildTemplatePage: Image entry & preview
  Tester->>BuildTemplatePage: fillImageName("nginx:latest")
  BuildTemplatePage->>SDL_UI: type into image input (getImageNameInput)
  Tester->>BuildTemplatePage: clickPreview()
  BuildTemplatePage->>SDL_UI: click preview button (getPreviewButton)
  SDL_UI-->>PreviewModal: render SDL preview
  PreviewModal-->>BuildTemplatePage: expose preview text (getPreviewTextLocator)
  Tester->>BuildTemplatePage: closePreview()

  Note right of BuildTemplatePage: Deploy flow
  Tester->>BuildTemplatePage: clickDeploy()
  BuildTemplatePage->>SDL_UI: click deploy button (getDeployButton)
  SDL_UI-->>WalletDialog: open wallet connect dialog

  Note right of BuildTemplatePage: Add service (async wait)
  Tester->>BuildTemplatePage: addService()
  BuildTemplatePage->>SDL_UI: click add service (getAddServiceButton)
  BuildTemplatePage->>BuildTemplatePage: waitForServiceAdded("service-2", timeout=10000)
  Tester->>BuildTemplatePage: clickReset()
  BuildTemplatePage->>SDL_UI: clear form fields
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I nibble keys and hop along,
Fill images, previewing the song.
Services sprout with a tiny cheer,
Reset and deploy—wallets near.
Hoppy tests, the build is strong 🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly captures the primary change by stating the addition of end-to-end tests for the SDL builder in the deployment scope and follows a clear conventional commit style, making the main focus of the PR immediately apparent.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts (4)

40-54: Replace arbitrary timeout with state-based wait.

Line 48 uses page.waitForTimeout(1000), which is a Playwright anti-pattern that makes tests fragile and slower. Wait for a specific UI state instead.

Replace the timeout with a wait for the new service to be visible:

 await sdlBuilderPage.addService();

-await page.waitForTimeout(1000);
+// Wait for the new service element to be added to the DOM
+await expect(page.getByTestId("service-2-container").or(page.getByText("service-2"))).toBeVisible();

 await sdlBuilderPage.clickPreview();

If you don't have a specific test ID for the second service, wait for any element that indicates the service was added.


56-75: Replace arbitrary timeouts with state-based waits.

Lines 64 and 68 use page.waitForTimeout(), which is a Playwright anti-pattern. Replace these with waits for specific UI states.

Apply these changes:

 await sdlBuilderPage.addService();
-await page.waitForTimeout(500);
+// Wait for service to be added
+await expect(page.getByTestId("service-2-container").or(page.getByText("service-2"))).toBeVisible();

 await sdlBuilderPage.clickReset();

-await page.waitForTimeout(1000);
+// Wait for form to reset - could wait for a loading indicator to disappear
+// or for the form to return to initial state
+await expect(page.getByTestId("image-name-input")).toHaveValue("");

 const imageInput = page.getByTestId("image-name-input");
 await expect(imageInput).toBeVisible();

77-92: Simplify negative assertion logic.

Lines 89-91 use .catch(() => true) to handle the case where the wallet button is not visible. This pattern is unclear and swallows errors. Use a straightforward negative assertion instead.

Apply this diff:

 const walletBtn = page.getByTestId("connect-wallet-btn");
-await expect(walletBtn)
-  .not.toBeVisible({ timeout: 2000 })
-  .catch(() => true);
+await expect(walletBtn).not.toBeVisible();

Playwright's not.toBeVisible() already handles the case where the element doesn't exist or is hidden, so no error handling is needed.


124-141: Replace arbitrary timeouts with state-based waits.

Lines 131 and 135 use page.waitForTimeout(), which is a Playwright anti-pattern. Replace these with waits for specific UI state changes.

Apply these changes:

 await sdlBuilderPage.addService();
-await page.waitForTimeout(500);
+// Wait for second service to appear
+await expect(page.getByTestId("service-2-container").or(page.getByText("service-2"))).toBeVisible();

 await sdlBuilderPage.clickPreview();

-await page.waitForTimeout(1000);
+// Wait for preview modal to fully render
+await expect(page.getByText(/service-1:/).first()).toBeVisible();

 await expect(page.getByText(/service-1:/).first()).toBeVisible();
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f5ac1d5 and 86d45a9.

📒 Files selected for processing (2)
  • apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (1 hunks)
  • apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Never use type any or cast to type any. Always define the proper TypeScript types.

Files:

  • apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx
  • apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code

Files:

  • apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx
  • apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)

Don't use jest.mock() to mock dependencies in test files. Instead, use jest-mock-extended to create mocks and pass mocks as dependencies to the service under test.

**/*.spec.{ts,tsx}: Use setup function instead of beforeEach in test files
setup function must be at the bottom of the root describe block in test files
setup function creates an object under test and returns it
setup function should accept a single parameter with inline type definition
Don't use shared state in setup function
Don't specify return type of setup function

Files:

  • apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts
🧬 Code graph analysis (2)
apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (3)
apps/deploy-web/tests/ui/pages/DeployBasePage.tsx (1)
  • DeployBasePage (7-88)
apps/deploy-web/tests/ui/fixture/test-env.config.ts (1)
  • testEnvConfig (12-16)
apps/deploy-web/tests/ui/fixture/context-with-extension.ts (1)
  • expect (77-77)
apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts (1)
apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (1)
  • BuildTemplatePage (6-43)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
🔇 Additional comments (15)
apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts (6)

1-4: LGTM!

The imports and test suite structure follow standard Playwright conventions.


14-27: LGTM!

The test logic properly verifies image name input and SDL preview functionality with appropriate assertions.


29-38: LGTM!

The test correctly verifies the deployment flow up to wallet connection. The explicit timeout on line 37 is reasonable given wallet interactions can be slower.


94-106: LGTM!

The test effectively verifies SDL preview functionality with multiple images. The loop-based approach provides good coverage without code duplication.


108-122: LGTM!

The test properly verifies the essential YAML structure components (version, services, profiles, deployment) in the generated SDL.


143-152: LGTM!

The test concisely verifies that the preview button is enabled when a valid image is present.

apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (9)

1-5: LGTM!

The imports are correct and properly organized.


7-10: LGTM!

The navigation method correctly overrides the parent implementation to reach the SDL Builder page.


12-14: LGTM!

The method properly encapsulates the image name input interaction.


16-18: LGTM!

The method uses accessible role-based selectors with case-insensitive matching, which is a Playwright best practice.


20-22: LGTM!

The regex anchors (^deploy$) correctly ensure an exact match to avoid clicking buttons with similar text like "deployment".


24-30: LGTM!

Both methods follow consistent patterns with appropriate selectors.


32-34: LGTM!

The method correctly uses .first() to handle potential multiple matches in the SDL preview content.


36-38: LGTM!

The method appropriately uses .first() to click the close button, handling scenarios where multiple close buttons might exist in the page.


40-42: LGTM!

The method properly verifies the input value using the appropriate toHaveValue assertion.

@domhhv domhhv requested a review from stalniy October 6, 2025 15:12
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (1)

30-32: Consider more specific selectors to avoid .first() fragility.

Both methods use .first() to select from potentially multiple matches, which can be fragile:

  • getPreviewTextLocator: If the same text appears elsewhere on the page, this returns the first match, which may not be from the preview dialog.
  • closePreview: If multiple "close" buttons exist (e.g., modals, sidebars), this clicks the first one, which might not be the preview close button.

Consider scoping selectors to the preview container:

-getPreviewTextLocator(text: string) {
-  return this.page.getByText(text).first();
+getPreviewTextLocator(text: string) {
+  return this.page.locator('[data-testid="preview-dialog"]').getByText(text);
 }
 
 async closePreview() {
-  await this.page.getByRole("button", { name: /close/i }).first().click();
+  await this.page.locator('[data-testid="preview-dialog"]').getByRole("button", { name: /close/i }).click();
 }

Alternatively, use more specific test-ids for these elements if available.

Also applies to: 34-36

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 86d45a9 and e511df9.

📒 Files selected for processing (2)
  • apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (1 hunks)
  • apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Never use type any or cast to type any. Always define the proper TypeScript types.

Files:

  • apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code

Files:

  • apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx
🧬 Code graph analysis (1)
apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (2)
apps/deploy-web/tests/ui/pages/DeployBasePage.tsx (1)
  • DeployBasePage (7-88)
apps/deploy-web/tests/ui/fixture/test-env.config.ts (1)
  • testEnvConfig (12-16)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
🔇 Additional comments (4)
apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (4)

5-8: LGTM!

The navigation logic is clean and correctly overrides the parent method to access the SDL builder directly.


10-28: LGTM!

The action methods use appropriate selectors and follow Playwright best practices. The use of role-based selectors with regex patterns is correct, and clickDeploy properly uses anchored regex to avoid matching similar button names.


38-52: LGTM!

The accessor methods properly return locators for test assertions, following the page object pattern correctly. The use of both test-id and role-based selectors is appropriate.


58-60: LGTM, pending fix to getServiceLocator.

The wait logic is correctly implemented. Once the regex escaping issue in getServiceLocator (lines 54-56) is resolved, this method will function reliably.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (1)

30-32: Consider precision of text locator.

Using .first() on a text locator could be brittle if multiple elements contain the same text. If the preview displays duplicate text in different contexts, this might select the wrong element.

If multiple matches are possible, consider using more specific locators or adding a container scope:

getPreviewTextLocator(text: string) {
  return this.page.locator('[data-testid="preview-modal"]').getByText(text).first();
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e511df9 and 796dae6.

📒 Files selected for processing (2)
  • apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (1 hunks)
  • apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)

Don't use jest.mock() to mock dependencies in test files. Instead, use jest-mock-extended to create mocks and pass mocks as dependencies to the service under test.

**/*.spec.{ts,tsx}: Use setup function instead of beforeEach in test files
setup function must be at the bottom of the root describe block in test files
setup function creates an object under test and returns it
setup function should accept a single parameter with inline type definition
Don't use shared state in setup function
Don't specify return type of setup function

Files:

  • apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Never use type any or cast to type any. Always define the proper TypeScript types.

Files:

  • apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts
  • apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code

Files:

  • apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts
  • apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx
🧠 Learnings (1)
📚 Learning: 2025-07-21T08:25:07.474Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-07-21T08:25:07.474Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `setup` function instead of `beforeEach` in test files

Applied to files:

  • apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts
🧬 Code graph analysis (2)
apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts (2)
apps/deploy-web/tests/ui/fixture/context-with-extension.ts (1)
  • expect (77-77)
apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (1)
  • BuildTemplatePage (4-66)
apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (2)
apps/deploy-web/tests/ui/pages/DeployBasePage.tsx (1)
  • DeployBasePage (7-88)
apps/deploy-web/tests/ui/fixture/test-env.config.ts (1)
  • testEnvConfig (12-16)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
🔇 Additional comments (3)
apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts (1)

97-106: LGTM! Setup function follows guidelines correctly.

The setup function is properly positioned at the bottom of the describe block, accepts a single parameter with inline type definition, has no return type annotation, and avoids shared state. This follows the project's coding guidelines exactly.

apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx (2)

54-57: LGTM! Regex escaping implemented correctly.

The service name is properly escaped before being used in the regular expression, preventing incorrect matches when service names contain regex metacharacters.


59-61: Verify filter precision for service name input.

The hasText filter might match unintended textboxes if serviceName appears in multiple locations. Consider whether a more specific selector (e.g., using container scope or test-id) would be more reliable.

Please verify that this locator uniquely identifies the intended service name input field, especially when multiple services with similar names are present.

@domhhv
Copy link
Contributor Author

domhhv commented Oct 14, 2025

@stalniy Is this ready to be merged? Let me know if there's anything else you'd like me to fix.

@domhhv
Copy link
Contributor Author

domhhv commented Oct 21, 2025

@stalniy Can you please merge this?

@ygrishajev ygrishajev merged commit e2383bb into akash-network:main Oct 22, 2025
62 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants