diff --git a/library/html-server.js b/library/html-server.js index bb89dcd..fc54436 100644 --- a/library/html-server.js +++ b/library/html-server.js @@ -72,7 +72,8 @@ class HtmlServer { .replace(/\[%total-packages%\]/g, escape(renderOptions.totalPackages.toLocaleString())) .replace(/\[%endpoint-path%\]/g, escape(renderOptions.endpointpath)) .replace(/\[%fhir-version%\]/g, escape(renderOptions.fhirversion)) - .replace(/\[%ms%\]/g, escape(renderOptions.processingTime.toString())); + .replace(/\[%ms%\]/g, escape(renderOptions.processingTime.toString())) + .replace(/\[%about%\]/g, renderOptions.about || ''); // Handle any custom template variables if (options.templateVars) { diff --git a/root-template.html b/root-template.html index 0581173..284c91f 100644 --- a/root-template.html +++ b/root-template.html @@ -74,6 +74,7 @@

[%content%] +[%about%] diff --git a/server.js b/server.js index 997bc9c..4098096 100644 --- a/server.js +++ b/server.js @@ -382,12 +382,20 @@ app.get('/', async (req, res) => { } const content = await buildRootPageContent(); - + + // Load optional about box fragment from data directory + let about = ''; + const aboutPath = path.join(folders.dataDir(), 'about.html'); + if (fs.existsSync(aboutPath)) { + about = fs.readFileSync(aboutPath, 'utf8'); + } + // Build basic stats for root page const stats = { version: packageJson.version, enabledModules: Object.keys(config.modules).filter(m => config.modules[m].enabled).length, - processingTime: Date.now() - startTime + processingTime: Date.now() - startTime, + about }; const html = htmlServer.renderPage('root', escape(config.hostName) || 'FHIRsmith Server', content, stats); diff --git a/tests/server/about-box.test.js b/tests/server/about-box.test.js new file mode 100644 index 0000000..94bd791 --- /dev/null +++ b/tests/server/about-box.test.js @@ -0,0 +1,59 @@ +const path = require('path'); +const fs = require('fs'); +const tmp = require('tmp'); + +const HtmlServer = require('../../library/html-server').constructor; + +describe('About box', () => { + let htmlServer; + let tmpDir; + + beforeAll(() => { + tmpDir = tmp.dirSync({ unsafeCleanup: true }); + htmlServer = new HtmlServer(); + htmlServer.useLog({ error: jest.fn(), warn: jest.fn() }); + + // Load root template + const templatePath = path.join(__dirname, '../../root-template.html'); + htmlServer.loadTemplate('root', templatePath); + }); + + afterAll(() => { + tmpDir.removeCallback(); + }); + + test('renders about content when provided', () => { + const aboutHtml = '
Custom About Content
'; + const html = htmlServer.renderPage('root', 'Test', '

Main

', { + version: '1.0.0', + processingTime: 0, + about: aboutHtml + }); + expect(html).toContain('Custom About Content'); + expect(html).toContain('
'); + }); + + test('renders empty when about is not provided', () => { + const html = htmlServer.renderPage('root', 'Test', '

Main

', { + version: '1.0.0', + processingTime: 0 + }); + expect(html).not.toContain('[%about%]'); + }); + + test('about.html is loaded from data directory when it exists', () => { + const aboutContent = '

Server operated by Acme Corp

'; + fs.writeFileSync(path.join(tmpDir.name, 'about.html'), aboutContent); + + const aboutPath = path.join(tmpDir.name, 'about.html'); + expect(fs.existsSync(aboutPath)).toBe(true); + + const loaded = fs.readFileSync(aboutPath, 'utf8'); + expect(loaded).toBe(aboutContent); + }); + + test('missing about.html does not cause errors', () => { + const aboutPath = path.join(tmpDir.name, 'nonexistent', 'about.html'); + expect(fs.existsSync(aboutPath)).toBe(false); + }); +});