From fdfb0037c70754b45696c7870dcf055eb7efc485 Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Wed, 21 Oct 2026 13:53:58 +0000 Subject: [PATCH] feat(crawl): Buy a day pass checkout on the custom /crawl page The gateway hands the page renderer ctx.checkout once CoinPay serves hosted checkout sessions; the custom page now renders the same form the stock page does (email, days) posting to /crawl/checkout. Co-Authored-By: Claude Opus 5.5 --- apps/web/src/views/crawl.jsx | 35 +++++++++++++++++++++++++++++++ test/crawl-page-checkout.test.js | 36 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 test/crawl-page-checkout.test.js diff --git a/apps/web/src/views/crawl.jsx b/apps/web/src/views/crawl.jsx index 4d061ecd..12065449 100644 --- a/apps/web/src/views/crawl.jsx +++ b/apps/web/src/views/crawl.jsx @@ -90,6 +90,41 @@ export function CrawlPage(ctx) { + {ctx.checkout ? ( +
+

Pay with any coin or PayPal

+

Buy a day pass

+

+ {price} a {term}, paid through CoinPay's hosted checkout. The pass appears on the next + page and works with any HTTP client. +

+
+ + + + + + +
+

Checkout is hosted by CoinPay. Up to {maxDays} days at once.

+
+ ) : null}

Get started

Buy once. Send the pass with your requests.

diff --git a/test/crawl-page-checkout.test.js b/test/crawl-page-checkout.test.js new file mode 100644 index 00000000..497e5f6b --- /dev/null +++ b/test/crawl-page-checkout.test.js @@ -0,0 +1,36 @@ +import { expect, test } from 'bun:test'; + +process.env.DATABASE_URL ??= 'postgres://test:test@localhost:5432/test'; +process.env.SITE_URL ??= 'https://nichedb.test'; +const { renderCrawlPage } = await import('../apps/web/src/views/crawl.jsx'); + +const ctx = { + siteName: 'NicheDB', + siteUrl: 'https://nichedb.dev', + buyUrl: 'https://nichedb.dev/crawl', + price: '1.00 USD', + total: '1.00 USD', + minutes: 1440, + days: 1, + maxDays: 30, + header: 'x-crawl-pass', + enabled: true, + training: ['GPTBot'], + retrieval: ['OAI-SearchBot'], +}; + +test('the Buy a day pass form posts to the gateway checkout when CoinPay serves it', () => { + const html = renderCrawlPage({ + ...ctx, + checkout: { action: '/crawl/checkout', from: '/games', days: 1 }, + }); + expect(html).toContain('Buy a day pass'); + expect(html).toContain('action="/crawl/checkout"'); + expect(html).toContain('name="from" value="/games"'); + expect(html).toContain('name="email"'); +}); + +test('no form while checkout is unavailable', () => { + const html = renderCrawlPage({ ...ctx, checkout: null }); + expect(html).not.toContain('/crawl/checkout'); +});