feat(phase9): isolate forms and counters for nonproduction
This commit is contained in:
20 files changed
+454
-157
No files matched your search
@@ -1071,14 +1071,15 @@ test('Phase 7 privacy page preserves policy sections and reciprocal eligible nav
|
||||
}
|
||||
});
|
||||
|
||||
test('Phase 7 rendered forms localize Spanish without enabling submission', () => {
|
||||
test('Phase 9 off-mode form surfaces localize Spanish without enabling submission', () => {
|
||||
for (const route of ['/es/contact','/es/client-consultation','/contact','/client-consultation','/referrals','/schedule-consultation']) {
|
||||
const $ = load(artifacts.get('staging').html.get(route));
|
||||
const form = $('form.contact-form-card, form.form');
|
||||
const form = $('[data-aia-form]');
|
||||
assert.equal(form.length, 1, route);
|
||||
assert.equal(form.attr('action'), '');
|
||||
assert.equal(form.attr('method'), 'post');
|
||||
assert.equal(form.find('button[type=submit][disabled]').length, 1);
|
||||
assert.equal(form.attr('data-form-mode'), 'off');
|
||||
assert.equal($('form').length, 0, route);
|
||||
assert.equal(form.find('[name]:not([disabled])').length, 0);
|
||||
assert.equal(form.find('[data-mock-submit]:not([disabled])').length, 0);
|
||||
assert.deepEqual(form.find('input').map((_i,e) => $(e).attr('name')).get(), ['name','email','phone']);
|
||||
assert.equal(form.find('select option').length, 4);
|
||||
assert.match(form.text(), route.startsWith('/es/') ? /Nombre del padre, la madre o el tutor/ : /Parent or guardian name/);
|
||||
|
||||
@@ -57,7 +57,7 @@ await test('service drawer delayed opening and keyboard containment',async()=>{a
|
||||
await test('page six boundaries',async()=>{const rows=[];for(const route of ['/library/page/6','/library/author/rula-diab/page/6']){await go(p,route);const cards=p.locator('article.blog-card');assert.equal(await cards.count(),5);const links=await p.locator('.library-pagination a').evaluateAll(es=>es.map(e=>e.getAttribute('href')));assert.ok(links.some(h=>h.endsWith('/5')));assert.ok(!links.some(h=>h.endsWith('/7')));rows.push({route,cards:5,links});}return rows;});
|
||||
await test('image link and browser Back',async()=>{await go(p,'/library/play-leisure-skills');const link=p.locator('main a[href$=".png"]').first();const href=await link.getAttribute('href');await link.focus();await p.keyboard.press('Enter');await p.waitForURL(origin+href);await p.goBack({waitUntil:'networkidle'});assert.equal(new URL(p.url()).pathname,'/library/play-leisure-skills');return {href};});
|
||||
await test('picky eating section fragments',async()=>{await go(p,'/library/picky-eating-autism-parent-guide');const links=await p.locator('main a[href^="#"]').evaluateAll(es=>es.map(e=>e.getAttribute('href')));assert.equal(links.length,4);for(const href of links){await p.locator(`main a[href="${href}"]`).click();assert.equal(new URL(p.url()).hash,href);assert.equal(await p.locator(`[id="${href.slice(1)}"]`).count(),1);}return links;});
|
||||
await test('disabled Spanish form and intercepted submission fixture',async()=>{await go(p,'/es/contact');const form=p.locator('main form').first();const html=await form.evaluate(e=>e.outerHTML);assert.equal(await form.getAttribute('action'),'');assert.equal(await form.locator('[type=submit]').isDisabled(),true);const fixture=await context(390);let prevented=false;await fixture.route(origin+'/__phase8_form_fixture',r=>{if(r.request().method()!=='GET'){prevented=true;return r.abort();}return r.fulfill({contentType:'text/html',body:'<!doctype html><html lang="es"><title>Isolated form fixture</title><body>'+html+'</body></html>'});});const page=await fixture.newPage();await page.goto(origin+'/__phase8_form_fixture');await page.evaluate(()=>HTMLFormElement.prototype.submit.call(document.querySelector('form')));await page.waitForTimeout(500);await fixture.close();assert.equal(prevented,true);return {programmaticPostPrevented:true,meaning:'Disabled submit is not complete form isolation; P9-03 remains pending. No field data supplied.'};});
|
||||
await test('off-mode Spanish form has no native submission surface',async()=>{await go(p,'/es/contact');assert.equal(await p.locator('main form').count(),0);const surface=p.locator('main [data-aia-form]').first();assert.equal(await surface.getAttribute('data-form-mode'),'off');assert.equal(await surface.locator('[name]:enabled').count(),0);assert.equal(await surface.locator('[data-mock-submit]:enabled').count(),0);return {nativeFormCount:0,enabledNamedControls:0,meaning:'Off mode has no native POST surface; no field data supplied.'};});
|
||||
await c.close();
|
||||
const nojs=await context(390,false),n=await nojs.newPage();n.setDefaultTimeout(6000);
|
||||
for(const route of ['/es/contact','/library','/ar/library/aba-school-readiness-guide'])await test(`no-JS keyboard ${route}`,async()=>{await go(n,route);const menu=n.locator('.mobile-nav > summary');await menu.focus();await n.keyboard.press('Enter');assert.equal(await n.locator('.mobile-nav').evaluate(e=>e.open),true);await n.keyboard.press('Enter');const language=n.locator('.lang-switcher summary');await language.focus();await n.keyboard.press('Enter');assert.equal(await n.locator('.lang-switcher__menu').isVisible(),true);if(route.includes('school-readiness')){const d=n.locator('details.faq').first();const before=await d.evaluate(e=>e.open);await d.locator('summary').focus();await n.keyboard.press('Enter');assert.equal(await d.evaluate(e=>e.open),!before);}return {h1:await n.locator('main h1').innerText(),searchNotice:await n.locator('.library-search__noscript').count()};});
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
counterModeForRuntime,
|
||||
resolveCounterConfig,
|
||||
} from '../src/utils/counter-mode.ts';
|
||||
import {
|
||||
formModeForRuntime,
|
||||
formRouteMapping,
|
||||
logicalFormForRoute,
|
||||
resolveFormMode,
|
||||
resolveMockFormResult,
|
||||
} from '../src/utils/form-integration.ts';
|
||||
|
||||
test('counter configuration defaults off and requires explicit approval', () => {
|
||||
assert.deepEqual(resolveCounterConfig(undefined, undefined, undefined), { mode: 'off', reason: 'default-off' });
|
||||
assert.equal(resolveCounterConfig('invalid', 'https://api.example.test', 'true').mode, 'off');
|
||||
assert.equal(resolveCounterConfig('live', 'https://api.example.test', 'false').mode, 'off');
|
||||
assert.equal(resolveCounterConfig('live', 'https://api.example.test', 'true').mode, 'live');
|
||||
assert.equal(resolveCounterConfig('live', 'http://api.example.test', 'true').mode, 'off');
|
||||
assert.equal(counterModeForRuntime(resolveCounterConfig('live', 'https://api.example.test', 'true')), 'off');
|
||||
assert.equal(resolveCounterConfig('mock', undefined, undefined).mode, 'mock');
|
||||
});
|
||||
|
||||
test('form configuration defaults off and live remains fail-closed', () => {
|
||||
assert.deepEqual(resolveFormMode(undefined, undefined), { mode: 'off', reason: 'default-off' });
|
||||
assert.equal(resolveFormMode('invalid', undefined).mode, 'off');
|
||||
assert.equal(resolveFormMode('live', 'false').mode, 'off');
|
||||
assert.equal(resolveFormMode('live', 'true').mode, 'live');
|
||||
assert.equal(formModeForRuntime(resolveFormMode('live', 'true')), 'off');
|
||||
assert.equal(resolveFormMode('mock', undefined).mode, 'mock');
|
||||
assert.equal(resolveMockFormResult(undefined), 'success');
|
||||
assert.equal(resolveMockFormResult('failed'), 'failed');
|
||||
assert.equal(resolveMockFormResult('unavailable'), 'unavailable');
|
||||
assert.equal(resolveMockFormResult('anything-else'), 'success');
|
||||
});
|
||||
|
||||
test('form mapping covers nine native instances and five landing journeys', () => {
|
||||
assert.equal(formRouteMapping.filter((entry) => entry.kind === 'native-instance').length, 9);
|
||||
assert.equal(formRouteMapping.filter((entry) => entry.kind === 'landing-journey').length, 5);
|
||||
assert.equal(logicalFormForRoute('/contact'), 'general');
|
||||
assert.equal(logicalFormForRoute('/es/client-consultation'), 'service');
|
||||
assert.equal(logicalFormForRoute('/referrals'), 'referral');
|
||||
assert.equal(logicalFormForRoute('/lp/early-intervention'), 'service');
|
||||
assert.equal(logicalFormForRoute('/ar/contact'), undefined);
|
||||
});
|
||||
|
||||
test('inactive source has no native form or live vendor destination', () => {
|
||||
const sources = [
|
||||
'src/components/ContactForm.astro',
|
||||
'src/components/FormShell.astro',
|
||||
'src/components/ServiceInquiryDrawer.astro',
|
||||
].map((file) => fs.readFileSync(file, 'utf8')).join('\n');
|
||||
assert.doesNotMatch(sources, /<form\b/);
|
||||
assert.doesNotMatch(sources, /250727122848156/);
|
||||
assert.doesNotMatch(sources, /jotform\.com/i);
|
||||
assert.match(sources, /data-form-mode/);
|
||||
});
|
||||
|
||||
test('counter source has no implicit production fallback or credentialed fetch', () => {
|
||||
const source = fs.readFileSync('src/components/LikeViewCounter.astro', 'utf8');
|
||||
assert.doesNotMatch(source, /api\.azinstitute4autism\.com/);
|
||||
assert.doesNotMatch(source, /credentials:\s*['"]include/);
|
||||
assert.doesNotMatch(source, /method:\s*['"](?:POST|DELETE)/);
|
||||
assert.match(source, /data-counter-mode/);
|
||||
});
|
||||
+11
-9
@@ -568,7 +568,7 @@ test('Phase 5A conversion CTAs resolve to the intended published local route or
|
||||
}
|
||||
});
|
||||
|
||||
test('Phase 5A preserves disabled forms and one localized H1 on every targeted page', () => {
|
||||
test('Phase 9 preserves isolated off-mode form surfaces and one localized H1 on every targeted page', () => {
|
||||
const slugs = ['aba-therapy', 'autism-evaluations', 'learner-social-club', 'services', 'client-consultation', 'aba-therapy-intake-process'];
|
||||
const routes = ['/referrals', '/schedule-consultation', '/insurance', ...['en', 'es'].flatMap((lang) => slugs.map((slug) => `${prefix(lang)}/${slug}`))];
|
||||
for (const route of routes) {
|
||||
@@ -577,12 +577,14 @@ test('Phase 5A preserves disabled forms and one localized H1 on every targeted p
|
||||
assert.equal($('html').attr('lang'), route.startsWith('/es/') ? 'es' : 'en', route);
|
||||
assert.equal($('html').attr('dir'), 'ltr', route);
|
||||
assert.equal($('iframe[src*="jotform"], script[src*="jotform"]').length, 0, route);
|
||||
$('main form').each((_, el) => {
|
||||
const form = $(el);
|
||||
assert.equal(form.attr('action'), '', route);
|
||||
assert.equal(form.find('[type="submit"]:not([disabled])').length, 0, route);
|
||||
assert.ok(form.find('[type="submit"][disabled]').length, route);
|
||||
assert.match(form.text(), route.startsWith('/es/') ? /El envío en línea aún no está habilitado/ : /Online submission is not yet connected/, route);
|
||||
const surfaces = $('main [data-aia-form]');
|
||||
assert.equal($('main form').length, 0, route);
|
||||
surfaces.each((_, el) => {
|
||||
const surface = $(el);
|
||||
assert.equal(surface.attr('data-form-mode'), 'off', route);
|
||||
assert.equal(surface.find('[name]:not([disabled])').length, 0, route);
|
||||
assert.equal(surface.find('[data-mock-submit]:not([disabled])').length, 0, route);
|
||||
assert.match(surface.text(), route.startsWith('/es/') ? /El envío en línea aún no está habilitado/ : /Online submission is not yet connected/, route);
|
||||
});
|
||||
}
|
||||
assert.equal(meta(page('/autism-evaluations'), 'description').attr('content'), "Get comprehensive childhood autism evaluations in Scottsdale, AZ. Our expert team provides accurate assessments to support your child's unique development.");
|
||||
@@ -672,8 +674,8 @@ test('Phase 5B consultation and six intake-step CTAs resolve in each homepage la
|
||||
assert.equal(link.length, 1);
|
||||
assert.equal(link.attr('href'), `${localePrefix}/client-consultation`);
|
||||
const destination = page(link.attr('href'));
|
||||
assert.equal(destination('form [type="submit"]:not([disabled])').length, 0);
|
||||
assert.match(destination('form').text(), localePrefix ? /El envío en línea aún no está habilitado/ : /Online submission is not yet connected/);
|
||||
assert.equal(destination('[data-aia-form] [data-mock-submit]:not([disabled])').length, 0);
|
||||
assert.match(destination('[data-aia-form]').text(), localePrefix ? /El envío en línea aún no está habilitado/ : /Online submission is not yet connected/);
|
||||
}
|
||||
const links = $('.process-grid a');
|
||||
assert.equal(links.length, 6);
|
||||
|
||||
Reference in new issue
Block a user