diff --git a/apps/readest-app/src/__tests__/app/opds/opds-content.test.ts b/apps/readest-app/src/__tests__/app/opds/opds-content.test.ts
new file mode 100644
index 00000000..ea902567
--- /dev/null
+++ b/apps/readest-app/src/__tests__/app/opds/opds-content.test.ts
@@ -0,0 +1,117 @@
+import { describe, it, expect } from 'vitest';
+import { getPublication } from 'foliate-js/opds.js';
+import { getOPDSDescriptionHtml } from '@/app/opds/utils/opdsContent';
+import { SYMBOL, type OPDSPublication } from '@/types/opds';
+
+// Render an HTML string the way `dangerouslySetInnerHTML` would and return the
+// visible text, so a test can tell "renders as markup" from "shows raw tags".
+const renderedText = (html: string): string => {
+ const el = document.createElement('div');
+ el.innerHTML = html;
+ return el.textContent ?? '';
+};
+
+const parsePublication = (entryInner: string): OPDSPublication => {
+ const xml = `
Hi "q"
', type: 'text' as const }; + const html = getOPDSDescriptionHtml(content); + expect(html).toContain(''); + expect(renderedText(html)).toBe('Hi "q"'); + }); + + it('renders HTML for type="html" content', () => { + const content = { value: '
Hello world
', type: 'html' as const }; + const html = getOPDSDescriptionHtml(content); + expect(html).toContain(''); + expect(renderedText(html)).toBe('Hello world'); + }); + + it('renders xhtml content and unwraps the namespaced wrapper div', () => { + const content = { + value: 'Hi
'); + expect(text).not.toContain('"'); + expect(text).not.toContain('''); + expect(text).toContain('Creators'); + expect(text).toContain('"Wall"'); + expect(text).toContain("Sollenar's"); + // The markup itself contains real paragraph elements. + expect(html).toContain('
');
+ });
+
+ it('end-to-end: a double-escaped Atom entry (issue #4503) renders as HTML', () => {
+ const pub = parsePublication(
+ '
'); + expect(text).toContain('Creators: Algis Budrys'); + expect(text).toContain('"Wall of Crystal"'); + expect(html).toContain('
');
+ });
+
+ it('leaves mixed real-and-escaped markup untouched (no over-decoding)', () => {
+ // Author intentionally shows a literal Use <code> here Hi tag inside a real paragraph.
+ const content = { value: ' here');
+ });
+
+ it('strips scripts from untrusted feed HTML', () => {
+ const content = {
+ value: '