Date: Thu, 30 Jan 2025 17:44:46 +0530
Subject: [PATCH 6/7] Confirmation for changing theme (#4313)
* add confirmation textMsg for theme change
* update textMsg
* localize the string with _()
* localize only the string
* Replaced string concatenation with template literals
---
js/toolbar.js | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/js/toolbar.js b/js/toolbar.js
index 72c1643b8a..a870720eb5 100644
--- a/js/toolbar.js
+++ b/js/toolbar.js
@@ -463,7 +463,12 @@ class Toolbar {
const darkModeIcon = docById("darkModeIcon");
darkModeIcon.onclick = () => {
- onclick();
+ this.activity.textMsg(` ${_("Refresh your browser to change your theme.")}
`);
+
+ const themeLink = docById("theme-link");
+ themeLink.addEventListener( "click", () => {
+ onclick();
+ })
}
}
From e90828812e35fa907861a72b9b99124c9302a21a Mon Sep 17 00:00:00 2001
From: Om Santosh Suneri <142336291+omsuneri@users.noreply.github.com>
Date: Thu, 30 Jan 2025 14:20:20 +0000
Subject: [PATCH 7/7] Tests for background.js and planetInterface.js (#4318)
* Create background.test.js
* Exporting modules for test
* Create planetInterface.test.js
* Exporting modules for test
* Update planetInterface.test.js
---
js/__tests__/background.test.js | 64 +++++++++++++++
js/__tests__/planetInterface.test.js | 117 +++++++++++++++++++++++++++
js/background.js | 6 ++
js/planetInterface.js | 3 +
4 files changed, 190 insertions(+)
create mode 100644 js/__tests__/background.test.js
create mode 100644 js/__tests__/planetInterface.test.js
diff --git a/js/__tests__/background.test.js b/js/__tests__/background.test.js
new file mode 100644
index 0000000000..ca82525dde
--- /dev/null
+++ b/js/__tests__/background.test.js
@@ -0,0 +1,64 @@
+describe("Browser Action Behavior", () => {
+ let mockBrowser;
+ let mockChrome;
+
+ beforeEach(() => {
+ // Mock objects
+ mockBrowser = {
+ browserAction: {
+ onClicked: { addListener: jest.fn() },
+ },
+ tabs: { create: jest.fn() },
+ runtime: {
+ onInstalled: { addListener: jest.fn() },
+ },
+ };
+
+ mockChrome = {
+ browserAction: {
+ onClicked: { addListener: jest.fn() },
+ },
+ runtime: {
+ onInstalled: { addListener: jest.fn() },
+ getURL: jest.fn((path) => `chrome-extension://fake-id/${path}`),
+ },
+ tabs: { create: jest.fn() },
+ };
+
+ global.browser = mockBrowser;
+ global.chrome = mockChrome;
+
+ Object.defineProperty(global.navigator, "userAgent", {
+ writable: true,
+ value: "",
+ });
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ delete global.browser;
+ delete global.chrome;
+ });
+
+ it("should set up Firefox-specific listeners when user agent is Firefox", () => {
+ navigator.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0";
+
+ jest.resetModules(); // Clear the module cache
+ const { isFirefox, browserAction } = require("../background.js");
+
+ expect(isFirefox).toBe(true);
+ expect(browserAction.onClicked.addListener).toHaveBeenCalledTimes(1);
+ expect(mockBrowser.runtime.onInstalled.addListener).toHaveBeenCalledTimes(1);
+ });
+
+ it("should set up Chrome-specific listeners when user agent is not Firefox", () => {
+ navigator.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36";
+
+ jest.resetModules(); // Clear the module cache
+ const { isFirefox, browserAction } = require("../background.js");
+
+ expect(isFirefox).toBe(false);
+ expect(browserAction.onClicked.addListener).toHaveBeenCalledTimes(1);
+ expect(mockChrome.runtime.onInstalled.addListener).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/js/__tests__/planetInterface.test.js b/js/__tests__/planetInterface.test.js
new file mode 100644
index 0000000000..ad7f75442f
--- /dev/null
+++ b/js/__tests__/planetInterface.test.js
@@ -0,0 +1,117 @@
+const PlanetInterface = require('../planetInterface');
+global.platformColor = {
+ header: '#8bc34a'
+};
+
+const mockActivity = {
+ hideSearchWidget: jest.fn(),
+ prepSearchWidget: jest.fn(),
+ sendAllToTrash: jest.fn(),
+ refreshCanvas: jest.fn(),
+ _loadStart: jest.fn(),
+ doLoadAnimation: jest.fn(),
+ textMsg: jest.fn(),
+ stage: { enableDOMEvents: jest.fn() },
+ blocks: { loadNewBlocks: jest.fn(), palettes: { _hideMenus: jest.fn() }, trashStacks: [] },
+ logo: { doStopTurtles: jest.fn() },
+ canvas: {},
+ turtles: {},
+ loading: false,
+ prepareExport: jest.fn(),
+ _allClear: jest.fn()
+};
+
+document.body.innerHTML = `
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+const docById = jest.fn((id) => document.getElementById(id));
+global.docById = docById;
+
+beforeAll(() => {
+ mockCanvas = {
+ click: jest.fn()
+ };
+ window.widgetWindows = {
+ hideAllWindows: jest.fn(),
+ showWindows: jest.fn(),
+ };
+ window.scroll = jest.fn();
+});
+
+describe('PlanetInterface', () => {
+ let planetInterface;
+
+ beforeEach(() => {
+ planetInterface = new PlanetInterface(mockActivity);
+ });
+
+ test('hideMusicBlocks hides relevant elements and disables DOM events', () => {
+ planetInterface.hideMusicBlocks();
+
+ expect(mockActivity.hideSearchWidget).toHaveBeenCalled();
+ expect(mockActivity.logo.doStopTurtles).toHaveBeenCalled();
+ expect(docById('helpElem').style.visibility).toBe('hidden');
+ expect(document.querySelector('.canvasHolder').classList.contains('hide')).toBe(true);
+ expect(document.querySelector('#canvas').style.display).toBe('none');
+ expect(document.querySelector('#theme-color').content).toBe('#8bc34a');
+ });
+
+ test('showMusicBlocks shows relevant elements and enables DOM events', () => {
+ mockActivity.planet = { getCurrentProjectName: jest.fn(() => 'Test Project') };
+
+ planetInterface.showMusicBlocks();
+
+ expect(document.title).toBe('Test Project');
+ expect(docById('toolbars').style.display).toBe('block');
+ expect(docById('palette').style.display).toBe('block');
+ expect(mockActivity.prepSearchWidget).toHaveBeenCalled();
+ expect(document.querySelector('.canvasHolder').classList.contains('hide')).toBe(false);
+ expect(document.querySelector('#canvas').style.display).toBe('');
+ });
+
+ test('hidePlanet hides the planet interface', () => {
+ planetInterface.iframe = document.querySelector('#planet-iframe');
+ planetInterface.hidePlanet();
+ expect(planetInterface.iframe.style.display).toBe('none');
+ });
+
+ test('openPlanet calls saveLocally, hideMusicBlocks, and showPlanet', () => {
+ jest.spyOn(planetInterface, 'saveLocally').mockImplementation(() => {});
+ jest.spyOn(planetInterface, 'hideMusicBlocks').mockImplementation(() => {});
+ jest.spyOn(planetInterface, 'showPlanet').mockImplementation(() => {});
+ planetInterface.openPlanet();
+ expect(planetInterface.saveLocally).toHaveBeenCalled();
+ expect(planetInterface.hideMusicBlocks).toHaveBeenCalled();
+ expect(planetInterface.showPlanet).toHaveBeenCalled();
+ });
+
+ test('closePlanet calls hidePlanet and showMusicBlocks', () => {
+ jest.spyOn(planetInterface, 'hidePlanet').mockImplementation(() => {});
+ jest.spyOn(planetInterface, 'showMusicBlocks').mockImplementation(() => {});
+ planetInterface.closePlanet();
+ expect(planetInterface.hidePlanet).toHaveBeenCalled();
+ expect(planetInterface.showMusicBlocks).toHaveBeenCalled();
+ });
+
+ test('newProject calls closePlanet, initialiseNewProject, _loadStart, and saveLocally', () => {
+ jest.spyOn(planetInterface, 'closePlanet').mockImplementation(() => {});
+ jest.spyOn(planetInterface, 'initialiseNewProject').mockImplementation(() => {});
+ jest.spyOn(planetInterface, 'saveLocally').mockImplementation(() => {});
+ planetInterface.newProject();
+ expect(planetInterface.closePlanet).toHaveBeenCalled();
+ expect(planetInterface.initialiseNewProject).toHaveBeenCalled();
+ expect(mockActivity._loadStart).toHaveBeenCalled();
+ expect(planetInterface.saveLocally).toHaveBeenCalled();
+ });
+});
diff --git a/js/background.js b/js/background.js
index 5e00403dd6..2fe00d3e55 100644
--- a/js/background.js
+++ b/js/background.js
@@ -34,3 +34,9 @@ if (navigator.userAgent.search("Firefox") !== -1) {
window.open(chrome.runtime.getURL("index.html"));
});
}
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = {
+ isFirefox: navigator.userAgent.search("Firefox") !== -1,
+ browserAction: navigator.userAgent.search("Firefox") !== -1 ? browser.browserAction : chrome.browserAction,
+ };
+}
diff --git a/js/planetInterface.js b/js/planetInterface.js
index 09e273ac32..7c97cd285d 100644
--- a/js/planetInterface.js
+++ b/js/planetInterface.js
@@ -331,3 +331,6 @@ class PlanetInterface {
};
}
}
+if (typeof module !== "undefined" && module.exports) {
+ module.exports = PlanetInterface;
+}