253 lines
7.5 KiB
TypeScript
253 lines
7.5 KiB
TypeScript
/*
|
|
* decaffeinate suggestions:
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
* DS205: Consider reworking code to avoid use of IIFEs
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
*/
|
|
|
|
import Notice from "../classes/Notice";
|
|
import Post from "../classes/Post";
|
|
import Config from "../config/Config";
|
|
import Filter from "../Filtering/Filter";
|
|
import ImageHost from "../Images/ImageHost";
|
|
import Keybinds from "../Miscellaneous/Keybinds";
|
|
import Unread from "../Monitoring/Unread";
|
|
import $$ from "../platform/$$";
|
|
import $ from "../platform/$";
|
|
import Header from "./Header";
|
|
import { g, Conf, c } from "../globals/globals";
|
|
import Menu from "../Menu/Menu";
|
|
|
|
const Test = {
|
|
init() {
|
|
if ((g.SITE.software !== 'yotsuba') || !['index', 'thread'].includes(g.VIEW)) { return; }
|
|
|
|
if (Conf['Menu']) {
|
|
const a = $.el('a',
|
|
{textContent: 'Test HTML building'});
|
|
$.on(a, 'click', this.cb.testOne);
|
|
Menu.menu.addEntry({
|
|
el: a,
|
|
open(post) {
|
|
a.dataset.fullID = post.fullID;
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
|
|
const a2 = $.el('a',
|
|
{textContent: 'Test HTML building'});
|
|
$.on(a2, 'click', this.cb.testAll);
|
|
Header.menu.addEntry({
|
|
el: a2});
|
|
|
|
if (Unread.posts) {
|
|
const testOrderLink = $.el('a',
|
|
{textContent: 'Test Post Order'});
|
|
$.on(testOrderLink, 'click', this.cb.testOrder);
|
|
Header.menu.addEntry({
|
|
el: testOrderLink});
|
|
}
|
|
|
|
return $.on(d, 'keydown', this.cb.keydown);
|
|
},
|
|
|
|
assert(condition) {
|
|
if (!condition()) {
|
|
return new Notice('warning', `Assertion failed: ${condition}`, 30);
|
|
}
|
|
},
|
|
|
|
normalize(root) {
|
|
let el, i;
|
|
let node;
|
|
const root2 = root.cloneNode(true);
|
|
for (el of $$('.mobile', root2)) {
|
|
$.rm(el);
|
|
}
|
|
for (el of $$('a[href]', root2)) {
|
|
var {
|
|
href
|
|
} = el;
|
|
href = href.replace(/(^\w+:\/\/boards\.4chan(?:nel)?\.org\/[^\/]+\/thread\/\d+)\/.*/, '$1');
|
|
el.setAttribute('href', href);
|
|
}
|
|
ImageHost.fixLinks($$('.fileText > a, a.fileThumb', root2));
|
|
for (el of $$('img[src]', root2)) {
|
|
el.src = el.src.replace(/(spoiler-\w+)\d(\.png)$/, '$11$2');
|
|
}
|
|
for (el of $$('pre.prettyprinted', root2)) {
|
|
var nodes = $.X('.//br|.//wbr|.//text()', el);
|
|
i = 0;
|
|
nodes = ((() => {
|
|
const result = [];
|
|
while (node = nodes.snapshotItem(i++)) {
|
|
result.push(node);
|
|
}
|
|
return result;
|
|
})());
|
|
$.rmAll(el);
|
|
$.add(el, nodes);
|
|
el.normalize();
|
|
$.rmClass(el, 'prettyprinted');
|
|
}
|
|
for (el of $$('pre[style=""]', root2)) {
|
|
el.removeAttribute('style');
|
|
}
|
|
// XXX https://bugzilla.mozilla.org/show_bug.cgi?id=1021289
|
|
$('.fileInfo[data-md5]', root2)?.removeAttribute('data-md5');
|
|
const textNodes = $.X('.//text()', root2);
|
|
i = 0;
|
|
while (node = textNodes.snapshotItem(i++)) {
|
|
node.data = node.data.replace(/\ +/g, ' ');
|
|
// XXX https://a.4cdn.org/sci/thread/5942502.json, https://a.4cdn.org/news/thread/6.json, https://a.4cdn.org/wsg/thread/957536.json
|
|
if (node.previousSibling?.nodeName === 'BR') { node.data = node.data.replace(/^\n+/g, ''); }
|
|
if (node.nextSibling?.nodeName === 'BR') { node.data = node.data.replace(/\n+$/g, ''); }
|
|
if (node.data === '') { $.rm(node); }
|
|
}
|
|
return root2;
|
|
},
|
|
|
|
firstDiff(x, y) {
|
|
let x2 = x.cloneNode(false);
|
|
let y2 = y.cloneNode(false);
|
|
if (!x2.isEqualNode(y2)) { return [x2, y2]; }
|
|
let i = 0;
|
|
while (true) {
|
|
x2 = x.childNodes[i];
|
|
y2 = y.childNodes[i];
|
|
if (!x2 || !y2) { return [x2, y2]; }
|
|
if (!x2.isEqualNode(y2)) { return Test.firstDiff(x2, y2); }
|
|
i++;
|
|
}
|
|
},
|
|
|
|
testOne(post) {
|
|
Test.postsRemaining++;
|
|
return $.cache(g.SITE.urls.threadJSON({boardID: post.boardID, threadID: post.threadID}), function() {
|
|
if (!this.response) { return; }
|
|
const {posts} = this.response;
|
|
g.SITE.Build.spoilerRange[post.board.ID] = posts[0].custom_spoiler;
|
|
for (var postData of posts) {
|
|
if (postData.no === post.ID) {
|
|
var t1 = new Date().getTime();
|
|
var obj = g.SITE.Build.parseJSON(postData, post.board);
|
|
var root = g.SITE.Build.post(obj);
|
|
var t2 = new Date().getTime();
|
|
Test.time += t2 - t1;
|
|
var post2 = new Post(root, post.thread, post.board, {forBuildTest: true});
|
|
var fail = false;
|
|
|
|
var x = post.normalizedOriginal;
|
|
var y = post2.normalizedOriginal;
|
|
if (!x.isEqualNode(y)) {
|
|
fail = true;
|
|
c.log(`${post.fullID} differs`);
|
|
var [x2, y2] = Test.firstDiff(x, y);
|
|
c.log(x2);
|
|
c.log(y2);
|
|
c.log(x.outerHTML);
|
|
c.log(y.outerHTML);
|
|
}
|
|
|
|
for (var key in Config.filter) {
|
|
if ((!key === 'General') && !((key === 'MD5') && (post.board.ID === 'f'))) {
|
|
var val1 = Filter.values(key, obj);
|
|
var val2 = Filter.values(key, post2);
|
|
if ((val1.length !== val2.length) || !val1.every((x, i) => x === val2[i])) {
|
|
fail = true;
|
|
c.log(`${post.fullID} has filter bug in ${key}`);
|
|
c.log(val1);
|
|
c.log(val2);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fail) {
|
|
Test.postsFailed++;
|
|
} else {
|
|
c.log(`${post.fullID} correct`);
|
|
}
|
|
Test.postsRemaining--;
|
|
if (Test.postsRemaining === 0) { Test.report(); }
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
testAll() {
|
|
g.posts.forEach(function(post) {
|
|
if (!post.isClone && !post.isFetchedQuote) {
|
|
let abbr;
|
|
if (!((abbr = $('.abbr', post.nodes.comment)) && /Comment too long\./.test(abbr.textContent))) {
|
|
return Test.testOne(post);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
postsRemaining: 0,
|
|
postsFailed: 0,
|
|
time: 0,
|
|
|
|
report() {
|
|
if (Test.postsFailed) {
|
|
new Notice('warning', `${Test.postsFailed} post(s) differ (${Test.time} ms)`, 30);
|
|
} else {
|
|
new Notice('success', `All correct (${Test.time} ms)`, 5);
|
|
}
|
|
return Test.postsFailed = (Test.time = 0);
|
|
},
|
|
|
|
cb: {
|
|
testOne() {
|
|
Test.testOne(g.posts.get(this.dataset.fullID));
|
|
return Menu.menu.close();
|
|
},
|
|
|
|
testAll() {
|
|
Test.testAll();
|
|
return Header.menu.close();
|
|
},
|
|
|
|
testOrder() {
|
|
let x;
|
|
const list1 = ((() => {
|
|
const result = [];
|
|
for (x of Unread.order.order()) { result.push(x.ID);
|
|
}
|
|
return result;
|
|
})());
|
|
const list2 = ((() => {
|
|
const result1 = [];
|
|
for (x of ($$((g.SITE.isOPContainerThread ? `${g.SITE.selectors.thread}, ` : '') + g.SITE.selectors.postContainer))) { result1.push(+x.id.match(/\d*$/)[0]);
|
|
}
|
|
return result1;
|
|
})());
|
|
const pass = (function() {
|
|
if (list1.length !== list2.length) { return false; }
|
|
for (let i = 0, end = list1.length; i < end; i++) {
|
|
if (list1[i] !== list2[i]) { return false; }
|
|
}
|
|
return true;
|
|
})();
|
|
if (pass) {
|
|
return new Notice('success', `Orders same (${list1.length} posts)`, 5);
|
|
} else {
|
|
new Notice('warning', 'Orders differ.', 30);
|
|
c.log(list1);
|
|
return c.log(list2);
|
|
}
|
|
},
|
|
|
|
keydown(e) {
|
|
if (Keybinds.keyCode(e) !== 'v') { return; }
|
|
if (['INPUT', 'TEXTAREA'].includes(e.target.nodeName)) { return; }
|
|
Test.testAll();
|
|
e.preventDefault();
|
|
return e.stopPropagation();
|
|
}
|
|
}
|
|
};
|
|
export default Test;
|