import assert from 'node:assert/strict';
import test from 'node:test';
import {
createPortalPublishedPageDelivery,
} from './portal-published-page-delivery.mjs';
function createResponse() {
return {
statusCode: 200,
body: undefined,
headers: {},
status(code) {
this.statusCode = code;
return this;
},
type(value) {
this.headers['Content-Type'] = value;
return this;
},
set(name, value) {
this.headers[name] = value;
return this;
},
send(body) {
this.body = body;
return this;
},
removeHeader(name) {
delete this.headers[name];
},
};
}
function createRequest(overrides = {}) {
return {
originalUrl:
'/u/alice/pages/demo?source=test',
url: '/u/alice/pages/demo',
query: {},
headers: {
host: 'portal.example',
},
protocol: 'https',
get(name) {
return name === 'user-agent'
? 'desktop browser'
: '';
},
...overrides,
};
}
function createResult(overrides = {}) {
return {
html: '
Demo PageDemo',
publication: {
accessMode: 'public',
},
pageSource: null,
...overrides,
};
}
test('injects rybbit tracker for publication HTML delivery', async () => {
const sendPublishedPage =
createPortalPublishedPageDelivery({
async registerLongImageArtifact() {},
rybbitConfig: {
enabled: true,
siteId: '2',
idSecret: 'secret',
scriptPath: '/rybbit/script.js',
hostPath: '/rybbit',
},
});
const response = createResponse();
await sendPublishedPage(
createRequest(),
response,
{
...createResult(),
ownerId: 'user-123',
pageSource: { pageId: 'page-1' },
publication: { id: 'pub-1', accessMode: 'login_required' },
},
{ raw: true },
);
assert.match(response.body, /src="\/rybbit\/script\.js"/);
assert.match(response.body, /data-site-id="2"/);
assert.doesNotMatch(response.body, /user-123/);
});
test('wraps a normal full HTML publication in the share shell', async () => {
const sendPublishedPage =
createPortalPublishedPageDelivery({
async registerLongImageArtifact() {},
});
const response = createResponse();
await sendPublishedPage(
createRequest(),
response,
createResult(),
);
assert.equal(response.statusCode, 200);
assert.match(
response.body,
/class="publication-frame"/,
);
assert.match(
response.body,
/view=raw/,
);
assert.equal(
response.headers['Cache-Control'],
'public, max-age=60',
);
});
test('raw and password publications bypass the share shell', async () => {
const sendPublishedPage =
createPortalPublishedPageDelivery({
async registerLongImageArtifact() {},
});
const rawResponse = createResponse();
await sendPublishedPage(
createRequest(),
rawResponse,
createResult(),
{ raw: true },
);
assert.doesNotMatch(
rawResponse.body,
/publication-frame/,
);
assert.match(rawResponse.body, /Demo/);
const passwordResponse = createResponse();
await sendPublishedPage(
createRequest(),
passwordResponse,
createResult({
publication: {
accessMode: 'password',
},
}),
);
assert.doesNotMatch(
passwordResponse.body,
/publication-frame/,
);
assert.equal(
passwordResponse.headers['Cache-Control'],
'private, no-store',
);
});
test('embed mode delivers embedded HTML and frame headers', async () => {
const sendPublishedPage =
createPortalPublishedPageDelivery({
async registerLongImageArtifact() {},
});
const response = createResponse();
await sendPublishedPage(
createRequest(),
response,
createResult(),
{ embed: true },
);
assert.doesNotMatch(
response.body,
/publication-frame/,
);
assert.equal(
response.headers['X-Frame-Options'],
undefined,
);
});
test('long-image download renders, registers, and returns PNG', async () => {
const calls = [];
const image = Buffer.from('png-image');
const sendPublishedPage =
createPortalPublishedPageDelivery({
async renderLongImage(options) {
calls.push(['render', options]);
return image;
},
async registerLongImageArtifact(
options,
) {
calls.push(['register', options]);
},
});
const response = createResponse();
await sendPublishedPage(
createRequest({
query: {
download: 'long-image',
},
}),
response,
createResult(),
);
assert.equal(response.body, image);
assert.equal(
response.headers['Content-Type'],
'image/png',
);
assert.equal(
response.headers['Cache-Control'],
'no-store',
);
assert.match(
calls[0][1].url,
/view=raw/,
);
assert.match(
calls[1][1].canonicalUrl,
/download=long-image/,
);
});
test('long-image failures preserve the public error response', async () => {
const sendPublishedPage =
createPortalPublishedPageDelivery({
async renderLongImage() {
throw new Error('renderer failed');
},
async registerLongImageArtifact() {},
});
const response = createResponse();
await sendPublishedPage(
createRequest({
query: {
download: 'long-image',
},
}),
response,
createResult(),
);
assert.equal(response.statusCode, 500);
assert.match(
response.body,
/renderer failed/,
);
});