fix remove food, efit food. assed playwright tests

This commit is contained in:
2025-10-03 13:46:38 -07:00
parent 661dbdf0af
commit f931edf8dd
486 changed files with 148847 additions and 88 deletions

34
tests/2_tracker.spec.js Normal file
View File

@@ -0,0 +1,34 @@
const { test, expect } = require('@playwright/test');
test('add breakfast meal', async ({ page }) => {
await page.goto('/tracker');
//RESET to make sure we are testing on a known state
page.on('dialog', dialog => dialog.accept());
await page.getByRole('button', { name: 'Reset Page' }).click();
await expect(page.locator('#meals-breakfast').getByText('No meals tracked')).toBeVisible();
// Add meal to breakfast
await page.locator('[data-testid="add-meal-breakfast"]').click();
await page.locator('select[name="meal_id"]').selectOption('3');
await page.getByRole('button', { name: 'Add Meal', exact: true }).click();
await expect(page.locator('[data-testid="meal-name-breakfast-protein-shake-pea-sdz-1"]')).toBeVisible();
//edit meal
await page.locator('[data-testid="edit-meal-breakfast-protein-shake-pea-sdz-1"]').click();
// Use a more robust locator to find the food by its name, then target the input
await page.locator('.d-flex.justify-content-between:has-text("Organic Strawberry Powder")').getByRole('spinbutton').fill('10');
// "Pea Protein Concentrate" is not in the meal, so we don't need to remove it.
await page.getByRole('button', { name: 'Save Changes' }).click();
await expect(page.locator('[data-testid="meal-card-breakfast-protein-shake-pea-sdz-1"]')).toContainText('• Organic Strawberry Powder 10.0 g');
await expect(page.locator('[data-testid="meal-card-breakfast-protein-shake-pea-sdz-1"]')).not.toContainText('• Pea Protein Concentrate 34.0 g');
//add food to tracker meal
await page.locator('[data-testid="edit-meal-breakfast-protein-shake-pea-sdz-1"]').click();
await page.locator('#foodSelectTrackedMeal').selectOption({ label: 'Coffee' });
await page.getByRole('button', { name: 'Add Food', exact: true }).click();
await page.getByRole('button', { name: 'Save Changes' }).click();
await expect(page.locator('[data-testid="meal-card-breakfast-protein-shake-pea-sdz-1"]')).toContainText('• Coffee 100.0 g');
});

350
tests/3_details.spec.js Normal file
View File

@@ -0,0 +1,350 @@
const { test, expect } = require('@playwright/test');
test('add breakfast meal', async ({ page }) => {
await page.goto('/detailed');
await page.getByRole('button', { name: 'View Template' }).click();
// Wait for and click the specific link
// This tells the locator to find an element where the text is *exactly* "Sarah-Day 1"
await page.locator('a.dropdown-item')
.filter({ hasText: /^Sarah-Day 1$/ })
.click();
await expect(page.locator('body')).toMatchAriaSnapshot(`
- heading "Sarah-Day 1 Template" [level=4]
- textbox
- button " View Day"
- button "View Template"
- text: / Morning Green Tea - SDZ - Custom \\(Beverage 1\\) \\d+ cal/
- table:
- rowgroup:
- row "Food Item Serving Cal Protein Carbs Fat Fiber Sodium":
- cell "Food Item"
- cell "Serving"
- cell "Cal"
- cell "Protein"
- cell "Carbs"
- cell "Fat"
- cell "Fiber"
- cell "Sodium"
- rowgroup:
- row /Green Tea \\d+\\.0g 0 0\\.0g 0\\.0g 0\\.0g 0\\.0g 0mg/:
- cell "Green Tea"
- cell /\\d+\\.0g/
- cell "0"
- cell "0.0g"
- cell "0.0g"
- cell "0.0g"
- cell "0.0g"
- cell "0mg"
- row /Organic Coconut Oil \\d+\\.0g \\d+ 0\\.0g 0\\.0g \\d+\\.0g 0\\.0g 0mg/:
- cell "Organic Coconut Oil"
- cell /\\d+\\.0g/
- cell /\\d+/
- cell "0.0g"
- cell "0.0g"
- cell /\\d+\\.0g/
- cell "0.0g"
- cell "0mg"
- row / Meal Totals - \\d+ 0\\.0g \\(0%\\) 0\\.0g \\(0%\\) \\d+\\.0g \\(\\d+\\.\\d+%\\) 0\\.0g 0mg/:
- cell " Meal Totals":
- strong:  Meal Totals
- cell "-"
- cell /\\d+/
- cell "0.0g (0%)"
- cell "0.0g (0%)"
- cell /\\d+\\.0g \\(\\d+\\.\\d+%\\)/
- cell "0.0g"
- cell "0mg"
- strong: "Net Carbs:"
- text: 0.0g
- strong: "Sugar:"
- text: 0.0g
- strong: "Calcium:"
- text: 0mg
- strong: "Ratio:"
- text: /0:0:\\d+\\.\\d+  Protein Shake - Pea - SDZ - Custom \\(Breakfast\\) \\d+ cal/
- table:
- rowgroup:
- row "Food Item Serving Cal Protein Carbs Fat Fiber Sodium":
- cell "Food Item"
- cell "Serving"
- cell "Cal"
- cell "Protein"
- cell "Carbs"
- cell "Fat"
- cell "Fiber"
- cell "Sodium"
- rowgroup:
- row /Pea Protein Concentrate \\d+\\.0g \\d+ \\d+\\.0g 1\\.0g 1\\.0g 1\\.0g 500mg/:
- cell "Pea Protein Concentrate"
- cell /\\d+\\.0g/
- cell /\\d+/
- cell /\\d+\\.0g/
- cell "1.0g"
- cell "1.0g"
- cell "1.0g"
- cell "500mg"
- row /Organic Strawberry Powder 3\\.0g \\d+ 0\\.0g 2\\.5g 0\\.0g 1\\.0g 0mg/:
- cell "Organic Strawberry Powder"
- cell "3.0g"
- cell /\\d+/
- cell "0.0g"
- cell "2.5g"
- cell "0.0g"
- cell "1.0g"
- cell "0mg"
- row /Organic Blueberry Powder 0\\.8g \\d+ 0\\.0g 2\\.5g 0\\.0g 1\\.0g 0mg/:
- cell "Organic Blueberry Powder"
- cell "0.8g"
- cell /\\d+/
- cell "0.0g"
- cell "2.5g"
- cell "0.0g"
- cell "1.0g"
- cell "0mg"
- row /Organic Pomegranate Powder 2\\.5g \\d+ 0\\.0g 2\\.5g 0\\.0g 0\\.0g 0mg/:
- cell "Organic Pomegranate Powder"
- cell "2.5g"
- cell /\\d+/
- cell "0.0g"
- cell "2.5g"
- cell "0.0g"
- cell "0.0g"
- cell "0mg"
- row "Organic Cranberry Powder 2.5g 8 0.0g 1.9g 0.0g 1.9g 0mg":
- cell "Organic Cranberry Powder"
- cell "2.5g"
- cell "8"
- cell "0.0g"
- cell "1.9g"
- cell "0.0g"
- cell "1.9g"
- cell "0mg"
- row / Meal Totals - \\d+ \\d+\\.0g \\(\\d+\\.\\d+%\\) \\d+\\.4g \\(\\d+\\.\\d+%\\) 1\\.0g \\(5\\.5%\\) 4\\.9g 500mg/:
- cell " Meal Totals":
- strong:  Meal Totals
- cell "-"
- cell /\\d+/
- cell /\\d+\\.0g \\(\\d+\\.\\d+%\\)/
- cell /\\d+\\.4g \\(\\d+\\.\\d+%\\)/
- cell "1.0g (5.5%)"
- cell "4.9g"
- cell "500mg"
- strong: "Net Carbs:"
- text: 5.5g
- strong: "Sugar:"
- text: 0.0g
- strong: "Calcium:"
- text: 13mg
- strong: "Ratio:"
- text: /\\d+\\.\\d+:\\d+\\.\\d+:5\\.5  Salad - Tuna - Custom \\(Lunch\\) \\d+ cal/
- table:
- rowgroup:
- row "Food Item Serving Cal Protein Carbs Fat Fiber Sodium":
- cell "Food Item"
- cell "Serving"
- cell "Cal"
- cell "Protein"
- cell "Carbs"
- cell "Fat"
- cell "Fiber"
- cell "Sodium"
- rowgroup:
- row /Tuna \\d+\\.5g \\d+ \\d+\\.0g 0\\.0g 1\\.5g 0\\.0g 330mg/:
- cell "Tuna"
- cell /\\d+\\.5g/
- cell /\\d+/
- cell /\\d+\\.0g/
- cell "0.0g"
- cell "1.5g"
- cell "0.0g"
- cell "330mg"
- row /Protein Greens \\d+\\.0g 8 1\\.1g 1\\.1g 0\\.0g 0\\.6g 8mg/:
- cell "Protein Greens"
- cell /\\d+\\.0g/
- cell "8"
- cell "1.1g"
- cell "1.1g"
- cell "0.0g"
- cell "0.6g"
- cell "8mg"
- row /Avocado \\d+\\.0g \\d+ 1\\.2g 5\\.1g 8\\.8g 4\\.0g 4mg/:
- cell "Avocado"
- cell /\\d+\\.0g/
- cell /\\d+/
- cell "1.2g"
- cell "5.1g"
- cell "8.8g"
- cell "4.0g"
- cell "4mg"
- row /Cucumber \\d+\\.0g \\d+ 0\\.5g 2\\.6g 0\\.0g 0\\.3g 2mg/:
- cell "Cucumber"
- cell /\\d+\\.0g/
- cell /\\d+/
- cell "0.5g"
- cell "2.6g"
- cell "0.0g"
- cell "0.3g"
- cell "2mg"
- row /Balsamic Vinegar \\d+\\.0g \\d+ 0\\.0g 3\\.0g 0\\.0g 0\\.0g 0mg/:
- cell "Balsamic Vinegar"
- cell /\\d+\\.0g/
- cell /\\d+/
- cell "0.0g"
- cell "3.0g"
- cell "0.0g"
- cell "0.0g"
- cell "0mg"
- row / Meal Totals - \\d+ \\d+\\.7g \\(\\d+\\.\\d+%\\) \\d+\\.7g \\(\\d+\\.\\d+%\\) \\d+\\.3g \\(\\d+\\.\\d+%\\) 5\\.0g 344mg/:
- cell " Meal Totals":
- strong:  Meal Totals
- cell "-"
- cell /\\d+/
- cell /\\d+\\.7g \\(\\d+\\.\\d+%\\)/
- cell /\\d+\\.7g \\(\\d+\\.\\d+%\\)/
- cell /\\d+\\.3g \\(\\d+\\.\\d+%\\)/
- cell "5.0g"
- cell "344mg"
- strong: "Net Carbs:"
- text: 6.8g
- strong: "Sugar:"
- text: 0.0g
- strong: "Calcium:"
- text: 69mg
- strong: "Ratio:"
- text: /\\d+\\.\\d+:\\d+\\.\\d+:\\d+\\.\\d+  Snack - Almond Milk & Protein - Custom \\(Dinner\\) \\d+ cal/
- table:
- rowgroup:
- row "Food Item Serving Cal Protein Carbs Fat Fiber Sodium":
- cell "Food Item"
- cell "Serving"
- cell "Cal"
- cell "Protein"
- cell "Carbs"
- cell "Fat"
- cell "Fiber"
- cell "Sodium"
- rowgroup:
- row /Almond Milk \\d+\\.0g \\d+ 1\\.0g 1\\.0g 2\\.5g 0\\.0g 170mg/:
- cell "Almond Milk"
- cell /\\d+\\.0g/
- cell /\\d+/
- cell "1.0g"
- cell "1.0g"
- cell "2.5g"
- cell "0.0g"
- cell "170mg"
- row /Pea Protein Concentrate \\d+\\.0g \\d+ \\d+\\.0g 1\\.0g 1\\.0g 1\\.0g 500mg/:
- cell "Pea Protein Concentrate"
- cell /\\d+\\.0g/
- cell /\\d+/
- cell /\\d+\\.0g/
- cell "1.0g"
- cell "1.0g"
- cell "1.0g"
- cell "500mg"
- row / Meal Totals - \\d+ \\d+\\.0g \\(\\d+\\.\\d+%\\) 2\\.0g \\(5\\.1%\\) 3\\.5g \\(\\d+\\.\\d+%\\) 1\\.0g 670mg/:
- cell " Meal Totals":
- strong:  Meal Totals
- cell "-"
- cell /\\d+/
- cell /\\d+\\.0g \\(\\d+\\.\\d+%\\)/
- cell "2.0g (5.1%)"
- cell /3\\.5g \\(\\d+\\.\\d+%\\)/
- cell "1.0g"
- cell "670mg"
- strong: "Net Carbs:"
- text: 1.0g
- strong: "Sugar:"
- text: 0.0g
- strong: "Calcium:"
- text: 450mg
- strong: "Ratio:"
- text: /\\d+\\.\\d+:5\\.1:\\d+\\.\\d+  Seabass - SDZ - Custom \\(Snack 1\\) \\d+ cal/
- table:
- rowgroup:
- row "Food Item Serving Cal Protein Carbs Fat Fiber Sodium":
- cell "Food Item"
- cell "Serving"
- cell "Cal"
- cell "Protein"
- cell "Carbs"
- cell "Fat"
- cell "Fiber"
- cell "Sodium"
- rowgroup:
- row /Seabass Cooked \\d+\\.0g \\d+ \\d+\\.4g 0\\.0g 3\\.9g 0\\.0g 130mg/:
- cell "Seabass Cooked"
- cell /\\d+\\.0g/
- cell /\\d+/
- cell /\\d+\\.4g/
- cell "0.0g"
- cell "3.9g"
- cell "0.0g"
- cell "130mg"
- row /Asparagus \\d+\\.0g \\d+ 3\\.5g 5\\.9g 0\\.3g 2\\.9g 20mg/:
- cell "Asparagus"
- cell /\\d+\\.0g/
- cell /\\d+/
- cell "3.5g"
- cell "5.9g"
- cell "0.3g"
- cell "2.9g"
- cell "20mg"
- row "Garlic Clove 5.0g 5 0.0g 1.2g 0.0g 0.0g 0mg":
- cell "Garlic Clove"
- cell "5.0g"
- cell "5"
- cell "0.0g"
- cell "1.2g"
- cell "0.0g"
- cell "0.0g"
- cell "0mg"
- row / Meal Totals - \\d+ \\d+\\.9g \\(\\d+\\.\\d+%\\) 7\\.2g \\(\\d+\\.\\d+%\\) 4\\.2g \\(\\d+\\.\\d+%\\) 2\\.9g 151mg/:
- cell " Meal Totals":
- strong:  Meal Totals
- cell "-"
- cell /\\d+/
- cell /\\d+\\.9g \\(\\d+\\.\\d+%\\)/
- cell /7\\.2g \\(\\d+\\.\\d+%\\)/
- cell /4\\.2g \\(\\d+\\.\\d+%\\)/
- cell "2.9g"
- cell "151mg"
- strong: "Net Carbs:"
- text: 4.3g
- strong: "Sugar:"
- text: 0.0g
- strong: "Calcium:"
- text: 3mg
- strong: "Ratio:"
- text: /\\d+\\.\\d+:\\d+\\.\\d+:\\d+\\.\\d+/
- heading / Daily Totals - \\d+ Total Calories/ [level=5]
- table:
- rowgroup:
- row "Calories Protein Carbs Fat Fiber Net Carbs Sodium Calcium":
- cell "Calories"
- cell "Protein"
- cell "Carbs"
- cell "Fat"
- cell "Fiber"
- cell "Net Carbs"
- cell "Sodium"
- cell "Calcium"
- rowgroup:
- row /\\d+ \\d+\\.6g \\(\\d+\\.\\d+%\\) \\d+\\.3g \\(\\d+\\.\\d+%\\) \\d+\\.0g \\(\\d+\\.\\d+%\\) \\d+\\.8g \\d+\\.6g 1665mg 536mg/:
- cell /\\d+/
- cell /\\d+\\.6g \\(\\d+\\.\\d+%\\)/
- cell /\\d+\\.3g \\(\\d+\\.\\d+%\\)/
- cell /\\d+\\.0g \\(\\d+\\.\\d+%\\)/
- cell /\\d+\\.8g/
- cell /\\d+\\.6g/
- cell "1665mg"
- cell "536mg"
- strong: "Daily Macro Ratio:"
- text: "/\\\\d+\\\\.\\\\d+% Protein : \\\\d+\\\\.\\\\d+% Carbs : \\\\d+\\\\.\\\\d+% Fat/"
`);
});

