caterium-app/tests/production-support-form.mjs
pavlov346346-source c3cb44419b
Add human support form with fixed email recipient (#40)
Add Help contact form and PHP mail endpoint for support@katerion.ru, with validated Reply-To, explicit diagnostics consent, CSRF/origin checks, hashed rate limits and duplicate protection. Preserve drafts on error and avoid serializing customer data or SDK internals. Full PR QA passed in 35559317001; isolated PHP and 30 browser cases passed in 35559179372. Standard production gates unchanged. Publication checks do not send real mail; inbox receipt remains unverified. No training photo assets or unfinished training lifecycle changes.
2026-09-21 07:12:26 +03:00

39 lines
2.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {chromium,expect} from '@playwright/test';
import fs from 'node:fs/promises';
import assert from 'node:assert/strict';
import {createHash} from 'node:crypto';
const base=new URL(process.env.TIMEWEB_BASE_URL||'https://app.caterium.ru');
assert.equal(base.href,'https://app.caterium.ru/');
const output='production-ui-results';await fs.mkdir(output,{recursive:true});
const browser=await chromium.launch(),results=[];
try{
for(const width of [390,1440]){
const context=await browser.newContext({viewport:{width,height:900},serviceWorkers:'block'});
try{
const page=await context.newPage();
await page.route('**/*',r=>{const u=new URL(r.request().url());return r.request().method()==='GET'&&u.origin===base.origin&&!u.pathname.startsWith('/api/')?r.continue():r.abort();});
await page.goto(base.href,{waitUntil:'domcontentloaded'});
await page.getByRole('button',{name:'Помощь со входом',exact:true}).click();
await page.locator('#ctContactTab').click();await expect(page.locator('#ctContactForm')).toBeVisible();
await expect(page.locator('#ctContactSection')).toContainText('support@katerion.ru');
assert(await page.locator('#ctContactForm').evaluate(el=>el.scrollWidth<=el.clientWidth));
await page.screenshot({path:`${output}/support-form-${width}.png`,animations:'disabled'});
results.push({width,form:true,recipient:'support@katerion.ru',draftOnly:true});
}finally{await context.close();}
}
const context=await browser.newContext();
try{
for(const path of ['core/help-center.js','core/support-form.js']){
const response=await context.request.get(new URL(path+'?verification='+Date.now(),base).href,{headers:{'Cache-Control':'no-cache'}});assert.equal(response.status(),200);
const local=await fs.readFile('public/'+path);assert.equal(createHash('sha256').update(await response.body()).digest('hex'),createHash('sha256').update(local).digest('hex'));
}
// No real message is sent. Check the live PHP/session contract and that a
// cross-origin request cannot reach mail(). Inbox delivery is a separate check.
const response=await context.request.get(new URL('api/support.php',base).href);
assert.equal(response.status(),200);assert.match(response.headers()['cache-control'],/no-store/);
const data=await response.json();assert.equal(data.recipient,'support@katerion.ru');assert.match(data.csrf,/^[a-f0-9]{64}$/);
const rejected=await context.request.post(new URL('api/support.php',base).href,{headers:{Origin:'https://example.invalid'},data:{}});assert.equal(rejected.status(),403);
await fs.writeFile(`${output}/support-form.json`,JSON.stringify({checkedAt:new Date().toISOString(),results,phpSessionEndpoint:true,crossOriginBlocked:true,realEmailSent:false,inboxDeliveryVerified:false},null,2));
}finally{await context.close();}
}finally{await browser.close();}