@owlmeans/web-payment 0.1.18-rc.2 → 0.1.18-rc.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -1
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/web-payment/SKILL.md +287 -20
- package/build/@/components/ui/card.d.ts +10 -0
- package/build/@/components/ui/card.d.ts.map +1 -0
- package/build/@/components/ui/card.js +25 -0
- package/build/@/components/ui/card.js.map +1 -0
- package/build/@/components/ui/checkbox.d.ts +5 -0
- package/build/@/components/ui/checkbox.d.ts.map +1 -0
- package/build/@/components/ui/checkbox.js +6 -0
- package/build/@/components/ui/checkbox.js.map +1 -0
- package/build/@/components/ui/progress.d.ts +5 -0
- package/build/@/components/ui/progress.d.ts.map +1 -0
- package/build/@/components/ui/progress.js +11 -0
- package/build/@/components/ui/progress.js.map +1 -0
- package/build/@/components/ui/select.d.ts +8 -0
- package/build/@/components/ui/select.d.ts.map +1 -0
- package/build/@/components/ui/select.js +9 -0
- package/build/@/components/ui/select.js.map +1 -0
- package/build/capability-list.d.ts +7 -0
- package/build/capability-list.d.ts.map +1 -0
- package/build/capability-list.js +24 -0
- package/build/capability-list.js.map +1 -0
- package/build/checkout-limit.d.ts +11 -0
- package/build/checkout-limit.d.ts.map +1 -0
- package/build/checkout-limit.js +34 -0
- package/build/checkout-limit.js.map +1 -0
- package/build/consumer/cancellation.d.ts +20 -0
- package/build/consumer/cancellation.d.ts.map +1 -0
- package/build/consumer/cancellation.js +115 -0
- package/build/consumer/cancellation.js.map +1 -0
- package/build/consumer/copy.d.ts +23 -0
- package/build/consumer/copy.d.ts.map +1 -0
- package/build/consumer/copy.js +75 -0
- package/build/consumer/copy.js.map +1 -0
- package/build/consumer/ensure.d.ts +56 -0
- package/build/consumer/ensure.d.ts.map +1 -0
- package/build/consumer/ensure.js +71 -0
- package/build/consumer/ensure.js.map +1 -0
- package/build/consumer/fields.d.ts +43 -0
- package/build/consumer/fields.d.ts.map +1 -0
- package/build/consumer/fields.js +19 -0
- package/build/consumer/fields.js.map +1 -0
- package/build/consumer/hooks.d.ts +113 -0
- package/build/consumer/hooks.d.ts.map +1 -0
- package/build/consumer/hooks.js +225 -0
- package/build/consumer/hooks.js.map +1 -0
- package/build/consumer/index.d.ts +14 -0
- package/build/consumer/index.d.ts.map +1 -0
- package/build/consumer/index.js +12 -0
- package/build/consumer/index.js.map +1 -0
- package/build/consumer/legal.d.ts +53 -0
- package/build/consumer/legal.d.ts.map +1 -0
- package/build/consumer/legal.js +77 -0
- package/build/consumer/legal.js.map +1 -0
- package/build/consumer/performance-consent-dialog.d.ts +18 -0
- package/build/consumer/performance-consent-dialog.d.ts.map +1 -0
- package/build/consumer/performance-consent-dialog.js +71 -0
- package/build/consumer/performance-consent-dialog.js.map +1 -0
- package/build/consumer/provider.d.ts +33 -0
- package/build/consumer/provider.d.ts.map +1 -0
- package/build/consumer/provider.js +26 -0
- package/build/consumer/provider.js.map +1 -0
- package/build/consumer/refusal.d.ts +35 -0
- package/build/consumer/refusal.d.ts.map +1 -0
- package/build/consumer/refusal.js +98 -0
- package/build/consumer/refusal.js.map +1 -0
- package/build/consumer/subscription-start-dialog.d.ts +16 -0
- package/build/consumer/subscription-start-dialog.d.ts.map +1 -0
- package/build/consumer/subscription-start-dialog.js +43 -0
- package/build/consumer/subscription-start-dialog.js.map +1 -0
- package/build/consumer/types.d.ts +114 -0
- package/build/consumer/types.d.ts.map +1 -0
- package/build/consumer/types.js +2 -0
- package/build/consumer/types.js.map +1 -0
- package/build/consumer/withdrawal.d.ts +29 -0
- package/build/consumer/withdrawal.d.ts.map +1 -0
- package/build/consumer/withdrawal.js +140 -0
- package/build/consumer/withdrawal.js.map +1 -0
- package/build/copy.d.ts +14 -0
- package/build/copy.d.ts.map +1 -0
- package/build/copy.js +51 -0
- package/build/copy.js.map +1 -0
- package/build/dialog.d.ts +1 -1
- package/build/dialog.d.ts.map +1 -1
- package/build/dialog.js +46 -17
- package/build/dialog.js.map +1 -1
- package/build/entitlement.d.ts +26 -0
- package/build/entitlement.d.ts.map +1 -0
- package/build/entitlement.js +42 -0
- package/build/entitlement.js.map +1 -0
- package/build/estimate-cache.d.ts +14 -0
- package/build/estimate-cache.d.ts.map +1 -0
- package/build/estimate-cache.js +39 -0
- package/build/estimate-cache.js.map +1 -0
- package/build/estimate-summary.d.ts +64 -0
- package/build/estimate-summary.d.ts.map +1 -0
- package/build/estimate-summary.js +94 -0
- package/build/estimate-summary.js.map +1 -0
- package/build/estimate.d.ts +34 -0
- package/build/estimate.d.ts.map +1 -0
- package/build/estimate.js +92 -0
- package/build/estimate.js.map +1 -0
- package/build/format.d.ts +15 -0
- package/build/format.d.ts.map +1 -0
- package/build/format.js +68 -0
- package/build/format.js.map +1 -0
- package/build/hooks.d.ts +0 -4
- package/build/hooks.d.ts.map +1 -1
- package/build/hooks.js +3 -30
- package/build/hooks.js.map +1 -1
- package/build/i18n/be.json +1 -1
- package/build/i18n/de.json +1 -1
- package/build/i18n/en.json +1 -1
- package/build/i18n/es.json +1 -1
- package/build/i18n/fr.json +145 -0
- package/build/i18n/pl.json +1 -1
- package/build/i18n/ru.json +1 -1
- package/build/i18n/uk.json +1 -1
- package/build/i18n.d.ts +2 -1
- package/build/i18n.d.ts.map +1 -1
- package/build/i18n.js +11 -7
- package/build/i18n.js.map +1 -1
- package/build/index.d.ts +9 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +9 -0
- package/build/index.js.map +1 -1
- package/build/limit-meter.d.ts +7 -0
- package/build/limit-meter.d.ts.map +1 -0
- package/build/limit-meter.js +26 -0
- package/build/limit-meter.js.map +1 -0
- package/build/plan-card.d.ts +7 -0
- package/build/plan-card.d.ts.map +1 -0
- package/build/plan-card.js +29 -0
- package/build/plan-card.js.map +1 -0
- package/build/poll.d.ts +7 -0
- package/build/poll.d.ts.map +1 -0
- package/build/poll.js +28 -0
- package/build/poll.js.map +1 -0
- package/build/selectors.d.ts +18 -0
- package/build/selectors.d.ts.map +1 -0
- package/build/selectors.js +78 -0
- package/build/selectors.js.map +1 -0
- package/build/types.d.ts +120 -2
- package/build/types.d.ts.map +1 -1
- package/package.json +22 -7
- package/src/@/components/ui/card.tsx +93 -0
- package/src/@/components/ui/checkbox.tsx +23 -0
- package/src/@/components/ui/progress.tsx +44 -0
- package/src/@/components/ui/select.tsx +62 -0
- package/src/@/globals.css +10 -0
- package/src/capability-list.tsx +50 -0
- package/src/checkout-limit.tsx +48 -0
- package/src/consumer/cancellation.tsx +214 -0
- package/src/consumer/copy.ts +93 -0
- package/src/consumer/ensure.ts +124 -0
- package/src/consumer/fields.tsx +89 -0
- package/src/consumer/hooks.ts +358 -0
- package/src/consumer/index.ts +13 -0
- package/src/consumer/legal.tsx +129 -0
- package/src/consumer/performance-consent-dialog.tsx +132 -0
- package/src/consumer/provider.tsx +49 -0
- package/src/consumer/refusal.ts +110 -0
- package/src/consumer/subscription-start-dialog.tsx +87 -0
- package/src/consumer/types.ts +121 -0
- package/src/consumer/withdrawal.tsx +279 -0
- package/src/copy.tsx +62 -0
- package/src/dialog.tsx +58 -25
- package/src/entitlement.ts +56 -0
- package/src/estimate-cache.ts +40 -0
- package/src/estimate-summary.tsx +172 -0
- package/src/estimate.ts +119 -0
- package/src/format.ts +71 -0
- package/src/hooks.ts +3 -35
- package/src/i18n/be.json +1 -1
- package/src/i18n/de.json +1 -1
- package/src/i18n/en.json +1 -1
- package/src/i18n/es.json +1 -1
- package/src/i18n/fr.json +145 -0
- package/src/i18n/pl.json +1 -1
- package/src/i18n/ru.json +1 -1
- package/src/i18n/uk.json +1 -1
- package/src/i18n.ts +12 -7
- package/src/index.ts +9 -0
- package/src/limit-meter.tsx +55 -0
- package/src/plan-card.tsx +67 -0
- package/src/poll.ts +27 -0
- package/src/selectors.ts +93 -0
- package/src/types.ts +142 -2
- package/tests/consent-refusal.spec.ts +83 -0
- package/tests/consumer-hooks.spec.ts +205 -0
- package/tests/consumer.spec.ts +343 -0
- package/tests/context.ts +9 -0
- package/tests/dialog.spec.ts +49 -0
- package/tests/entitlement.spec.ts +117 -0
- package/tests/estimate-cache.spec.ts +46 -0
- package/tests/harness/consumer-fixtures.ts +105 -0
- package/tests/harness/consumer.tsx +197 -0
- package/tests/harness/entitlement.tsx +159 -0
- package/tests/harness/estimate-fixtures.ts +48 -0
- package/tests/harness/mount.tsx +19 -3
- package/tests/i18n.spec.ts +78 -8
- package/tests/pieces.spec.ts +134 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { afterAll, describe, expect, test } from 'bun:test'
|
|
2
|
+
import { closeBrowser, mountComponent, type Page } from '@owlmeans/test-ui'
|
|
3
|
+
import { closeHarness, harnessUrl } from './context.js'
|
|
4
|
+
|
|
5
|
+
const TIMEOUT = 60_000
|
|
6
|
+
|
|
7
|
+
afterAll(async () => {
|
|
8
|
+
await closeBrowser()
|
|
9
|
+
await closeHarness()
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const open = async (scenario: string) => {
|
|
13
|
+
const mounted = await mountComponent({ url: `${await harnessUrl()}?case=${scenario}` })
|
|
14
|
+
await mounted.page.locator('main').waitFor()
|
|
15
|
+
return mounted
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const text = async (page: Page, selector: string): Promise<string> =>
|
|
19
|
+
(await page.locator(selector).innerText()).replace(/\s+/g, ' ').trim()
|
|
20
|
+
|
|
21
|
+
describe('PlanCard', () => {
|
|
22
|
+
test('writes the status line of every plan state', async () => {
|
|
23
|
+
const { page, close } = await open('pieces')
|
|
24
|
+
try {
|
|
25
|
+
const line = (name: string) => text(page, `[data-case="${name}"] [data-plan-status-line]`)
|
|
26
|
+
expect(await line('renews')).toBe('Renews on Oct 16, 2026')
|
|
27
|
+
expect(await line('trial')).toBe('Trial ends on Sep 30, 2026')
|
|
28
|
+
expect(await line('past-due')).toBe('Payment past due')
|
|
29
|
+
expect(await line('cancel-scheduled')).toBe('Cancels on Oct 16, 2026')
|
|
30
|
+
expect(await line('paused')).toBe('Paused since Sep 1, 2026')
|
|
31
|
+
expect(await line('free')).toBe('Free plan')
|
|
32
|
+
expect(await line('active')).toBe('Active')
|
|
33
|
+
expect(await page.locator('[data-case="past-due"] [data-plan-card]').getAttribute('data-plan-tone')).toBe('warning')
|
|
34
|
+
} finally { await close() }
|
|
35
|
+
}, TIMEOUT)
|
|
36
|
+
|
|
37
|
+
test('renders an offer with its price, marks the current plan, and reports the action', async () => {
|
|
38
|
+
const { page, close } = await open('pieces')
|
|
39
|
+
try {
|
|
40
|
+
const current = page.locator('[data-case="offer-current"] [data-plan-card]')
|
|
41
|
+
expect(await current.getAttribute('data-current')).toBe('true')
|
|
42
|
+
expect(await text(page, '[data-case="offer-current"] [data-plan-current]')).toBe('Current plan')
|
|
43
|
+
expect(await text(page, '[data-case="offer-current"] [data-plan-status-line]')).toBe('Free plan')
|
|
44
|
+
|
|
45
|
+
const upgrade = page.locator('[data-case="offer-upgrade"] [data-plan-card]')
|
|
46
|
+
expect(await upgrade.getAttribute('data-plan-sku')).toBe('pro-monthly')
|
|
47
|
+
expect(await upgrade.getAttribute('data-current')).toBeNull()
|
|
48
|
+
expect(await upgrade.locator('[data-plan-status-line]').count()).toBe(0)
|
|
49
|
+
expect(await text(page, '[data-case="offer-upgrade"] [data-plan-price]')).toBe('$20 / month')
|
|
50
|
+
expect(await upgrade.innerText()).toContain('Everything in Free, and more.')
|
|
51
|
+
|
|
52
|
+
expect(await page.locator('[data-case="offer-pending"] button').isDisabled()).toBe(true)
|
|
53
|
+
await upgrade.getByRole('button', { name: 'Upgrade' }).click()
|
|
54
|
+
expect(await page.locator('#acted').textContent()).toBe('pro-monthly')
|
|
55
|
+
} finally { await close() }
|
|
56
|
+
}, TIMEOUT)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
describe('LimitMeter and CapabilityList', () => {
|
|
60
|
+
test('meter usage, resets, exhaustion, "not included" and promos', async () => {
|
|
61
|
+
const { page, close } = await open('pieces')
|
|
62
|
+
try {
|
|
63
|
+
const meter = (key: string) => page.locator(`[data-case="limits"] > [data-limit-key="${key}"]`)
|
|
64
|
+
expect(await text(page, '[data-case="limits"] > [data-limit-key="seats"] [data-limit-usage]')).toBe('3 of 5')
|
|
65
|
+
expect(await meter('seats').getByRole('progressbar', { name: 'Seats' }).getAttribute('aria-valuenow')).toBe('60')
|
|
66
|
+
expect(await text(page, '[data-case="limits"] > [data-limit-key="seats"] [data-limit-resets]')).toBe('Resets on Oct 1, 2026')
|
|
67
|
+
|
|
68
|
+
expect(await meter('exports').getAttribute('data-exhausted')).toBe('true')
|
|
69
|
+
expect(await meter('exports').innerText()).toContain('Limit reached')
|
|
70
|
+
expect(await meter('exports').innerText()).toContain('Resets on Sep 17, 2026')
|
|
71
|
+
|
|
72
|
+
expect(await text(page, '[data-case="limits"] > [data-limit-key="projects"] [data-limit-usage]')).toBe('Not included')
|
|
73
|
+
expect(await meter('projects').getByRole('progressbar').count()).toBe(0)
|
|
74
|
+
expect(await meter('projects').locator('[data-limit-resets]').count()).toBe(0)
|
|
75
|
+
|
|
76
|
+
expect(await text(page, '[data-case="limits"] > [data-limit-key="sites"] [data-promo]')).toBe('Free until Dec 31, 2026')
|
|
77
|
+
expect(await page.locator('[data-case="no-reset"] [data-limit-resets]').count()).toBe(0)
|
|
78
|
+
} finally { await close() }
|
|
79
|
+
}, TIMEOUT)
|
|
80
|
+
|
|
81
|
+
test('list labelled capabilities with their promo inscriptions and skip the rest', async () => {
|
|
82
|
+
const { page, close } = await open('pieces')
|
|
83
|
+
try {
|
|
84
|
+
const rows = page.locator('[data-case="capabilities"] [data-capability]')
|
|
85
|
+
expect(await rows.evaluateAll(items => items.map(item => item.getAttribute('data-capability'))))
|
|
86
|
+
.toEqual(['feature:whitelabel', 'feature:local-llm', 'feature:conversions', 'feature:beta'])
|
|
87
|
+
const promo = (param: string) => text(page, `[data-case="capabilities"] [data-capability="${param}"] [data-promo]`)
|
|
88
|
+
expect(await promo('feature:local-llm')).toBe('Free until Dec 31, 2026')
|
|
89
|
+
expect(await promo('feature:conversions')).toBe('Included for your plan')
|
|
90
|
+
expect(await promo('feature:beta')).toBe('Promotion ended')
|
|
91
|
+
expect(await page.locator('[data-case="capabilities"] [data-capability="feature:beta"]').getAttribute('data-granted'))
|
|
92
|
+
.toBe('false')
|
|
93
|
+
expect(await page.locator('[data-capability="feature:custom-domain"]').count()).toBe(0)
|
|
94
|
+
expect(await page.locator('[data-case="only-granted"] [data-capability]').count()).toBe(3)
|
|
95
|
+
expect(await page.locator('[data-case="only-granted"] [data-capability="feature:beta"]').count()).toBe(0)
|
|
96
|
+
} finally { await close() }
|
|
97
|
+
}, TIMEOUT)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
describe('CountrySelect + PriceEstimateAmount — one country, several controlled estimates', () => {
|
|
101
|
+
test('changing the one country picker refetches and re-renders every estimate that shares it', async () => {
|
|
102
|
+
const { page, close } = await open('shared-estimate')
|
|
103
|
+
try {
|
|
104
|
+
await page.locator('[data-case="pro"] [data-price-estimate]').waitFor()
|
|
105
|
+
expect(await page.locator('[data-case="pro"] [data-price-estimate]').getAttribute('data-status')).toBe('location-required')
|
|
106
|
+
expect(await page.locator('[data-case="team"] [data-price-estimate]').getAttribute('data-status')).toBe('location-required')
|
|
107
|
+
|
|
108
|
+
await page.getByLabel('Billing country').click()
|
|
109
|
+
// A raw DOM click: this minimal harness page is too short for Radix's own collision-aware
|
|
110
|
+
// placement, so Playwright's viewport-bound click never lands — the dialog spec covers the
|
|
111
|
+
// same option in a real, taller layout with an ordinary click.
|
|
112
|
+
await page.getByRole('option', { name: 'Poland' }).evaluate(el => (el as HTMLElement).click())
|
|
113
|
+
|
|
114
|
+
await page.locator('[data-case="pro"] [data-status="taxed"]').waitFor()
|
|
115
|
+
await page.locator('[data-case="team"] [data-status="taxed"]').waitFor()
|
|
116
|
+
expect(await text(page, '[data-case="pro"] [data-estimate-total]')).toContain('$24.60')
|
|
117
|
+
expect(await text(page, '[data-case="team"] [data-estimate-total]')).toContain('$61.50')
|
|
118
|
+
} finally { await close() }
|
|
119
|
+
}, TIMEOUT)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
describe('useEntitlementView', () => {
|
|
123
|
+
test('answers null until the protocol answers, then renders the revived wire view', async () => {
|
|
124
|
+
const { page, close } = await open('hook')
|
|
125
|
+
try {
|
|
126
|
+
expect(await page.locator('#capability').textContent()).toBe('null')
|
|
127
|
+
await page.locator('[data-plan-card]').waitFor()
|
|
128
|
+
expect(await page.locator('#capability').textContent()).toBe('true')
|
|
129
|
+
expect(await page.locator('#seats').textContent()).toBe('3/5:0.6')
|
|
130
|
+
expect(await text(page, '[data-plan-status-line]')).toBe('Renews on Oct 16, 2026')
|
|
131
|
+
expect(await text(page, '[data-limit-key="seats"] [data-limit-resets]')).toBe('Resets on Oct 1, 2026')
|
|
132
|
+
} finally { await close() }
|
|
133
|
+
}, TIMEOUT)
|
|
134
|
+
})
|