test(e2e): add Playwright end-to-end tests and CI - #1
Merged
Conversation
Full venue-side schema, roles, permissions, and the publisher SPA at /manage.
- DocTypes: full Venue (7 new fields + gallery/exceptions/pricing child tables,
tab/column breaks) + Venue Resource category/sort_order; 3 new child DocTypes
- Venue Publisher role via pre-model-sync patch; become_publisher onboarding
- venue.py: unique-slug de-dupe, seed 7 weekday rows, publish/unpublish guards
- permissions.py: venue_query/venue_resource_query + has_permission, wired in hooks
- api/publisher.py: get_current_publisher, become_publisher, publish/unpublish
- SPA: /manage My Venues + venue editor (Details/Resources/Availability/Pricing/
Gallery/Publish); one www page serves /v and /manage
- Tests: slug uniqueness, publish guards, cross-publisher isolation (17 total green)
Deviations from spec (reconciled in specs/): publisher app at /manage not /app
(Desk collision); frappe-ui 0.1.278 uses confirmDialog + Dialog v-model; doc I/O
via imperative call('frappe.client.*'); publish wrappers accept str|int names.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Full pricing engine (additive surcharge loop over day-type + time-band) and slot engine gains exceptions (Closed / Special Hours override), midnight crossing, and past-slot filtering. Public API returns a guest-safe venue payload (gallery + details, no publisher/draft leak) and guards get_slots to Published venues + Active resources. Rebuilt public /v/:slug page into VenueHero + SlotGrid + SelectionCart with a client-side multi-slot cart spanning resources/dates; Book CTA carries the selection to a /v/:slug/book stub (real checkout is Phase 3). 13 new tests (30 total green); agent-browser e2e verifies weekend-evening price stacking, Closed/Special-Hours days, and the unpublished "not available" path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
End-to-end booking: select multiple slots, hold them together for 10 minutes, pay once through a mock gateway, get a Confirmed order that locks every slot. All-or-nothing on the slot_key unique index; lapsed holds are freed by a per-minute scheduler. - Booking.validate derives end_time + amount (pricing engine) + slot_key - BookingOrder.recompute_total / sync_status move order + lines together - hold_slots (validate, all-or-nothing, taken list), confirm_payment (guards), create_account_from_order, get_order - tasks.expire_holds (cron * * * * *) frees lapsed holds + fails payment - Checkout, MockGateway (10-min countdown), Confirmation pages + routes - 7 new tests (37 total green); agent-browser e2e green Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Completes the MVP with the three launch extras. Part A — Email confirmations: Booking Order on_update doc_event fires only on the real Held->Confirmed transition and enqueues one customer + one publisher email listing every slot; sending is best-effort so a mail outage never fails a paid booking. Part B — Reviews & ratings: new Venue Review DocType (Rating stored as a 0-1 fraction, booking unique), gated create_review (guest-allowed; Confirmed + owner + one-per-booking), and get_public_venue now returns avg_rating/review_count/ latest reviews. Frontend StarRating widget, venue-page review list, and a confirmation-page review form. Part C — Publisher dashboard: get_publisher_dashboard aggregates own-venue totals (today/week bookings, week/month revenue, upcoming, per-venue breakdown); Booking/Booking Order/Venue Review gain permission_query_conditions + has_permission scoping and Venue Publisher read perms; SPA /manage/dashboard and /manage/bookings (grouped-by-order + venue/status filters) with nav. 12 new tests (49 total green); agent-browser e2e verified. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rewrite the deferred grab-bag into ordered tracer-bullet sub-phases, each with goal/backend/frontend/tests/acceptance. Order: marketplace, My Bookings, notification channels first (no payment work); real payments then unblocks cancellation/refunds and monetization; per-resource schedules and hardening last. Update PROGRESS + README. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ralph.sh feeds prompt.md to Claude Code in a loop (implement thinnest next slice), then runs qa_prompt.md to review the last commit into REVIEWS.md; stops on 'complete'. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Public marketplace listing so customers discover venues beyond a shared link. - search_venues(city, q, start, page_length) + list_cities() (allow_guest, Published-only, card payload; text search over name/city; no publisher/draft leak) - home_page = "v" serves the SPA at the site root - Browse.vue (card grid + city filter + search) + browse/VenueCard.vue; router `/` - 4 new tests (53 total green); agent-browser e2e green Thinnest slice: city filter + text search live. category/date filters, pagination UI and a separate /search route deferred to the next widening. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Problem QA review of the marketplace browse slice flagged an N+1 review query with an unbounded page_length on a guest endpoint, a search box with no debounce and a stale-response race, a deprecated get_all param, and an unused currency field on the card. ## Solution - search_venues caps page_length at 50 and computes avg/count with one grouped _review_summaries query (Avg/Count GROUP BY venue) instead of a per-venue N+1 - get_all uses limit= (drops deprecated page_length=) - drop unused currency from the card payload - Browse.vue debounces the query watcher (300ms), loads city immediately, and drops stale responses via a monotonic token 9/9 test_public_api green; grouped avg verified live; frontend rebuilt. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Port hive's Playwright harness into apna_slot: root package.json + playwright.config.ts, e2e/ helpers and admin auth setup, an idempotent seed (apna_slot/e2e_seed.py) creating a Published venue + resource, a public-venue smoke spec, and a UI Tests GitHub Actions workflow that spins up a bench, seeds, starts the server, and runs the tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace boilerplate README with a full app README: table of contents, customer and publisher screenshots, how-it-works (slot locking, pricing, holds), data model, tech stack, structure, install/run/test and roadmap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fix Frappe Linter CI job: replace ambiguous unicode dashes in comments/docstrings/strings with ASCII, swap single-element slice for next(iter(...)) (RUF015), and apply ruff-format + prettier formatting across the app and frontend. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- get_order: guest confirmation endpoint reads its own order by id - e2e_seed commit: seed script run via `bench execute` must persist Both suppressed with `# nosemgrep` per frappe-semgrep-rules convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A `# nosemgrep: <text>` colon form is parsed as a rule-id list, so it suppressed nothing. Move the justification to the preceding line and keep a bare `# nosemgrep`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
NagariaHussain
added a commit
that referenced
this pull request
Jul 13, 2026
Address all 6 findings from the "My Bookings" QA review: - #1: add UI entry points — Browse header "My bookings" link when authenticated + "View my bookings" on the confirmation page - #2: batch venue/line/resource lookups (no N+1) + limit order fetch to 100 - #3: guard _first_slot against a line-less order (no min([]) 500) - #4: MyBookings.vue catches load failure → error state, not empty state - #5: drop the unused confirmed_on from the order payload - #6: add /my bare route rule + vue-router /my → /my/bookings redirect 4/4 customer API tests green, full app 57/57 green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why?
The Vue SPA has no automated end-to-end coverage — it's only checked manually. This ports the Playwright harness from the
hiveapp so booking/venue flows are tested in a real browser, in CI.What?
package.json+playwright.config.ts(Playwright,setup+chromiumprojects).e2e/— Frappe REST/auth helpers, admin auth setup, and apublic-venuesmoke spec (/v/e2e-arena).apna_slot/e2e_seed.py— idempotent seed: a Published venue + active resource..github/workflows/ui-tests.yml— spins up a bench, seeds, starts the server, runs the tests, uploads the report.How?
CI builds a site
apnaslot.test, runs the seed,bench start, thennpx playwright test. Browser reaches*.localhost/*.testvia Chromium--host-resolver-rules+ an/etc/hostsentry; Node API calls go to127.0.0.1with aHostheader. Verified locally: 2/2 passing.🤖 Generated with Claude Code