Skip to content

test(widgets): E2E Widget Lab consumption — duplicate, filter, search (#489) - #523

Merged
alfredo1996 merged 1 commit into
release/1.1from
test/issue-489-widget-lab-consumption
Apr 12, 2026
Merged

test(widgets): E2E Widget Lab consumption — duplicate, filter, search (#489)#523
alfredo1996 merged 1 commit into
release/1.1from
test/issue-489-widget-lab-consumption

Conversation

@alfredo1996

@alfredo1996 alfredo1996 commented Apr 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add 4 E2E tests to widget-lab.spec.ts for template consumption flows
  • Duplicate: Click duplicate → template with "(copy)" suffix appears
  • Filter by chart type: Select "Bar Chart" → only bar templates shown
  • Filter by connector: Select "PostgreSQL" → only pg templates shown
  • Search by name: Type query → results filtered, clear → all restored

Closes #489

Test plan

  • npx playwright test widget-lab --grep "consumption" — 4/4 passing
  • CI green

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests
    • Added end-to-end tests for Widget Lab covering template duplication, chart-type and connector-type filtering, and name-based search.
    • Tests include setup/teardown of test templates and assertions that UI updates (visibility and naming) behave as expected.

@alfredo1996 alfredo1996 added enhancement New feature or request pkg:app Next.js application package area:widgets Widget system testing labels Apr 12, 2026
@coderabbitai

coderabbitai Bot commented Apr 12, 2026

Copy link
Copy Markdown

Walkthrough

Adds a new E2E test suite for Widget Lab consumption that creates two templates via API in beforeEach, removes them in afterEach, and exercises duplicating a template, filtering by chart type, filtering by connector type, and searching templates by name.

Changes

Cohort / File(s) Summary
Widget Lab E2E Tests
app/e2e/widget-lab.spec.ts
New test suite with API setup/teardown for widget templates. Four UI tests: duplicate template (expects (copy) title and conditionally records duplicate ID for cleanup), filter by chart type (combobox), filter by connector type (combobox, matches /PostgreSQL/i), and search-by-name with clear-to-restore visibility assertions.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning PR implements 3 of 7 required consumption flows (duplicate, filter by chart/connector, search) but omits edit, use-in-dashboard, and sync tests. Add remaining tests for edit template, use template from dashboard, and template sync functionality to fully satisfy issue #489 acceptance criteria.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title clearly describes the main change: E2E tests for Widget Lab consumption flows (duplicate, filter, search).
Out of Scope Changes check ✅ Passed All changes are within scope—only widget-lab.spec.ts modified to add consumption tests directly tied to issue #489.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/issue-489-widget-lab-consumption

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/e2e/widget-lab.spec.ts`:
- Around line 628-656: The test setup in test.beforeEach uses fixed template
names and does not assert API responses; update the POST calls
(page.request.post in test.beforeEach) to create unique names (e.g., append a
timestamp or random suffix) so fixtures cannot collide across runs, capture and
assert the response status/body for both neo4jBar and pgTable (verify success
and extract IDs into templateIds), and in test.afterEach assert each DELETE
(page.request.delete) returns a successful status before clearing templateIds;
reference the test.beforeEach/test.afterEach blocks, the templateIds variable,
and the page.request.post/page.request.delete calls when making these changes.
- Around line 676-679: Replace the use of any by declaring an explicit response
type for the API result: introduce a type (e.g., WidgetTemplateListResponse with
data: Array<{ id: string; name: string }>) and cast the result of res.json() to
that type when assigning templates, then use templates.find((t) => t.name ===
"Neo4j Bar Template (copy)") to locate copy; update references to res.json(),
templates and copy so the eslint disable and any are removed and strict
TypeScript is preserved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ee3cb65d-684d-495e-8b94-c626102fc5d8

📥 Commits

Reviewing files that changed from the base of the PR and between 6d853de and 56e1053.

📒 Files selected for processing (1)
  • app/e2e/widget-lab.spec.ts

Comment on lines +628 to +656
test.beforeEach(async ({ page }) => {
// Create two templates via API for filter/search tests
const neo4jBar = await page.request.post("/api/widget-templates", {
data: {
name: "Neo4j Bar Template",
chartType: "bar",
connectorType: "neo4j",
query: "MATCH (m:Movie) RETURN m.title AS label, count(*) AS value",
},
});
const pgTable = await page.request.post("/api/widget-templates", {
data: {
name: "PostgreSQL Table Template",
chartType: "table",
connectorType: "postgresql",
query: "SELECT title FROM movies LIMIT 5",
},
});
const t1 = (await neo4jBar.json()).data;
const t2 = (await pgTable.json()).data;
templateIds = [t1.id, t2.id];
});

test.afterEach(async ({ page }) => {
for (const id of templateIds) {
await page.request.delete(`/api/widget-templates/${id}`);
}
templateIds = [];
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Make fixture data unique and assert API setup/cleanup responses.

Line 632 and Line 640 use fixed names, which can collide with stale/retry data and make duplicate/filter assertions ambiguous. Also, setup/teardown API calls (Line 630-Line 645, Line 653) should assert success to fail fast when fixtures don’t load/clean correctly.

Suggested hardening diff
 test.describe("Widget Lab consumption", () => {
   let templateIds: string[] = [];
+  let neo4jTemplateName = "";
+  let pgTemplateName = "";

   test.beforeEach(async ({ page }) => {
+    const suffix = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
+    neo4jTemplateName = `Neo4j Bar Template ${suffix}`;
+    pgTemplateName = `PostgreSQL Table Template ${suffix}`;
+
     // Create two templates via API for filter/search tests
     const neo4jBar = await page.request.post("/api/widget-templates", {
       data: {
-        name: "Neo4j Bar Template",
+        name: neo4jTemplateName,
         chartType: "bar",
         connectorType: "neo4j",
         query: "MATCH (m:Movie) RETURN m.title AS label, count(*) AS value",
       },
     });
+    expect(neo4jBar.ok()).toBeTruthy();

     const pgTable = await page.request.post("/api/widget-templates", {
       data: {
-        name: "PostgreSQL Table Template",
+        name: pgTemplateName,
         chartType: "table",
         connectorType: "postgresql",
         query: "SELECT title FROM movies LIMIT 5",
       },
     });
+    expect(pgTable.ok()).toBeTruthy();

     const t1 = (await neo4jBar.json()).data;
     const t2 = (await pgTable.json()).data;
     templateIds = [t1.id, t2.id];
   });

   test.afterEach(async ({ page }) => {
     for (const id of templateIds) {
-      await page.request.delete(`/api/widget-templates/${id}`);
+      const delRes = await page.request.delete(`/api/widget-templates/${id}`);
+      expect(delRes.ok()).toBeTruthy();
     }
     templateIds = [];
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/e2e/widget-lab.spec.ts` around lines 628 - 656, The test setup in
test.beforeEach uses fixed template names and does not assert API responses;
update the POST calls (page.request.post in test.beforeEach) to create unique
names (e.g., append a timestamp or random suffix) so fixtures cannot collide
across runs, capture and assert the response status/body for both neo4jBar and
pgTable (verify success and extract IDs into templateIds), and in test.afterEach
assert each DELETE (page.request.delete) returns a successful status before
clearing templateIds; reference the test.beforeEach/test.afterEach blocks, the
templateIds variable, and the page.request.post/page.request.delete calls when
making these changes.

Comment on lines +676 to +679
const copy = templates.find(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(t: any) => t.name === "Neo4j Bar Template (copy)",
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Check explicit any usage in the changed test file:"
rg -nP '\bany\b' app/e2e/widget-lab.spec.ts

echo
echo "Check TS strict/noImplicitAny config under app/:"
fd -i '^tsconfig.*\.json$' app --exec rg -n '"strict"\s*:\s*true|"noImplicitAny"\s*:\s*true' {}

Repository: alfredo1996/neoboard

Length of output: 683


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check full context of the template lookup at lines 676-679 ==="
sed -n '670,690p' app/e2e/widget-lab.spec.ts

echo
echo "=== Check the /api/widget-templates endpoint to understand response structure ==="
fd -t f '\.(ts|tsx)$' app --exec grep -l 'widget-templates' {} \;

echo
echo "=== Check all occurrences of the template pattern to see if they're all identical ==="
sed -n '126,140p' app/e2e/widget-lab.spec.ts
echo "---"
sed -n '350,365p' app/e2e/widget-lab.spec.ts

Repository: alfredo1996/neoboard

Length of output: 1537


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check the widget-templates API route ==="
cat -n app/src/app/api/widget-templates/route.ts | head -80

echo
echo "=== Check hook that uses widget-templates ==="
cat -n app/src/hooks/use-widget-templates.ts

echo
echo "=== Check if there's a types file for templates ==="
fd -t f 'template' app/src --type f | grep -E '\.(ts|tsx)$' | head -20

Repository: alfredo1996/neoboard

Length of output: 7305


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check apiList response structure ==="
grep -A 20 'export function apiList' app/src/lib/api/api-response.ts

echo
echo "=== Check unwrapResponse ==="
grep -A 15 'export.*unwrapResponse' app/src/lib/api/api-client.ts

echo
echo "=== Check WidgetTemplate type ==="
grep -B 5 -A 20 'export.*WidgetTemplate' app/src/lib/db/schema.ts | head -50

Repository: alfredo1996/neoboard

Length of output: 2372


Remove any and properly type the API response to maintain strict TypeScript.

Line 678 uses any, which violates strict TS mode. The /api/widget-templates endpoint returns a structured envelope with { data, error, meta }, so the response type can be declared explicitly:

type WidgetTemplateListResponse = {
  data: Array<{ id: string; name: string }>;
};
const templates = ((await res.json()) as WidgetTemplateListResponse).data;
const copy = templates.find(
  (t) => t.name === "Neo4j Bar Template (copy)",
);

This eliminates the need for @typescript-eslint/no-explicit-any and strengthens type safety.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/e2e/widget-lab.spec.ts` around lines 676 - 679, Replace the use of any by
declaring an explicit response type for the API result: introduce a type (e.g.,
WidgetTemplateListResponse with data: Array<{ id: string; name: string }>) and
cast the result of res.json() to that type when assigning templates, then use
templates.find((t) => t.name === "Neo4j Bar Template (copy)") to locate copy;
update references to res.json(), templates and copy so the eslint disable and
any are removed and strict TypeScript is preserved.

…#489)

Add 4 tests: duplicate template with (copy) suffix, filter by chart
type, filter by connector type, and search templates by name.

Closes #489

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@alfredo1996
alfredo1996 force-pushed the test/issue-489-widget-lab-consumption branch from 56e1053 to 5ef8842 Compare April 12, 2026 17:39

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
app/e2e/widget-lab.spec.ts (2)

738-766: ⚠️ Potential issue | 🟠 Major

Harden fixture setup/teardown to avoid flaky collisions.

The fixed template names and missing API status assertions make this suite brittle on retries/reruns and can hide setup failures.

Suggested hardening diff
 test.describe("Widget Lab consumption", () => {
   let templateIds: string[] = [];
+  let neo4jTemplateName = "";
+  let pgTemplateName = "";

   test.beforeEach(async ({ page }) => {
+    const suffix = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
+    neo4jTemplateName = `Neo4j Bar Template ${suffix}`;
+    pgTemplateName = `PostgreSQL Table Template ${suffix}`;
+
     // Create two templates via API for filter/search tests
     const neo4jBar = await page.request.post("/api/widget-templates", {
       data: {
-        name: "Neo4j Bar Template",
+        name: neo4jTemplateName,
         chartType: "bar",
         connectorType: "neo4j",
         query: "MATCH (m:Movie) RETURN m.title AS label, count(*) AS value",
       },
     });
+    expect(neo4jBar.ok()).toBeTruthy();

     const pgTable = await page.request.post("/api/widget-templates", {
       data: {
-        name: "PostgreSQL Table Template",
+        name: pgTemplateName,
         chartType: "table",
         connectorType: "postgresql",
         query: "SELECT title FROM movies LIMIT 5",
       },
     });
+    expect(pgTable.ok()).toBeTruthy();

     const t1 = (await neo4jBar.json()).data;
     const t2 = (await pgTable.json()).data;
     templateIds = [t1.id, t2.id];
   });

   test.afterEach(async ({ page }) => {
     for (const id of templateIds) {
-      await page.request.delete(`/api/widget-templates/${id}`);
+      const delRes = await page.request.delete(`/api/widget-templates/${id}`);
+      expect(delRes.ok()).toBeTruthy();
     }
     templateIds = [];
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/e2e/widget-lab.spec.ts` around lines 738 - 766, The fixture
setup/teardown uses fixed template names and doesn't assert API responses,
causing flaky collisions; update test.beforeEach to POST templates with unique
names (e.g., append timestamp/UUID) when calling
page.request.post("/api/widget-templates"), assert the response status (expect
201 or success) and extract ids into templateIds, and make test.afterEach robust
by iterating templateIds to DELETE `/api/widget-templates/${id}` while
tolerating 404s and ensuring cleanup runs even if setup partially failed;
reference the test.beforeEach/test.afterEach blocks and the templateIds variable
when making these changes.

786-789: ⚠️ Potential issue | 🟡 Minor

Replace any in template lookup to preserve strict TS.

Use a small response type for /api/widget-templates and remove the eslint suppression.

Typed fix
+      type WidgetTemplateListResponse = {
+        data: Array<{ id: string; name: string }>;
+      };
       const res = await page.request.get("/api/widget-templates");
-      const templates = (await res.json()).data;
+      const templates = ((await res.json()) as WidgetTemplateListResponse).data;
       const copy = templates.find(
-        // eslint-disable-next-line `@typescript-eslint/no-explicit-any`
-        (t: any) => t.name === "Neo4j Bar Template (copy)",
+        (t) => t.name === "Neo4j Bar Template (copy)",
       );

As per coding guidelines: "**/*.{ts,tsx}: TypeScript must be strict. No any without a comment explaining why."

#!/bin/bash
set -euo pipefail
rg -nP '\bany\b|no-explicit-any' app/e2e/widget-lab.spec.ts
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/e2e/widget-lab.spec.ts` around lines 786 - 789, The lookup uses an any
type and an eslint-disable; define a small response type (e.g., interface
TemplateBrief { name: string; id?: string; /* add fields actually used */ }) for
the /api/widget-templates response, type the variable holding templates as
TemplateBrief[], remove the eslint-disable comment, and update the find call to
templates.find((t: TemplateBrief) => t.name === "Neo4j Bar Template (copy)");
ensure the fetch/parser of the API in this spec uses that TemplateBrief type so
TS strict mode is preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@app/e2e/widget-lab.spec.ts`:
- Around line 738-766: The fixture setup/teardown uses fixed template names and
doesn't assert API responses, causing flaky collisions; update test.beforeEach
to POST templates with unique names (e.g., append timestamp/UUID) when calling
page.request.post("/api/widget-templates"), assert the response status (expect
201 or success) and extract ids into templateIds, and make test.afterEach robust
by iterating templateIds to DELETE `/api/widget-templates/${id}` while
tolerating 404s and ensuring cleanup runs even if setup partially failed;
reference the test.beforeEach/test.afterEach blocks and the templateIds variable
when making these changes.
- Around line 786-789: The lookup uses an any type and an eslint-disable; define
a small response type (e.g., interface TemplateBrief { name: string; id?:
string; /* add fields actually used */ }) for the /api/widget-templates
response, type the variable holding templates as TemplateBrief[], remove the
eslint-disable comment, and update the find call to templates.find((t:
TemplateBrief) => t.name === "Neo4j Bar Template (copy)"); ensure the
fetch/parser of the API in this spec uses that TemplateBrief type so TS strict
mode is preserved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: af3699ee-b66d-47ae-93e6-aee527fa9fa2

📥 Commits

Reviewing files that changed from the base of the PR and between 56e1053 and 5ef8842.

📒 Files selected for processing (1)
  • app/e2e/widget-lab.spec.ts

@sonarqubecloud

Copy link
Copy Markdown

@alfredo1996
alfredo1996 merged commit b5e1832 into release/1.1 Apr 12, 2026
13 checks passed
@alfredo1996
alfredo1996 deleted the test/issue-489-widget-lab-consumption branch April 12, 2026 17:58
alfredo1996 added a commit that referenced this pull request May 10, 2026
…#489) (#523)

Add 4 tests: duplicate template with (copy) suffix, filter by chart
type, filter by connector type, and search templates by name.

Closes #489

Co-authored-by: alfredorubin96 <alfredo.rubin@neotechnology.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:widgets Widget system enhancement New feature or request pkg:app Next.js application package testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants