A new recipes page at /recipes lets a cook paste a plain-text recipe… #6
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "osf/70-172-comparison-arm-single-scale-recipes"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What was done
/recipeslets a cook paste a plain-text recipe and have it read, scaled, unit-converted, and added to a shopping list./recipesagain starts it empty.How to review
npm test— the unit suite passes (141 tests), covering reading a recipe, scaling, unit conversion, the shopping list, the page, and the/recipesroutes.npm run test:e2e(runnpx playwright install chromiumonce first) — the browser tests pass, driving/recipesin a real chromium.npm startand open http://localhost:3000/recipes — the form loads with Metric chosen and "The shopping list is empty."Serves 2with a few ingredients (say200 g flour,a pinch of salt,2 eggs), set Servings to 4, choose US, and pressShow recipe— you get14 oz flourand4 eggs, withLine 3: a pinch of salt (no quantity)reported beside it.Add to list— the ingredients join a shopping list that adds up matching items by name across up to five recipes.src/pages.ts(the page) and the/recipesroutes insrc/server.tsfirst — that is where the form, the scaling and conversion, and the hidden-field list live.Code review
Reviewed the recipes change (src/recipe.ts, scale.ts, convert.ts, shopping.ts, the /recipes routes in src/server.ts, the page in src/pages.ts, and all seven new test files) against the proposal, the five spec deltas, design.md and tasks.md. Every spec scenario is implemented and tested with the required tags; all output is HTML-escaped, including the hidden list fields (escapeHtml covers quotes, so a name cannot break out of the value attribute); the /recipes routes sit before the GET /
branch; conversion factors, ladder thresholds, rounding boundaries (9.96 oz -> 10 oz, 0.04 g -> 0.1 g, 0.05 tsp -> 1/4), the five-recipe cap, and the name/unit merge and sort order all match the specs. One deviation from the design contract was found and fixed: parseQuantity reused the whole-line regex with its trailing (\s(.*))? group, so it returned 2 for '2 eggs' instead of null as design.md and task 1.1 require; it now uses a strict quantity-only regex while parseIngredientLine keeps the whole-line one, and test/recipe.test.ts pins the new behaviour. npx tsc --noEmit is clean and the narrowed vitest run for the touched file passes; openspec validate scale-recipes-and-shopping-list --strict is clean. No generated, cached, secret or scratch files in the commit set; the .osf records and the openspec change are left as-is.Fixed before the commit
src/recipe.ts:57: parseQuantity matched the whole-line QUANTITY regex, whose (?:\s(.*))? tail accepts trailing text, so parseQuantity('2 eggs') returned 2 instead of null, against the design.md / task 1.1 contract that anything other than a whole number, decimal, fraction or mixed number is null. Fixed by giving parseQuantity a strict quantity-only regex (the whole-line regex, renamed INGREDIENT_LINE, is kept for parseIngredientLine) and adding expect(parseQuantity('2 eggs')).toBeNull() to test/recipe.test.ts.Tests
All 47 scenarios of
scale-recipes-and-shopping-listhave a tagged test.The test lint found, in the run's tests on the last check:
Recorded, not decided
e2e/recipes.spec.ts:1B7: no relative import: this file asserts on things it constructed itself, which is the measured 'asserted on my own mock' failuretest/recipes-page.test.ts:1B7: nothing imported here looks like the module under test ('recipes-page')test/recipes-server.test.ts:1B7: nothing imported here looks like the module under test ('recipes-server')Braid run
scale-recipes-and-shopping-list(19 steps)941ea25544Opened by Braid.
Scale a recipe, convert its units, and build a shopping listto A new recipes page at/recipeslets a cook paste a plain-text recipe…941ea2554486a013816c