1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-06-28 10:55:27 +02:00

[PM-5878] Rework window call within OverlayBackground to function within AutofillOverlayIframe service (#7770)

This commit is contained in:
Cesar Gonzalez 2024-02-07 16:45:41 -06:00 committed by GitHub
parent c26f1fbf0e
commit 52c8cab152
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 75 additions and 36 deletions

View File

@ -1028,12 +1028,13 @@ describe("OverlayBackground", () => {
it("gets the system theme", async () => {
jest.spyOn(overlayBackground["stateService"], "getTheme").mockResolvedValue(ThemeType.System);
window.matchMedia = jest.fn(() => mock<MediaQueryList>({ matches: true }));
initOverlayElementPorts({ initList: true, initButton: false });
await flushPromises();
expect(window.matchMedia).toHaveBeenCalledWith("(prefers-color-scheme: dark)");
expect(listPortSpy.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ theme: ThemeType.System }),
);
});
});

View File

@ -5,7 +5,6 @@ import { EnvironmentService } from "@bitwarden/common/platform/abstractions/envi
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { ThemeType } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { CipherType } from "@bitwarden/common/vault/enums";
@ -482,21 +481,6 @@ class OverlayBackground implements OverlayBackgroundInterface {
return this.userAuthStatus;
}
/**
* Gets the currently set theme for the user.
*/
private async getCurrentTheme() {
const theme = await this.stateService.getTheme();
if (theme !== ThemeType.System) {
return theme;
}
return window.matchMedia("(prefers-color-scheme: dark)").matches
? ThemeType.Dark
: ThemeType.Light;
}
/**
* Sends a message to the overlay button to update its authentication status.
*/
@ -744,7 +728,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
command: `initAutofillOverlay${isOverlayListPort ? "List" : "Button"}`,
authStatus: await this.getAuthStatus(),
styleSheetUrl: chrome.runtime.getURL(`overlay/${isOverlayListPort ? "list" : "button"}.css`),
theme: `theme_${await this.getCurrentTheme()}`,
theme: await this.stateService.getTheme(),
translations: this.getTranslations(),
ciphers: isOverlayListPort ? this.getOverlayCipherData() : null,
});

View File

