From 58dc00de5388ca5e220933ccf1dd65e8a169aa29 Mon Sep 17 00:00:00 2001 From: Siddharth VP Date: Sun, 22 Sep 2024 17:58:15 +0530 Subject: [PATCH] page: fix inconsistent behaviour in getRedirectTarget(), other refactoring Fixes #75 --- src/page.ts | 64 +++++++++++++++------------------------------- tests/page.test.js | 13 +++++++--- 2 files changed, 30 insertions(+), 47 deletions(-) diff --git a/src/page.ts b/src/page.ts index 6f66e9f..366b50f 100644 --- a/src/page.ts +++ b/src/page.ts @@ -1,6 +1,5 @@ import { MwnError } from './error'; - -import type { Mwn, MwnTitle, EditTransform } from './bot'; +import type { Mwn, MwnTitle, EditTransform, ApiQueryResponse } from './bot'; import type { ApiDeleteParams, ApiEditPageParams, @@ -19,7 +18,6 @@ export interface MwnPageStatic { } export interface MwnPage extends MwnTitle { - data: any; getTalkPage(): MwnPage; getSubjectPage(): MwnPage; /** @@ -166,8 +164,6 @@ export interface MwnPage extends MwnTitle { export default function (bot: Mwn): MwnPageStatic { class Page extends bot.Title implements MwnPage { - data: any; - constructor(title: MwnTitle | string, namespace?: number) { // bot property is set by mwn#Page() method if (typeof title === 'string') { @@ -177,7 +173,6 @@ export default function (bot: Mwn): MwnPageStatic { } else { throw new Error('unknown constructor type for mwn Page'); } - this.data = {}; } /** @@ -311,8 +306,7 @@ export default function (bot: Mwn): MwnPageStatic { /** @inheritDoc */ subpages(options?: ApiQueryAllPagesParams): Promise { return bot - .request({ - action: 'query', + .query({ list: 'allpages', apprefix: this.title + '/', apnamespace: this.namespace, @@ -320,7 +314,7 @@ export default function (bot: Mwn): MwnPageStatic { ...options, }) .then((data) => { - return data.query.allpages.map((pg: ApiPage) => pg.title); + return data.query.allpages.map((pg) => pg.title); }); } @@ -333,33 +327,21 @@ export default function (bot: Mwn): MwnPageStatic { /** @inheritDoc */ getRedirectTarget(): Promise { - if (this.data.text) { - let target = /^\s*#redirect \[\[(.*?)\]\]/.exec(this.data.text); - if (!target) { - return Promise.resolve(this.toText()); - } - return Promise.resolve(new bot.Title(target[1]).toText()); - } return bot - .request({ - action: 'query', + .query({ titles: this.toString(), - redirects: '1', + redirects: true, }) .then((data) => { - let page = data.query.pages[0]; - if (page.missing) { - return Promise.reject(new MwnError.MissingPage()); - } - return page.title; + this.throwIfPageMissing(data); + return data.query.pages[0].title; }); } /** @inheritDoc */ getCreator(): Promise { return bot - .request({ - action: 'query', + .query({ titles: this.toString(), prop: 'revisions', rvprop: 'user', @@ -367,11 +349,8 @@ export default function (bot: Mwn): MwnPageStatic { rvdir: 'newer', }) .then((data) => { - let page = data.query.pages[0]; - if (page.missing) { - return Promise.reject(new MwnError.MissingPage()); - } - return page.revisions[0].user; + this.throwIfPageMissing(data); + return data.query.pages[0].revisions[0].user; }); } @@ -396,19 +375,14 @@ export default function (bot: Mwn): MwnPageStatic { /** @inheritDoc */ getDescription(customOptions: WikibaseClientApiDescriptionParams) { - // ApiParams return bot - .request({ - action: 'query', + .query({ prop: 'description', titles: this.toString(), ...customOptions, }) .then((data) => { - let page = data.query.pages[0]; - if (page.missing) { - return Promise.reject(new MwnError.MissingPage()); - } + this.throwIfPageMissing(data); return data.query.pages[0].description; }); } @@ -420,8 +394,7 @@ export default function (bot: Mwn): MwnPageStatic { customOptions?: ApiQueryRevisionsParams ): Promise { return bot - .request({ - action: 'query', + .query({ prop: 'revisions', titles: this.toString(), rvprop: props || 'ids|timestamp|flags|comment|user', @@ -429,10 +402,7 @@ export default function (bot: Mwn): MwnPageStatic { ...customOptions, }) .then((data) => { - let page = data.query.pages[0]; - if (page.missing) { - return Promise.reject(new MwnError.MissingPage()); - } + this.throwIfPageMissing(data); return data.query.pages[0].revisions; }); } @@ -507,6 +477,12 @@ export default function (bot: Mwn): MwnPageStatic { } } + private throwIfPageMissing(data: ApiQueryResponse) { + if (data.query.pages[0].missing || data.query.pages[0].invalid) { + throw new MwnError.MissingPage(); + } + } + /** @inheritDoc */ async pageViews(options: PageViewOptions = {}): Promise { let project = bot.options.apiUrl.match(/.*\/(.*?)\.(?:org|com|net)/)?.[1]; diff --git a/tests/page.test.js b/tests/page.test.js index 98a4ce8..83f2064 100644 --- a/tests/page.test.js +++ b/tests/page.test.js @@ -1,6 +1,7 @@ 'use strict'; const { bot, expect, teardown } = require('./base/test_wiki'); +const { MwnError } = require('../build/error'); describe('Page', async function () { this.timeout(10000); @@ -40,8 +41,7 @@ describe('Page', async function () { return page.categories().then((cats) => { expect(cats).to.be.instanceOf(Array); expect(cats.length).to.be.gte(1); // check it on testwiki, could change - expect(cats[0].category).to.be.a('string'); - expect(cats[0].sortkey).to.be.a('string'); + expect(cats[0]).to.be.a('string'); }); }); @@ -90,10 +90,17 @@ describe('Page', async function () { return page.links().then((links) => { expect(links).to.be.instanceOf(Array); expect(links.length).to.be.gte(1); - expect(links[0].title).to.be.a('string'); + expect(links[0]).to.be.a('string'); }); }); + it('links on non-existing page', async function () { + await expect(new bot.Page('1239012390e32413').links()) + .to.be.eventually.rejectedWith(MwnError) + .that.has.property('code') + .which.equals('missingtitle'); + }); + it('backlinks', function () { return page.backlinks().then((backlinks) => { expect(backlinks).to.be.instanceOf(Array);