Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: asan OR http3 OR http2
- Manifest: devtools/client/webconsole/test/browser/_webconsole.toml
/* Any copyright is dedicated to the Public Domain.
"use strict";
const TEST_FILE = "test-console.html";
const TEST_COM_URI = URL_ROOT_COM_SSL + TEST_FILE;
const TEST_ORG_URI = URL_ROOT_ORG_SSL + TEST_FILE;
// TEST_MOCHI_URI uses a non standart port and hence
// is not subject to https-first mode
const TEST_MOCHI_URI = URL_ROOT_MOCHI_8888 + TEST_FILE;
registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.webconsole.persistlog");
});
const INITIAL_LOGS_NUMBER = 5;
const {
MESSAGE_TYPE,
} = require("resource://devtools/client/webconsole/constants.js");
const {
WILL_NAVIGATE_TIME_SHIFT,
} = require("resource://devtools/server/actors/webconsole/listeners/document-events.js");
async function logAndAssertInitialMessages(hud) {
await SpecialPowers.spawn(
gBrowser.selectedBrowser,
[INITIAL_LOGS_NUMBER],
count => {
content.wrappedJSObject.doLogs(count);
}
);
await waitFor(() => findAllMessages(hud).length === INITIAL_LOGS_NUMBER);
ok(true, "Messages showed up initially");
}
add_task(async function () {
info("Testing that messages disappear on a refresh if logs aren't persisted");
const hud = await openNewTabAndConsole(TEST_COM_URI);
await logAndAssertInitialMessages(hud);
const onReloaded = hud.ui.once("reloaded");
await reloadBrowser();
await onReloaded;
info("Wait for messages to be cleared");
await waitFor(() => findAllMessages(hud).length === 0);
ok(true, "Messages disappeared");
await closeToolbox();
});
add_task(async function () {
info(
"Testing that messages disappear on a cross origin navigation if logs aren't persisted"
);
const hud = await openNewTabAndConsole(TEST_COM_URI);
await logAndAssertInitialMessages(hud);
await navigateTo(TEST_ORG_URI);
await waitFor(() => findAllMessages(hud).length === 0);
ok(true, "Messages disappeared");
await closeToolbox();
});
add_task(async function () {
info("Testing that messages disappear on bfcache navigations");
const firstLocation =
"data:text/html,<!DOCTYPE html><script>console.log('first document load');window.onpageshow=()=>console.log('first document show');</script>";
const secondLocation =
"data:text/html,<!DOCTYPE html><script>console.log('second document load');window.onpageshow=()=>console.log('second document show');</script>";
const hud = await openNewTabAndConsole(firstLocation);
info("Wait for first page messages");
// Look into .message-body as the default selector also include the frame,
// which is the document url, which also include the logged string...
await waitFor(
() =>
findMessagePartsByType(hud, {
text: "first document load",
typeSelector: ".console-api",
partSelector: ".message-body",
}).length === 1 &&
findMessagePartsByType(hud, {
text: "first document show",
typeSelector: ".console-api",
partSelector: ".message-body",
}).length === 1
);
const firstPageInnerWindowId =
gBrowser.selectedBrowser.browsingContext.currentWindowGlobal.innerWindowId;
await navigateTo(secondLocation);
const secondPageInnerWindowId =
gBrowser.selectedBrowser.browsingContext.currentWindowGlobal.innerWindowId;
isnot(
firstPageInnerWindowId,
secondPageInnerWindowId,
"The second page is having a distinct inner window id"
);
await waitFor(
() =>
findMessagePartsByType(hud, {
text: "second",
typeSelector: ".console-api",
partSelector: ".message-body",
}).length === 2
);
ok("Second page message appeared");
is(
findMessagePartsByType(hud, {
text: "first",
typeSelector: ".console-api",
partSelector: ".message-body",
}).length,
0,
"First page message disappeared"
);
info("Go back to the first page");
gBrowser.selectedBrowser.goBack();
// When going back, the page isn't reloaded, so in theory we should only get
// the pageshow event.
await waitFor(
() =>
findMessagePartsByType(hud, {
text: "first document show",
typeSelector: ".console-api",
partSelector: ".message-body",
}).length === 1
);
ok("First page message re-appeared");
// However `clearMessagesCache` can fail on navigation, and in this case the
// cache will still contain the two initial logs:
// - "first document load"
// - "first document show"
let isLoadMessageDisplayed = findMessagePartsByType(hud, {
text: "first document load",
typeSelector: ".console-api",
partSelector: ".message-body",
}).length;
// With the additional "first document show" from the new bfcache navigation
// this means we should wait for "first document show" to have a repeated
// count of 2.
// Otherwise the second "first document show" resource might be throttled and
// handled later in the test.
if (isLoadMessageDisplayed) {
await waitForRepeatedMessageByType(
hud,
"first document show",
".console-api",
2
);
}
is(
gBrowser.selectedBrowser.browsingContext.currentWindowGlobal.innerWindowId,
firstPageInnerWindowId,
"The first page is really a bfcache navigation, keeping the same WindowGlobal"
);
is(
findMessagePartsByType(hud, {
text: "second",
typeSelector: ".console-api",
partSelector: ".message-body",
}).length,
0,
"Second page message disappeared"
);
info("Go forward to the original second page");
gBrowser.selectedBrowser.goForward();
await waitFor(
() =>
findMessagePartsByType(hud, {
text: "second document show",
typeSelector: ".console-api",
partSelector: ".message-body",
}).length === 1
);
ok("Second page message appeared");
isLoadMessageDisplayed = findMessagePartsByType(hud, {
text: "second document load",
typeSelector: ".console-api",
partSelector: ".message-body",
}).length;
if (isLoadMessageDisplayed) {
await waitForRepeatedMessageByType(
hud,
"second document show",
".console-api",
2
);
}
is(
gBrowser.selectedBrowser.browsingContext.currentWindowGlobal.innerWindowId,
secondPageInnerWindowId,
"The second page is really a bfcache navigation, keeping the same WindowGlobal"
);
is(
findMessagePartsByType(hud, {
text: "first",
typeSelector: ".console-api",
partSelector: ".message-body",
}).length,
0,
"First page message disappeared"
);
await closeToolbox();
});
add_task(async function () {
info("Testing that messages persist on a refresh if logs are persisted");
const hud = await openNewTabAndConsole(TEST_COM_URI);
await toggleConsoleSetting(
hud,
".webconsole-console-settings-menu-item-persistentLogs"
);
await logAndAssertInitialMessages(hud);
const onNavigatedMessage = waitForMessageByType(
hud,
"Navigated to " + TEST_COM_URI,
".navigationMarker"
);
const onReloaded = hud.ui.once("reloaded");
// Because will-navigate DOCUMENT_EVENT timestamp is shifted to workaround some other limitation,
// the reported time of navigation may actually be slightly off and be older than the real navigation start
let timeBeforeNavigation = Date.now() - WILL_NAVIGATE_TIME_SHIFT;
reloadBrowser();
await onNavigatedMessage;
await onReloaded;
ok(true, "Navigation message appeared as expected");
is(
findAllMessages(hud).length,
INITIAL_LOGS_NUMBER + 1,
"Messages logged before navigation are still visible"
);
assertLastMessageIsNavigationMessage(hud, timeBeforeNavigation, TEST_COM_URI);
info(
"Testing that messages also persist when doing a cross origin navigation if logs are persisted"
);
const onNavigatedMessage2 = waitForMessageByType(
hud,
"Navigated to " + TEST_ORG_URI,
".navigationMarker"
);
timeBeforeNavigation = Date.now() - WILL_NAVIGATE_TIME_SHIFT;
await navigateTo(TEST_ORG_URI);
await onNavigatedMessage2;
ok(true, "Second navigation message appeared as expected");
is(
findAllMessages(hud).length,
INITIAL_LOGS_NUMBER + 2,
"Messages logged before the second navigation are still visible"
);
assertLastMessageIsNavigationMessage(hud, timeBeforeNavigation, TEST_ORG_URI);
info(
"Test doing a second cross origin navigation in order to triger a target switching with a target following the window global lifecycle"
);
const onNavigatedMessage3 = waitForMessageByType(
hud,
"Navigated to " + TEST_MOCHI_URI,
".navigationMarker"
);
timeBeforeNavigation = Date.now() - WILL_NAVIGATE_TIME_SHIFT;
await navigateTo(TEST_MOCHI_URI);
await onNavigatedMessage3;
ok(true, "Third navigation message appeared as expected");
is(
findAllMessages(hud).length,
INITIAL_LOGS_NUMBER + 3,
"Messages logged before the third navigation are still visible"
);
assertLastMessageIsNavigationMessage(
hud,
timeBeforeNavigation,
TEST_MOCHI_URI
);
await closeToolbox();
});
add_task(async function consoleClearPersist() {
info("Testing that messages persist on console.clear if logs are persisted");
await pushPref("devtools.webconsole.persistlog", true);
const hud = await openNewTabAndConsole(TEST_COM_URI);
await logAndAssertInitialMessages(hud);
info("Send a console.clear() and another log from the content page");
const onConsoleClearPrevented = waitForMessageByType(
hud,
"console.clear() was prevented",
".console-api"
);
SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => {
content.wrappedJSObject.console.clear();
content.wrappedJSObject.console.log("after clear");
});
await waitForMessageByType(hud, "after clear", ".log");
await onConsoleClearPrevented;
ok(true, "console.clear was handled by the client");
Assert.strictEqual(
findAllMessages(hud).length,
INITIAL_LOGS_NUMBER + 2,
"All initial messages are still displayed, with the 2 new ones"
);
await closeToolbox();
});
function assertLastMessageIsNavigationMessage(hud, timeBeforeNavigation, url) {
const { visibleMessages, mutableMessagesById } = hud.ui.wrapper
.getStore()
.getState().messages;
const lastMessageId = visibleMessages.at(-1);
const lastMessage = mutableMessagesById.get(lastMessageId);
is(
lastMessage.type,
MESSAGE_TYPE.NAVIGATION_MARKER,
"The last message is a navigation marker"
);
is(
lastMessage.messageText,
"Navigated to " + url,
"The navigation message is correct"
);
// It is surprising, but the navigation may be timestamped at the same exact time
// as timeBeforeNavigation time record.
Assert.greaterOrEqual(
lastMessage.timeStamp,
timeBeforeNavigation,
"The navigation message has a timestamp newer (or equal) than the time before the navigation..."
);
Assert.less(
lastMessage.timeStamp,
Date.now(),
"...and older than current time"
);
}