@ -1,6 +1,7 @@
import { mock } from "jest-mock-extended";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { ThemeType } from "@bitwarden/common/platform/enums";
import { UriMatchType, CipherType } from "@bitwarden/common/vault/enums";
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
@ -199,7 +200,7 @@ function createInitAutofillOverlayListMessageMock(
command: "initAutofillOverlayList",
translations: overlayPagesTranslations,
styleSheetUrl: "https://jest-testing-website.com",
theme: "light",
theme: ThemeType.Light,
authStatus: AuthenticationStatus.Unlocked,
ciphers: [
createAutofillOverlayCipherDataMock(1, {

View File

@ -1,3 +1,7 @@
import { mock } from "jest-mock-extended";
import { ThemeType } from "@bitwarden/common/platform/enums";
import { EVENTS } from "../../constants";
import { createPortSpyMock } from "../../jest/autofill-mocks";
import {
@ -208,10 +212,10 @@ describe("AutofillOverlayIframeService", () => {
);
});
it("passed the message on to the iframe element", () => {
it("passes the message on to the iframe element", () => {
const message = {
command: "initAutofillOverlayList",
theme: "theme_light",
theme: ThemeType.Light,
};
sendPortMessage(portSpy, message);
@ -223,10 +227,48 @@ describe("AutofillOverlayIframeService", () => {
);
});
it("sets a light theme based on the user's system preferences", () => {
window.matchMedia = jest.fn(() => mock<MediaQueryList>({ matches: false }));
const message = {
command: "initAutofillOverlayList",
theme: ThemeType.System,
};
sendPortMessage(portSpy, message);
expect(window.matchMedia).toHaveBeenCalledWith("(prefers-color-scheme: dark)");
expect(autofillOverlayIframeService["iframe"].contentWindow.postMessage).toBeCalledWith(
{
command: "initAutofillOverlayList",
theme: ThemeType.Light,
},
"*",
);
});
it("sets a dark theme based on the user's system preferences", () => {
window.matchMedia = jest.fn(() => mock<MediaQueryList>({ matches: true }));
const message = {
command: "initAutofillOverlayList",
theme: ThemeType.System,
};
sendPortMessage(portSpy, message);
expect(window.matchMedia).toHaveBeenCalledWith("(prefers-color-scheme: dark)");
expect(autofillOverlayIframeService["iframe"].contentWindow.postMessage).toBeCalledWith(
{
command: "initAutofillOverlayList",
theme: ThemeType.Dark,
},
"*",
);
});
it("updates the border to match the `dark` theme", () => {
const message = {
command: "initAutofillOverlayList",
theme: "theme_dark",
theme: ThemeType.Dark,
};
sendPortMessage(portSpy, message);
@ -239,7 +281,7 @@ describe("AutofillOverlayIframeService", () => {
it("updates the border to match the `nord` theme", () => {
const message = {
command: "initAutofillOverlayList",
theme: "theme_nord",
theme: ThemeType.Nord,
};
sendPortMessage(portSpy, message);
@ -252,7 +294,7 @@ describe("AutofillOverlayIframeService", () => {
it("updates the border to match the `solarizedDark` theme", () => {
const message = {
command: "initAutofillOverlayList",
theme: "theme_solarizedDark",
theme: ThemeType.SolarizedDark,
};
sendPortMessage(portSpy, message);

View File

@ -1,3 +1,5 @@
import { ThemeType } from "@bitwarden/common/platform/enums";
import { EVENTS } from "../../constants";
import { setElementStyles } from "../../utils";
import {
@ -207,19 +209,27 @@ class AutofillOverlayIframeService implements AutofillOverlayIframeServiceInterf
private initAutofillOverlayList(message: AutofillOverlayIframeExtensionMessage) {
const { theme } = message;
let borderColor: string;
if (theme === "theme_dark") {
let verifiedTheme = theme;
if (verifiedTheme === ThemeType.System) {
verifiedTheme = window.matchMedia("(prefers-color-scheme: dark)").matches
? ThemeType.Dark
: ThemeType.Light;
}
if (verifiedTheme === ThemeType.Dark) {
borderColor = "#4c525f";
}
if (theme === "theme_nord") {
if (theme === ThemeType.Nord) {
borderColor = "#2E3440";
}
if (theme === "theme_solarizedDark") {
if (theme === ThemeType.SolarizedDark) {
borderColor = "#073642";
}
if (borderColor) {
this.updateElementStyles(this.iframe, { borderColor });
}
message.theme = verifiedTheme;
this.iframe.contentWindow?.postMessage(message, "*");
}

View File

@ -3,7 +3,7 @@
exports[`AutofillOverlayList initAutofillOverlayList the list of ciphers for an authenticated user creates the view for a list of ciphers 1`] = `
<div
aria-modal="true"
class="overlay-list-container light"
class="overlay-list-container theme_light"
role="dialog"
>
<ul
@ -437,7 +437,7 @@ exports[`AutofillOverlayList initAutofillOverlayList the list of ciphers for an
exports[`AutofillOverlayList initAutofillOverlayList the locked overlay for an unauthenticated user creates the views for the locked overlay 1`] = `
<div
aria-modal="true"
class="overlay-list-container light"
class="overlay-list-container theme_light"
role="dialog"
>
<div
@ -491,7 +491,7 @@ exports[`AutofillOverlayList initAutofillOverlayList the locked overlay for an u
exports[`AutofillOverlayList initAutofillOverlayList the overlay with an empty list of ciphers creates the views for the no results overlay 1`] = `
<div
aria-modal="true"
class="overlay-list-container light"
class="overlay-list-container theme_light"
role="dialog"
>
<div

View File

@ -54,10 +54,11 @@ class AutofillOverlayList extends AutofillOverlayPageElement {
}: InitAutofillOverlayListMessage) {
const linkElement = this.initOverlayPage("button", styleSheetUrl, translations);
globalThis.document.documentElement.classList.add(theme);
const themeClass = `theme_${theme}`;
globalThis.document.documentElement.classList.add(themeClass);
this.overlayListContainer = globalThis.document.createElement("div");
this.overlayListContainer.classList.add("overlay-list-container", theme);
this.overlayListContainer.classList.add("overlay-list-container", themeClass);
this.overlayListContainer.setAttribute("role", "dialog");
this.overlayListContainer.setAttribute("aria-modal", "true");
this.resizeObserver.observe(this.overlayListContainer);

View File

@ -57,7 +57,7 @@ $themes: (
inputBorderColor: #4c525f,
inputBackgroundColor: #2f343d,
borderColor: #4c525f,
focusOutlineColor: $focus-outline-color,
focusOutlineColor: lighten($focus-outline-color, 25%),
successColor: $success-color-dark,
errorColor: $error-color-dark,
),
@ -72,7 +72,7 @@ $themes: (
inputBorderColor: $nord0,
inputBackgroundColor: $nord2,
borderColor: $nord0,
focusOutlineColor: $focus-outline-color,
focusOutlineColor: lighten($focus-outline-color, 25%),
successColor: $success-color-dark,
),
solarizedDark: (
@ -87,7 +87,7 @@ $themes: (
inputBorderColor: rgba($solarizedDarkBase2, 0.2),
inputBackgroundColor: $solarizedDarkBase01,
borderColor: $solarizedDarkBase2,
focusOutlineColor: $focus-outline-color,
focusOutlineColor: lighten($focus-outline-color, 15%),
successColor: $success-color-dark,
),
);