'use strict'; const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs/promises'); const os = require('node:os'); const path = require('node:path'); const { adapterFor } = require('../adapters'); const { parse } = require('../plugins/registry'); const { discoverMangaPillCatalog, discoverMangaPillChapter } = require('../adapters/mangapill'); const { validateHostRequest } = require('../plugins/broker'); const { runArchive } = require('../jobs/weebcentral-archive'); const { Canvas } = require('../../tools/png'); const { scanLibrary } = require('../lib/library-inventory'); const seriesUrl = 'https://mangapill.com/manga/552/bleach'; const chapterUrl = 'https://mangapill.com/chapters/552-10001000/bleach-chapter-1'; const imageUrl = 'https://cdn.readdetectiveconan.com/file/mangap/552/10001000/1.jpg'; const catalogHtml = `

Bleach

Chapter 2Chapter 1
`; const chapterHtml = ``; test('MangaPill discovery stays in its host and keeps ordered source chapter IDs', async () => { assert.equal(adapterFor(seriesUrl).adapter.id, 'mangapill'); assert.equal(adapterFor('http://mangapill.com/manga/552/bleach'), null); const http = { async get(url) { assert.ok([seriesUrl, chapterUrl].includes(url)); return { async text() { return url === seriesUrl ? catalogHtml : chapterHtml; } }; } }; const catalog = await discoverMangaPillCatalog(seriesUrl, http); assert.deepEqual(catalog.chapters.map(chapter => [chapter.id, chapter.number]), [['552-10001000', '1'], ['552-10002000', '2']]); const chapter = await discoverMangaPillChapter(catalog.chapters[0], http); assert.deepEqual(chapter.pages, [{ url: imageUrl, headers: { referer: chapterUrl } }]); assert.throws(() => parse('mangapill', 'pages', { html: '', url: chapterUrl, }), /page host/); assert.throws(() => validateHostRequest('https://other.example/manga/552', 'mangapill.com', { accept: 'text/html' }), /left its source host/); }); test('MangaPill uses the shared checkpoint-safe publisher and skips an existing chapter', async t => { const root = await fs.mkdtemp(path.join(os.tmpdir(), 'mc-mangapill-')); t.after(() => fs.rm(root, { recursive: true, force: true })); const png = new Canvas(10, 20, [1, 2, 3]).png(); const createHttp = () => ({ async get(url) { if (url === seriesUrl) return { async text() { return catalogHtml.replace(/]*>Chapter 2<\/a>/, ''); } }; if (url === chapterUrl) return { async text() { return chapterHtml; } }; if (url === imageUrl) return { async arrayBuffer() { return png; } }; throw new Error(`Unexpected source request: ${url}`); } }); const options = { source: 'mangapill', sourceLabel: 'MangaPill', sourceId: '552', discoverCatalog: discoverMangaPillCatalog, discoverChapter: discoverMangaPillChapter, createHttp, seriesUrl, libraryRoot: root, scope: { mode: 'missing' }, minMs: 1000, maxMs: 1000, chapterMinMs: 5000, chapterMaxMs: 5000 }; const first = await runArchive(options); assert.equal(first.publishedCount, 1); const manga = (await scanLibrary(root)).mangas[0]; assert.equal(manga.ids.mangapill, '552'); assert.equal(manga.chapters[0].sourceKey, 'mangapill'); const second = await runArchive(options); assert.equal(second.publishedCount, 0); assert.equal(second.selectedCount, 0); });