Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Tests scripting.insertCSS()</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="text/javascript">
"use strict";
const MOCHITEST_HOST_PERMISSIONS = [
"*://mochi.test/",
"*://mochi.xorigin-test/",
"*://test1.example.com/",
];
const makeExtension = ({ manifest: manifestProps, ...otherProps }) => {
return ExtensionTestUtils.loadExtension({
manifest: {
manifest_version: 3,
permissions: ["scripting"],
host_permissions: [
...MOCHITEST_HOST_PERMISSIONS,
// Used in `file_contains_iframe.html`
],
granted_host_permissions: true,
...manifestProps,
},
useAddonManager: "temporary",
...otherProps,
});
};
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({
set: [["extensions.manifestV3.enabled", true]],
});
});
add_task(async function test_insertCSS_and_removeCSS_params_validation() {
let extension = makeExtension({
async background() {
const tabs = await browser.tabs.query({ active: true });
const TEST_CASES = [
{
title: "no files and no css",
cssParams: {},
expectedError: "Exactly one of files and css must be specified.",
},
{
title: "both files and css are passed",
cssParams: {
files: ["styles.css"],
css: "* { background: rgb(1, 1, 1) }",
},
expectedError: "Exactly one of files and css must be specified.",
},
{
title: "both allFrames and frameIds are passed",
cssParams: {
target: {
tabId: tabs[0].id,
allFrames: true,
frameIds: [1, 2, 3],
},
files: ["styles.css"],
},
expectedError: "Cannot specify both 'allFrames' and 'frameIds'.",
},
{
title: "empty css string with a file",
cssParams: {
css: "",
files: ["styles.css"],
},
expectedError: "Exactly one of files and css must be specified.",
},
];
for (const { title, cssParams, expectedError } of TEST_CASES) {
await browser.test.assertRejects(
browser.scripting.insertCSS({
target: { tabId: tabs[0].id },
...cssParams,
}),
expectedError,
`${title} - expected error for insertCSS()`
);
await browser.test.assertRejects(
browser.scripting.removeCSS({
target: { tabId: tabs[0].id },
...cssParams,
}),
expectedError,
`${title} - expected error for removeCSS()`
);
}
browser.test.notifyPass("checks-done");
},
});
await extension.startup();
await extension.awaitFinish("checks-done");
await extension.unload();
});
add_task(async function test_insertCSS_with_invalid_tabId() {
let extension = makeExtension({
async background() {
// This tab ID should not exist.
const tabId = 123456789;
await browser.test.assertRejects(
browser.scripting.insertCSS({
target: { tabId },
css: "* { background: rgb(1, 1, 1) }",
}),
`Invalid tab ID: ${tabId}`
);
browser.test.notifyPass("insert-css");
},
});
await extension.startup();
await extension.awaitFinish("insert-css");
await extension.unload();
});
add_task(async function test_insertCSS_with_wrong_host_permissions() {
let extension = makeExtension({
manifest: {
host_permissions: [],
},
async background() {
const tabs = await browser.tabs.query({ active: true });
browser.test.assertEq(1, tabs.length, "expected 1 tab");
browser.test.assertRejects(
browser.scripting.insertCSS({
target: { tabId: tabs[0].id },
css: "* { background: rgb(1, 1, 1) }",
}),
/Missing host permission for the tab/,
"expected host permission error"
);
browser.test.notifyPass("insert-css");
},
});
await extension.startup();
await extension.awaitFinish("insert-css");
await extension.unload();
});
add_task(async function test_insertCSS_and_removeCSS() {
let extension = makeExtension({
manifest: {
permissions: ["scripting", "webNavigation"],
},
async background() {
const tabs = await browser.tabs.query({ active: true });
browser.test.assertEq(1, tabs.length, "expected 1 tab");
const tabId = tabs[0].id;
const frames = await browser.webNavigation.getAllFrames({ tabId });
// 1. Top-level frame that loads `file_contains_iframe.html`
// 2. Frame that loads `file_contains_img.html`
browser.test.assertEq(2, frames.length, "expected 2 frames");
const frameIds = frames.map(frame => frame.frameId);
const cssColor1 = "rgb(1, 1, 1)";
const cssColor2 = "rgb(2, 2, 2)";
const cssColorInFile1 = "rgb(3, 3, 3)";
const defaultColor = "rgba(0, 0, 0, 0)";
const TEST_CASES = [
{
title: "with css prop",
elementId: "div-1",
cssParams: [
{
target: { tabId },
css: `#div-1 { background: ${cssColor1} }`,
},
],
expectedResults: [cssColor1, defaultColor],
},
{
title: "with a file",
elementId: "div-2",
cssParams: [
{
target: { tabId },
files: ["file1.css"],
},
],
expectedResults: [cssColorInFile1, defaultColor],
},
{
title: "css prop in a single frame",
elementId: "div-3",
cssParams: [
{
target: { tabId, frameIds: [frameIds[0]] },
css: `#div-3 { background: ${cssColor2} }`,
},
],
expectedResults: [cssColor2, defaultColor],
},
{
title: "css prop in multiple frames",
elementId: "div-4",
cssParams: [
{
target: { tabId, frameIds },
css: `#div-4 { background: ${cssColor1} }`,
},
],
expectedResults: [cssColor1, cssColor1],
},
{
title: "allFrames is true",
elementId: "div-5",
cssParams: [
{
target: { tabId, allFrames: true },
css: `#div-5 { background: ${defaultColor} }`,
},
],
expectedResults: [defaultColor, defaultColor],
},
{
title: "origin: 'AUTHOR'",
elementId: "div-6",
cssParams: [
{
target: { tabId },
css: `#div-6 { background: ${cssColor1} }`,
origin: "AUTHOR",
},
{
target: { tabId },
css: `#div-6 { background: ${cssColor2} }`,
origin: "AUTHOR",
},
],
expectedResults: [cssColor2, defaultColor],
},
{
title: "origin: 'USER'",
elementId: "div-7",
cssParams: [
{
target: { tabId },
css: `#div-7 { background: ${cssColor1} !important }`,
origin: "USER",
},
{
target: { tabId },
css: `#div-7 { background: ${cssColor2} !important }`,
origin: "AUTHOR",
},
],
// User has higher importance.
expectedResults: [cssColor1, defaultColor],
},
{
title: "empty css string",
elementId: "div-8",
cssParams: [
{
target: { tabId },
css: "",
},
],
expectedResults: [defaultColor, defaultColor],
},
{
title: "allFrames is false",
elementId: "div-9",
cssParams: [
{
target: { tabId, allFrames: false },
css: `#div-9 { background: ${cssColor1} }`,
},
],
expectedResults: [cssColor1, defaultColor],
},
];
const getBackgroundColor = elementId => {
return window.getComputedStyle(document.getElementById(elementId))
.backgroundColor;
};
for (const {
title,
elementId,
cssParams,
expectedResults,
} of TEST_CASES) {
// Create a unique element for the current test case.
await browser.scripting.executeScript({
target: { tabId, allFrames: true },
func: elementId => {
const element = document.createElement("div");
element.setAttribute("id", elementId);
document.body.appendChild(element);
},
args: [elementId],
});
for (const params of cssParams) {
const result = await browser.scripting.insertCSS(params);
// `insertCSS()` should not resolve to a value.
browser.test.assertEq(undefined, result, "got expected empty result");
}
let results = await browser.scripting.executeScript({
target: { tabId, allFrames: true },
func: getBackgroundColor,
args: [elementId],
});
results.sort((a, b) => a.frameId - b.frameId);
browser.test.assertEq(
expectedResults.length,
results.length,
`${title} - got the expected number of results`
);
results.forEach((result, index) => {
browser.test.assertEq(
expectedResults[index],
result.result,
`${title} - got expected result (index=${index}): ${title}`
);
});
results = await Promise.all(
cssParams.map(params => browser.scripting.removeCSS(params))
);
// `removeCSS()` should not resolve to a value.
results.forEach(result => {
browser.test.assertEq(undefined, result, "got expected empty result");
});
results = await browser.scripting.executeScript({
target: { tabId, allFrames: true },
func: getBackgroundColor,
args: [elementId],
});
browser.test.assertTrue(
results.every(({ result }) => result === defaultColor),
"got expected default color in all frames"
);
}
browser.test.notifyPass("insert-and-remove-css");
},
files: {
"file1.css": "#div-2 { background: rgb(3, 3, 3) }",
},
});
let tab = await AppTestDelegate.openNewForegroundTab(
window,
true
);
await extension.startup();
await extension.awaitFinish("insert-and-remove-css");
await extension.unload();
await AppTestDelegate.removeTab(window, tab);
});
</script>
</body>
</html>