Compare commits
3 Commits
d078339288
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5d6a0d7d41 | |||
| bde00f27d3 | |||
| 893fe47ace |
File diff suppressed because it is too large
Load Diff
@@ -86,43 +86,43 @@ assert.match(
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/data-tm-thumb-scale-following-list="1"[\s\S]*--tm-thumb-following-list-columns/,
|
||||
"followed-cams list should be separated from homepage list column count",
|
||||
/data-tm-thumb-scale-following-list="1"[\s\S]*--tm-thumb-following-list-min-width/,
|
||||
"followed-cams list should use its own detected minimum column width",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/data-tm-thumb-scale-following-list="1"[\s\S]*grid-template-columns:\s*repeat\(var\(--tm-thumb-following-list-columns\),\s*minmax\(0,\s*1fr\)\)\s*!important/,
|
||||
"followed-cams list should reduce the original column count and keep 1fr alignment",
|
||||
/data-tm-thumb-scale-following-list="1"[\s\S]*grid-template-columns:\s*repeat\(auto-fill,\s*minmax\(var\(--tm-thumb-following-list-min-width\),\s*1fr\)\)\s*!important/,
|
||||
"followed-cams list should reduce columns responsively using scaled minimum width",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/#main\.roomPage\s+ul\.list:has\(li\.roomCard\)\s+\.room_thumbnail_container[\s\S]*width:\s*100%\s*!important[\s\S]*height:\s*var\(--tm-thumb-related-height\)\s*!important/,
|
||||
"room page related rooms thumbnail containers should follow card width and use detected height",
|
||||
/#main\.roomPage\s+ul\.list:has\(li\.roomCard\)\s+\.room_thumbnail_container[\s\S]*width:\s*100%\s*!important[\s\S]*height:\s*auto\s*!important/,
|
||||
"room page related rooms thumbnail containers should follow card width and automatic height",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/\.BaseRoomContents\s+ul\.list:has\(li\.roomCard\)\s+\.room_thumbnail[\s\S]*width:\s*100%\s*!important[\s\S]*height:\s*var\(--tm-thumb-related-height\)\s*!important/,
|
||||
"base room related thumbnails should follow card width and use detected height",
|
||||
/\.BaseRoomContents\s+ul\.list:has\(li\.roomCard\)\s+\.room_thumbnail[\s\S]*width:\s*100%\s*!important[\s\S]*height:\s*auto\s*!important/,
|
||||
"base room related thumbnails should follow card width and automatic height",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/\.BaseRoomContents\s+ul\.RoomCardGrid[\s\S]*grid-template-columns:\s*repeat\(auto-fill,\s*var\(--tm-thumb-related-width\)\)\s*!important/,
|
||||
"base room RoomCardGrid related rooms should use detected card width",
|
||||
/\.BaseRoomContents\s+ul\.RoomCardGrid[\s\S]*grid-template-columns:\s*repeat\(auto-fill,\s*minmax\(var\(--tm-thumb-related-width\),\s*1fr\)\)\s*!important/,
|
||||
"base room RoomCardGrid related rooms should fill the row using detected scaled minimum width",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/\.BaseRoomContents\s+ul\.RoomCardGrid\s+\.RoomCardThumbnail[\s\S]*width:\s*100%\s*!important[\s\S]*height:\s*var\(--tm-thumb-related-height\)\s*!important/,
|
||||
"base room RoomCardGrid thumbnails should follow card width and use detected height",
|
||||
/\.BaseRoomContents\s+ul\.RoomCardGrid\s+\.RoomCardThumbnail[\s\S]*width:\s*100%\s*!important[\s\S]*height:\s*auto\s*!important/,
|
||||
"base room RoomCardGrid thumbnails should follow card width and automatic height",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/\.BaseRoomContents\s+ul\.RoomCardGrid\s*>\s*li\.RoomCard[\s\S]*height:\s*var\(--tm-thumb-related-card-height\)\s*!important/,
|
||||
"base room RoomCardGrid related cards should use detected card height",
|
||||
/\.BaseRoomContents\s+ul\.RoomCardGrid\s*>\s*li\.RoomCard[\s\S]*height:\s*auto\s*!important[\s\S]*max-height:\s*none\s*!important/,
|
||||
"base room RoomCardGrid related cards should use automatic height",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/\.BaseRoomContents\s+ul\.RoomCardGrid\s*>\s*li\.RoomCard[\s\S]*width:\s*var\(--tm-thumb-related-width\)\s*!important/,
|
||||
"base room RoomCardGrid related cards should use detected card width",
|
||||
/\.BaseRoomContents\s+ul\.RoomCardGrid\s*>\s*li\.RoomCard[\s\S]*width:\s*auto\s*!important[\s\S]*justify-self:\s*stretch\s*!important[\s\S]*max-width:\s*none\s*!important/,
|
||||
"base room RoomCardGrid related cards should stretch to fill responsive columns",
|
||||
);
|
||||
assert.doesNotMatch(capturedCss, /--tm-thumb-min-root:\s*\d+px;/, "script should not hard-code a root thumbnail fallback width");
|
||||
assert.doesNotMatch(capturedCss, /--tm-thumb-height-root:\s*\d+px;/, "script should not hard-code a root thumbnail fallback height");
|
||||
@@ -136,6 +136,11 @@ assert.match(
|
||||
/#discover_root\s+\.room-list-carousel\s+\.room_thumbnail_container\s+img/,
|
||||
"discover carousel thumbnail images should fill enlarged items",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/#discover_root\s+\.room-list-carousel\s+\.room_thumbnail_container[\s\S]*height:\s*var\(--tm-thumb-discover-height\)\s*!important/,
|
||||
"discover carousel thumbnail containers should use detected scaled height",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/height:\s*var\(--tm-thumb-discover-triple-ul\)\s*!important/,
|
||||
@@ -146,6 +151,36 @@ assert.match(
|
||||
/height:\s*var\(--tm-thumb-discover-double-arrow\)\s*!important/,
|
||||
"discover carousel arrow heights should use detected original heights",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/data-tm-thumb-scale-followed-page="1"[\s\S]*\.carousel-root\s+\.single-row\s+ul\.list[\s\S]*height:\s*auto\s*!important[\s\S]*max-height:\s*none\s*!important[\s\S]*overflow:\s*visible\s*!important/,
|
||||
"followed-cams recommendations should release carousel list height after scaling",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/data-tm-thumb-scale-followed-page="1"[\s\S]*grid-template-columns:\s*repeat\(auto-fill,\s*minmax\(var\(--tm-thumb-discover-width\),\s*1fr\)\)\s*!important/,
|
||||
"followed-cams legacy recommendations should use responsive scaled minimum width",
|
||||
);
|
||||
assert.doesNotMatch(
|
||||
capturedCss,
|
||||
/data-tm-thumb-scale-followed-page="1"[\s\S]*grid-template-columns:\s*repeat\(2,/,
|
||||
"followed-cams recommendations should not force a hard-coded two-column layout",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/data-tm-thumb-scale-followed-recommendations="1"[\s\S]*data-tm-thumb-followed-recommendations-list="1"[\s\S]*grid-template-columns:\s*repeat\(auto-fill,\s*minmax\(var\(--tm-thumb-followed-recommendations-width\),\s*1fr\)\)\s*!important[\s\S]*grid-auto-rows:\s*auto\s*!important/,
|
||||
"title-detected followed recommendations should use responsive scaled minimum columns and automatic row height",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/data-tm-thumb-scale-followed-recommendations="1"[\s\S]*data-tm-thumb-followed-recommendations-card="1"[\s\S]*width:\s*auto\s*!important[\s\S]*max-width:\s*none\s*!important[\s\S]*height:\s*auto\s*!important[\s\S]*max-height:\s*none\s*!important/,
|
||||
"title-detected followed recommendation cards should stretch responsively and grow naturally",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/data-tm-thumb-scale-followed-recommendations="1"[\s\S]*data-tm-thumb-followed-recommendations-thumb="1"[\s\S]*height:\s*auto\s*!important/,
|
||||
"title-detected followed recommendation thumbnails should keep automatic height",
|
||||
);
|
||||
assert.match(
|
||||
capturedCss,
|
||||
/#discover_root\s+\.room-list-carousel\s+\.room_thumbnail[\s\S]*height:\s*var\(--tm-thumb-discover-height\)\s*!important/,
|
||||
@@ -176,6 +211,11 @@ assert.match(source, /detectAndApplySizes/, "script should detect original sizes
|
||||
assert.match(source, /moduleReady/, "script should lock each module after detecting its original size");
|
||||
assert.match(source, /CARD_HEIGHT_SCALE/, "script should use a separate scale for card heights");
|
||||
assert.match(source, /setCardHeightVar/, "script should apply card height scaling separately from thumbnail scaling");
|
||||
assert.match(source, /setDiscoverStackHeightVars/, "discover carousel stack heights should be derived from scaled card rows");
|
||||
assert.match(source, /setCardHeightFromThumbVar\("--tm-thumb-discover-card-height"/, "discover card height should scale the thumbnail area and keep metadata height");
|
||||
assert.match(source, /stackHeight == null\) return true/, "discover should not require every carousel row type to exist before enabling");
|
||||
assert.match(source, /TAG_TRANSLATIONS/, "script should include a centralized tag translation table");
|
||||
assert.match(source, /translateTagsPage/, "script should translate the Chaturbate tags page");
|
||||
assert.doesNotMatch(source, /localStorage\.setItem/, "script should not write detected sizes to localStorage");
|
||||
assert.match(source, /LEGACY_CACHE_PREFIX/, "script should only keep legacy cache cleanup support");
|
||||
assert.match(source, /scheduleMeasure\("after-800ms"\)/, "script should delay the first page measurement until original layout can render");
|
||||
@@ -230,6 +270,144 @@ assert.equal(earlyAppendedTarget, null, "GM_addStyle should avoid manual documen
|
||||
assert.equal(typeof earlyDomContentLoadedHandler, "function", "script should reinject after head becomes available");
|
||||
assert.equal(earlyObservedTarget, null, "script should not observe a missing head");
|
||||
|
||||
const tagAnchors = [
|
||||
{
|
||||
href: "https://zh-hans.chaturbate.com/tag/asian/",
|
||||
textContent: "#asian",
|
||||
dataset: {},
|
||||
title: "",
|
||||
getAttribute(name) {
|
||||
return name === "href" ? this.href : "";
|
||||
},
|
||||
},
|
||||
{
|
||||
href: "https://zh-hans.chaturbate.com/tag/bigboobs/",
|
||||
textContent: "#bigboobs",
|
||||
dataset: {},
|
||||
title: "",
|
||||
getAttribute(name) {
|
||||
return name === "href" ? this.href : "";
|
||||
},
|
||||
},
|
||||
{
|
||||
href: "https://zh-hans.chaturbate.com/tag/ebony/female/",
|
||||
textContent: "#ebony",
|
||||
dataset: {},
|
||||
title: "",
|
||||
getAttribute(name) {
|
||||
return name === "href" ? this.href : "";
|
||||
},
|
||||
},
|
||||
{
|
||||
href: "https://zh-hans.chaturbate.com/tag/not-in-table/",
|
||||
textContent: "Not In Table",
|
||||
dataset: {},
|
||||
title: "",
|
||||
getAttribute(name) {
|
||||
return name === "href" ? this.href : "";
|
||||
},
|
||||
},
|
||||
{
|
||||
href: "https://zh-hans.chaturbate.com/tag/new-custom-tag/",
|
||||
textContent: "#new-custom-tag",
|
||||
dataset: {},
|
||||
title: "",
|
||||
getAttribute(name) {
|
||||
return name === "href" ? this.href : "";
|
||||
},
|
||||
},
|
||||
{
|
||||
href: "https://zh-hans.chaturbate.com/tag/colombiana/female/",
|
||||
textContent: "#colombiana",
|
||||
dataset: {},
|
||||
title: "",
|
||||
getAttribute(name) {
|
||||
return name === "href" ? this.href : "";
|
||||
},
|
||||
},
|
||||
{
|
||||
href: "https://zh-hans.chaturbate.com/tag/untranslated-example/",
|
||||
textContent: "#untranslated-example",
|
||||
dataset: {},
|
||||
title: "",
|
||||
getAttribute(name) {
|
||||
return name === "href" ? this.href : "";
|
||||
},
|
||||
},
|
||||
{
|
||||
href: "https://zh-hans.chaturbate.com/tags/female/?page=2",
|
||||
textContent: "2",
|
||||
dataset: {},
|
||||
title: "",
|
||||
getAttribute(name) {
|
||||
return name === "href" ? this.href : "";
|
||||
},
|
||||
},
|
||||
];
|
||||
const tagFakeDocument = {
|
||||
documentElement: {
|
||||
setAttribute() {},
|
||||
},
|
||||
head: {
|
||||
appendChild() {},
|
||||
},
|
||||
body: {},
|
||||
createElement() {
|
||||
return { id: "", textContent: "", setAttribute() {} };
|
||||
},
|
||||
getElementById() {
|
||||
return null;
|
||||
},
|
||||
querySelectorAll(selector) {
|
||||
return selector.includes("/tag") ? tagAnchors : [];
|
||||
},
|
||||
addEventListener() {},
|
||||
};
|
||||
|
||||
const runTagsPageTranslationTest = (pathname = "/tags/") => vm.runInNewContext(source, {
|
||||
console,
|
||||
document: tagFakeDocument,
|
||||
location: {
|
||||
href: `https://zh-hans.chaturbate.com${pathname}`,
|
||||
pathname,
|
||||
},
|
||||
URL,
|
||||
GM_addStyle() {
|
||||
return { id: "", textContent: "", setAttribute() {} };
|
||||
},
|
||||
GM_registerMenuCommand() {},
|
||||
MutationObserver: class {
|
||||
observe() {}
|
||||
},
|
||||
});
|
||||
|
||||
runTagsPageTranslationTest();
|
||||
|
||||
assert.equal(tagAnchors[0].textContent, "亚洲", "tags page should translate known tag link text");
|
||||
assert.equal(tagAnchors[0].dataset.tmTagOriginal, "#asian", "translated tags should keep the original label in dataset");
|
||||
assert.equal(tagAnchors[0].title, "#asian", "translated tags should expose the original label in title");
|
||||
assert.equal(tagAnchors[1].textContent, "大胸", "tags page should translate compact multi-word tag slugs");
|
||||
assert.equal(tagAnchors[2].textContent, "黑人", "gender-scoped tag links should translate by the first slug segment");
|
||||
assert.equal(tagAnchors[3].textContent, "Not In Table", "unknown tags should remain unchanged");
|
||||
assert.equal(tagAnchors[4].textContent, "新自定义标签", "untranslated hashtag-style tags should use slug word translation");
|
||||
assert.equal(tagAnchors[5].textContent, "哥伦比亚女性", "known gendered nationality tags should be translated");
|
||||
assert.equal(tagAnchors[6].textContent, "#untranslated-example", "untranslated hashtag-style tags should keep the original slug");
|
||||
assert.equal(tagAnchors[7].textContent, "2", "tags pagination links should not be translated");
|
||||
|
||||
tagAnchors.forEach((anchor, index) => {
|
||||
anchor.textContent = ["#asian", "#bigboobs", "#ebony", "Not In Table", "#new-custom-tag", "#colombiana", "#untranslated-example", "2"][index];
|
||||
anchor.dataset = {};
|
||||
anchor.title = "";
|
||||
});
|
||||
|
||||
runTagsPageTranslationTest("/tags/female/");
|
||||
assert.equal(tagAnchors[0].textContent, "亚洲", "tag category pages under /tags/ should also translate links");
|
||||
assert.equal(tagAnchors[1].textContent, "大胸", "tag category pages should translate compact slugs too");
|
||||
assert.equal(tagAnchors[2].textContent, "黑人", "tag category pages should translate /tag/slug/gender/ links");
|
||||
assert.equal(tagAnchors[5].textContent, "哥伦比亚女性", "tag category pages should translate gendered nationality links");
|
||||
assert.equal(tagAnchors[6].textContent, "#untranslated-example", "tag category pages should preserve unknown hashtag-style tags");
|
||||
assert.equal(tagAnchors[7].textContent, "2", "tag category page pagination should keep page numbers");
|
||||
|
||||
const followingVars = new Map();
|
||||
const followingAttrs = new Map();
|
||||
const followingFakeDocument = {
|
||||
@@ -272,12 +450,12 @@ vm.runInNewContext(source, {
|
||||
cardHeightScale: 1.55,
|
||||
modules: {
|
||||
home: {
|
||||
homeColumns: 7,
|
||||
homeMinWidth: 190,
|
||||
homeCard: { width: 174, height: 120 },
|
||||
homeThumb: { width: 174, height: 98 },
|
||||
},
|
||||
followingList: {
|
||||
followingListColumns: 7,
|
||||
followingListMinWidth: 190,
|
||||
followingListCard: { width: 190, height: 120 },
|
||||
followingListThumb: { width: 188, height: 106 },
|
||||
},
|
||||
@@ -305,8 +483,8 @@ vm.runInNewContext(source, {
|
||||
|
||||
assert.equal(followingAttrs.get("data-tm-thumb-scale-following-list"), undefined, "followed-cams should not apply legacy cached list module");
|
||||
assert.equal(followingAttrs.get("data-tm-thumb-scale-home"), undefined, "followed-cams should not apply legacy homepage cache");
|
||||
assert.equal(followingVars.get("--tm-thumb-following-list-columns"), undefined);
|
||||
assert.equal(followingVars.get("--tm-thumb-following-list-min-width"), undefined);
|
||||
assert.equal(followingVars.get("--tm-thumb-following-list-card-height"), undefined);
|
||||
assert.equal(followingVars.get("--tm-thumb-following-list-thumb-width"), undefined);
|
||||
assert.equal(followingVars.get("--tm-thumb-following-list-thumb-height"), undefined);
|
||||
assert.equal(followingVars.get("--tm-thumb-home-columns"), undefined);
|
||||
assert.equal(followingVars.get("--tm-thumb-home-min-width"), undefined);
|
||||
|
||||
Reference in New Issue
Block a user