Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
// Tests that the text filter box works to filter based on location.
"use strict";
// In this test, we are trying to test the filtering functionality of the filter
// input. We test filtering not only for the contents of logs themseleves but
// also for the filenames.
//
// We simulate an HTML file which executes two Javascript files, one with an
// ASCII filename outputs some ASCII logs and the other one with a Unicode
// filename outputs some Unicode logs.
const SEASON = {
english: "season",
chinese: "\u5b63",
};
const SEASONS = [
{
english: "spring",
chinese: "\u6625",
escapedChinese: "\\u6625",
},
{
english: "summer",
chinese: "\u590f",
escapedChinese: "\\u590f",
},
{
english: "autumn",
chinese: "\u79cb",
escapedChinese: "\\u79cb",
},
{
english: "winter",
chinese: "\u51ac",
escapedChinese: "\\u51ac",
},
];
// filenames
const HTML_FILENAME = `test.html`;
const JS_ASCII_FILENAME = `${SEASON.english}.js`;
const JS_UNICODE_FILENAME = `${SEASON.chinese}.js`;
const ENCODED_JS_UNICODE_FILENAME = encodeURIComponent(JS_UNICODE_FILENAME);
// file contents
const HTML_CONSOLE_OUTPUT = `Test filtering ${SEASON.english} names.`;
const HTML_CONTENT = `<!DOCTYPE html>
<meta charset="utf-8">
<title>Test filtering logs by filling keywords in the filter input.</title>
<script>
console.log("${HTML_CONSOLE_OUTPUT}");
</script>
<script src="/${JS_ASCII_FILENAME}"></script>
<script src="/${ENCODED_JS_UNICODE_FILENAME}"></script>`;
add_task(async function () {
const testUrl = createServerAndGetTestUrl();
const hud = await openNewTabAndConsole(testUrl);
// Let's wait for the last logged message of each file to be displayed in the
// output, in order to make sure all the logged messages have been displayed.
const lastSeason = SEASONS[SEASONS.length - 1];
await waitFor(
() =>
findConsoleAPIMessage(hud, lastSeason.english) &&
findConsoleAPIMessage(hud, lastSeason.chinese)
);
// One external Javascript file outputs every season name in English, and the
// other Javascript file outputs every season name in Chinese.
// The HTML file outputs one line on its own.
// So the total number of all the logs is the doubled number of seasons plus
// one.
let visibleLogs = getVisibleLogs(hud);
is(
visibleLogs.length,
SEASONS.length * 2 + 1,
"the total number of all the logs before starting filtering"
);
checkLogContent(visibleLogs[0], HTML_CONSOLE_OUTPUT, HTML_FILENAME);
for (let i = 0; i < SEASONS.length; i++) {
checkLogContent(visibleLogs[i + 1], SEASONS[i].english, JS_ASCII_FILENAME);
}
for (let i = 0; i < SEASONS.length; i++) {
checkLogContent(
visibleLogs[i + 1 + SEASONS.length],
SEASONS[i].chinese,
JS_UNICODE_FILENAME
);
}
// checking the visibility of clear button, it should be visible only when
// there is text inside filter input box
await setFilterState(hud, { text: "" });
is(getClearButton(hud).hidden, true, "Clear button is hidden");
await setFilterState(hud, { text: JS_ASCII_FILENAME });
is(getClearButton(hud).hidden, false, "Clear button is visible");
// All the logs outputted by the ASCII Javascript file are visible, the others
// are hidden.
await setFilterState(hud, { text: JS_ASCII_FILENAME });
visibleLogs = getVisibleLogs(hud);
is(
visibleLogs.length,
SEASONS.length,
`the number of all the logs containing ${JS_ASCII_FILENAME}`
);
for (let i = 0; i < SEASONS.length; i++) {
checkLogContent(visibleLogs[i], SEASONS[i].english, JS_ASCII_FILENAME);
}
// Every season name in English is outputted once.
for (const curSeason of SEASONS) {
await setFilterState(hud, { text: curSeason.english });
visibleLogs = getVisibleLogs(hud);
is(
visibleLogs.length,
1,
`the number of all the logs containing ${curSeason.english}`
);
checkLogContent(visibleLogs[0], curSeason.english, JS_ASCII_FILENAME);
}
// All the logs outputted by the Unicode Javascript file are visible, the
// others are hidden.
await setFilterState(hud, { text: JS_UNICODE_FILENAME });
visibleLogs = getVisibleLogs(hud);
is(
visibleLogs.length,
SEASONS.length,
`the number of all the logs containing ${JS_UNICODE_FILENAME}`
);
for (let i = 0; i < SEASONS.length; i++) {
checkLogContent(visibleLogs[i], SEASONS[i].chinese, JS_UNICODE_FILENAME);
}
// Every season name in Chinese is outputted once.
for (const curSeason of SEASONS) {
await setFilterState(hud, { text: curSeason.chinese });
visibleLogs = getVisibleLogs(hud);
is(
visibleLogs.length,
1,
`the number of all the logs containing ${curSeason.chinese}`
);
checkLogContent(visibleLogs[0], curSeason.chinese, JS_UNICODE_FILENAME);
}
// The filename of the ASCII Javascript file contains the English word season,
// so all the logs outputted by the file are visible, besides, the HTML
// outputs one line containing the English word season, so it is also visible.
// The other logs are hidden. So the number of all the visible logs is the
// season number plus one.
await setFilterState(hud, { text: SEASON.english });
visibleLogs = getVisibleLogs(hud);
is(
visibleLogs.length,
SEASONS.length + 1,
`the number of all the logs containing ${SEASON.english}`
);
checkLogContent(visibleLogs[0], HTML_CONSOLE_OUTPUT, HTML_FILENAME);
for (let i = 0; i < SEASONS.length; i++) {
checkLogContent(visibleLogs[i + 1], SEASONS[i].english, JS_ASCII_FILENAME);
}
// The filename of the Unicode Javascript file contains the Chinese word
// season, so all the logs outputted by the file are visible. The other logs
// are hidden. So the number of all the visible logs is the season number.
await setFilterState(hud, { text: SEASON.chinese });
visibleLogs = getVisibleLogs(hud);
is(
visibleLogs.length,
SEASONS.length,
`the number of all the logs containing ${SEASON.chinese}`
);
for (let i = 0; i < SEASONS.length; i++) {
checkLogContent(visibleLogs[i], SEASONS[i].chinese, JS_UNICODE_FILENAME);
}
// After clearing the text in the filter input box, all the logs are visible
// again.
await setFilterState(hud, { text: "" });
checkAllMessagesAreVisible(hud);
// clearing the text in the filter input box using clear button, so after which
// all logs will be visible again
await setFilterState(hud, { text: JS_ASCII_FILENAME });
info("Click the input clear button");
clickClearButton(hud);
await waitFor(() => getClearButton(hud).hidden === true);
checkAllMessagesAreVisible(hud);
});
// Create an HTTP server to simulate a response for the a URL request and return
// the URL.
function createServerAndGetTestUrl() {
const httpServer = createTestHTTPServer();
httpServer.registerContentType("html", "text/html");
httpServer.registerContentType("js", "application/javascript");
httpServer.registerPathHandler(
"/" + HTML_FILENAME,
function (request, response) {
response.setStatusLine(request.httpVersion, 200, "OK");
response.write(HTML_CONTENT);
}
);
httpServer.registerPathHandler(
"/" + JS_ASCII_FILENAME,
function (request, response) {
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "application/javascript", false);
let content = "";
for (const curSeason of SEASONS) {
content += `console.log("${curSeason.english}");`;
}
response.write(content);
}
);
httpServer.registerPathHandler(
"/" + ENCODED_JS_UNICODE_FILENAME,
function (request, response) {
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "application/javascript", false);
let content = "";
for (const curSeason of SEASONS) {
content += `console.log("${curSeason.escapedChinese}");`;
}
response.write(content);
}
);
const port = httpServer.identity.primaryPort;
return `http://localhost:${port}/${HTML_FILENAME}`;
}
function getClearButton(hud) {
return hud.ui.outputNode.querySelector(
".devtools-searchbox .devtools-searchinput-clear"
);
}
function clickClearButton(hud) {
getClearButton(hud).click();
}
function getVisibleLogs(hud) {
const outputNode = hud.ui.outputNode;
return outputNode.querySelectorAll(".message");
}
function checkAllMessagesAreVisible(hud) {
const visibleLogs = getVisibleLogs(hud);
is(
visibleLogs.length,
SEASONS.length * 2 + 1,
"the total number of all the logs after clearing filtering"
);
checkLogContent(visibleLogs[0], HTML_CONSOLE_OUTPUT, HTML_FILENAME);
for (let i = 0; i < SEASONS.length; i++) {
checkLogContent(visibleLogs[i + 1], SEASONS[i].english, JS_ASCII_FILENAME);
}
for (let i = 0; i < SEASONS.length; i++) {
checkLogContent(
visibleLogs[i + 1 + SEASONS.length],
SEASONS[i].chinese,
JS_UNICODE_FILENAME
);
}
}
/**
* Check if the content of a log message is what we expect.
*
* @param Object node
* The node for the log message.
* @param String expectedMessageBody
* The string we expect to match the message body in the log message.
* @param String expectedFilename
* The string we expect to match the filename in the log message.
*/
function checkLogContent(node, expectedMessageBody, expectedFilename) {
const messageBody = node.querySelector(".message-body").textContent;
const location = node.querySelector(".message-location").textContent;
// The location detail contains the line number and the column number, let's
// strip them to get the filename.
const filename = location.split(":")[0];
is(messageBody, expectedMessageBody, "the expected message body");
is(filename, expectedFilename, "the expected filename");
}