Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions scripts/create-testenv.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const ROOT_PAGE_CANONICALS = {
'app.html': `${TESTENV_CANONICAL_SITE_URL}/app.html`,
'generator.html': `${TESTENV_CANONICAL_SITE_URL}/generator.html`,
'combinatorial.html': `${TESTENV_CANONICAL_SITE_URL}/combinatorial.html`,
'webmcp.html': `${TESTENV_CANONICAL_SITE_URL}/webmcp.html`,
};
const TESTENV_INDICATOR_STYLE = `<style data-testenv-indicator>
body::before {
Expand Down Expand Up @@ -272,6 +273,7 @@ Primary production URLs:
- ${TESTENV_CANONICAL_SITE_URL}/app.html
- ${TESTENV_CANONICAL_SITE_URL}/generator.html
- ${TESTENV_CANONICAL_SITE_URL}/combinatorial.html
- ${TESTENV_CANONICAL_SITE_URL}/webmcp.html
- ${TESTENV_CANONICAL_SITE_URL}/docs/
`;
}
Expand Down Expand Up @@ -493,11 +495,11 @@ const TESTENV_HIDE_HEADER_STYLE = `
</style>`;

function hideTopHeaderInBuiltHtml(html) {
if (html.includes('data-testenv-hide-header')) {
return html;
}
return upsertHeadStyle(html, 'data-testenv-hide-header', TESTENV_HIDE_HEADER_STYLE);
}

return html.replace('</head>', `${TESTENV_HIDE_HEADER_STYLE}\n </head>`);
function applyTopHeaderHideToHtml(html) {
return hideTopHeaderInBuiltHtml(html);
}

async function hideTopHeaderInBuiltPage(pagePath) {
Expand All @@ -507,7 +509,6 @@ async function hideTopHeaderInBuiltPage(pagePath) {
if (nextHtml === html) {
return;
}

await writeFile(pagePath, nextHtml, 'utf8');
Comment thread
eviltester marked this conversation as resolved.
}

Expand Down Expand Up @@ -575,6 +576,7 @@ async function main() {
await hideTopHeaderInBuiltPage(path.join(outputDir, 'app.html'));
await hideTopHeaderInBuiltPage(path.join(outputDir, 'generator.html'));
await hideTopHeaderInBuiltPage(path.join(outputDir, 'combinatorial.html'));
await hideTopHeaderInBuiltPage(path.join(outputDir, 'webmcp.html'));
Comment thread
eviltester marked this conversation as resolved.

await mkdir(fullSiteDir, { recursive: true });
await createTemporaryDocsAppPlaceholder();
Expand All @@ -593,6 +595,18 @@ async function main() {
}

await copyWebBuildIntoDirectory(tempWebDir, fullSiteDir);
await applySeoDirectivesToFile(path.join(fullSiteDir, 'app.html'), {
canonicalUrl: ROOT_PAGE_CANONICALS['app.html'],
});
await applySeoDirectivesToFile(path.join(fullSiteDir, 'generator.html'), {
canonicalUrl: ROOT_PAGE_CANONICALS['generator.html'],
});
await applySeoDirectivesToFile(path.join(fullSiteDir, 'combinatorial.html'), {
canonicalUrl: ROOT_PAGE_CANONICALS['combinatorial.html'],
});
Comment thread
eviltester marked this conversation as resolved.
await applySeoDirectivesToFile(path.join(fullSiteDir, 'webmcp.html'), {
canonicalUrl: ROOT_PAGE_CANONICALS['webmcp.html'],
});
await rm(tempWebDir, {
recursive: true,
force: true,
Expand All @@ -619,6 +633,7 @@ export {
TESTENV_CANONICAL_SITE_URL,
TESTENV_ROBOTS_DIRECTIVES,
applySeoDirectivesToHtml,
applyTopHeaderHideToHtml,
createLlmsTxt,
createSiteRobotsTxt,
createTestenvRobotsTxt,
Expand Down
30 changes: 30 additions & 0 deletions tests/integration/create-testenv-seo.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
ROOT_CANONICAL_URL,
TESTENV_CANONICAL_SITE_URL,
applySeoDirectivesToHtml,
applyTopHeaderHideToHtml,
createLlmsTxt,
createSiteRobotsTxt,
createTestenvRobotsTxt,
Expand Down Expand Up @@ -30,6 +31,7 @@ describe('create-testenv SEO helpers', () => {

expect(llmsTxt).toContain('non-production review and test deployment');
expect(llmsTxt).toContain(ROOT_CANONICAL_URL);
expect(llmsTxt).toContain(`${TESTENV_CANONICAL_SITE_URL}/webmcp.html`);
expect(llmsTxt).toContain(`${TESTENV_CANONICAL_SITE_URL}/docs/`);
});

Expand Down Expand Up @@ -99,4 +101,32 @@ describe('create-testenv SEO helpers', () => {
expect(html).toContain('.header {');
expect(html).toContain('display: none !important;');
});

test('adds the testenv header-hiding style for top-level published app pages', () => {
const html = applyTopHeaderHideToHtml('<!doctype html><html><head><title>WebMCP</title></head><body><div class="header"></div></body></html>');

expect(html).toContain('data-testenv-hide-header');
expect(html).toContain('.header {');
expect(html).toContain('display: none !important;');
});

test('SEO rewrite can target webmcp.html with canonical and test environment marker', () => {
const html = applySeoDirectivesToHtml('<!doctype html><html><head><title>WebMCP</title></head><body></body></html>', {
canonicalUrl: `${TESTENV_CANONICAL_SITE_URL}/webmcp.html`,
});

expect(html).toContain('data-testenv-indicator');
expect(html).toContain('<meta name="robots" content="noindex,nofollow,noarchive,nosnippet" />');
expect(html).toContain('<link rel="canonical" href="https://anywaydata.com/webmcp.html" />');
});

test('updates the existing top-level header-hiding style without duplicating it', () => {
const html = applyTopHeaderHideToHtml(
'<!doctype html><html><head><style data-testenv-hide-header>.header{display:block!important;}</style></head><body></body></html>',
);

expect(html.match(/data-testenv-hide-header/g)).toHaveLength(1);
expect(html).toContain('display: none !important;');
expect(html).not.toContain('display:block!important;');
});
});