View File

@@ -0,0 +1,21 @@
const { test, expect } = require('@playwright/test');
test('reset tracker page', async ({ page }) => {
await page.goto('/tracker');
// Add a meal to ensure there is something to reset
await page.locator('.btn.btn-sm').first().click();
await page.locator('select[name="meal_id"]').selectOption('3');
await page.getByRole('button', { name: 'Add Meal', exact: true }).click();
await expect(page.locator('#meals-breakfast').getByText('Protein Shake - Pea - SDZ')).toBeVisible();
// Confirm the dialog
page.on('dialog', dialog => dialog.accept());
// Click the reset button
await page.getByRole('button', { name: 'Reset Page' }).click();
// The meal should no longer be visible
await expect(page.locator('#meals-breakfast').getByText('No meals tracked')).toBeVisible();
});

View File

@@ -0,0 +1,52 @@
const { test, expect } = require('@playwright/test');
test('create food', async ({ page }) => {
await page.goto('/foods');
// Create a new food
await page.getByRole('button', { name: ' Add New Food' }).click();
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="name"]').fill('TESTFOOD');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="name"]').press('Tab');
await page.getByRole('textbox', { name: 'Optional' }).press('Tab');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="serving_size"]').fill('100');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="serving_size"]').press('Tab');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="serving_unit"]').fill('g');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="serving_unit"]').press('Tab');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="calories"]').fill('1');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="calories"]').press('Tab');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="protein"]').fill('1');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="protein"]').press('Tab');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="carbs"]').fill('1');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="carbs"]').press('Tab');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="fat"]').fill('2');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="fat"]').press('Tab');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="fiber"]').fill('2');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="fiber"]').press('Tab');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="sugar"]').fill('4');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="sugar"]').press('Tab');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="sodium"]').fill('5');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="sodium"]').press('Tab');
await page.getByRole('dialog', { name: 'Add New Food' }).locator('input[name="calcium"]').fill('5');
await page.getByRole('button', { name: 'Add Food' }).click();
// Verify the food was created
const newFoodRow = page.getByRole('row').filter({ hasText: 'TESTFOOD' });
await expect(newFoodRow).toBeVisible();
await page.getByRole('row', { name: 'TESTFOOD 100.0 g 1.00 1.00g 1' }).getByRole('button').click();
await page.locator('#edit_serving_size').click();
await page.locator('#edit_serving_size').fill('200');
await page.getByRole('button', { name: 'Update Food' }).click();
//delete it
await page.getByRole('row', { name: 'TESTFOOD 200.0 g 1.00 1.00g 1' }).getByRole('checkbox').check();
// Set up dialog handler BEFORE clicking delete
page.on('dialog', async dialog => {
console.log(`Dialog message: ${dialog.message()}`);
await dialog.accept(); // or dialog.dismiss()
});
await page.getByRole('button', { name: ' Delete Selected Foods' }).click();
await expect(page.getByRole('row', { name: /Test Food/ })).not.toBeVisible();
});