Feature/add unit testing framework and start writing unit tests (acceptance tests) (#708)

* add jest and rewire for testing

* wrap loose code for initMutationObserver() in function and call it instead of just executing it

Otherwise this code is executed everytime state.js is imported somewhere in a file.
This leads to not being able to test properly, since state.js is imported in a lot
of the src files and fails when running the tests since we are missing global environment
settings such as document, window etc in the jest environment.

* export roundDown and getNumberformatter to make them testable as well

* add basic acceptance tests for utils.js, create snapshots and add jest config

* add failing test for buggy behaviour in a separate test case and skip it until fixed

* Fixes after merge conflicts

---------

Co-authored-by: Dmitrii Selivanov <selivano.d@gmail.com>
This commit is contained in:
Leon Bubova
2024-06-16 19:52:58 +02:00
committed by GitHub
parent fbf00e474d
commit d62130b898
9 changed files with 400 additions and 8134 deletions
+1
View File
@@ -1,3 +1,4 @@
{ {
"presets": ["@babel/preset-env"], "presets": ["@babel/preset-env"],
"plugins": ["rewire"]
} }
+24 -47
View File
@@ -32,17 +32,12 @@ api.runtime.onMessage.addListener((request, sender, sendResponse) => {
} else if (request.message == "set_state") { } else if (request.message == "set_state") {
// chrome.identity.getAuthToken({ interactive: true }, function (token) { // chrome.identity.getAuthToken({ interactive: true }, function (token) {
let token = ""; let token = "";
fetch( fetch(`${apiUrl}/votes?videoId=${request.videoId}&likeCount=${request.likeCount || ""}`, {
`${apiUrl}/votes?videoId=${request.videoId}&likeCount=${ method: "GET",
request.likeCount || "" headers: {
}`, Accept: "application/json",
{
method: "GET",
headers: {
Accept: "application/json",
},
}, },
) })
.then((response) => response.json()) .then((response) => response.json())
.then((response) => { .then((response) => {
sendResponse(response); sendResponse(response);
@@ -147,15 +142,12 @@ async function sendVote(videoId, vote) {
async function register() { async function register() {
const userId = generateUserID(); const userId = generateUserID();
api.storage.sync.set({ userId }); api.storage.sync.set({ userId });
const registrationResponse = await fetch( const registrationResponse = await fetch(`${apiUrl}/puzzle/registration?userId=${userId}`, {
`${apiUrl}/puzzle/registration?userId=${userId}`, method: "GET",
{ headers: {
method: "GET", Accept: "application/json",
headers: {
Accept: "application/json",
},
}, },
).then((response) => response.json()); }).then((response) => response.json());
const solvedPuzzle = await solvePuzzle(registrationResponse); const solvedPuzzle = await solvePuzzle(registrationResponse);
if (!solvedPuzzle.solution) { if (!solvedPuzzle.solution) {
await register(); await register();
@@ -210,9 +202,7 @@ function countLeadingZeroes(uInt8View, limit) {
} }
async function solvePuzzle(puzzle) { async function solvePuzzle(puzzle) {
let challenge = Uint8Array.from(atob(puzzle.challenge), (c) => let challenge = Uint8Array.from(atob(puzzle.challenge), (c) => c.charCodeAt(0));
c.charCodeAt(0),
);
let buffer = new ArrayBuffer(20); let buffer = new ArrayBuffer(20);
let uInt8View = new Uint8Array(buffer); let uInt8View = new Uint8Array(buffer);
let uInt32View = new Uint32Array(buffer); let uInt32View = new Uint32Array(buffer);
@@ -235,8 +225,7 @@ async function solvePuzzle(puzzle) {
} }
function generateUserID(length = 36) { function generateUserID(length = 36) {
const charset = const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let result = ""; let result = "";
if (crypto && crypto.getRandomValues) { if (crypto && crypto.getRandomValues) {
const values = new Uint32Array(length); const values = new Uint32Array(length);
@@ -255,9 +244,7 @@ function generateUserID(length = 36) {
function storageChangeHandler(changes, area) { function storageChangeHandler(changes, area) {
if (changes.disableVoteSubmission !== undefined) { if (changes.disableVoteSubmission !== undefined) {
handleDisableVoteSubmissionChangeEvent( handleDisableVoteSubmissionChangeEvent(changes.disableVoteSubmission.newValue);
changes.disableVoteSubmission.newValue,
);
} }
if (changes.coloredThumbs !== undefined) { if (changes.coloredThumbs !== undefined) {
handleColoredThumbsChangeEvent(changes.coloredThumbs.newValue); handleColoredThumbsChangeEvent(changes.coloredThumbs.newValue);
@@ -272,21 +259,16 @@ function storageChangeHandler(changes, area) {
handleNumberDisplayFormatChangeEvent(changes.numberDisplayFormat.newValue); handleNumberDisplayFormatChangeEvent(changes.numberDisplayFormat.newValue);
} }
if (changes.numberDisplayReformatLikes !== undefined) { if (changes.numberDisplayReformatLikes !== undefined) {
handleNumberDisplayReformatLikesChangeEvent( handleNumberDisplayReformatLikesChangeEvent(changes.numberDisplayReformatLikes.newValue);
changes.numberDisplayReformatLikes.newValue,
);
} }
if (changes.disableLogging !== undefined) { if (changes.disableLogging !== undefined) {
handleDisableLoggingChangeEvent(changes.disableLogging.newValue); handleDisableLoggingChangeEvent(changes.disableLogging.newValue);
}
if (changes.showTooltipPercentage !== undefined) { if (changes.showTooltipPercentage !== undefined) {
handleShowTooltipPercentageChangeEvent( handleShowTooltipPercentageChangeEvent(changes.showTooltipPercentage.newValue);
changes.showTooltipPercentage.newValue,
);
} }
if (changes.numberDisplayReformatLikes !== undefined) { if (changes.numberDisplayReformatLikes !== undefined) {
handleNumberDisplayReformatLikesChangeEvent( handleNumberDisplayReformatLikesChangeEvent(changes.numberDisplayReformatLikes.newValue);
changes.numberDisplayReformatLikes.newValue,
);
} }
} }
@@ -318,10 +300,8 @@ function handleTooltipPercentageModeChangeEvent(value) {
} }
function changeIcon(iconName) { function changeIcon(iconName) {
if (api.action !== undefined) if (api.action !== undefined) api.action.setIcon({ path: "/icons/" + iconName });
api.action.setIcon({ path: "/icons/" + iconName }); else if (api.browserAction !== undefined) api.browserAction.setIcon({ path: "/icons/" + iconName });
else if (api.browserAction !== undefined)
api.browserAction.setIcon({ path: "/icons/" + iconName });
else console.log("changing icon is not supported"); else console.log("changing icon is not supported");
} }
@@ -369,12 +349,11 @@ function initializeDisableVoteSubmission() {
}); });
} }
function initializeDisableLogging(){ function initializeDisableLogging() {
api.storage.sync.get(['disableLogging'],(res)=>{ api.storage.sync.get(["disableLogging"], (res) => {
if (res.disableLogging === undefined) { if (res.disableLogging === undefined) {
api.storage.sync.set({disableLogging:true}); api.storage.sync.set({ disableLogging: true });
} } else {
else {
extConfig.disableLogging = res.disableLogging; extConfig.disableLogging = res.disableLogging;
} }
}); });
@@ -454,7 +433,5 @@ function isChrome() {
} }
function isFirefox() { function isFirefox() {
return ( return typeof browser !== "undefined" && typeof browser.runtime !== "undefined";
typeof browser !== "undefined" && typeof browser.runtime !== "undefined"
);
} }
@@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`getNumberFormatter should return a correct formatter when falling back to default locale 1`] = `NumberFormat {}`;
exports[`getNumberFormatter should return a correct formatter when using chrome 1`] = `NumberFormat {}`;
exports[`getNumberFormatter should return a correct formatter when using firefox 1`] = `NumberFormat {}`;
exports[`getNumberFormatter should return a correct formatter when using the URL locale (possibly buggy) 1`] = `NumberFormat {}`;
exports[`getNumberFormatter should return a correct formatter when using the URL locale 1`] = `NumberFormat {}`;
exports[`getNumberFormatter should return a correct formatter whith standard option 1`] = `NumberFormat {}`;
exports[`getNumberFormatter should return a correct formatter with compactLong option 1`] = `NumberFormat {}`;
+19 -55
View File
@@ -1,10 +1,4 @@
import { import { getLikeButton, getDislikeButton, getButtons, getLikeTextContainer, getDislikeTextContainer } from "./buttons";
getLikeButton,
getDislikeButton,
getButtons,
getLikeTextContainer,
getDislikeTextContainer,
} from "./buttons";
import { createRateBar } from "./bar"; import { createRateBar } from "./bar";
import { import {
getBrowser, getBrowser,
@@ -25,7 +19,7 @@ const NEUTRAL_STATE = "NEUTRAL_STATE";
let extConfig = { let extConfig = {
disableVoteSubmission: false, disableVoteSubmission: false,
disableLogging: true, disableLogging: false,
coloredThumbs: false, coloredThumbs: false,
coloredBar: false, coloredBar: false,
colorTheme: "classic", colorTheme: "classic",
@@ -110,11 +104,7 @@ if (isShorts() && !shortsObserver) {
} }
return; return;
} }
cLog( cLog("Unexpected mutation observer event: " + mutation.target + mutation.type);
"Unexpected mutation observer event: " +
mutation.target +
mutation.type,
);
}); });
}, },
); );
@@ -123,38 +113,28 @@ if (isShorts() && !shortsObserver) {
function isLikesDisabled() { function isLikesDisabled() {
// return true if the like button's text doesn't contain any number // return true if the like button's text doesn't contain any number
if (isMobile()) { if (isMobile()) {
return /^\D*$/.test( return /^\D*$/.test(getButtons().children[0].querySelector(".button-renderer-text").innerText);
getButtons().children[0].querySelector(".button-renderer-text").innerText,
);
} }
return /^\D*$/.test(getLikeTextContainer().innerText); return /^\D*$/.test(getLikeTextContainer().innerText);
} }
function isVideoLiked() { function isVideoLiked() {
if (isMobile()) { if (isMobile()) {
return ( return getLikeButton().querySelector("button").getAttribute("aria-label") === "true";
getLikeButton().querySelector("button").getAttribute("aria-label") ===
"true"
);
} }
return ( return (
getLikeButton().classList.contains("style-default-active") || getLikeButton().classList.contains("style-default-active") ||
getLikeButton().querySelector("button")?.getAttribute("aria-pressed") === getLikeButton().querySelector("button")?.getAttribute("aria-pressed") === "true"
"true"
); );
} }
function isVideoDisliked() { function isVideoDisliked() {
if (isMobile()) { if (isMobile()) {
return ( return getDislikeButton().querySelector("button").getAttribute("aria-label") === "true";
getDislikeButton().querySelector("button").getAttribute("aria-label") ===
"true"
);
} }
return ( return (
getDislikeButton().classList.contains("style-default-active") || getDislikeButton().classList.contains("style-default-active") ||
getDislikeButton().querySelector("button")?.getAttribute("aria-pressed") === getDislikeButton().querySelector("button")?.getAttribute("aria-pressed") === "true"
"true"
); );
} }
@@ -179,18 +159,14 @@ function setDislikes(dislikesCount) {
getDislikeTextContainer()?.removeAttribute("is-empty"); getDislikeTextContainer()?.removeAttribute("is-empty");
if (!isLikesDisabled()) { if (!isLikesDisabled()) {
if (isMobile()) { if (isMobile()) {
getButtons().children[1].querySelector( getButtons().children[1].querySelector(".button-renderer-text").innerText = dislikesCount;
".button-renderer-text",
).innerText = dislikesCount;
return; return;
} }
getDislikeTextContainer().innerText = dislikesCount; getDislikeTextContainer().innerText = dislikesCount;
} else { } else {
cLog("likes count disabled by creator"); cLog("likes count disabled by creator");
if (isMobile()) { if (isMobile()) {
getButtons().children[1].querySelector( getButtons().children[1].querySelector(".button-renderer-text").innerText = localize("TextLikesDisabled");
".button-renderer-text",
).innerText = localize("TextLikesDisabled");
return; return;
} }
getDislikeTextContainer().innerText = localize("TextLikesDisabled"); getDislikeTextContainer().innerText = localize("TextLikesDisabled");
@@ -206,8 +182,7 @@ function getLikeCountFromButton() {
} }
let likeButton = let likeButton =
getLikeButton().querySelector("yt-formatted-string#text") ?? getLikeButton().querySelector("yt-formatted-string#text") ?? getLikeButton().querySelector("button");
getLikeButton().querySelector("button");
let likesStr = likeButton.getAttribute("aria-label").replace(/\D/g, ""); let likesStr = likeButton.getAttribute("aria-label").replace(/\D/g, "");
return likesStr.length > 0 ? parseInt(likesStr) : false; return likesStr.length > 0 ? parseInt(likesStr) : false;
@@ -231,12 +206,8 @@ function processResponse(response, storedData) {
if (extConfig.coloredThumbs === true) { if (extConfig.coloredThumbs === true) {
if (isShorts()) { if (isShorts()) {
// for shorts, leave deactivated buttons in default color // for shorts, leave deactivated buttons in default color
let shortLikeButton = getLikeButton().querySelector( let shortLikeButton = getLikeButton().querySelector("tp-yt-paper-button#button");
"tp-yt-paper-button#button", let shortDislikeButton = getDislikeButton().querySelector("tp-yt-paper-button#button");
);
let shortDislikeButton = getDislikeButton().querySelector(
"tp-yt-paper-button#button",
);
if (shortLikeButton.getAttribute("aria-pressed") === "true") { if (shortLikeButton.getAttribute("aria-pressed") === "true") {
shortLikeButton.style.color = getColorFromTheme(true); shortLikeButton.style.color = getColorFromTheme(true);
} }
@@ -260,26 +231,19 @@ function displayError(error) {
} }
async function setState(storedData) { async function setState(storedData) {
storedData.previousState = isVideoDisliked() storedData.previousState = isVideoDisliked() ? DISLIKED_STATE : isVideoLiked() ? LIKED_STATE : NEUTRAL_STATE;
? DISLIKED_STATE
: isVideoLiked()
? LIKED_STATE
: NEUTRAL_STATE;
let statsSet = false; let statsSet = false;
cLog("Video is loaded. Adding buttons..."); cLog("Video is loaded. Adding buttons...");
let videoId = getVideoId(window.location.href); let videoId = getVideoId(window.location.href);
let likeCount = getLikeCountFromButton() || null; let likeCount = getLikeCountFromButton() || null;
let response = await fetch( let response = await fetch(`${apiUrl}/votes?videoId=${videoId}&likeCount=${likeCount || ""}`, {
`${apiUrl}/votes?videoId=${videoId}&likeCount=${likeCount || ""}`, method: "GET",
{ headers: {
method: "GET", Accept: "application/json",
headers: {
Accept: "application/json",
},
}, },
) })
.then((response) => { .then((response) => {
if (!response.ok) displayError(response.error); if (!response.ok) displayError(response.error);
return response; return response;
+4 -2
View File
@@ -66,7 +66,8 @@ function getVideoId(url) {
const urlObject = new URL(url); const urlObject = new URL(url);
const pathname = urlObject.pathname; const pathname = urlObject.pathname;
if (pathname.startsWith("/clip")) { if (pathname.startsWith("/clip")) {
return (document.querySelector("meta[itemprop='videoId']") || document.querySelector("meta[itemprop='identifier']")).content; return (document.querySelector("meta[itemprop='videoId']") || document.querySelector("meta[itemprop='identifier']"))
.content;
} else { } else {
if (pathname.startsWith("/shorts")) { if (pathname.startsWith("/shorts")) {
return pathname.slice(8); return pathname.slice(8);
@@ -103,7 +104,7 @@ function isVideoLoaded() {
} }
function cLog(message, writer) { function cLog(message, writer) {
if (!extConfig.disableLogging){ if (!extConfig.disableLogging) {
message = `[return youtube dislike]: ${message}`; message = `[return youtube dislike]: ${message}`;
if (writer) { if (writer) {
writer(message); writer(message);
@@ -177,6 +178,7 @@ function createObserver(options, callback) {
export { export {
numberFormat, numberFormat,
getNumberFormatter,
getBrowser, getBrowser,
getVideoId, getVideoId,
isInViewport, isInViewport,
+325
View File
@@ -0,0 +1,325 @@
/**
* @jest-environment jsdom
*/
import {
__Rewire__ as rewiredUtils,
numberFormat,
getNumberFormatter,
localize,
getBrowser,
getVideoId,
isInViewport,
isVideoLoaded,
cLog,
getColorFromTheme,
} from "./utils";
import { extConfig } from "./state";
jest.mock("./state");
describe("numberFormat", () => {
it("should format high numbers correctly", () => {
rewiredUtils(
"getNumberFormatter",
jest.fn().mockReturnValue(
Intl.NumberFormat("en", {
notation: "compact",
compactDisplay: "short",
}),
),
);
expect(numberFormat(91492)).toBe("91K");
jest.resetAllMocks();
});
it("should not format input when < 1000", () => {
rewiredUtils(
"getNumberFormatter",
jest.fn().mockReturnValue(
Intl.NumberFormat("en", {
notation: "compact",
compactDisplay: "short",
}),
),
);
expect(numberFormat(100)).toBe("100");
});
it("should not round down when rounding is diabled in config", () => {
rewiredUtils(
"getNumberFormatter",
jest.fn().mockReturnValue(
Intl.NumberFormat("de", {
notation: "compact",
compactDisplay: "short",
}),
),
);
extConfig.numberDisplayRoundDown = false;
expect(numberFormat(912391)).toBe("912.391");
});
});
describe("getNumberFormatter", () => {
it("should return a correct formatter with compactLong option", () => {
expect(getNumberFormatter("compactLong")).toMatchSnapshot();
});
it("should return a correct formatter whith standard option", () => {
expect(getNumberFormatter("standard")).toMatchSnapshot();
});
it("should return a correct formatter when using chrome", () => {
Object.defineProperty(document.documentElement, "lang", {
value: "en",
configurable: true,
});
expect(getNumberFormatter()).toMatchSnapshot();
});
it("should return a correct formatter when using firefox", () => {
Object.defineProperty(document.documentElement, "lang", {
value: null,
configurable: true,
});
expect(getNumberFormatter()).toMatchSnapshot();
});
it("should return a correct formatter when using the URL locale (possibly buggy)", () => {
// Disclaimer: The case we are testing here is actually not correct and
// am almost sure I found a bug in the actual implementation of
// getNumberFormatter(). As I am currently writing acceptance tests only
// e.g. tests that are exclusively testing the current behaviour as is, as
// a first step of adding tests to the codebase, I will add it like this
// for now and document how we should actually be testing down below.
// The reason why this bug is not causing faulty behaviour is, that we
// have a fallback for it, that is always triggered.
// This is how we make the test go green:
Object.defineProperty(document.documentElement, "lang", {
value: null,
configurable: true,
});
Object.defineProperty(navigator, "language", {
value: null,
configurable: true,
});
const mockedNode = document.createElement("link");
mockedNode.setAttribute("href", "https://www.youtube.com/opensearch?locale=en");
document.querySelectorAll = jest.fn().mockReturnValue([mockedNode]);
expect(getNumberFormatter()).toMatchSnapshot();
});
it.skip("should return a correct formatter when using the URL locale", () => {
// But we actually want to test like so, which is the correct value of the locale attribute:
Object.defineProperty(document.documentElement, "lang", {
value: null,
configurable: true,
});
Object.defineProperty(navigator, "language", {
value: null,
configurable: true,
});
const mockedNode = document.createElement("link");
mockedNode.setAttribute("href", "https://www.youtube.com/opensearch?locale=en_US");
document.querySelectorAll = jest.fn().mockReturnValue([mockedNode]);
expect(getNumberFormatter()).toMatchSnapshot();
});
it("should return a correct formatter when falling back to default locale", () => {
Object.defineProperty(document.documentElement, "lang", {
value: null,
configurable: true,
});
Object.defineProperty(navigator, "language", {
value: null,
configurable: true,
});
expect(getNumberFormatter()).toMatchSnapshot();
});
describe("localize", () => {
it("should return a translated string", () => {
global.chrome = {
i18n: {
getMessage: () => "Return YouTube Dislike",
},
};
expect(localize("extensionName")).toBe("Return YouTube Dislike");
});
});
describe("getBrowser", () => {
it("should return a chrome browser instance", () => {
global.chrome = {
runtime: jest.fn(),
};
expect(getBrowser()).toBeDefined();
});
it("should return a mozilla browser instance", () => {
global.chrome.runtime = undefined;
global.browser = {
runtime: jest.fn(),
};
expect(getBrowser()).toBeDefined();
});
it("should fail on unsupported browser", () => {
global.chrome = undefined;
global.browser = undefined;
const log = console.log;
console.log = jest.fn();
expect(getBrowser()).toBe(false);
expect(console.log).toBeCalledWith("browser is not supported");
console.log = log;
});
});
describe("getVideoId", () => {
it("should return the video Id on valid url input", () => {
const url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";
expect(getVideoId(url)).toBe("dQw4w9WgXcQ");
});
it("should return the video Id on valid shorts url input", () => {
const url = "https://www.youtube.com/shorts/niMcQ9Vmmj8";
expect(getVideoId(url)).toBe("niMcQ9Vmmj8");
});
it("should return the video Id on clip url input", () => {
document.querySelector = jest.fn().mockReturnValue({
content: "niMcQ9Vmmj8",
});
const url = "https://www.youtube.com/clip";
expect(getVideoId(url)).toBe("niMcQ9Vmmj8");
});
it("should return null on invalid url input", () => {
const url = "https://www.youtube.com/wrong-url";
expect(getVideoId(url)).toBe(null);
});
});
describe("isInViewport", () => {
it("should return true if element is in viewport", () => {
const rect = {
getBoundingClientRect: jest.fn().mockReturnValue({
top: 0,
left: 0,
bottom: 0,
right: 0,
}),
};
expect(isInViewport(rect)).toBe(false);
});
it("should return false if element is out of viewport", () => {
const rect = {
getBoundingClientRect: jest.fn().mockReturnValue({
top: 0,
left: 0,
bottom: 769,
right: 0,
}),
};
expect(isInViewport(rect)).toBe(false);
});
});
describe("isVideoLoaded", () => {
describe("on desktop", () => {
it("should return true on loaded video", () => {
rewiredUtils("getVideoId", jest.fn().mockReturnValue("fakeId"));
document.querySelector = jest.fn().mockReturnValue("notNull");
expect(isVideoLoaded()).toBe(true);
expect(document.querySelector).toBeCalledWith("ytd-watch-grid[video-id='fakeId']");
});
it("should return false on not loaded video", () => {
rewiredUtils("getVideoId", jest.fn().mockReturnValue("fakeId"));
document.querySelector = jest.fn().mockReturnValue(null);
expect(isVideoLoaded()).toBe(false);
expect(document.querySelector).toBeCalledWith("ytd-watch-flexy[video-id='fakeId']");
});
});
describe("on mobile", () => {
it("should return true on loaded video", () => {
rewiredUtils("getVideoId", jest.fn().mockReturnValue("fakeId"));
document.querySelector = jest.fn().mockReturnValueOnce(null).mockReturnValue("notNull");
expect(isVideoLoaded()).toBe(true);
expect(document.querySelector).toHaveBeenLastCalledWith("ytd-watch-flexy[video-id='fakeId']");
});
it("should return false on not loaded video", () => {
rewiredUtils("getVideoId", jest.fn().mockReturnValue("fakeId"));
document.querySelector = jest.fn().mockReturnValueOnce(null).mockReturnValue(null);
expect(isVideoLoaded()).toBe(false);
expect(document.querySelector).toHaveBeenLastCalledWith('#player[loading="false"]:not([hidden])');
});
});
});
describe("cLog", () => {
it("should log a message with the correct prefix", () => {
const log = console.log;
console.log = jest.fn();
cLog("Test message");
expect(console.log).toBeCalledWith("[return youtube dislike]: Test message");
console.log = log;
});
it("should log a message with the correct prefix when given a writer", () => {
const fakeWriter = jest.fn();
cLog("Test message", fakeWriter);
expect(fakeWriter).toBeCalledWith("[return youtube dislike]: Test message");
});
});
describe("getColorFromTheme", () => {
describe("accessible", () => {
it("should return the correct color for like", () => {
extConfig.colorTheme = "accessible";
expect(getColorFromTheme(true)).toBe("dodgerblue");
});
it("should return the correct color for not liked", () => {
extConfig.colorTheme = "accessible";
expect(getColorFromTheme(false)).toBe("gold");
});
});
describe("neon", () => {
it("should return the correct color for like", () => {
extConfig.colorTheme = "neon";
expect(getColorFromTheme(true)).toBe("aqua");
});
it("should return the correct color for not liked", () => {
extConfig.colorTheme = "neon";
expect(getColorFromTheme(false)).toBe("magenta");
});
});
describe("classic", () => {
it("should return the correct color for like", () => {
extConfig.colorTheme = "classic";
expect(getColorFromTheme(true)).toBe("lime");
});
it("should return the correct color for not liked", () => {
extConfig.colorTheme = "classic";
expect(getColorFromTheme(false)).toBe("red");
});
});
});
});
+8
View File
@@ -0,0 +1,8 @@
module.exports = {
resetMocks: true,
collectCoverage: false,
collectCoverageFrom: [
"Extensions/combined/src/**/*.js",
"Extensions/combined/*.js",
],
};
-8029
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -7,8 +7,8 @@
"start": "echo To build for development, please use \"npm run dev\". To build for production, please use \"npm run build\".", "start": "echo To build for development, please use \"npm run dev\". To build for production, please use \"npm run build\".",
"dev": "webpack --mode=production --watch", "dev": "webpack --mode=production --watch",
"build": "webpack --mode=production", "build": "webpack --mode=production",
"test": "jest",
"build:safari": "webpack --mode=production && xcrun safari-web-extension-converter Extensions/combined/dist/safari --project-location Extensions/combined/dist --bundle-identifier com.returnyoutubedislike.safari-ext --force", "build:safari": "webpack --mode=production && xcrun safari-web-extension-converter Extensions/combined/dist/safari --project-location Extensions/combined/dist --bundle-identifier com.returnyoutubedislike.safari-ext --force",
"test": "echo \"Error: no test specified\" && exit 1",
"prepare": "husky install" "prepare": "husky install"
}, },
"lint-staged": { "lint-staged": {
@@ -34,9 +34,12 @@
"@babel/preset-env": "^7.23.5", "@babel/preset-env": "^7.23.5",
"@babel/runtime": "^7.23.5", "@babel/runtime": "^7.23.5",
"babel-loader": "^9.1.3", "babel-loader": "^9.1.3",
"babel-plugin-rewire": "^1.2.0",
"copy-webpack-plugin": "^11.0.0", "copy-webpack-plugin": "^11.0.0",
"filemanager-webpack-plugin": "^8.0.0", "filemanager-webpack-plugin": "^8.0.0",
"husky": "^8.0.0", "husky": "^8.0.0",
"jest": "^28.1.3",
"jest-environment-jsdom": "^28.1.3",
"lint-staged": "^15.2.0", "lint-staged": "^15.2.0",
"prettier": "^3.2.2", "prettier": "^3.2.2",
"webpack": "^5.89.0", "webpack": "^5.89.0",