Initial commit
This commit is contained in:
commit
2683eae6b3
36 files changed
+7369
No files matched your search
@@ -0,0 +1,264 @@
|
||||
import { createServer } from 'node:http'
|
||||
|
||||
const logo = `<svg xmlns="http://www.w3.org/2000/svg" width="120" height="40" viewBox="0 0 120 40">
|
||||
<rect width="120" height="40" rx="6" fill="#0b63b6"/>
|
||||
<text x="60" y="26" text-anchor="middle" font-family="Arial" font-size="16" fill="white">WIKI</text>
|
||||
</svg>`
|
||||
|
||||
const pages = [
|
||||
{
|
||||
id: 1,
|
||||
path: 'docs',
|
||||
locale: 'en',
|
||||
title: 'Documentation',
|
||||
description: 'Documentation root',
|
||||
contentType: 'markdown',
|
||||
isPublished: true,
|
||||
updatedAt: '2026-01-02T10:00:00.000Z',
|
||||
render: `
|
||||
<h1 id="welcome">Documentation</h1>
|
||||
<p>Start with <a href="/en/docs/install">Install</a>. The Linux details are in
|
||||
<a href="/en/docs/install/linux#requirements">Linux requirements</a>.</p>
|
||||
<p><a href="#welcome">Jump to welcome</a></p>
|
||||
<p><a href="https://example.com/docs">External docs</a></p>
|
||||
<p><a href="/en/guide">Outside guide</a></p>
|
||||
<p><a href="/en/docs-other">Excluded sibling</a></p>
|
||||
<img src="/assets/logo.svg" alt="Wiki logo">
|
||||
<script>window.evil = true</script>
|
||||
<iframe src="https://example.com/embed"></iframe>
|
||||
<p>DOCS_MARKER</p>
|
||||
`,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
path: 'docs/install',
|
||||
locale: 'en',
|
||||
title: 'Installation',
|
||||
description: 'Install guide',
|
||||
contentType: 'markdown',
|
||||
isPublished: true,
|
||||
updatedAt: '2026-01-03T10:00:00.000Z',
|
||||
render: `
|
||||
<h1 id="install">Installation</h1>
|
||||
<p>Back to <a href="/en/docs">Documentation</a>.</p>
|
||||
<p>Choose <a href="/en/docs/install/linux">Linux</a>.</p>
|
||||
<p>INSTALL_MARKER</p>
|
||||
`,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
path: 'docs/install/linux',
|
||||
locale: 'en',
|
||||
title: 'Linux requirements',
|
||||
description: 'Linux install',
|
||||
contentType: 'markdown',
|
||||
isPublished: true,
|
||||
updatedAt: '2026-01-04T10:00:00.000Z',
|
||||
render: `
|
||||
<h1 id="linux">Linux</h1>
|
||||
<h2 id="requirements">Requirements</h2>
|
||||
<ul><li>Node.js 22</li><li>PostgreSQL</li></ul>
|
||||
<p><a href="/en/docs/install">Back to installation</a></p>
|
||||
<p>LINUX_MARKER</p>
|
||||
`,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
path: 'docs/other',
|
||||
locale: 'en',
|
||||
title: 'Other notes',
|
||||
description: 'Other notes',
|
||||
contentType: 'markdown',
|
||||
isPublished: true,
|
||||
updatedAt: '2026-01-05T10:00:00.000Z',
|
||||
render: `<h1>Other notes</h1><p>OTHER_MARKER</p>`,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
path: 'docs/fallback',
|
||||
locale: 'en',
|
||||
title: 'Fallback Markdown',
|
||||
description: 'Rendered from source',
|
||||
contentType: 'markdown',
|
||||
isPublished: true,
|
||||
updatedAt: '2026-01-06T10:00:00.000Z',
|
||||
render: null,
|
||||
content: `# Fallback Markdown
|
||||
|
||||
This page is rendered from its markdown source. See [Installation](install).
|
||||
|
||||
FALLBACK_MARKER
|
||||
`,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
path: 'docs/draft',
|
||||
locale: 'en',
|
||||
title: 'Draft page',
|
||||
description: 'Unpublished',
|
||||
contentType: 'markdown',
|
||||
isPublished: false,
|
||||
updatedAt: '2026-01-07T10:00:00.000Z',
|
||||
render: `<h1>Draft page</h1><p>DRAFT_MARKER</p>`,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
path: 'docs-other',
|
||||
locale: 'en',
|
||||
title: 'Excluded sibling',
|
||||
description: 'Not below docs',
|
||||
contentType: 'markdown',
|
||||
isPublished: true,
|
||||
updatedAt: '2026-01-08T10:00:00.000Z',
|
||||
render: `<h1>Excluded sibling</h1><p>EXCLUDED_SIBLING_MARKER</p>`,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
path: 'guide',
|
||||
locale: 'en',
|
||||
title: 'Outside guide page',
|
||||
description: 'Outside the subtree',
|
||||
contentType: 'markdown',
|
||||
isPublished: true,
|
||||
updatedAt: '2026-01-09T10:00:00.000Z',
|
||||
render: `<h1>Outside guide page</h1><p>GUIDE_OUTSIDE_MARKER</p>`,
|
||||
},
|
||||
]
|
||||
|
||||
function pageListItem(page) {
|
||||
return {
|
||||
id: page.id,
|
||||
path: page.path,
|
||||
locale: page.locale,
|
||||
title: page.title,
|
||||
description: page.description,
|
||||
contentType: page.contentType,
|
||||
isPublished: page.isPublished,
|
||||
updatedAt: page.updatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
function sendJson(response, status, payload) {
|
||||
const body = JSON.stringify(payload)
|
||||
response.writeHead(status, {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': Buffer.byteLength(body),
|
||||
})
|
||||
response.end(body)
|
||||
}
|
||||
|
||||
export async function startMockWiki() {
|
||||
const state = { assetHits: 0, graphqlHits: 0 }
|
||||
|
||||
const server = createServer((request, response) => {
|
||||
const url = new URL(request.url, 'http://127.0.0.1')
|
||||
|
||||
if (url.pathname === '/assets/logo.svg') {
|
||||
state.assetHits += 1
|
||||
response.writeHead(200, { 'Content-Type': 'image/svg+xml' })
|
||||
response.end(logo)
|
||||
return
|
||||
}
|
||||
|
||||
if (url.pathname !== '/graphql' || request.method !== 'POST') {
|
||||
response.writeHead(404, { 'Content-Type': 'text/plain' })
|
||||
response.end('not found')
|
||||
return
|
||||
}
|
||||
|
||||
if (request.headers.authorization !== 'Bearer test-key') {
|
||||
sendJson(response, 401, { error: 'unauthorized' })
|
||||
return
|
||||
}
|
||||
|
||||
state.graphqlHits += 1
|
||||
let raw = ''
|
||||
request.setEncoding('utf8')
|
||||
request.on('data', (chunk) => {
|
||||
raw += chunk
|
||||
})
|
||||
request.on('end', () => {
|
||||
let payload
|
||||
try {
|
||||
payload = JSON.parse(raw)
|
||||
} catch {
|
||||
sendJson(response, 400, { error: 'bad json' })
|
||||
return
|
||||
}
|
||||
|
||||
const query = payload.query || ''
|
||||
const variables = payload.variables || {}
|
||||
|
||||
if (query.includes('WikiPrintLocalization')) {
|
||||
sendJson(response, 200, {
|
||||
data: {
|
||||
localization: {
|
||||
config: { locale: 'en', namespacing: true, namespaces: ['en'] },
|
||||
},
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (query.includes('WikiPrintPages')) {
|
||||
sendJson(response, 200, {
|
||||
data: { pages: { list: pages.map(pageListItem) } },
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (query.includes('WikiPrintPageSource')) {
|
||||
const page = pages.find((candidate) => candidate.id === variables.id)
|
||||
sendJson(response, 200, {
|
||||
data: {
|
||||
pages: {
|
||||
single: page
|
||||
? { content: page.content || '', contentType: page.contentType }
|
||||
: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (query.includes('WikiPrintPage')) {
|
||||
const page = pages.find(
|
||||
(candidate) =>
|
||||
candidate.path === variables.path && candidate.locale === variables.locale,
|
||||
)
|
||||
sendJson(response, 200, {
|
||||
data: {
|
||||
pages: {
|
||||
singleByPath: page
|
||||
? {
|
||||
id: page.id,
|
||||
path: page.path,
|
||||
locale: page.locale,
|
||||
title: page.title,
|
||||
description: page.description,
|
||||
contentType: page.contentType,
|
||||
render: page.render,
|
||||
createdAt: page.updatedAt,
|
||||
updatedAt: page.updatedAt,
|
||||
}
|
||||
: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
sendJson(response, 400, { errors: [{ message: 'Unknown mock query' }] })
|
||||
})
|
||||
})
|
||||
|
||||
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve))
|
||||
const address = server.address()
|
||||
|
||||
return {
|
||||
url: `http://127.0.0.1:${address.port}`,
|
||||
state,
|
||||
pages,
|
||||
close: () => new Promise((resolve) => server.close(resolve)),
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user