Live visitor smoke check, and the written explanation for Manson

qa/live-visitor.mjs is read-only against production: a visitor on any ID-keyed
shared link must see no modal, no invitation, no 401 and no page errors. It is the
check that the optional-profile change did not disturb anyone who is not signed in.
Passing 9/9 against rmcircle.team.

docs/for-manson-optional-profiles.md is the note to send him before anything goes
to the team, since he asked to see it first. It leads with his objection being
right, states plainly that nothing is required, and is honest about the trade: we
accept lower coverage rather than mandate identity. It also covers the level-8
question, where the pay rules were already fine and only the ladder graphic was
misleading.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-17 04:53:49 -05:00
parent 91a6893df9
commit 8bdc105a7a
2 changed files with 120 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
// Read-only smoke check against PRODUCTION: a visitor on any ID-keyed shared link
// must see no profile prompt of any kind, and no errors. Anonymous, GET only.
// Run: node qa/live-visitor.mjs
import { pathToFileURL } from 'node:url';
const PW = 'D:/Projects/MarketingAgent/qa-tester/node_modules/playwright';
const { chromium } = (await import(pathToFileURL(PW + '/index.js').href)).default;
const B = process.env.LIVE || 'https://rmcircle.team';
const ok = [], bad = [];
const t = (n, c, extra) => { (c ? ok : bad).push(n + (c || !extra ? '' : ' -> ' + extra)); };
const browser = await chromium.launch();
const ctx = await browser.newContext({ viewport: { width: 1280, height: 950 } });
const p = await ctx.newPage();
const errs = [], bad401 = [];
p.on('pageerror', e => errs.push(String(e.message).slice(0, 140)));
p.on('response', r => { if (r.status() === 401 && /\/profile|\/reach/.test(r.url())) bad401.push(r.url()); });
for (const u of ['/my/21', '/my/49', '/my/787', '/join/21', '/fast-start?id=21', '/generation-pay?id=21', '/flyers?id=21']) {
await p.goto(B + u, { waitUntil: 'domcontentloaded' }).catch(() => {});
await p.waitForTimeout(2600);
const modal = await p.evaluate(() => !!document.querySelector('#pgCard'));
const invite = await p.evaluate(() => !!document.getElementById('pcGo'));
const txt = await p.evaluate(() => document.body.innerText);
t('visitor ' + u + ': renders, no modal, no invitation',
!modal && !invite && txt.length > 300, 'modal=' + modal + ' invite=' + invite + ' len=' + txt.length);
}
t('no 401s on profile/reach for a visitor', bad401.length === 0, bad401.join(','));
t('no uncaught page errors', errs.length === 0, errs.slice(0, 3).join(' | '));
console.log('LIVE PASS ' + ok.length);
for (const b of bad) console.log('LIVE FAIL ' + b);
await browser.close();
process.exit(bad.length ? 1 : 0);