203 lines
6.1 KiB
JavaScript
203 lines
6.1 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { attachPortalPlazaDiscoveryRoutes } from './portal-plaza-discovery-routes.mjs';
|
|
|
|
function createRouterRecorder() {
|
|
const routes = new Map();
|
|
return {
|
|
routes,
|
|
get(path, handler) {
|
|
routes.set(path, handler);
|
|
},
|
|
};
|
|
}
|
|
|
|
function createResponseRecorder() {
|
|
return {
|
|
statusCode: 200,
|
|
body: undefined,
|
|
status(code) {
|
|
this.statusCode = code;
|
|
return this;
|
|
},
|
|
json(body) {
|
|
this.body = body;
|
|
return this;
|
|
},
|
|
};
|
|
}
|
|
|
|
function createRouteDependencies(overrides = {}) {
|
|
const calls = {
|
|
data: [],
|
|
errors: [],
|
|
routeErrors: [],
|
|
};
|
|
return {
|
|
calls,
|
|
dependencies: {
|
|
sendData(res, req, data) {
|
|
calls.data.push({ res, req, data });
|
|
return res.json({ data });
|
|
},
|
|
sendError(res, req, status, code, message) {
|
|
calls.errors.push({ res, req, status, code, message });
|
|
return res.status(status).json({ error: { code, message } });
|
|
},
|
|
handleRouteError(res, req, error) {
|
|
calls.routeErrors.push({ res, req, error });
|
|
return res.status(418).json({ mapped: error.message });
|
|
},
|
|
...overrides,
|
|
},
|
|
};
|
|
}
|
|
|
|
test('portal Plaza discovery module preserves route inventory and order', () => {
|
|
const api = createRouterRecorder();
|
|
attachPortalPlazaDiscoveryRoutes(api);
|
|
assert.deepEqual(
|
|
[...api.routes.keys()],
|
|
['/plaza/v1/categories', '/plaza/v1/seo/sitemap'],
|
|
);
|
|
});
|
|
|
|
test('GET /plaza/v1/categories preserves Plaza unavailable response', async () => {
|
|
const api = createRouterRecorder();
|
|
const { calls, dependencies } = createRouteDependencies();
|
|
attachPortalPlazaDiscoveryRoutes(api, dependencies);
|
|
const req = {};
|
|
const res = createResponseRecorder();
|
|
|
|
await api.routes.get('/plaza/v1/categories')(req, res);
|
|
|
|
assert.equal(res.statusCode, 503);
|
|
assert.deepEqual(res.body, {
|
|
error: { code: 'plaza_unavailable', message: 'Plaza 未启用' },
|
|
});
|
|
assert.deepEqual(calls.errors[0], {
|
|
res,
|
|
req,
|
|
status: 503,
|
|
code: 'plaza_unavailable',
|
|
message: 'Plaza 未启用',
|
|
});
|
|
});
|
|
|
|
test('GET /plaza/v1/categories preserves successful response envelope', async () => {
|
|
const api = createRouterRecorder();
|
|
const categories = [{ slug: 'technology', name: '科技' }];
|
|
const { calls, dependencies } = createRouteDependencies({
|
|
getPlazaPosts: () => ({
|
|
async listCategories() {
|
|
return categories;
|
|
},
|
|
}),
|
|
});
|
|
attachPortalPlazaDiscoveryRoutes(api, dependencies);
|
|
const req = {};
|
|
const res = createResponseRecorder();
|
|
|
|
await api.routes.get('/plaza/v1/categories')(req, res);
|
|
|
|
assert.deepEqual(calls.data[0], {
|
|
res,
|
|
req,
|
|
data: { categories },
|
|
});
|
|
assert.deepEqual(res.body, { data: { categories } });
|
|
});
|
|
|
|
test('GET /plaza/v1/categories preserves route error mapping', async () => {
|
|
const api = createRouterRecorder();
|
|
const failure = new Error('category query failed');
|
|
const { calls, dependencies } = createRouteDependencies({
|
|
getPlazaPosts: () => ({
|
|
async listCategories() {
|
|
throw failure;
|
|
},
|
|
}),
|
|
});
|
|
attachPortalPlazaDiscoveryRoutes(api, dependencies);
|
|
const req = {};
|
|
const res = createResponseRecorder();
|
|
|
|
await api.routes.get('/plaza/v1/categories')(req, res);
|
|
|
|
assert.deepEqual(calls.routeErrors[0], { res, req, error: failure });
|
|
assert.equal(res.statusCode, 418);
|
|
assert.deepEqual(res.body, { mapped: 'category query failed' });
|
|
});
|
|
|
|
test('GET /plaza/v1/seo/sitemap preserves Plaza and SEO availability gates', async () => {
|
|
const plazaUnavailableApi = createRouterRecorder();
|
|
const plazaUnavailable = createRouteDependencies();
|
|
attachPortalPlazaDiscoveryRoutes(plazaUnavailableApi, plazaUnavailable.dependencies);
|
|
const plazaUnavailableRes = createResponseRecorder();
|
|
await plazaUnavailableApi.routes.get('/plaza/v1/seo/sitemap')(
|
|
{ query: {} },
|
|
plazaUnavailableRes,
|
|
);
|
|
assert.equal(plazaUnavailableRes.statusCode, 503);
|
|
assert.equal(plazaUnavailable.calls.errors[0].message, 'Plaza 未启用');
|
|
|
|
const seoUnavailableApi = createRouterRecorder();
|
|
const seoUnavailable = createRouteDependencies({
|
|
getPlazaPosts: () => ({}),
|
|
});
|
|
attachPortalPlazaDiscoveryRoutes(seoUnavailableApi, seoUnavailable.dependencies);
|
|
const seoUnavailableRes = createResponseRecorder();
|
|
await seoUnavailableApi.routes.get('/plaza/v1/seo/sitemap')(
|
|
{ query: {} },
|
|
seoUnavailableRes,
|
|
);
|
|
assert.equal(seoUnavailableRes.statusCode, 503);
|
|
assert.equal(seoUnavailable.calls.errors[0].message, 'Plaza SEO 未启用');
|
|
});
|
|
|
|
test('GET /plaza/v1/seo/sitemap preserves query forwarding and response envelope', async () => {
|
|
const api = createRouterRecorder();
|
|
const sitemap = { categories: [], posts: [{ id: 'post-1' }], users: [] };
|
|
let receivedLimits = null;
|
|
const { calls, dependencies } = createRouteDependencies({
|
|
getPlazaPosts: () => ({}),
|
|
getPlazaSeo: () => ({
|
|
async listSitemapData(limits) {
|
|
receivedLimits = limits;
|
|
return sitemap;
|
|
},
|
|
}),
|
|
});
|
|
attachPortalPlazaDiscoveryRoutes(api, dependencies);
|
|
const req = { query: { post_limit: '25', user_limit: '10' } };
|
|
const res = createResponseRecorder();
|
|
|
|
await api.routes.get('/plaza/v1/seo/sitemap')(req, res);
|
|
|
|
assert.deepEqual(receivedLimits, { postLimit: '25', userLimit: '10' });
|
|
assert.deepEqual(calls.data[0], { res, req, data: sitemap });
|
|
assert.deepEqual(res.body, { data: sitemap });
|
|
});
|
|
|
|
test('GET /plaza/v1/seo/sitemap preserves route error mapping', async () => {
|
|
const api = createRouterRecorder();
|
|
const failure = new Error('sitemap query failed');
|
|
const { calls, dependencies } = createRouteDependencies({
|
|
getPlazaPosts: () => ({}),
|
|
getPlazaSeo: () => ({
|
|
async listSitemapData() {
|
|
throw failure;
|
|
},
|
|
}),
|
|
});
|
|
attachPortalPlazaDiscoveryRoutes(api, dependencies);
|
|
const req = { query: {} };
|
|
const res = createResponseRecorder();
|
|
|
|
await api.routes.get('/plaza/v1/seo/sitemap')(req, res);
|
|
|
|
assert.deepEqual(calls.routeErrors[0], { res, req, error: failure });
|
|
assert.equal(res.statusCode, 418);
|
|
assert.deepEqual(res.body, { mapped: 'sitemap query failed' });
|
|
});
|