Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
8ae7c73
feat: add promo code discovery with usePromoCode hook
gcutrini Apr 23, 2026
faac5ad
test: add unit tests for usePromoCode hook
gcutrini Apr 23, 2026
acd1cea
test: add e2e tests with Playwright route interception
gcutrini Apr 23, 2026
d29c5e8
fix: use i18n keys for promo discovery labels
gcutrini Apr 23, 2026
2da0a76
fix: re-validate manual promo codes on Next with final quantity
gcutrini Apr 23, 2026
48d7659
fix: add error handling for discovered code re-validation
gcutrini Apr 23, 2026
fdc7253
fix: dismiss suggestion when input is cleared
gcutrini Apr 23, 2026
d857037
fix: return null on discovery error
gcutrini Apr 23, 2026
f31c629
test: add tests for error handling in onTicketSelected and input clea…
gcutrini Apr 23, 2026
b8005dc
fix: extract canApply guard for Enter key and Apply button
gcutrini Apr 23, 2026
a0088af
fix: clamp quantity when maxQuantity is zero
gcutrini Apr 23, 2026
6e040a0
fix: use nullish coalescing in getTicketMaxQuantity
gcutrini Apr 23, 2026
ce82d27
fix: use i18n for validation error messages and add fallback
gcutrini Apr 23, 2026
32f145a
test: add assertions to empty test and init i18n in test setup
gcutrini Apr 23, 2026
946f177
chore(ci): add e2e integration (#142)
smarcet Apr 27, 2026
2c11e71
fix: suppress auto-apply when multiple codes are returned
gcutrini May 11, 2026
a28f322
merge: resolve conflict with main in personal-information tests
gcutrini May 11, 2026
8a5cf81
fix: await page.route() calls in e2e tests
gcutrini May 12, 2026
e382b7f
fix: allow ticket dropdown to clear when ticket types become empty
gcutrini May 13, 2026
ce73e2d
feat: early auto-apply for WithPromoCode-only ticket types
gcutrini May 13, 2026
033c1aa
feat: hide ticket selector when no tickets, show notice instead
gcutrini May 13, 2026
521e7bd
fix: promo code input shows checkmark when applied, fix disabled text…
gcutrini May 13, 2026
bb5c05b
fix: fallback background for applied promo input on host sites withou…
gcutrini May 14, 2026
0d4c567
style: use PromoCodeNotice for no-tickets-available to match other no…
gcutrini May 14, 2026
b59a026
fix: !important on applied promo input styles to beat host global inp…
gcutrini May 14, 2026
8a38e6e
fix: detect invalid promo code applied without a ticket selected
gcutrini May 14, 2026
8c7aed7
fix: hide empty ticket dropdown when applied code yields zero tickets
gcutrini May 14, 2026
71e2eeb
fix: show spinner during APPLYING and use 'Applying promo code...' label
gcutrini May 14, 2026
4beda6d
refactor: consolidate promo code error state into a single computed v…
gcutrini May 14, 2026
72eb58c
refactor: extract tryAutoApply helper used by both auto-apply call sites
gcutrini May 14, 2026
d22673c
refactor: move unapplied-code warning out of the promo hook
gcutrini May 14, 2026
2ab17d8
fix: don't clear form errors on promo code change
gcutrini May 14, 2026
6f743a3
feat: make 'no tickets available' message configurable via prop
gcutrini May 14, 2026
b28c4b2
fix: align CI Node version with .nvmrc, stop widgetLoading on revalid…
gcutrini May 14, 2026
a0e9675
fix: address CodeRabbit nitpicks on cap symmetry, error coercion, i18…
gcutrini May 14, 2026
cddf6bc
fix: include quantity in clamp effect deps and default promo to {}
gcutrini May 14, 2026
22dd46b
test(e2e): fix no-tickets selector to match actual i18n wording
gcutrini May 14, 2026
b4b1baa
refactor: surface auto-apply errors, rename isApplied->isLocked, expa…
gcutrini May 14, 2026
f4342a7
refactor: reshape usePromoCode contract for clarity
gcutrini May 15, 2026
7f4d781
feat: TicketNotice with stacked messages + per-order limit line
gcutrini May 15, 2026
7882a01
style: hide 'Have multiple promo codes?' link on mobile (<=540px)
gcutrini May 15, 2026
dc424e3
fix(usePromoCode): surface manual onApply errors consistently with au…
gcutrini May 18, 2026
e6b2886
fix(ticket-type): clamp quantity to 0 when cap is below minQuantity
gcutrini May 18, 2026
4819073
refactor(ticket-step): centralize ticket selection validity
gcutrini May 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: CI

on:
push:
branches: [main]
pull_request:

jobs:
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: yarn
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Run unit tests
run: yarn test:ci

e2e-tests:
name: E2E Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: yarn

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Install Playwright Chromium
run: npx playwright install chromium

- name: Run E2E tests
run: yarn test:e2e

- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report/
retention-days: 14
84 changes: 84 additions & 0 deletions e2e/fixtures.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* Mock API response factories for e2e tests.
* Each factory returns a response body matching the API contract.
*/

const ticketType = (overrides = {}) => ({
id: 188,
name: 'Early Bird Ticket',
cost: 700,
currency: 'USD',
currency_symbol: '$',
quantity_2_sell: 1000,
quantity_sold: 0,
max_quantity_per_order: 10,
sales_start_date: null,
sales_end_date: null,
sub_type: 'Regular',
audience: 'All',
badge_type: { id: 1, name: 'General', access_levels: [], badge_features: [] },
...overrides,
});

const discoveredCode = (overrides = {}) => ({
id: 100,
code: 'EARLYBIRD',
auto_apply: true,
allows_to_reassign: true,
quantity_per_account: 3,
remaining_quantity_per_account: 3,
quantity_available: 100,
quantity_used: 0,
class_name: 'DOMAIN_AUTHORIZED_DISCOUNT_CODE',
amount: 50,
rate: 0,
allowed_ticket_types: [188],
badge_features: [],
tags: [],
...overrides,
});

const discoveryResponse = (codes = []) => ({
total: codes.length,
per_page: codes.length,
current_page: 1,
last_page: 1,
data: codes,
});

const ticketTypesResponse = (tickets = []) => ({
total: tickets.length,
per_page: tickets.length,
current_page: 1,
last_page: 1,
data: tickets,
});

const taxTypesResponse = (taxes = []) => ({
total: taxes.length,
per_page: taxes.length,
current_page: 1,
last_page: 1,
data: taxes,
});

const validationResponse = (overrides = {}) => ({
allows_to_reassign: true,
...overrides,
});

const validationError = (message) => ({
message: 'Validation Failed',
errors: [message],
code: 0,
});

module.exports = {
ticketType,
discoveredCode,
discoveryResponse,
ticketTypesResponse,
taxTypesResponse,
validationResponse,
validationError,
};
Loading
Loading