From 357097ab7d58fbedcb843a6cfdd2d72945184379 Mon Sep 17 00:00:00 2001 From: Ruthenic Date: Tue, 3 Jan 2023 22:11:49 -0500 Subject: [PATCH] make chapters manually inited --- src/classes/Chapter.ts | 88 ++++++++++++------------------------------ src/classes/Work.ts | 13 ------- tests/chapter.ts | 38 ++++++++++++------ tests/search.ts | 1 - 4 files changed, 51 insertions(+), 89 deletions(-) diff --git a/src/classes/Chapter.ts b/src/classes/Chapter.ts index ae6d53c..c4dcfce 100644 --- a/src/classes/Chapter.ts +++ b/src/classes/Chapter.ts @@ -4,26 +4,16 @@ export default class Chapter { #session: { get: (path: string) => Promise; }; - isInited = false; #document!: HTMLDocument; #DOMParser: DOMParser; - #id: ID; - #workID: ID; - #name!: string; - #html!: string; - #text!: string; - #summary!: string; - #startNote!: string; - #endNote!: string; - earlyName?: Promise; - id!: Promise; - workID!: Promise; - name!: Promise; - html!: Promise; - text!: Promise; - summary!: Promise; - startNote!: Promise; - endNote!: Promise; + id: ID; + workID: ID; + name!: string; + html!: string; + text!: string; + summary!: string; + startNote!: string; + endNote!: string; constructor( workId: ID, @@ -36,45 +26,15 @@ export default class Chapter { extraInfo: Record, ) { this.#session = session; - this.#workID = workId; - this.#id = id; + this.workID = workId; + this.id = id; this.#DOMParser = DOMParser; - this.earlyName = extraInfo.name; - - return new Proxy(this, { - get: async (target, prop) => { - if (prop === "earlyName") { - return this.earlyName; - } - if (!this.isInited) { - await target.init(); - target.isInited = true; - } - switch (prop) { - case "id": - return target.#id; - case "workID": - return target.#workID; - case "name": - return target.#name; - case "html": - return target.#html; - case "text": - return target.#text; - case "summary": - return target.#summary; - case "startNote": - return target.#startNote; - case "endNote": - return target.#endNote; - } - }, - }); + this.name = extraInfo.name; } async init() { const res = await this.#session.get( - `/works/${this.#workID}/chapters/${this.#id}?view_adult=true`, + `/works/${this.workID}/chapters/${this.id}?view_adult=true`, ); this.#document = this.#DOMParser.parseFromString( await res.text(), @@ -93,7 +53,7 @@ export default class Chapter { } populateMetadata() { - this.#name = this.#document.querySelector("h3.title")?.innerText + this.name = this.#document.querySelector("h3.title")?.innerText .replace( /Chapter \d+: /, "", @@ -101,7 +61,7 @@ export default class Chapter { } populateSummary() { - this.#summary = this.#document.querySelector("#summary > .userstuff") + this.summary = this.#document.querySelector("#summary > .userstuff") ?.innerText.trim() as string; } @@ -109,14 +69,14 @@ export default class Chapter { const notesList = Array.from( this.#document.querySelectorAll(".notes > .userstuff"), ).map((n) => (n as Element).innerHTML); - this.#startNote = notesList[0]?.trim()?.replace(/<\/{0,1}p>/g, "\n") + this.startNote = notesList[0]?.trim()?.replace(/<\/{0,1}p>/g, "\n") ?.trim(); - this.#endNote = notesList[1]?.trim()?.replace(/<\/{0,1}p>/g, "\n") + this.endNote = notesList[1]?.trim()?.replace(/<\/{0,1}p>/g, "\n") ?.trim(); } async populateText() { - this.#text = ""; + this.text = ""; const elements = this.#document.querySelectorAll( "div.userstuff[role='article'] > p", @@ -125,25 +85,25 @@ export default class Chapter { for (let i = 0; i < elements.length; i++) { const element = elements[i] as Element; - this.#text += element.innerText + "\n"; + this.text += element.innerText + "\n"; } try { - this.#text = this.#text.trim(); + this.text = this.text.trim(); - this.#html = (this.#document.querySelector( + this.html = (this.#document.querySelector( "div.userstuff[role='article']", ) as Element).innerHTML; } catch { //assume single chapter work const res = await this.#session.get( - `/works/${this.#workID}?view_adult=true`, + `/works/${this.workID}?view_adult=true`, ); this.#document = this.#DOMParser.parseFromString( await res.text(), "text/html", ) as HTMLDocument; - this.#html = (this.#document.querySelector( + this.html = (this.#document.querySelector( "[role='article'] > div.userstuff", ) as Element).innerHTML; @@ -154,8 +114,8 @@ export default class Chapter { for (let i = 0; i < elements.length; i++) { const element = elements[i] as Element; - this.#text += element.innerText + "\n"; - this.#html += element.innerHTML; + this.text += element.innerText + "\n"; + this.html += element.innerHTML; } } } diff --git a/src/classes/Work.ts b/src/classes/Work.ts index e881745..e7c51d8 100644 --- a/src/classes/Work.ts +++ b/src/classes/Work.ts @@ -75,19 +75,6 @@ export default class Work { } populateTags() { - /* this.#document.querySelectorAll("dd.fandom > ul.commas > li").map( - (t) => this.tags.push(t.text), - ); - this.#document.querySelectorAll("dd.relationship > ul.commas > li").map( - (t) => this.tags.push(t.text), - ); - this.#document.querySelectorAll("dd.character > ul.commas > li").map( - (t) => this.tags.push(t.text), - ); - this.#document.querySelectorAll("dd.freeform > ul.commas > li").map( - (t) => this.tags.push(t.text), - ); */ - const elements = this.#document.querySelectorAll("dd > ul.commas > li"); for (let i = 0; i < elements.length; i++) { diff --git a/tests/chapter.ts b/tests/chapter.ts index 20f5f37..de1bf69 100644 --- a/tests/chapter.ts +++ b/tests/chapter.ts @@ -1,40 +1,56 @@ //FIXME: we need to test single-chapter works too (because those seem to be really inconsistent for some reason?) import AO3 from "../mod.ts"; -import { assert } from "https://deno.land/std@0.167.0/testing/asserts.ts"; +import { + assert, + AssertionError, +} from "https://deno.land/std@0.167.0/testing/asserts.ts"; export default function test(ao3: AO3) { Deno.test("chapters", async (test) => { const work = await ao3.getWork("43251729"); await work.init(); - assert(work.chapters.length > 0, "chapters array is not initialized"); - await test.step("IDs", async () => { + await test.step("initialization", async () => { assert( - await work.chapters[0].id === "108714198", + work.chapters.length > 0, + "chapters array is not initialized", + ); + + try { + await work.chapters[0].init(); + await work.chapters[3].init(); + } catch { + throw new AssertionError("failed to initialize chapter"); + } + }); + + await test.step("IDs", () => { + assert( + work.chapters[0].id === "108714198", "incorrect chapter ID", ); assert( - await work.chapters[0].workID === "43251729", + work.chapters[0].workID === "43251729", "incorrect work ID", ); //why do we even store the work's ID publicly in a chapter? }); - await test.step("name", async () => { + await test.step("name", () => { assert( - await work.chapters[0].name === "Welcome to the Studio", + work.chapters[0].name === "Welcome to the Studio", "incorrect/missing chapter names", ); }); - await test.step("content", async () => { + await test.step("content", () => { //FIXME: this should probably be tested better assert( - (await work.chapters[0].text).length > 0, + (work.chapters[0].text).length > 0, "text/content is completely missing", ); }); - await test.step("notes and summary", async () => { + await test.step("notes and summary", () => { //FIXME: write a chapter of my fic (lol) that includes a summary and end note for testing assert( - await work.chapters[3].startNote === + work.chapters[3].startNote === `If you haven't noticed yet, most of these chapters are named after Bendy fansongs This is definitely because I'm trying to be smart and cool and make funny references, and definitely not because I'm uncreative :)`, diff --git a/tests/search.ts b/tests/search.ts index c81fa00..4da4b1e 100644 --- a/tests/search.ts +++ b/tests/search.ts @@ -1,5 +1,4 @@ import AO3 from "../mod.ts"; -import type { Search } from "../mod.ts"; import { assert } from "https://deno.land/std@0.167.0/testing/asserts.ts"; export default function test(ao3: AO3) {