89 lines
3.2 KiB
TypeScript
89 lines
3.2 KiB
TypeScript
import { test } from '@japa/runner'
|
|
import PublicContentService from '#base_modules/WebManager/services/public_content_service'
|
|
|
|
test.group('Web Manager public content', () => {
|
|
test('keeps safe rich text and removes executable markup', async ({ assert }) => {
|
|
const service = new PublicContentService()
|
|
const content = await service.prepare(
|
|
{
|
|
content:
|
|
'<p class="lead" onclick="alert(1)">Hello <strong>world</strong></p><script>alert(1)</script><svg><a onload="alert(1)"></a></svg>',
|
|
},
|
|
new Map()
|
|
)
|
|
|
|
assert.deepEqual(content, {
|
|
content: '<p class="lead">Hello <strong>world</strong></p>',
|
|
})
|
|
})
|
|
|
|
test('rejects encoded unsafe links and resolves internal page links', async ({ assert }) => {
|
|
const service = new PublicContentService()
|
|
const content = await service.prepare(
|
|
{
|
|
html: '<a href="javascript:alert(1)" target="_blank">Unsafe</a>',
|
|
ctaItems: [{ linkType: 'internal', pageId: 42, label: 'About' }],
|
|
externalUrl: 'javascript:alert(1)',
|
|
},
|
|
new Map([['42', '/en/about']])
|
|
)
|
|
|
|
assert.deepEqual(content, {
|
|
html: '<a target="_blank" rel="noopener noreferrer">Unsafe</a>',
|
|
ctaItems: [{ linkType: 'internal', pageId: 42, label: 'About', href: '/en/about' }],
|
|
externalUrl: '',
|
|
})
|
|
})
|
|
|
|
test('survives out-of-range numeric character references', async ({ assert }) => {
|
|
const service = new PublicContentService()
|
|
const content = await service.prepare({ html: '<a href="�">Link</a>' }, new Map())
|
|
|
|
assert.deepEqual(content, { html: '<a href="�">Link</a>' })
|
|
})
|
|
})
|
|
|
|
/**
|
|
* The link map is fetched by id, so anything this collector misses renders as an empty href
|
|
* on the public site.
|
|
*/
|
|
test.group('Web Manager internal link collection', () => {
|
|
test('finds internal page ids at any depth and normalizes them to strings', ({ assert }) => {
|
|
const service = new PublicContentService()
|
|
|
|
const ids = service.collectInternalPageIds({
|
|
menus: [
|
|
{
|
|
items: [
|
|
{ linkType: 'internal', pageId: 13 },
|
|
{ linkType: 'external', url: '/x' },
|
|
],
|
|
},
|
|
{ items: [{ linkType: 'internal', pageId: '16' }] },
|
|
],
|
|
nested: { deep: { cta: { linkType: 'internal', pageId: 7 } } },
|
|
})
|
|
|
|
assert.deepEqual([...ids].sort(), ['13', '16', '7'])
|
|
})
|
|
|
|
test('ignores links that are not internal and empty content', ({ assert }) => {
|
|
const service = new PublicContentService()
|
|
|
|
assert.deepEqual([...service.collectInternalPageIds({ linkType: 'external', pageId: 5 })], [])
|
|
assert.deepEqual([...service.collectInternalPageIds(null)], [])
|
|
assert.deepEqual([...service.collectInternalPageIds({ title: 'No links here' })], [])
|
|
})
|
|
|
|
test('accumulates across several content sections into one set', ({ assert }) => {
|
|
const service = new PublicContentService()
|
|
const ids = new Set<string>()
|
|
|
|
service.collectInternalPageIds({ cta: { linkType: 'internal', pageId: 3 } }, ids)
|
|
service.collectInternalPageIds({ cta: { linkType: 'internal', pageId: 3 } }, ids)
|
|
service.collectInternalPageIds({ cta: { linkType: 'internal', pageId: 4 } }, ids)
|
|
|
|
assert.deepEqual([...ids].sort(), ['3', '4'])
|
|
})
|
|
})
|