mirror of
https://github.com/bitwarden/browser
synced 2026-01-30 16:23:53 +00:00
[WIP] updates tests.
This commit is contained in:
@@ -2240,6 +2240,121 @@ describe("CollectAutofillContentService", () => {
|
||||
|
||||
expect(collectAutofillContentService["setupOverlayListenersOnMutatedElements"]).toBeCalled();
|
||||
});
|
||||
|
||||
it("triggers debounced page details update when mutations occur in shadow roots", () => {
|
||||
jest.useFakeTimers();
|
||||
const mutationRecord: MutationRecord = {
|
||||
type: "childList",
|
||||
addedNodes: document.querySelectorAll("div"),
|
||||
attributeName: null,
|
||||
attributeNamespace: null,
|
||||
nextSibling: null,
|
||||
oldValue: null,
|
||||
previousSibling: null,
|
||||
removedNodes: null,
|
||||
target: document.body,
|
||||
};
|
||||
collectAutofillContentService["currentLocationHref"] = window.location.href;
|
||||
|
||||
jest.spyOn(domQueryService, "checkMutationsInShadowRoots").mockReturnValue(true);
|
||||
jest.spyOn(collectAutofillContentService as any, "debouncedRequirePageDetailsUpdate");
|
||||
|
||||
collectAutofillContentService["handleMutationObserverMutation"]([mutationRecord]);
|
||||
|
||||
expect(domQueryService.checkMutationsInShadowRoots).toHaveBeenCalledWith([mutationRecord]);
|
||||
expect(collectAutofillContentService["debouncedRequirePageDetailsUpdate"]).toHaveBeenCalled();
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it("does not trigger debounced update when mutations are not in shadow roots", () => {
|
||||
jest.useFakeTimers();
|
||||
const mutationRecord: MutationRecord = {
|
||||
type: "childList",
|
||||
addedNodes: document.querySelectorAll("div"),
|
||||
attributeName: null,
|
||||
attributeNamespace: null,
|
||||
nextSibling: null,
|
||||
oldValue: null,
|
||||
previousSibling: null,
|
||||
removedNodes: null,
|
||||
target: document.body,
|
||||
};
|
||||
collectAutofillContentService["currentLocationHref"] = window.location.href;
|
||||
|
||||
jest.spyOn(domQueryService, "checkMutationsInShadowRoots").mockReturnValue(false);
|
||||
jest.spyOn(collectAutofillContentService as any, "debouncedRequirePageDetailsUpdate");
|
||||
|
||||
collectAutofillContentService["handleMutationObserverMutation"]([mutationRecord]);
|
||||
|
||||
expect(domQueryService.checkMutationsInShadowRoots).toHaveBeenCalledWith([mutationRecord]);
|
||||
expect(
|
||||
collectAutofillContentService["debouncedRequirePageDetailsUpdate"],
|
||||
).not.toHaveBeenCalled();
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it("schedules a debounced check for new shadow roots", () => {
|
||||
jest.useFakeTimers();
|
||||
const mutationRecord: MutationRecord = {
|
||||
type: "childList",
|
||||
addedNodes: document.querySelectorAll("div"),
|
||||
attributeName: null,
|
||||
attributeNamespace: null,
|
||||
nextSibling: null,
|
||||
oldValue: null,
|
||||
previousSibling: null,
|
||||
removedNodes: null,
|
||||
target: document.body,
|
||||
};
|
||||
collectAutofillContentService["currentLocationHref"] = window.location.href;
|
||||
collectAutofillContentService["pendingShadowDomCheck"] = false;
|
||||
|
||||
jest.spyOn(domQueryService, "checkMutationsInShadowRoots").mockReturnValue(false);
|
||||
jest.spyOn(collectAutofillContentService as any, "checkForNewShadowRoots");
|
||||
|
||||
collectAutofillContentService["handleMutationObserverMutation"]([mutationRecord]);
|
||||
|
||||
expect(collectAutofillContentService["pendingShadowDomCheck"]).toBe(true);
|
||||
expect(collectAutofillContentService["shadowDomCheckTimeout"]).not.toBeNull();
|
||||
|
||||
// Fast-forward time to trigger the debounced check
|
||||
jest.advanceTimersByTime(500);
|
||||
|
||||
expect(collectAutofillContentService["checkForNewShadowRoots"]).toHaveBeenCalled();
|
||||
expect(collectAutofillContentService["pendingShadowDomCheck"]).toBe(false);
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it("does not schedule duplicate shadow root checks when already pending", () => {
|
||||
jest.useFakeTimers();
|
||||
const mutationRecord: MutationRecord = {
|
||||
type: "childList",
|
||||
addedNodes: document.querySelectorAll("div"),
|
||||
attributeName: null,
|
||||
attributeNamespace: null,
|
||||
nextSibling: null,
|
||||
oldValue: null,
|
||||
previousSibling: null,
|
||||
removedNodes: null,
|
||||
target: document.body,
|
||||
};
|
||||
collectAutofillContentService["currentLocationHref"] = window.location.href;
|
||||
collectAutofillContentService["pendingShadowDomCheck"] = true;
|
||||
|
||||
const initialTimeout = setTimeout(() => {}, 500);
|
||||
collectAutofillContentService["shadowDomCheckTimeout"] = initialTimeout;
|
||||
|
||||
collectAutofillContentService["handleMutationObserverMutation"]([mutationRecord]);
|
||||
|
||||
// Should not change the timeout since check is already pending
|
||||
expect(collectAutofillContentService["shadowDomCheckTimeout"]).toBe(initialTimeout);
|
||||
|
||||
clearTimeout(initialTimeout);
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
||||
describe("setupOverlayListenersOnMutatedElements", () => {
|
||||
@@ -2660,22 +2775,25 @@ describe("CollectAutofillContentService", () => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it("will require an update to page details if shadow DOM is present", () => {
|
||||
jest
|
||||
.spyOn(domQueryService as any, "checkPageContainsShadowDom")
|
||||
.mockImplementationOnce(() => true);
|
||||
it("processes queued mutations and clears the queue", () => {
|
||||
const mutationRecord: MutationRecord = {
|
||||
type: "childList",
|
||||
addedNodes: document.querySelectorAll("div"),
|
||||
attributeName: null,
|
||||
attributeNamespace: null,
|
||||
nextSibling: null,
|
||||
oldValue: null,
|
||||
previousSibling: null,
|
||||
removedNodes: document.querySelectorAll("li"),
|
||||
target: document.body,
|
||||
};
|
||||
|
||||
collectAutofillContentService["requirePageDetailsUpdate"] = jest.fn();
|
||||
|
||||
collectAutofillContentService["mutationsQueue"] = [[], []];
|
||||
collectAutofillContentService["mutationsQueue"] = [[mutationRecord], [mutationRecord]];
|
||||
jest.spyOn(collectAutofillContentService as any, "processMutationRecords");
|
||||
|
||||
collectAutofillContentService["processMutations"]();
|
||||
|
||||
jest.runOnlyPendingTimers();
|
||||
|
||||
expect(domQueryService.checkPageContainsShadowDom).toHaveBeenCalled();
|
||||
expect(collectAutofillContentService["mutationsQueue"]).toHaveLength(0);
|
||||
expect(collectAutofillContentService["requirePageDetailsUpdate"]).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -147,4 +147,122 @@ describe("DomQueryService", () => {
|
||||
expect(formFieldElements).toStrictEqual([input]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("checkMutationsInShadowRoots", () => {
|
||||
it("returns true when a mutation occurred within a shadow root", () => {
|
||||
const customElement = document.createElement("custom-element");
|
||||
const shadowRoot = customElement.attachShadow({ mode: "open" });
|
||||
const input = document.createElement("input");
|
||||
shadowRoot.appendChild(input);
|
||||
|
||||
const mutationRecord: MutationRecord = {
|
||||
type: "childList",
|
||||
addedNodes: NodeList.prototype,
|
||||
attributeName: null,
|
||||
attributeNamespace: null,
|
||||
nextSibling: null,
|
||||
oldValue: null,
|
||||
previousSibling: null,
|
||||
removedNodes: NodeList.prototype,
|
||||
target: input,
|
||||
};
|
||||
|
||||
const result = domQueryService.checkMutationsInShadowRoots([mutationRecord]);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when mutations occurred in the light DOM", () => {
|
||||
const div = document.createElement("div");
|
||||
document.body.appendChild(div);
|
||||
|
||||
const mutationRecord: MutationRecord = {
|
||||
type: "childList",
|
||||
addedNodes: NodeList.prototype,
|
||||
attributeName: null,
|
||||
attributeNamespace: null,
|
||||
nextSibling: null,
|
||||
oldValue: null,
|
||||
previousSibling: null,
|
||||
removedNodes: NodeList.prototype,
|
||||
target: div,
|
||||
};
|
||||
|
||||
const result = domQueryService.checkMutationsInShadowRoots([mutationRecord]);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("returns true if any mutation in the array is in a shadow root", () => {
|
||||
const customElement = document.createElement("custom-element");
|
||||
const shadowRoot = customElement.attachShadow({ mode: "open" });
|
||||
const shadowInput = document.createElement("input");
|
||||
shadowRoot.appendChild(shadowInput);
|
||||
|
||||
const lightDiv = document.createElement("div");
|
||||
document.body.appendChild(lightDiv);
|
||||
|
||||
const shadowMutation: MutationRecord = {
|
||||
type: "childList",
|
||||
addedNodes: NodeList.prototype,
|
||||
attributeName: null,
|
||||
attributeNamespace: null,
|
||||
nextSibling: null,
|
||||
oldValue: null,
|
||||
previousSibling: null,
|
||||
removedNodes: NodeList.prototype,
|
||||
target: shadowInput,
|
||||
};
|
||||
|
||||
const lightMutation: MutationRecord = {
|
||||
type: "childList",
|
||||
addedNodes: NodeList.prototype,
|
||||
attributeName: null,
|
||||
attributeNamespace: null,
|
||||
nextSibling: null,
|
||||
oldValue: null,
|
||||
previousSibling: null,
|
||||
removedNodes: NodeList.prototype,
|
||||
target: lightDiv,
|
||||
};
|
||||
|
||||
const result = domQueryService.checkMutationsInShadowRoots([lightMutation, shadowMutation]);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("checkForNewShadowRoots", () => {
|
||||
it("returns true when a shadow root is not in the observed set", () => {
|
||||
const customElement = document.createElement("custom-element");
|
||||
customElement.attachShadow({ mode: "open" });
|
||||
document.body.appendChild(customElement);
|
||||
|
||||
const result = domQueryService.checkForNewShadowRoots();
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when all shadow roots are already observed", () => {
|
||||
const customElement = document.createElement("custom-element");
|
||||
const shadowRoot = customElement.attachShadow({ mode: "open" });
|
||||
document.body.appendChild(customElement);
|
||||
|
||||
// Simulate the shadow root being observed by adding it to the tracked set
|
||||
domQueryService["observedShadowRoots"].add(shadowRoot);
|
||||
|
||||
const result = domQueryService.checkForNewShadowRoots();
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when there are no shadow roots on the page", () => {
|
||||
const div = document.createElement("div");
|
||||
document.body.appendChild(div);
|
||||
|
||||
const result = domQueryService.checkForNewShadowRoots();
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user