mirror of
https://github.com/SoPat712/Speeder.git
synced 2026-08-21 20:32:07 -04:00
264 lines
8.4 KiB
JavaScript
264 lines
8.4 KiB
JavaScript
import controllerUtils from "../extension/shared/controller-utils.js";
|
|
import importExportUtils from "../extension/shared/import-export.js";
|
|
import keyBindingUtils from "../extension/shared/key-bindings.js";
|
|
import popupControls from "../extension/shared/popup-controls.js";
|
|
import siteRules from "../extension/shared/site-rules.js";
|
|
|
|
describe("shared helpers", () => {
|
|
it("matches site rules and skips invalid regex patterns", () => {
|
|
const literalRule = { pattern: "example.com/watch" };
|
|
const regexRule = { pattern: "/youtube\\.com\\/watch/i" };
|
|
|
|
expect(
|
|
siteRules.matchSiteRule("https://example.com/watch?v=1", [literalRule])
|
|
).toBe(literalRule);
|
|
expect(
|
|
siteRules.matchSiteRule("https://www.youtube.com/watch?v=2", [regexRule])
|
|
).toBe(regexRule);
|
|
expect(
|
|
siteRules.matchSiteRule("https://www.youtube.com/shorts/3", [
|
|
{ pattern: "/(/" },
|
|
regexRule
|
|
])
|
|
).toBeNull();
|
|
expect(siteRules.isSiteRuleDisabled({ enabled: false })).toBe(true);
|
|
});
|
|
|
|
it("matches plain and regex rules against safely decoded URL text", () => {
|
|
expect(
|
|
siteRules.siteRuleMatchesUrl(
|
|
{ pattern: "example.com/path?title=Hello World#part one" },
|
|
"https://example.com/%70ath?title=Hello%20World#part%20one"
|
|
)
|
|
).toBe(true);
|
|
expect(
|
|
siteRules.siteRuleMatchesUrl(
|
|
{ pattern: "/example\\.com\\/path\\?title=Hello World#part one/i" },
|
|
"https://example.com/%70ath?title=Hello%20World#part%20one"
|
|
)
|
|
).toBe(true);
|
|
|
|
// Raw matching remains available for rules intentionally written against
|
|
// the encoded form.
|
|
expect(
|
|
siteRules.siteRuleMatchesUrl(
|
|
{ pattern: "/%70ath\\?title=Hello%20World/" },
|
|
"https://example.com/%70ath?title=Hello%20World"
|
|
)
|
|
).toBe(true);
|
|
});
|
|
|
|
it("tolerates malformed URL escapes and keeps regex matching deterministic", () => {
|
|
expect(siteRules.safelyDecodeUrlText("/%70%ZZ%E2/end")).toBe(
|
|
"/p%ZZ%E2/end"
|
|
);
|
|
expect(siteRules.safelyDecodeUrlText("/%E2%82%AC%FF%70")).toBe(
|
|
"/€%FFp"
|
|
);
|
|
expect(
|
|
siteRules.siteRuleMatchesUrl(
|
|
{ pattern: "/example\\.com\\/p%ZZ%E2/" },
|
|
"https://example.com/%70%ZZ%E2"
|
|
)
|
|
).toBe(true);
|
|
|
|
const globalRule = { pattern: "/example\\.com\\/watch/g" };
|
|
expect(
|
|
siteRules.siteRuleMatchesUrl(globalRule, "https://example.com/watch")
|
|
).toBe(true);
|
|
expect(
|
|
siteRules.siteRuleMatchesUrl(globalRule, "https://example.com/watch")
|
|
).toBe(true);
|
|
});
|
|
|
|
it("combines global enabled with matched site rules (whitelist / blacklist)", () => {
|
|
const allowSite = { pattern: "good.test", enabled: true };
|
|
const blockSite = { pattern: "bad.test", enabled: false };
|
|
|
|
expect(siteRules.isSpeederActiveForSite(true, null)).toBe(true);
|
|
expect(siteRules.isSpeederActiveForSite(false, null)).toBe(false);
|
|
|
|
expect(siteRules.isSpeederActiveForSite(true, blockSite)).toBe(false);
|
|
expect(siteRules.isSpeederActiveForSite(false, blockSite)).toBe(false);
|
|
|
|
expect(siteRules.isSpeederActiveForSite(true, allowSite)).toBe(true);
|
|
expect(siteRules.isSpeederActiveForSite(false, allowSite)).toBe(true);
|
|
});
|
|
|
|
it("sanitizes and resolves popup button orders", () => {
|
|
const controllerButtonDefs = {
|
|
rewind: {},
|
|
faster: {},
|
|
advance: {},
|
|
display: {},
|
|
settings: {}
|
|
};
|
|
|
|
expect(
|
|
popupControls.sanitizeButtonOrder(
|
|
["rewind", "settings", "rewind", "faster", "missing"],
|
|
controllerButtonDefs,
|
|
new Set(["settings"])
|
|
)
|
|
).toEqual(["rewind", "faster"]);
|
|
|
|
expect(
|
|
popupControls.resolvePopupButtons(
|
|
{
|
|
popupMatchHoverControls: true,
|
|
controllerButtons: ["advance", "display"],
|
|
popupControllerButtons: ["rewind"]
|
|
},
|
|
{ controllerButtons: ["faster", "advance"] },
|
|
{
|
|
controllerButtonDefs,
|
|
defaultButtons: ["rewind", "display"],
|
|
excludedIds: ["settings"]
|
|
}
|
|
)
|
|
).toEqual(["faster", "advance"]);
|
|
|
|
expect(
|
|
popupControls.resolvePopupButtons(
|
|
{
|
|
popupMatchHoverControls: false,
|
|
popupControllerButtons: ["rewind", "display"]
|
|
},
|
|
{ popupControllerButtons: ["advance", "settings", "advance"] },
|
|
{
|
|
controllerButtonDefs,
|
|
defaultButtons: ["rewind", "display"],
|
|
excludedIds: ["settings"]
|
|
}
|
|
)
|
|
).toEqual(["advance"]);
|
|
});
|
|
|
|
it("normalizes controller locations and margins", () => {
|
|
expect(controllerUtils.normalizeControllerLocation("top-right")).toBe(
|
|
"top-right"
|
|
);
|
|
expect(controllerUtils.normalizeControllerLocation("bogus")).toBe(
|
|
controllerUtils.defaultControllerLocation
|
|
);
|
|
expect(controllerUtils.clampControllerMarginPx(300, 65)).toBe(200);
|
|
expect(controllerUtils.clampControllerMarginPx(-5, 65)).toBe(0);
|
|
expect(controllerUtils.getNextControllerLocation("top-left")).toBe(
|
|
"top-center"
|
|
);
|
|
});
|
|
|
|
it("infers key binding codes from legacy formats", () => {
|
|
expect(keyBindingUtils.normalizeBindingKey("a")).toBe("A");
|
|
expect(keyBindingUtils.normalizeBindingKey("Esc")).toBe("Escape");
|
|
expect(keyBindingUtils.legacyBindingKeyToCode(" ")).toBe("Space");
|
|
expect(keyBindingUtils.legacyKeyCodeToCode(90)).toBe("KeyZ");
|
|
expect(keyBindingUtils.inferBindingCode({ key: "x" }, null)).toBe("KeyX");
|
|
expect(keyBindingUtils.inferBindingCode({ keyCode: 107 }, null)).toBe(
|
|
"NumpadAdd"
|
|
);
|
|
expect(keyBindingUtils.getLegacyKeyCode({ key: 65 })).toBe(65);
|
|
expect(keyBindingUtils.getActionValueError("fast", 0.01)).toBeNull();
|
|
expect(keyBindingUtils.getActionValueError("fast", 100)).toBeNull();
|
|
expect(keyBindingUtils.getActionValueError("fast", 0.009)).toContain(
|
|
"between 0.01 and 100"
|
|
);
|
|
});
|
|
|
|
it("builds and parses import/export payloads", () => {
|
|
expect(
|
|
importExportUtils.generateBackupFilename(new Date(2026, 3, 4, 8, 9, 10))
|
|
).toBe("speeder-backup_2026-04-04_08.09.10.json");
|
|
|
|
expect(
|
|
importExportUtils.buildBackupPayload(
|
|
{ rememberSpeed: true },
|
|
{ customButtonIcons: {} },
|
|
"2026-04-04T08:09:10Z"
|
|
)
|
|
).toEqual({
|
|
version: "1.1",
|
|
exportDate: "2026-04-04T08:09:10.000Z",
|
|
settings: { rememberSpeed: true },
|
|
localSettings: { customButtonIcons: {} }
|
|
});
|
|
|
|
expect(
|
|
importExportUtils.extractImportSettings({
|
|
settings: { rememberSpeed: true },
|
|
localSettings: { customButtonIcons: {} }
|
|
})
|
|
).toEqual({
|
|
isWrappedBackup: true,
|
|
settings: { rememberSpeed: true },
|
|
localSettings: { customButtonIcons: {} }
|
|
});
|
|
|
|
expect(
|
|
importExportUtils.parseImportText(
|
|
JSON.stringify({ rememberSpeed: true, keyBindings: [] })
|
|
)
|
|
).toEqual({
|
|
isWrappedBackup: false,
|
|
settings: { rememberSpeed: true, keyBindings: [] },
|
|
localSettings: null
|
|
});
|
|
|
|
expect(
|
|
importExportUtils.extractImportSettings({
|
|
subtitleNudgeEnabledByDefault: false
|
|
})
|
|
).toEqual({
|
|
isWrappedBackup: false,
|
|
settings: { subtitleNudgeEnabledByDefault: false },
|
|
localSettings: null
|
|
});
|
|
|
|
expect(
|
|
importExportUtils.extractImportSettings({ enabled: true })
|
|
).toEqual({
|
|
isWrappedBackup: false,
|
|
settings: { enabled: true },
|
|
localSettings: null
|
|
});
|
|
|
|
expect(importExportUtils.isRecognizedRawSettingsObject({ wat: true })).toBe(
|
|
false
|
|
);
|
|
expect(
|
|
importExportUtils.isRecognizedRawSettingsObject({
|
|
siteRulesFormat: "defaults-diff-v2"
|
|
})
|
|
).toBe(true);
|
|
expect(
|
|
importExportUtils.extractImportSettings({ settings: [] })
|
|
).toBeNull();
|
|
expect(
|
|
importExportUtils.extractImportSettings({
|
|
settings: { enabled: true },
|
|
localSettings: []
|
|
})
|
|
).toBeNull();
|
|
[null, "bad", []].forEach((customButtonIcons) => {
|
|
expect(
|
|
importExportUtils.extractImportSettings({
|
|
settings: { enabled: true },
|
|
localSettings: { customButtonIcons }
|
|
})
|
|
).toBeNull();
|
|
});
|
|
|
|
expect(
|
|
importExportUtils.filterLocalSettingsForExport({
|
|
customButtonIcons: { faster: { slug: "zap" } },
|
|
lucideTagsCacheV1: { "a-arrow-down": ["letter"] },
|
|
lucideTagsCacheV1At: 123,
|
|
rememberedSpeeds: { "https://example.com/video.mp4": 1.75 },
|
|
futureRuntimeData: true
|
|
})
|
|
).toEqual({
|
|
customButtonIcons: { faster: { slug: "zap" } }
|
|
});
|
|
});
|
|
});
|