mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-23 20:25:56 +00:00
Integrate reviewed Recovery safe-reporting navigation
Preserve exact Product Intelligence commits48dc32d1a3and2a9e4183a6. Correct the existing Recovery link in both shipped mirrors and retain its renderer and desktop/phone keyboard-navigation controls. Reviewed source-3ytpvq_m and content-bound browser evidence remain adequate; no native recovery or released availability is claimed. Contract-Neutral: Existing help-link repair and regression controls only; no runtime or API contract changes. Change-source: pulse-maintainer
This commit is contained in:
+1
-1
@@ -124,7 +124,7 @@ When reporting missing records, share the failing view, running Pulse version,
|
||||
affected provider, time range, expected reading and relevant redacted error.
|
||||
Use consistent placeholders for private hostnames, datasets and IDs. Do not
|
||||
share full backup inventories, request headers, tokens, cookies or recovery
|
||||
keys. See [safe issue reporting](TROUBLESHOOTING.md#getting-help).
|
||||
keys. See [safe issue reporting](TROUBLESHOOTING.md#-getting-help).
|
||||
|
||||
## API reference
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
// Shipped Recovery -> Troubleshooting navigation, with the production Docs page.
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const { chromium, webkit } = require('playwright');
|
||||
|
||||
(async () => {
|
||||
const root = '/workspace/frontend-modern';
|
||||
process.chdir(root);
|
||||
const artifacts = path.join(root, 'node_modules', 'recovery-safe-reporting-browser');
|
||||
fs.mkdirSync(artifacts, { recursive: true });
|
||||
const { createServer } = await import(path.join(root, 'node_modules/vite/dist/node/index.js'));
|
||||
const server = await createServer({
|
||||
root,
|
||||
configFile: path.join(root, 'vite.config.ts'),
|
||||
cacheDir: path.join(root, 'node_modules', '.vite-recovery-safe-reporting'),
|
||||
server: { host: '127.0.0.1', port: 5249, strictPort: true },
|
||||
optimizeDeps: { noDiscovery: true, include: [] },
|
||||
});
|
||||
let browser;
|
||||
const results = [];
|
||||
try {
|
||||
await server.listen();
|
||||
for (const [engine, width, dark] of [
|
||||
['chromium', 1280, false],
|
||||
['webkit', 390, true],
|
||||
]) {
|
||||
browser = await { chromium, webkit }[engine].launch(
|
||||
engine === 'chromium'
|
||||
? { headless: true, channel: 'chromium', args: ['--no-sandbox'] }
|
||||
: { headless: true },
|
||||
);
|
||||
const page = await browser.newPage({
|
||||
viewport: { width, height: 900 },
|
||||
...(engine === 'webkit' ? { isMobile: true, hasTouch: true } : {}),
|
||||
});
|
||||
const errors = [];
|
||||
page.on('pageerror', (error) => errors.push(error.message));
|
||||
page.on('console', (message) => {
|
||||
if (message.type() === 'error') errors.push(message.text());
|
||||
});
|
||||
await page.goto('http://127.0.0.1:5249/browser-tests/docs-fragment-navigation.html', {
|
||||
waitUntil: 'domcontentloaded',
|
||||
timeout: 60000,
|
||||
});
|
||||
// The fixture mounts the actual /docs router. Navigate without mocking assets.
|
||||
await page.evaluate(() => {
|
||||
history.pushState({}, '', '/docs/RECOVERY');
|
||||
dispatchEvent(new PopStateEvent('popstate'));
|
||||
});
|
||||
const link = page.getByRole('link', { name: 'safe issue reporting', exact: true });
|
||||
await link.waitFor();
|
||||
if (dark) await page.evaluate(() => document.documentElement.classList.add('dark'));
|
||||
await link.focus();
|
||||
await page.keyboard.press('Enter');
|
||||
const verifyDestination = async () => {
|
||||
await page.waitForFunction(() => {
|
||||
const heading = document.getElementById('-getting-help');
|
||||
if (!heading) return false;
|
||||
const rect = heading.getBoundingClientRect();
|
||||
return document.activeElement === heading && rect.top >= 0 && rect.top < innerHeight;
|
||||
});
|
||||
assert.ok(page.url().endsWith('/docs/TROUBLESHOOTING#-getting-help'));
|
||||
assert.equal(await page.locator('h2#-getting-help').textContent(), '🆘 Getting Help');
|
||||
const article = await page.locator('article').innerText();
|
||||
for (const text of [
|
||||
'Export for GitHub (sanitized)',
|
||||
'Review before posting',
|
||||
'Never post bootstrap/recovery',
|
||||
'Do not refile information you have already supplied',
|
||||
])
|
||||
assert.ok(article.includes(text), text);
|
||||
assert.ok(
|
||||
await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth + 1),
|
||||
);
|
||||
};
|
||||
await verifyDestination();
|
||||
await page.screenshot({ path: path.join(artifacts, `${engine}-safe-reporting.png`) });
|
||||
assert.deepEqual(errors, []);
|
||||
results.push({
|
||||
engine,
|
||||
version: browser.version(),
|
||||
width,
|
||||
dark,
|
||||
keyboardNavigation: true,
|
||||
targetFocusedAndVisible: true,
|
||||
safeGuidance: true,
|
||||
noHorizontalOverflow: true,
|
||||
errors,
|
||||
});
|
||||
await browser.close();
|
||||
browser = undefined;
|
||||
}
|
||||
const result = {
|
||||
result: 'passed',
|
||||
playwright: require('playwright/package.json').version,
|
||||
scope: 'shipped help navigation, not native recovery or release availability',
|
||||
results,
|
||||
};
|
||||
fs.writeFileSync(path.join(artifacts, 'result.json'), JSON.stringify(result, null, 2) + '\n');
|
||||
console.log(JSON.stringify(result));
|
||||
} finally {
|
||||
if (browser) await browser.close();
|
||||
await server.close();
|
||||
}
|
||||
})().catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
@@ -124,7 +124,7 @@ When reporting missing records, share the failing view, running Pulse version,
|
||||
affected provider, time range, expected reading and relevant redacted error.
|
||||
Use consistent placeholders for private hostnames, datasets and IDs. Do not
|
||||
share full backup inventories, request headers, tokens, cookies or recovery
|
||||
keys. See [safe issue reporting](TROUBLESHOOTING.md#getting-help).
|
||||
keys. See [safe issue reporting](TROUBLESHOOTING.md#-getting-help).
|
||||
|
||||
## API reference
|
||||
|
||||
|
||||
@@ -42,6 +42,24 @@ describe('recovery help', () => {
|
||||
expect(target.querySelector('#backup-safety')?.textContent).toBe('Backup safety');
|
||||
});
|
||||
|
||||
it('resolves safe issue reporting to the actual troubleshooting heading', () => {
|
||||
const rendered = document.createElement('article');
|
||||
rendered.innerHTML = renderDocMarkdown(guide, 'RECOVERY');
|
||||
const link = rendered.querySelector<HTMLAnchorElement>('a[href^="/docs/TROUBLESHOOTING#"]');
|
||||
expect(link?.textContent).toBe('safe issue reporting');
|
||||
expect(link?.hasAttribute('data-doc-link')).toBe(true);
|
||||
const destination = new URL(link!.getAttribute('href')!, 'https://pulse.example.invalid');
|
||||
expect(destination.pathname).toBe('/docs/TROUBLESHOOTING');
|
||||
expect(destination.hash).not.toBe('');
|
||||
|
||||
const target = document.createElement('article');
|
||||
target.innerHTML = renderDocMarkdown(read('docs/TROUBLESHOOTING.md'), 'TROUBLESHOOTING');
|
||||
const heading = [...target.querySelectorAll('h2')].find(
|
||||
(element) => element.id === decodeURIComponent(destination.hash.slice(1)),
|
||||
);
|
||||
expect(heading?.textContent).toBe('🆘 Getting Help');
|
||||
});
|
||||
|
||||
it('documents actual point filters and an example the handlers consume', () => {
|
||||
const handlers = read('internal/api/recovery_handlers.go');
|
||||
const model = read('internal/recovery/model/types.go');
|
||||
|
||||
Reference in New Issue
Block a user