Guía de pruebas
Esta guía cubre los conjuntos de pruebas automatizadas, la infraestructura de pruebas local y las rutas de verificación manual.
Referencia rápida
npm run test:unit # Unit tests (Vitest) — ~700ms
npm run test:unit:watch # Watch mode
npm run test:unit:coverage # With coverage report
npm run test:secrets # Secret exposure audit for local env files
npm run test:premerge # Merge-readiness checks for changed Worker logic
npm run test:e2e # E2E tests (Playwright) — fully automated browser coverage
npm run test:e2e:headless # CI mode
npm run test:e2e:headless:podman # Automated browser suite with Playwright in Podman
npm run test:e2e:parity # First-party critical-path browser flows
npx playwright test tests/e2e/admin-dashboard.spec.ts --project=chromium # Focused admin dashboard browser suite
npm run podman:doctor # Cross-platform Podman readiness check
npm run test:security # Security pen tests (Worker must be running)
npm run test:security:podman # Security pen tests with a one-shot Podman-backed stack
npm run test:security:staging # Security tests against a staging worker, if you maintain one
npm run media:optimize:check # Check dashboard-uploaded media for pending optimization/responsive variants/derivatives
npm run media:optimize:check:podman # Same media check inside the Podman toolchain
./scripts/test-checkout.sh --podman # Manual checkout helper against the Podman stack
./scripts/test-e2e.sh --podman # Automated browser helper against the Podman stack
npm run test:usps # Live USPS credential + quote sanity check
npm test # Run all tests
./scripts/test-e2e.sh --podman es ahora la ruta del navegador totalmente automatizada. Utilice ./scripts/test-checkout.sh --podman cuando desee específicamente realizar el pago manualmente en un navegador real.
La ruta de prueba del trabajador local ahora prefiere el nodo 24, que coincide con las acciones de GitHub. Los scripts del host recurren al Nodo 22 si una bifurcación lo tiene instalado, pero ya no fuerzan el Nodo 20 porque Wrangler 4 requiere el Nodo 22 o posterior.
Para la sección del navegador centrada en la accesibilidad, utilice:
./scripts/podman-playwright-run.sh npx playwright test \
tests/e2e/accessibility-public-pages.spec.ts \
tests/e2e/manage-flows.spec.ts \
tests/e2e/community-flows.spec.ts \
tests/e2e/public-page-controls.spec.ts \
tests/e2e/campaign-checkout.spec.ts \
--project=chromium \
--grep "Public Page Accessibility|keyboard-only|Community Flows|Public Page Keyboard Controls"
Si desea solo el barrido de regresión de accesibilidad pública y no desea depender del host Ruby/Bundler, prefiera la ruta respaldada por Podman:
npm run test:e2e:headless:podman -- tests/e2e/accessibility-public-pages.spec.ts --project=chromium
Pruebas unitarias (Vitest)
Pruebas rápidas y aisladas para funciones JS en tests/unit/.
Cobertura
| Módulo | Funciones probadas |
|---|---|
live-stats.js |
formatMoney, updateProgressBar, updateMarkerState, checkTierUnlocks, checkLateSupport, updateSupportItems, updateTierInventory |
platform-tip |
Desinfección de propinas, derivación del porcentaje de propinas, cálculo del monto de la propina |
pledge-management |
Cumplimiento de plazos según el horario de verano a través de la zona horaria configurada de la plataforma, cancelación/modificación/validación del método de pago, transiciones de estado de compromiso, independencia de múltiples campañas, envío en registros de compromiso, forma de respuesta API |
settlement |
Agregación de cargos (incluidas tarifas de envío), éxito o fracaso del pago, flujo de reintento, modo de prueba, casos extremos, liquidación por lotes, índice de compromiso de campaña, envío de liquidación, envío en liquidación, latido cron |
email-broadcasts |
Extracción de extractos del diario (con truncamiento de puntos suspensivos), ayudas de seguimiento del diario/hitos, lógica de verificación de hitos, limitación de velocidad |
email-tip |
Desgloses de correos electrónicos de soporte conscientes de las sugerencias en correos electrónicos de confirmación/modificados/cancelados/fallidos/cargados, además del enrutamiento de correos electrónicos de recordatorio de lanzamiento a través del remitente de actualizaciones compartidas |
votes |
Almacenamiento/descopia de votos basado en correo electrónico, recuperación del estado de los votos, resultados de campaña, agregación de resultados |
admin-dashboard |
Seguimiento del estado sucio del panel, serialización de configuraciones, normalización de contenido/editor, cargas de medios por etapas, análisis/relleno de tarifas reales de Stripe, ayudas de URL de referencia, utilidades de soporte responsivo/i18n |
campaign-page |
Construcción de URL de enlaces compartidos, preservación segura de consultas, texto compartido con reconocimiento de estado, envío de formularios de recordatorio de lanzamiento, controles de campañas públicas y comportamiento de la página de campaña sensible a SEO |
page-prefetch |
Listas permitidas de rutas públicas del mismo origen, exclusiones de consultas confidenciales, protecciones de red, manejo de retrasos/límites y creación de sugerencias de captación previa de documentos |
cart-runtime-loader |
Arranque diferido en tiempo de ejecución del carrito, detección de carrito persistente/de recuperación, carga idempotente y activadores de intención del usuario |
site-asset-minification |
Comportamiento de minificación CSS/JS generado _site y casos de falla del modo de verificación |
media-optimization-script |
Selección de archivos modificados, decisiones de optimización de imágenes sin pérdidas, denominación de derivados de vídeo y reescritura de referencias de fuente a WebM |
Correr
npm run test:unit # Run once
npm run test:unit:watch # Watch mode for development
npm run test:unit:coverage # Generate coverage report
Runbook de regresión previo a la fusión
Úselo antes de fusionar ramas que toquen el pago, la lógica empresarial del trabajador, el cumplimiento o los flujos de transmisión.
Puerta automatizada
npm run test:premerge
Esto se ejecuta:
npm run test:secretspara verificar que los archivos env locales permanezcan ignorados y sus valores secretos no aparezcan en los archivos rastreados o en el historial de gitnode --checkpara los puntos de entrada de los trabajadores modificados- Suites de regresión enfocadas:
tests/unit/worker-business-logic.test.tstests/unit/worker-ops-integrity.test.tstests/unit/stats-pagination.test.tsEstas Worker suites cubren la validación del registro de recordatorio de lanzamiento, la supresión de cancelación de suscripción, la idempotencia de envío en cola y la ruta de envío de reenvío compartida.
- Regresiones del filtro de seguridad de contenido en
tests/unit/content-safety-filter.test.ts, incluidos esquemas de enlaces Markdown inseguros, espaciado de énfasis creado por el panel y validación estricta de URL incrustadas estructuradas - Cobertura de auditoría de contenido de campaña en
tests/unit/campaign-content-security.test.ts, incluido el subconjunto HTML en línea permitido y el rechazo de etiquetas sin procesar no permitidas. - Cobertura de serialización de inventario de niveles de objetos duraderos en
tests/unit/tier-inventory-do.test.ts - Guiones de humo locales contra la campaña mutable de solo prueba:
scripts/test-worker.shpara verificaciones de contrato de sitio/trabajador y verificación de/checkout-intent/startcon formato incorrectoscripts/smoke-pledge-management.shpara una cobertura de modificación/cancelación exitosa en la campaña mutable solo local, utilizando las respuestas de reconstrucción del administrador más verificaciones de deriva de proyección de solo lectura como fuente autorizada de estadísticas/inventario durante el humo. El script ahora rota sus IP de solicitud de administrador sintéticas durante esas llamadas de reconstrucción/verificación para que el limitador de velocidad de administrador real no cree un falso negativo en la activación de fusión local.
- Suite de unidad completa a través de
npm run test:unit - Paquete de seguridad a través de
npm run test:securitycontra un trabajador local iniciado automáticamente - Suite de seguridad respaldada por Podman a través de
npm run test:security:podmancuando desea que el sitio/pila de trabajo se inicie y se ejerza en la misma invocación. - Verificaciones de artefactos de compilación propios que ejecutan Jekyll, minimizan los activos CSS/JS
_sitegenerados y verifican que la salida minimizada no tenga ahorros restantes. - Rendimiento de páginas públicas y regresiones de uso compartido a través de cobertura de unidades para captación previa de intenciones, carga diferida en tiempo de ejecución del carrito, minificación de activos generados y comportamiento de enlaces compartidos de campañas.
- Dramaturgo sin cabeza E2E vía
npm run test:e2e:headless
El script previo a la fusión ahora inicia automáticamente Jekyll con _config.yml,_config.local.yml cuando es necesario, de modo que la campaña smoke-editable solo local esté disponible durante la activación de la fusión y el arnés Playwright use la misma configuración combinada localmente.
Esa puerta ahora intenta primero la ruta del host Bundler/Jekyll, incluido un intento único de bundle install cuando Bundler está presente pero faltan gemas. Mantiene el humo del trabajador del host más ligero, pero ejecuta el humo de compromiso mutable a través de la pila respaldada por Podman para que la ruta de modificación/cancelación con estado utilice un estado de servicio local aislado incluso cuando la ruta de compilación del host tiene éxito. Si la ruta Ruby del host aún no puede compilarse limpiamente, recurre a una compilación Jekyll respaldada por Podman más los asistentes de navegador/humo compatibles con Podman restantes en lugar de fallar solo en la configuración del host.
Para ejecuciones de navegadores sin cabeza, Playwright ahora construye un _site estático y sirve esa salida con un servidor HTTP liviano en lugar de usar jekyll serve, lo que mantiene las comprobaciones automatizadas del navegador más cercanas al diseño real de los activos publicados.
Esta rama ahora tiene como valor predeterminado la ruta de tiempo de ejecución/carro propio tanto en _config.yml como en _config.local.yml, y la ruta del navegador ya no admite el antiguo tiempo de ejecución del carro alojado.
El reciente refuerzo de seguridad que ahora cubre la puerta incluye:
- comportamiento de cierre fallido de
GET /pledgecuando existe un token de enlace mágico pero la fila de compromiso no - Neutralización del esquema de enlaces de Markdown en contenido de formato largo
- Validación de origen exacto para incrustaciones estructuradas (
spotify,youtube,vimeo) - reservas serializadas de inventario de nivel limitado al inicio del pago y confirmación en el momento de persistencia exitosa
- recordatorio de lanzamiento Verificación de torniquete, almacenamiento de registro deduplicado, supresión de cancelación de suscripción con alcance y envío idempotente
La optimización de medios está intencionalmente separada de la puerta previa a la fusión porque depende de herramientas nativas como FFmpeg y optimizadores de imágenes. Las cargas de imágenes/videos del panel solicitan el optimizador después de la confirmación, pero cuando una rama incluye medios agregados manualmente o necesita verificar las variantes generadas antes de fusionar, ejecute:
npm run media:optimize:check
npm run media:optimize:check:podman # use when host-native media tools are missing
Los valores predeterminados del trabajador local en worker/wrangler.toml ahora coinciden con la configuración propia. ./scripts/dev.sh --podman ahora genera automáticamente un CHECKOUT_INTENT_SECRET local en worker/.dev.vars si falta, por lo que los nuevos inicios de pago local no fallan al cerrarse en un secreto de desarrollo no inicializado.
Para trabajo local, prefiera ./scripts/dev.sh --podman. Inicia a Jekyll y al Trabajador en contenedores Podman desarraigados, preservando al mismo tiempo los mismos puertos y el estado local de Wrangler.
_config.local.yml ahora es una capa de solo anulación, no una segunda configuración base. Cuando cambie o agregue configuraciones de orientación hacia la bifurcación, prefiera _config.yml a menos que el valor realmente difiera solo en su máquina local.
Los scripts de ayuda del navegador admiten el mismo modo:
./scripts/test-checkout.sh --podman
./scripts/test-e2e.sh --podman
./scripts/test-worker.sh --podman
./scripts/smoke-pledge-management.sh --podman
./scripts/pledge-report.sh --podman --local
./scripts/fulfillment-report.sh --podman --local
Esos ayudantes todavía ejecutan Playwright y shell smoke logic en el host por ahora, pero primero inician el sitio y el Worker a través de la pila local compartida respaldada por Podman. Los scripts de informes ahora también se pueden ejecutar directamente a través del contenedor de trabajadores. Esto mantiene las pruebas y exportaciones locales más cerca de los límites del servicio similar a la producción sin forzar la configuración del host Ruby o Wrangler.
Para los comandos del lado del host que necesitan la pila respaldada por Podman pero que no deben depender de la persistencia de la pila separada en shells separados, use scripts/podman-stack-run.sh. npm run test:security:podman usa ese contenedor.
Para una ruta de navegador mayoritariamente independiente del host, npm run test:e2e:headless:podman ahora ejecuta la suite Playwright automatizada dentro de un contenedor Podman dedicado en la misma red de pod local que el sitio y el Worker.
La cobertura reciente del navegador también incluye aserciones de ventanas gráficas móviles dedicadas para:
- páginas de campaña y controles públicos secundarios
- Cajones de carrito/caja en tamaños de teléfono pequeños
- Administre la accesibilidad de la tarjeta de promesa y actualización en ventanas gráficas móviles cortas
- controles sin desbordamiento horizontal en las principales vías públicas y de gestión de promesas
La cobertura reciente de páginas públicas ahora también protege el Chrome de campaña más localizado, que incluye:
- Estados de carga/reproducción de vídeo heroico
- copia teaser de la comunidad de seguidores
- etiquetas de pestañas del diario y estados vacíos
- etiquetas de la fase de producción y copia de CTA
- etiquetas de accesibilidad de la galería
El conjunto de filtros de seguridad de contenido en tests/unit/content-safety-filter.test.ts también recurre a Podman cuando las gemas del host Bundler/Jekyll no están disponibles. En macOS, puede iniciar la máquina Podman como parte de ese respaldo.
El alcance actual de Podman es intencionalmente limitado:
- incluido: Jekyll, Worker,
worker/.dev.varslocal, estado de Wrangler local, reenvío CLI de Stripe de host opcional,test-checkout.sh,test-e2e.sh,test-worker.sh,smoke-pledge-management.sh,pledge-report.shyfulfillment-report.shcompatibles con Podman - También se incluye: Playwright sin cabeza en contenedores para el conjunto de navegadores automatizados.
- aún no incluido: un paso del navegador de pago manual interactivo en contenedores
Utilice docs/PODMAN.md para conocer la configuración exacta y las limitaciones actuales.
Si cambia pricing.sales_tax_rate o shipping.fallback_flat_rate en la configuración de Jekyll, el repositorio ahora sincroniza automáticamente los valores de Worker reflejados en worker/wrangler.toml a través de las rutas principales de desarrollo/prueba. Reinicie ./scripts/dev.sh --podman antes de probar las matemáticas de pago para que ambos servicios recojan los nuevos valores.
Si ajusta el comportamiento de lectura del plan gratuito, manténgalos sincronizados también:
cache.live_stats_ttl_secondscache.live_inventory_ttl_secondsperformance.intent_prefetch_enabledperformance.intent_prefetch_delay_msperformance.intent_prefetch_limit
Después de cambiar esos controles de rendimiento o caché localmente, reinicie ./scripts/dev.sh --podman y vuelva a ejecutar:
npx vitest run tests/unit/live-stats.test.ts tests/unit/manage-page.test.ts tests/unit/config-boot.test.ts
Esas suites protegen la ruta de lectura combinada /live/:slug, el comportamiento de la caché del navegador y el cableado de arranque de configuración del que dependen las bifurcaciones.
Para las superficies públicas de captación previa, enlace compartido y tiempo de ejecución de carrito diferido, utilice:
npx vitest run \
tests/unit/page-prefetch.test.ts \
tests/unit/cart-runtime-loader.test.ts \
tests/unit/campaign-page.test.ts \
tests/unit/seo-layouts.test.ts \
tests/unit/site-asset-minification.test.ts
En GitHub, la misma puerta se ejecuta automáticamente en el flujo de trabajo Merge Smoke para solicitudes de extracción dirigidas a main.
La puerta de fusión ahora escribe un archivo de registro por fase e imprime un resumen final de PASA/FALLA con las rutas de registro. Si falla una fase tardía respaldada por Podman, comience con el directorio de registro impreso al final de la ejecución en lugar de desplazarse por toda la transcripción.
Auditoría secreta
Ejecute esto antes de presionar cuando los secretos locales hayan cambiado, o deje que npm run test:premerge lo ejecute automáticamente:
npm run test:secrets
La auditoría comprueba:
worker/.dev.varspermanece ignorado y sin seguimiento- Los valores secretos no permitidos de los archivos env locales no aparecen en los archivos de repositorio con o sin seguimiento.
- esos valores no aparecen en el historial de git
CI permanece seguro cuando worker/.dev.vars no existe; en ese caso, la auditoría aún verifica las reglas de ignorar y omite el escaneo de valores locales.
Comparación de sucursales principales
Ejecute la misma puerta automatizada en main en un árbol de trabajo limpio para que la línea base y la rama del parche sean directamente comparables. Si main es anterior a test:premerge, ejecute manualmente allí los comandos de sintaxis, unidad, seguridad y E2E equivalentes.
git worktree add ../pool-main-check main
ln -s "$(pwd)/node_modules" ../pool-main-check/node_modules
cd ../pool-main-check
npm run test:premerge
Si crea el árbol de trabajo temporal, elimínelo después de la comparación:
cd -
git worktree remove ../pool-main-check
Lista de verificación manual de humo
Ejecútelos contra la preparación antes de fusionarlos cuando exista un entorno de preparación. Si no existe un entorno de prueba para The Pool, ejecute la misma lista de verificación localmente con ./scripts/dev.sh --podman y registre esa excepción en las notas de la versión/PR.
- Inicie un nuevo pago en una campaña de prueba en vivo y confirme que
/checkout-intent/startdevuelve un arranque de sesión personalizado cuando se configura la clave publicable de Stripe coincidente, o una URL alojada cuando se utiliza intencionalmente el respaldo alojado. - Complete una promesa y verifique que el webhook almacene la promesa, la actualización de estadísticas y la ruta del correo electrónico de confirmación se mantenga en buen estado.
- Modifique una promesa con cambios de nivel/soporte/cantidad personalizada y verifique los totales, el historial y la actualización del inventario correctamente.
- Cancele una promesa no cargada y verifique que las estadísticas y el inventario se publiquen correctamente.
- Realice ensayos de liquidación y ejecución real de las promesas iniciales, confirmando que las campañas solo marcan el acuerdo cuando nada necesita atención.
- Active transmisiones de diarios, anuncios e hitos en una campaña lo suficientemente grande como para cruzar los límites de paginación.
- Active un informe de cumplimiento en una campaña con elementos de campaña y de plataforma, confirmando que los destinatarios del corredor reciben solo filas de campaña y
support_emailrecibe el archivo adjunto solo de plataforma.
Para cambios en la lógica empresarial de pago o de trabajador, aún se requiere un pase de humo antes de fusionar:
- Prefiere la puesta en escena cuando esté disponible.
- Si no existe ninguna preparación, utilice la ruta local más segura:
./scripts/dev.sh --podman./scripts/smoke-pledge-management.sh- la lista de verificación del operador en docs/MERGE_SMOKE_CHECKLIST.md
- una nota de relaciones públicas que indique explícitamente que no existe un entorno de prueba
Para obtener una versión lista para el operador con comandos exactos y resultados esperados, use docs/MERGE_SMOKE_CHECKLIST.md.
Para un ensayo local de gestión de promesas, prefiera la campaña smoke-editable. Es solo local a través de test_only: true, permanece activo mucho más allá de la ventana de humo normal y le brinda a /test/setup un objetivo estable para la cobertura de modificación/cancelación.
Puedes ejercitar ese camino de principio a fin con:
./scripts/smoke-pledge-management.sh
Cuando ADMIN_SECRET está disponible, esa ruta de humo ahora también verifica que la campaña permanezca limpia en la proyección después de la configuración, modificación y cancelación llamando al punto final de solo lectura POST /stats/:slug/check entre fases de mutación.
Para la verificación CSV local con respecto a su estado de trabajador local real, utilice:
./scripts/pledge-report.sh --local
./scripts/fulfillment-report.sh --local
Utilice pledge-report.sh cuando desee el libro mayor completo, incluidas las deltas de modificación/cancelación y las anotaciones de cambio de propinas. Utilice fulfillment-report.sh cuando desee fusionar el estado actual de un patrocinador dentro de una campaña.
Si la vista de cumplimiento fusionada y el sitio público alguna vez no están de acuerdo para una campaña, trátelo primero como un problema probable de estadísticas obsoletas/proyección de inventario, no como un error de notificación de forma predeterminada. Las estadísticas de administración y los puntos finales de recálculo de inventario ahora reparan índices campaign-pledges:{slug} obsoletos mientras reconstruyen el estado de proyección de la campaña.
Antes de reparar una proyección, ahora puede comprobar explícitamente la desviación:
./scripts/check-projections.sh # Check all campaigns
./scripts/check-projections.sh hand-relations # Check one campaign
./scripts/check-projections.sh --podman # Reuse/start the Podman dev stack first
Ese script llama a los puntos finales de verificación de deriva del administrador de solo lectura y sale de un valor distinto de cero cuando las proyecciones almacenadas campaign-pledges:{slug}, stats:{slug} o tier-inventory:{slug} ya no coinciden con la verdad del compromiso activo.
Cambios de comportamiento intencionales
Al revisar los resultados, no los marque como regresiones:
- Los enlaces mágicos ahora tienen un alcance de pedido en lugar de un alcance de correo electrónico.
/checkout-intent/startahora reserva un inventario limitado y escaso antes de la confirmación del pago, y la persistencia exitosa confirma esa reserva.- El
GET /checkoutheredado está deshabilitado intencionalmente.
Agregar pruebas
Cree archivos en tests/unit/ con la extensión .test.ts:
import { describe, it, expect } from 'vitest';
describe('myFunction', () => {
it('does something', () => {
expect(myFunction()).toBe(expected);
});
});
Pruebas E2E (Dramaturgo)
Pruebas basadas en navegador para flujos de usuarios completos en tests/e2e/.
Cobertura
Estructura de la página de campaña:
- Elementos de página requeridos (héroe, barra lateral, barra de progreso)
- Atributos de datos de la barra de progreso para live-stats.js
- Marcadores de hitos (1/3, 2/3, meta)
- Marcadores de meta estirados
Tarjetas de nivel:
- Atributos y ganchos de artículos de carrito propios
- Visualización de inventario para niveles limitados
- Estado de bloqueo de nivel cerrado e insignia de desbloqueo
- Estados deshabilitados en campañas no activas
Productos físicos y envío:
- Campo personalizado
_category(físico/digital) en botones de nivel - Los niveles físicos activan el estado de expectativa de envío propio antes de la recolección de Stripe
- Las campañas solo digitales no tienen niveles de categorías físicas
Artículos de soporte:
- Estructura (cantidad, progreso, entrada, botón)
- Entrada → sincronización de precios del carrito propio
- Atributos de datos de soporte tardío
Cantidad personalizada:
- Atributos de estructura y datos
- Entrada → sincronización de precios del carrito propio
- Atributos de soporte tardío
Tarjetas de página de inicio y campaña:
- Visualización de tarjetas y elementos requeridos.
- Enlaces de campaña válidos
- Atributos del botón de nivel destacado
Integración en tiempo de ejecución del carrito:
- Arranque en tiempo de ejecución y raíz de carrito neutral
- POOL_CONFIG para live-stats.js
- Funciones globales (refreshLiveStats, getTierInventory)
Flujo del carrito:
- Navegación y añadir al carrito
- Estado del carrito a través de PoolCartProvider
- Autocompletar de facturación/estado de pago controlado por el proveedor
- El control deslizante de propinas actualiza los totales del carrito inmediatamente
- Las campañas de un solo nivel reemplazan el nivel anterior inmediatamente cuando se selecciona un nuevo nivel.
- La vista previa del pago propio publica cargas útiles canónicas en
/checkout-intent/start - Las páginas de resultados canceladas o exitosas de origen restauran o hidratan el estado del compromiso guardado
Administrar flujo:
- Carga de promesas respaldadas por tokens en
/manage/ - Inicio de actualización del método de pago para promesas activas y
payment_failed - Cancelar publicaciones de confirmación en
/pledge/cancel - Modificar publicaciones de confirmación a
/pledge/modify
Accesibilidad:
- Saltar enlace
- Hito de contenido principal
- Etiquetas de botones accesibles
- Etiquetas de entrada de formulario
Temporizadores de cuenta regresiva:
- Valores pre-renderizados (sin flash “00 00 00 00”)
- El temporizador se actualiza cada segundo.
Estados de la campaña:
- Niveles habilitados para campañas en vivo
- Próximos niveles de campaña inhabilitados
- Indicadores estatales en progreso meta
Aspectos destacados de la cobertura de pago:
- Flujo completo del compromiso: tiempo de ejecución del carrito → revisión del compromiso → paso de pago de Stripe en el sitio → página de éxito
- Verifique que la vista previa del resumen del pedido de pago aparezca inmediatamente y se resuelva en totales que tengan en cuenta las propinas
- Cobertura de prueba de integración de API de trabajador para estadísticas en vivo y arranque de pago
Aspectos destacados de la cobertura del panel de administración:
- Inicio de sesión con enlace mágico, pestañas con alcance de función y restricciones de acceso de usuarios de campaña
- Configuración, complementos, campañas, análisis, informes, seguidores y comportamiento de la pestaña Marketing
- Editor de contenido Edición de bloques WYSIWYG, configuración de enlaces/medios, reutilización del editor de diario, estado de borrador, estado de publicación y vista previa móvil
- Códigos de referencia de marketing guardados, creador de URL de campaña, exportaciones CSV, clasificación y flujos de lectura sin escritura
- Capacidad de respuesta de escritorio/tableta/móvil, incluidos menús compactos de tableta en español
- Ax comprueba el shell del panel autenticado
Correr
npm run test:e2e # Full suite (auto-starts Jekyll)
npm run test:e2e:quick # Headed mode (requires running server)
npm run test:e2e:headless # CI mode (headless)
npm run test:e2e:parity # Critical cart/manage browser regressions
npm run test:e2e:ui # Interactive UI mode
npx playwright test tests/e2e/admin-dashboard.spec.ts --project=chromium
Agregar pruebas
Cree archivos en tests/e2e/ con la extensión .spec.ts:
import { test, expect } from '@playwright/test';
test('user can do something', async ({ page }) => {
await page.goto('/');
await expect(page.locator('.element')).toBeVisible();
});
Pruebas de seguridad (Vitest)
Pruebas de penetración para la API Worker. Ubicado en tests/security/.
Cobertura
| Categoría | Pruebas |
|---|---|
| Omisión de autenticación | Omisión de token de desarrollo, validación de token, caducidad, manipulación |
| Seguridad del webhook | Verificación de firma de franja, manejo de eventos duplicados, inyección de dirección de envío, manejo de webhooks heredados eliminados |
| Autorización | Puntos finales de administración, acceso entre usuarios, protecciones de puntos finales de prueba |
| Validación de entrada | XSS, inyección, desbordamiento, entrada con formato incorrecto, normalización de campos del panel de control, abuso de indicadores físicos, manipulación de tarifas de envío, niveles adicionales/inyección de artículos de soporte |
| Limitación de tasa | Solicitudes de ráfaga, resistencia DoS |
Correr
# Start local Worker first
cd worker && wrangler dev
# In another terminal:
npm run test:security # Against localhost:8787
# Against staging, if you maintain one:
npm run test:security:staging
# Against production (read-only tests):
WORKER_URL=https://worker.example.com PROD_MODE=true npm run test:security
Requisitos previos
- Trabajador que se ejecuta localmente (
wrangler dev) o URL de preparación/producción accesible - Para una cobertura de prueba completa, establezca las variables de entorno:
WORKER_URL: URL base (predeterminada:http://localhost:8787)PROD_MODE: omitir pruebas destructivas (predeterminado:false)ADMIN_SECRET: para pruebas de autenticación de administradorTEST_TOKEN— Token de enlace mágico válido
Consulte tests/security/README.md para obtener más detalles.
Requisitos previos de las pruebas manuales
- Wrangler CLI (
npm install -g wrangler) - Stripe CLI para pruebas de webhook
- Cuenta Stripe (modo de prueba)
- Reenviar cuenta (nivel gratuito: 3000 correos electrónicos/mes)
1. Configuración del trabajador de Cloudflare
Crear espacios de nombres KV
wrangler login
wrangler kv:namespace create "VOTES"
wrangler kv:namespace create "VOTES" --preview
wrangler kv:namespace create "PLEDGES"
wrangler kv:namespace create "PLEDGES" --preview
Establecer secretos
cd worker
openssl rand -base64 32
wrangler secret put STRIPE_SECRET_KEY
wrangler secret put MAGIC_LINK_SECRET
wrangler secret put CHECKOUT_INTENT_SECRET
wrangler secret put RESEND_API_KEY
wrangler secret put ADMIN_SECRET
Ejecutar trabajador localmente
Privilegiado:
./scripts/dev.sh --podman
Respaldo manual:
cd worker
npx wrangler dev --env dev --port 8787
2. Reenviar configuración
Crear cuenta y clave API
- Regístrese en resend.com
- Vaya a Claves API → Crear clave API
- Nombre: “Desarrollador de proyectos”
- Permiso: “Enviando acceso”
- Copie la clave (comienza con
re_)
Verificar dominio (para producción)
- Vaya a Dominios → Agregar dominio
- Agregue el dominio de remitente exacto utilizado por
PLEDGES_EMAIL_FROM/UPDATES_EMAIL_FROM(para esta implementación,site.example.com) - Agregue los registros DNS que proporciona Reenviar
- Esperar verificación
Modo de prueba (no se necesita dominio)
Para realizar pruebas, puede enviar a su propio correo electrónico sin verificación de dominio:
- Reenviar permite enviar desde
[email protected]en modo de prueba - O utilice su correo electrónico personal verificado
Envío de correo electrónico de prueba
curl -X POST 'https://api.resend.com/emails' \
-H 'Authorization: Bearer re_YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"from": "[email protected]",
"to": "[email protected]",
"subject": "Test from your deployment",
"html": "<p>Magic link test!</p>"
}'
3. Configuración de franjas (modo de prueba)
Obtener claves de prueba
- Inicie sesión en dashboard.stripe.com
- Cambiar a Modo de prueba (arriba a la derecha)
- Vaya a Desarrolladores → Claves API
- Copiar Clave secreta (
sk_test_...)
Instalar CLI de banda
# macOS
brew install stripe/stripe-cli/stripe
# Login
stripe login
Reenviar webhooks al trabajador local
Opción preferida para pruebas locales de un extremo a otro:
./scripts/dev.sh --podman
Esto inicia el reenvío Jekyll, the Worker, Stripe CLI y escribe el STRIPE_WEBHOOK_SECRET coincidente en worker/.dev.vars.
También borra los procesos obsoletos en los puertos 4000, 8787 y 4040 para que la pila local coincida con el arnés de prueba/humo automatizado.
Respaldo manual:
# Forward Stripe webhooks to your local Worker
stripe listen --forward-to 127.0.0.1:8787/webhooks/stripe
# Note the webhook signing secret it outputs (whsec_...)
Agregue el secreto del webhook a su configuración de trabajador local:
printf '\nSTRIPE_WEBHOOK_SECRET=whsec_...\n' >> worker/.dev.vars
# Or edit worker/.dev.vars and replace the existing STRIPE_WEBHOOK_SECRET value
4. Prueba completa de un extremo a otro
Iniciar todos los servicios
Privilegiado:
./scripts/dev.sh --podman
Respaldo manual:
Terminal 1 - Jekyll:
bundle exec jekyll serve --config _config.yml,_config.local.yml --port 4000
# Site at http://127.0.0.1:4000
Terminal 2 - Trabajador:
cd worker
npx wrangler dev --env dev --port 8787
# Worker at http://127.0.0.1:8787
Terminal 3 - CLI de banda:
stripe listen --forward-to 127.0.0.1:8787/webhooks/stripe
Pruebe el flujo
- Añadir al carrito: Ir a http://127.0.0.1:4000/campaigns/hand-relations/
- Haga clic en “Prometer $5” en un nivel
- El carrito se abre con el artículo.
- Pagar: haga clic en “Continuar con el compromiso” en la revisión del carrito propio
- Verifique que la reseña muestre el subtotal + propina + impuestos + envío inmediatamente
- Utilice la tarjeta de prueba Stripe:
4242 4242 4242 4242 - Cualquier vencimiento futuro, cualquier CVC
- Configuración de Stripe: el segundo sidecar de pago lo mantiene en el sitio y monta la interfaz de usuario de pago seguro de Stripe.
- La tarjeta está guardada (no cargada)
- El cliente espera la confirmación de persistencia del compromiso antes de considerar el flujo como exitoso.
- Luego serás enviado a la página de éxito.
-
Consultar correo electrónico: Deberías recibir los correos electrónicos de los seguidores con enlaces mágicos.
- Pruebe el acceso a la comunidad:
- Haga clic en el enlace de la comunidad en el correo electrónico.
- O utilice: http://127.0.0.1:4000/community/hand-relations/?dev=1
- Votación de prueba:
- Votar sobre una decisión
- Actualizar página: tu voto debe persistir
Tarjetas de prueba de rayas
| Número de tarjeta | Escenario |
|---|---|
4242 4242 4242 4242 |
Guardado/configuración exitosos |
4000 0000 0000 3220 |
Se requiere 3D Secure |
4000 0000 0000 9995 |
Rechazado (fondos insuficientes) |
4000 0000 0000 0002 |
Rechazado (genérico) |
5. Prueba de componentes individuales
Prueba de ficha de enlace mágico
// In browser console on any page with the Worker running
const token = 'YOUR_TOKEN';
fetch(`http://localhost:8787/pledge?token=${token}`)
.then(r => r.json())
.then(console.log);
API de votación de prueba
# Get vote status
curl "http://localhost:8787/votes?token=YOUR_TOKEN&decisions=poster,festival"
# Cast vote
curl -X POST http://localhost:8787/votes \
-H "Content-Type: application/json" \
-d '{"token":"YOUR_TOKEN","decisionId":"poster","option":"A"}'
Pruebe KV localmente
# List keys
wrangler kv:key list --binding VOTES --preview
# Get a value
wrangler kv:key get "results:hand-relations:poster" --binding VOTES --preview
6. Solución de problemas
El inicio del proceso de pago falla y se cierra
- Verifique que
CHECKOUT_INTENT_SECRETexista enworker/.dev.vars - Confirme que la carga útil del carrito utilice ID de artículo propios válidos, como
{campaignSlug}__{tierId}.
Webhook no recibido
- Verifique que Stripe CLI se esté ejecutando y reenviando
- Verificar registros de trabajadores:
wrangler tail - Verificar que el secreto del webhook esté configurado
Correo electrónico no enviado
- Verifique Reenviar panel para ver si hay errores
- Verifique que la clave API sea correcta
- Verifique que la dirección “de” esté verificada o use
[email protected]
La página de la comunidad muestra “Acceso denegado”
- Utilice
?dev=1para pruebas locales sin trabajador - Verificar clave de almacenamiento de sesión:
supporter_token_hand-relations
Los votos no persisten
- Verifique el enlace KV en wrangler.toml
- Utilice el espacio de nombres
--previewpara desarrolladores locales - Verifique los registros de trabajadores en busca de errores
7. Mejoras para los trabajadores de pruebas
Validación de campaña de prueba
- Construye Jekyll para generar campañas.json:
bundle exec jekyll build cat _site/api/campaigns.json # Verify it exists - Prueba de inicio de pago propio con formato incorrecto:
curl -X POST http://localhost:8787/checkout-intent/start \ -H "Content-Type: application/json" \ -d '{"campaignSlug":"hand-relations","items":[{"id":"bad-item","quantity":1}],"email":"[email protected]"}'Esperado: Devuelve un error de validación de cierre fallido como
Invalid cart item id
Verificación de firma de Test Stripe Webhook
- Asegúrese de que Stripe CLI reenvíe webhooks:
./scripts/dev.sh --podman # Or, manually: stripe listen --forward-to localhost:8787/webhooks/stripe - Establecer el secreto del webhook:
# scripts/dev.sh --podman does this automatically for worker/.dev.vars # Manual setup only if you are not using the main Podman dev script - Activar un webhook de prueba:
stripe trigger checkout.session.completedVerifique los registros de trabajadores para ver el mensaje “Compromiso confirmado”.
- Prueba de firma no válida (debe fallar):
curl -X POST http://localhost:8787/webhooks/stripe \ -H "stripe-signature: invalid" \ -d '{"type":"test"}'Esperado:
{"error":"Invalid signature"}
Prueba de metadatos de compromiso almacenados
Después de completar un flujo de contribución:
- Consulte los datos de las promesas respaldadas por los trabajadores a través de
/pledge?token=... - Verifique que los datos contengan:
stripeCustomerIdstripePaymentMethodIdpledgeStatus: "active"charged: false
Puntos finales de gestión de compromisos de prueba
- Obtenga detalles de la promesa (requiere un token válido):
# Use token from supporter email curl "http://localhost:8787/pledge?token=YOUR_TOKEN"Esperado: devuelve detalles del pedido con indicadores
canModify,canCancel. - Cancelar compromiso:
curl -X POST http://localhost:8787/pledge/cancel \ -H "Content-Type: application/json" \ -d '{"token":"YOUR_TOKEN"}'Esperado:
{"success":true,"message":"Pledge cancelled"} - Verificar cancelación:
- Consulte el compromiso ahora informa
pledgeStatus: "cancelled" - Reintentar cancelar: debería obtener una respuesta de error limpia
- Consulte el compromiso ahora informa
Método de pago de actualización de prueba
curl -X POST http://localhost:8787/pledge/payment-method/start \
-H "Content-Type: application/json" \
-d '{"token":"YOUR_TOKEN"}'
Esperado: devuelve un arranque de sesión personalizado para Update Card en el sitio o una URL alojada en modo alternativo.
Pruebe el punto final de estadísticas en vivo
- Obtenga estadísticas en vivo para una campaña:
curl http://localhost:8787/stats/hand-relationsEsperado: Devuelve
{ pledgedAmount, pledgeCount, tierCounts, goalAmount, ... } - Verificar la actualización de las estadísticas después del compromiso:
- Haz una promesa de prueba
- Llamar al punto final de estadísticas nuevamente
- Confirmar que
pledgedAmountaumentó
- Recalcular estadísticas (admin):
curl -X POST http://localhost:8787/stats/hand-relations/recalculate \ -H "Authorization: Bearer YOUR_ADMIN_SECRET"
Activador de reconstrucción de administrador de prueba
curl -X POST http://localhost:8787/admin/rebuild \
-H "Authorization: Bearer YOUR_ADMIN_SECRET" \
-H "Content-Type: application/json" \
-d '{"reason":"test-rebuild"}'
Esperado: devuelve { success: true } y activa el flujo de trabajo de GitHub.
8. Lista de verificación de producción
- [] Cambiar Stripe a claves en vivo
- [] Verifique el dominio del remitente de reenvío utilizado por
PLEDGES_EMAIL_FROMyUPDATES_EMAIL_FROM(para esta implementación,site.example.com) - [] Si los recordatorios de inicio o los widgets de administración de Turnstile están habilitados, verifique que las claves públicas del sitio y los secretos coincidentes de Worker Turnstile estén configurados.
- [] Implementar trabajador:
wrangler deploy - [] Configurar el webhook de Stripe en el panel →
https://worker.example.com/webhooks/stripe - Pruebe con una contribución real de $1
9. Referencia de secretos
Acciones de GitHub (Repositorio → Configuración → Secretos)
STRIPE_SECRET_KEY— Secreto en vivo de Stripe (sk_…)CHECKOUT_INTENT_SECRET: secreto de HMAC para la firma de intención de pago- Utiliza
GITHUB_TOKENproporcionado automáticamente para confirmaciones
Trabajador de Cloudflare (wrangler o panel → Variables)
STRIPE_SECRET_KEY- igual que arribaSITE_BASE—https://site.example.comWORKER_BASE—https://worker.example.comAPP_MODE—liveotestCHECKOUT_INTENT_SECRET: cadena aleatoria de más de 32 caracteres para firmar el pagoMAGIC_LINK_SECRET: cadena aleatoria de más de 32 caracteres para la firma de tokens HMACRESEND_API_KEY— Reenviar clave API para correos electrónicos de soporte (re_…)ADMIN_SECRET: cadena aleatoria para puntos finales de API de administraciónTURNSTILE_SECRET_KEY: Secreto compartido de Cloudflare Turnstile cuando el inicio de sesión de administrador o los widgets de recordatorio de inicio están habilitadosLAUNCH_REMINDER_TURNSTILE_SECRET_KEY— Secreto de torniquete específico de recordatorio opcional si no se utiliza el secreto compartidoLAUNCH_REMINDER_TOKEN_SECRET: secreto de token de cancelación de suscripción de recordatorio opcional; vuelve aMAGIC_LINK_SECRETGITHUB_TOKEN: GitHub PAT con acceso a repositorio/flujo de trabajo para acciones de publicación del panel y activadores de reconstrucción; opcional solo cuando no estás probando la publicación respaldada por GitHubADMIN_BOOTSTRAP_EMAILS: lista de correo electrónico de superadministrador local/de recuperación opcional para iniciar sesión en el panel; El desarrollador local lee esto deworker/.dev.vars.ADMIN_USERS_JSON: lista de usuarios administradores de inicialización/recuperación opcional reflejada desde_config.yml; Panel de control Las ediciones de los usuarios se guardan en KV enadmin-users:v1.CORS_ALLOWED_ORIGIN: debe coincidir con el origen del sitio para las solicitudes del panel del navegador; Podman local deriva esto parahttp://127.0.0.1:4000
Cloudflare KV
- Espacio de nombres:
PLEDGES: almacena datos de promesas y estadísticas agregadas.- Claves:
pledge:{orderId}→ promesa JSON - Claves:
email:{email}→ conjunto de ID de pedido - Teclas:
stats:{campaignSlug}→{ pledgedAmount, pledgeCount, tierCounts }
- Claves:
- Espacio de nombres:
VOTES— Votos de la comunidad de tiendas- Claves:
vote:{campaignSlug}:{decisionId}:{orderId}→ cadena de opción - Claves:
results:{campaignSlug}:{decisionId}→ JSON{optionA: count, ...}
- Claves:
Panel de control de rayas
- Punto final del webhook =
https://worker.example.com/webhooks/stripe- Eventos:
checkout.session.completed
- Eventos:
- No se requiere catálogo de productos; los montos provienen de artículos del carrito propios canonizados por los trabajadores
Reenviar panel
- Dominio: Verifique la parte del dominio de las direcciones del remitente configuradas en
_config.yml/Worker env. Para esta implementación,PLEDGES_EMAIL_FROMesThe Pool <[email protected]>, por lo que Resend debe autorizarsite.example.com. - Clave API: Crear clave con permiso de “Acceso de envío”
- Se utiliza para: todos los correos electrónicos de compromiso dirigidos a los seguidores (confirmación, administración/acceso a la comunidad, recordatorios de lanzamiento, actualizaciones del diario, anuncios, informes, éxito de carga, fracaso de pago, cancelaciones)
- Nota del desarrollador local: incluso cuando
SITE_BASEapunta a127.0.0.1, las imágenes de correo electrónico incrustadas aún usan la base de recursos públicahttps://site.example.com, por lo que las vistas previas de la bandeja de entrada no muestran URL de imágenes de host local rotas.