62 lines
5.3 KiB
Python
62 lines
5.3 KiB
Python
"""Prepare a browser test adapter, without editing active application/configuration."""
|
|
from pathlib import Path
|
|
import json
|
|
root=Path(__file__).resolve().parent.parent
|
|
private=root/'storage/app/private/investmoz-v2/portal-audit'
|
|
plan=json.loads((private/'portal-stability-latest.json').read_text(encoding='utf-8-sig'))
|
|
source=Path(plan['source'])
|
|
assert source.is_relative_to(private) and (source/'app').is_dir()
|
|
env_path=source/'.env.stability-consumers'
|
|
backup=source/'.env.stability-consumers.before-functional'
|
|
if not backup.exists(): backup.write_bytes(env_path.read_bytes())
|
|
env=env_path.read_text(encoding='utf-8')
|
|
import re
|
|
for name in ['PORTAL_OPPORTUNITY_MODULAR_PROFILES_QA_ENABLED','PORTAL_LEGACY_CONTENT_QA_ENABLED','INVESTOR_PATH_ENABLED']:
|
|
env,n=re.subn('^'+name+'=.*$',name+'=false',env,flags=re.M)
|
|
assert n==1
|
|
env_path.write_text(env,encoding='utf-8')
|
|
old=(root/'tools/portal-visual-qa-lib.cjs').read_text(encoding='utf-8')
|
|
old=old.replace("const BASE = 'http://127.0.0.1:18097',\n TARGET = 'desk_restore_20261009_174726_test:55441';", "const BASE = "+json.dumps(plan['consumer_environment']['base'])+",\n TARGET = "+json.dumps(plan['consumer_environment']['target']['database']+':55441')+";")
|
|
assert 'http://127.0.0.1:18097' not in old
|
|
old=old.replace("executablePath:\n 'C:/Users/macbook/AppData/Local/ms-playwright/chromium-1243/chrome-win64/chrome.exe',", "executablePath:\n 'C:/Users/macbook/AppData/Local/ms-playwright/chromium-1243/chrome-win64/chrome.exe',\n args: ['--host-resolver-rules=MAP portal-investidor.test 127.0.0.1', '--no-proxy-server'],")
|
|
old=old.replace("locale: 'pt-MZ',", "locale: 'pt-MZ',\n ignoreHTTPSErrors: false,")
|
|
old=old.replace("u.pathname.startsWith('/build-qa-opportunities/assets/')", "u.pathname.startsWith('/build/assets/')")
|
|
# Native Chromium verifies the installed CA. Do not route asset TLS through
|
|
# Node's independent certificate store or disable TLS validation to cache them.
|
|
cache_start=old.index(" if (\n req.method() === 'GET'")
|
|
cache_end=old.index(' return await route.continue();',cache_start)
|
|
old=old[:cache_start]+old[cache_end:]
|
|
old=old.replace("await page.locator('input[name=\"code\"]').fill(otp(a.totp_secret));", "if (Date.now() % 30000 > 27500) await page.waitForTimeout(31000 - Date.now() % 30000);\n await page.locator('input[name=\"code\"]').fill(otp(a.totp_secret));")
|
|
json_start=old.index(' async function json(page, url) {')
|
|
json_end=old.index(' return {',json_start)
|
|
# Keep the helper's return statement outside json(), replacing only its body.
|
|
json_end=old.index(' return {\n proof,',json_start)
|
|
old=old[:json_start]+''' async function json(page, url) {
|
|
const result = await page.evaluate(async route => {
|
|
const r = await fetch(route, {headers: {Accept: 'application/json'}});
|
|
return {status:r.status,target:r.headers.get('X-Investmoz-QA-Target'),data:await r.json()};
|
|
}, url);
|
|
assert.equal(result.target, TARGET);
|
|
return {status:result.status,data:result.data};
|
|
}
|
|
'''+old[json_end:]
|
|
(root/'tools/portal-functional-qa-lib.cjs').write_text(old,encoding='utf-8')
|
|
resources=(root/'tools/portal-territory-resource-visual-qa.cjs').read_text(encoding='utf-8')
|
|
resources=resources.replace('./portal-visual-qa-lib.cjs','./portal-functional-qa-lib.cjs').replace('/51/resources','/15/resources').replace('territory-resource-chromium-20261010','functional-coedit-resources-chromium-20261011').replace('territory-resource-map-shot-20261010','functional-coedit-map-chromium-20261011').replace('10/10/2026','11/10/2026 coedição QA22').replace("q.context('promoter'", "q.context('colleague'").replace("q.login(page, 'promoter')", "q.login(page, 'colleague')")
|
|
resources=resources.replace('await page.request.get(', "await browserRequest(page, 'GET', ").replace('await page.request.post(', "await browserRequest(page, 'POST', ")
|
|
wrapper='''async function browserRequest(page, method, url, options={}) {
|
|
assert.equal(new URL(url).origin,BASE);
|
|
const result=await page.evaluate(async ({method,url,options})=>{
|
|
const r=await fetch(url,{method,headers:{...options.headers,...(method==='POST'?{'Content-Type':'application/json'}:{})},...(method==='POST'?{body:JSON.stringify(options.data)}:{})});
|
|
return {status:r.status,headers:Object.fromEntries(r.headers.entries()),text:await r.text()};
|
|
},{method,url,options});
|
|
return {status:()=>result.status,headers:()=>result.headers,text:async()=>result.text,json:async()=>JSON.parse(result.text)};
|
|
}
|
|
'''
|
|
resources=resources.replace('void (async () => {',wrapper+'void (async () => {',1)
|
|
(root/'tools/portal-functional-coedit-resources-qa.cjs').write_text(resources,encoding='utf-8')
|
|
baseline={p:__import__('hashlib').sha256((root/p).read_bytes()).hexdigest() for p in ['.env','public/build/manifest.json','app/Services/OpportunityReviewMateriality.php','app/Services/OrganizationCountry.php','app/Services/OrganizationCountryInstallation.php']}
|
|
baseline_path=private/'functional-active-files-before-20261011.json'
|
|
if not baseline_path.exists(): baseline_path.write_text(json.dumps(baseline,indent=2),encoding='utf-8')
|
|
print(json.dumps({'result':'QA_browser_adapter_prepared','origin':plan['consumer_environment']['base'],'target':plan['consumer_environment']['target'],'active_application_writes':0}))
|