← Back to list

smart-recipe-planner-test-ui
by LuisDavidTF
Culina Smart is a menu planning app with integrated AI to suggest recipes to include in your weekly meal plan based on your nutritional goals and the ingredients you have at home.
⭐ 0🍴 0📅 Jan 21, 2026
SKILL.md
name: smart-recipe-planner-test-ui description: > Smart Recipe Planner UI testing patterns with Playwright. Trigger: When writing E2E tests for the frontend, creating Page Objects, or validating UI flows in Smart Recipe Planner. license: Apache-2.0 metadata: author: ant-gravity version: "1.0" scope: [root, ui] auto_invoke: "Writing Playwright E2E tests" allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
Related Generic Skills
playwright- Generic Playwright patterns (selectors, MCP workflow)smart-recipe-planner-ui- UI component structure
File Structure
e2e/ # Root level e2e folder (Smart Recipe Planner convention)
├── base-page.ts # Parent class for ALL pages
├── helpers.ts # Shared utilities (auth, data gen)
├── auth/ # Auth feature tests
│ ├── login-page.ts
│ └── login.spec.ts
├── recipes/ # Recipe management tests
│ ├── recipe-page.ts
│ └── recipes.spec.ts
└── planning/ # Meal planning tests
├── planner-page.ts
└── planner.spec.ts
Smart Recipe Planner Page Object Pattern
BasePage
import { Page, Locator, expect } from "@playwright/test";
export class BasePage {
constructor(protected page: Page) {}
async goto(path: string): Promise<void> {
await this.page.goto(path);
await this.page.waitForLoadState("domcontentloaded");
}
// Shared UI components (Header, Footer, Toast)
async getToastMessage(): Promise<string | null> {
const toast = this.page.locator('[role="status"]'); // Radix/Sonner toast
if (await toast.isVisible()) {
return toast.textContent();
}
return null;
}
}
Feature Page (Example: Recipe)
import { BasePage } from "../base-page";
import { Page, Locator, expect } from "@playwright/test";
export class RecipePage extends BasePage {
readonly createButton: Locator;
readonly titleInput: Locator;
readonly saveButton: Locator;
constructor(page: Page) {
super(page);
this.createButton = page.getByRole("button", { name: "New Recipe" });
this.titleInput = page.getByLabel("Recipe Title");
this.saveButton = page.getByRole("button", { name: "Save Recipe" });
}
async createRecipe(title: string) {
await this.createButton.click();
await this.titleInput.fill(title);
await this.saveButton.click();
}
}
Testing Guidelines
Authentication
Tests that require authentication should use a setup state or helper to bypass manual login for every test, unless testing the login flow itself.
// e2e/auth.setup.ts
import { test as setup } from '@playwright/test';
setup('authenticate', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('test@example.com');
await page.getByLabel('Password').fill('password');
await page.getByRole('button', { name: 'Sign in' }).click();
await page.waitForURL('/dashboard');
await page.context().storageState({ path: 'playwright/.auth/user.json' });
});
Data Test IDs
Prefer accessibility roles (getByRole, getByLabel), but use data-testid for elements that are hard to select otherwise (like specific containers or non-interactive elements).
<!-- Component code -->
<div data-testid="recipe-card-123">...</div>
// Test code
await page.getByTestId("recipe-card-123").click();
Commands
# Run all E2E tests
npx playwright test
# Run UI mode (interactive)
npx playwright test --ui
# Debug tests
npx playwright test --debug
QA Checklist
- Page Objects are used (no direct locators in spec files)
- Tests are independent (clean state)
- Sensitive data is not hardcoded (use env vars)
- Happy path AND error states are tested
- Mobile viewports are considered (if configured)
Score
Total Score
65/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
✓説明文
100文字以上の説明がある
+10
○人気
GitHub Stars 100以上
0/15
✓最近の活動
1ヶ月以内に更新
+10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
✓タグ
1つ以上のタグが設定されている
+5
Reviews
💬
Reviews coming soon


