summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/tools/wave/www/configuration.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/tools/wave/www/configuration.html')
-rw-r--r--testing/web-platform/tests/tools/wave/www/configuration.html1586
1 files changed, 1586 insertions, 0 deletions
diff --git a/testing/web-platform/tests/tools/wave/www/configuration.html b/testing/web-platform/tests/tools/wave/www/configuration.html
new file mode 100644
index 0000000000..327a155154
--- /dev/null
+++ b/testing/web-platform/tests/tools/wave/www/configuration.html
@@ -0,0 +1,1586 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <title>Session Configuration - Web Platform Test</title>
+ <link rel="stylesheet" href="css/bulma-0.7.5/bulma.min.css" />
+ <link rel="stylesheet" href="css/fontawesome-5.7.2.min.css" />
+ <script src="lib/utils.js"></script>
+ <script src="lib/wave-service.js"></script>
+ <script src="lib/ui.js"></script>
+ <style>
+ .site-logo {
+ max-width: 300px;
+ margin: 0 0 30px -15px;
+ }
+ </style>
+ </head>
+ <body>
+ <script>
+ // var apis = [
+ // { title: "2D Context", path: "/2dcontext" },
+ // { title: "Content Security Policy", path: "/content-security-policy" },
+ // { title: "CSS", path: "/css" },
+ // { title: "DOM", path: "/dom" },
+ // { title: "ECMAScript", path: "/ecmascript" },
+ // { title: "Encrypted media", path: "/encrypted-media" },
+ // { title: "Fetch", path: "/fetch" },
+ // { title: "FileAPI", path: "/FileAPI" },
+ // { title: "Fullscreen", path: "/fullscreen" },
+ // { title: "WebGL", path: "/webgl" },
+ // { title: "HTML", path: "/html" },
+ // { title: "IndexedDB", path: "/IndexedDB" },
+ // { title: "Media Source", path: "/media-source" },
+ // { title: "Notifications", path: "/notifications" },
+ // { title: "Page Visibility", path: "/page-visibility" },
+ // { title: "Service Workers", path: "/service-workers" },
+ // { title: "UI Events", path: "/uievents" },
+ // { title: "WAVE Extra", path: "/wave-extra" },
+ // { title: "Webaudio", path: "/webaudio" },
+ // { title: "WebCryptoAPI", path: "/WebCryptoAPI" },
+ // { title: "Webmessaging", path: "/webmessaging" },
+ // { title: "Websockets", path: "/websockets" },
+ // { title: "Webstorage", path: "/webstorage" },
+ // { title: "Workers", path: "/workers" },
+ // { title: "XHR", path: "/xhr" }
+ // ];
+
+ // var referenceSessions = [
+ // {
+ // title: "Edge 44.17763",
+ // engine: "",
+ // token: "b2924d20-6a93-11e9-98b4-a11fb92a6d1c",
+ // icon: "fab fa-edge"
+ // },
+ // {
+ // title: "Firefox 64.0",
+ // engine: "Gecko 64.0",
+ // token: "bb7aafa0-6a92-11e9-8ec2-04f58dad2e4f",
+ // icon: "fab fa-firefox"
+ // },
+ // {
+ // title: "WebKit 605.1.15",
+ // engine: "Revision 239158",
+ // token: "caf823e0-6a92-11e9-b732-3188d0065ebc",
+ // icon: "fab fa-safari"
+ // },
+ // {
+ // title: "Chromium 73.0.3640.0",
+ // engine: "Blink 537.36",
+ // token: "a50c6db0-6a94-11e9-8d1b-e23fc4555885",
+ // icon: "fab fa-chrome"
+ // }
+ // ];
+
+ var testFileSelectionEnabled = true;
+
+ window.onload = function () {
+ new ConfigurationView();
+ };
+
+ function ConfigurationView() {
+ const query = utils.parseQuery(location.search);
+ var token = query.token;
+ if (token) WaveService.addRecentSession(token);
+ var referenceSessions = [];
+ var apis = [];
+ var testTypeSelectionEnabled = true;
+ var testFileSelectionEnabled = false;
+
+ var types = [
+ { title: "Automatic", value: "automatic" },
+ { title: "Manual", value: "manual" },
+ ];
+ var state = {};
+ loadServerStatus();
+ loadSessionData(token, function () {
+ loadPublicSessionData(function () {
+ renderReferencesField();
+ });
+ });
+ render();
+
+ function loadServerStatus() {
+ WaveService.readStatus(function (status) {
+ testTypeSelectionEnabled = status.testTypeSelectionEnabled;
+ testFileSelectionEnabled = status.testFileSelectionEnabled;
+ renderSessionConfiguration();
+ });
+ }
+
+ function loadSessionData(token, callback) {
+ if (!token) {
+ state.expired = true;
+ return;
+ }
+ WaveService.readSessionStatus(
+ token,
+ function (status) {
+ if (status.status !== "pending") {
+ openResultsPage(token);
+ return;
+ }
+ state.status = status;
+
+ WaveService.readSession(token, function (configuration) {
+ if (
+ configuration.tests.include.findIndex(
+ (test) => test === "/"
+ ) !== -1
+ ) {
+ configuration.tests.include = apis.map((api) => api.path);
+ }
+ state.configurationBackup = utils.copyObject(configuration);
+ state.configuration = configuration;
+ setTimeout(
+ handleExpiration,
+ status.expirationDate.getTime() - Date.now()
+ );
+ renderSessionConfiguration();
+ callback();
+ WaveService.readAvailableApis(function (available_apis) {
+ available_apis = available_apis.sort((apiA, apiB) =>
+ apiA.title.toLowerCase() > apiB.title.toLowerCase() ? 1 : -1
+ );
+ apis = available_apis;
+ selectAllTests();
+ renderSessionConfiguration();
+ });
+ });
+ },
+ function () {
+ state.expired = true;
+ renderSessionConfiguration();
+ renderExcludedTests();
+ renderResumeView();
+ }
+ );
+ }
+
+ function loadPublicSessionData(callback) {
+ WaveService.readPublicSessions(function (tokens) {
+ WaveService.readMultipleSessions(tokens, function (configurations) {
+ console.log(configurations);
+ referenceSessions = configurations
+ .sort((confA, confB) =>
+ confA.browser.name.toLowerCase() >
+ confB.browser.name.toLowerCase()
+ ? 1
+ : -1
+ )
+ .map((configuration) => {
+ var icon = "";
+ switch (configuration.browser.name.toLowerCase()) {
+ case "firefox":
+ icon = "fab fa-firefox";
+ break;
+ case "webkit":
+ case "safari":
+ icon = "fab fa-safari";
+ break;
+ case "edge":
+ icon = "fab fa-edge";
+ break;
+ case "chrome":
+ case "chromium":
+ icon = "fab fa-chrome";
+ break;
+ }
+ return {
+ title:
+ configuration.browser.name +
+ " " +
+ configuration.browser.version,
+ token: configuration.token,
+ icon,
+ engine: configuration.browser.engine || "",
+ };
+ });
+ callback(referenceSessions);
+ });
+ });
+ }
+
+ function handleConfigureSession() {
+ const tokenFragmentInput = UI.getElement("token-fragment");
+ const fragment = tokenFragmentInput.value;
+ findSession(fragment, function (session) {
+ if (!session) {
+ const errorBox = UI.getElement("find-error");
+ errorBox.setAttribute("style", "display: block");
+ return;
+ }
+ tokenFragmentInput.value = "";
+ const errorBox = UI.getElement("find-error");
+ errorBox.setAttribute("style", "display: none");
+ const path = location.pathname + "?token=" + session.token;
+ location.href = path;
+ });
+ }
+
+ function findSession(fragment, callback) {
+ if (!fragment || fragment.length < 8) {
+ callback(null);
+ return;
+ }
+ WaveService.findToken(
+ fragment,
+ function (token) {
+ WaveService.readSession(token, function (session) {
+ WaveService.readSessionStatus(token, function (status) {
+ session.status = status.status;
+ session.dateStarted = status.dateStarted;
+ session.dateFinished = status.dateFinished;
+ callback(session);
+ });
+ });
+ },
+ function () {
+ callback(null);
+ }
+ );
+ }
+
+ function hasIncludedTest(path) {
+ var tests = state.configuration.tests;
+ //var index = tests.include.findIndex(function (test) {
+ // return test.match(new RegExp("^" + path));
+ //});
+ var index = tests.include.indexOf(path);
+ return index !== -1;
+ }
+
+ function handleIncludedTestToggle(path) {
+ var configuration = state.configuration;
+ if (hasIncludedTest(path)) {
+ handleRemoveIncludedTest(path);
+ } else {
+ handleAddIncludedTest(path);
+ }
+ }
+
+ function handleAddIncludedTest(path) {
+ var tests = state.configuration.tests;
+ if (state.tests && state.tests[path.substr(1)]) {
+ tests.include = tests.include.filter(function (test) {
+ return !test.match(new RegExp("^" + path + "/"));
+ });
+ tests.include = tests.include.concat(state.tests[path.substr(1)]);
+ } else {
+ tests.include.push(path);
+ }
+ }
+
+ function handleRemoveIncludedTest(path) {
+ var tests = state.configuration.tests;
+
+ if (state.tests && state.tests[path.substr(1)]) {
+ tests.include = tests.include.filter(function (test) {
+ return !test.match(new RegExp("^" + path + "/"));
+ });
+ } else {
+ var index = tests.include.findIndex((test) => test === path);
+ tests.include.splice(index, 1);
+ }
+ }
+
+ function getIncludedRatio(path) {
+ var includedTests = state.configuration.tests.include;
+ if (!state.tests) {
+ return includedTests.indexOf(path) !== -1 ? 1 : 0;
+ }
+ var count = 0;
+ for (var test of includedTests) {
+ if (!test.match(new RegExp("^" + path))) continue;
+ count++;
+ }
+ return count / state.tests[path.substr(1)].length;
+ }
+
+ function selectAllTests() {
+ var tests = state.configuration.tests;
+ if (state.tests) {
+ tests.include = [];
+ for (var api in state.tests) {
+ tests.include = tests.include.concat(state.tests[api]);
+ }
+ } else {
+ tests.include = apis.map((api) => api.path);
+ }
+ }
+
+ function deselectAllTests() {
+ var configuration = state.configuration;
+ configuration.tests.include = [];
+ }
+
+ function hasTestType(value) {
+ var configuration = state.configuration;
+ var index = configuration.types.findIndex((type) => type === value);
+ return index !== -1;
+ }
+
+ function handleTestTypeToggle(value) {
+ var configuration = state.configuration;
+ if (hasTestType(value)) {
+ var index = configuration.types.findIndex((type) => type === value);
+ configuration.types.splice(index, 1);
+ } else {
+ configuration.types.push(value);
+ }
+ }
+
+ function selectAllTestTypes() {
+ var configuration = state.configuration;
+ configuration.types = types.map((type) => type.value);
+ }
+
+ function deselectAllTestTypes() {
+ var configuration = state.configuration;
+ configuration.types = [];
+ }
+
+ function hasRefSession(session) {
+ var configuration = state.configuration;
+ var index = configuration.referenceTokens.findIndex(
+ (token) => token === session.token
+ );
+ return index !== -1;
+ }
+
+ function handleRefSessionToggle(session) {
+ var configuration = state.configuration;
+ if (hasRefSession(session)) {
+ var index = configuration.referenceTokens.findIndex(
+ (token) => token === session.token
+ );
+ configuration.referenceTokens.splice(index, 1);
+ } else {
+ configuration.referenceTokens.push(session.token);
+ }
+ }
+
+ function selectAllRefSessions() {
+ var configuration = state.configuration;
+ configuration.referenceTokens = referenceSessions.map(
+ (session) => session.token
+ );
+ }
+
+ function deselectAllRefSessions() {
+ var configuration = state.configuration;
+ configuration.referenceTokens = [];
+ }
+
+ function isTestListValid() {
+ var configuration = state.configuration;
+ return configuration.tests.include.length > 0;
+ }
+
+ function isTestTypeListValid() {
+ var configuration = state.configuration;
+ return configuration.types.length > 0;
+ }
+
+ function isConfigurationValid() {
+ if (!isTestListValid()) return false;
+ if (!isTestTypeListValid()) return false;
+ return true;
+ }
+
+ function isSessionStarting() {
+ return state.isStarting;
+ }
+
+ function checkApiList() {
+ var apiErrorElement = UI.getElement("api-error");
+ apiErrorElement.innerHTML = "";
+ if (!isTestListValid()) {
+ apiErrorElement.appendChild(
+ UI.createElement(
+ createErrorMessage(
+ "Select at least one API or at least one test within an API"
+ )
+ )
+ );
+ }
+ renderButtonsField();
+ }
+
+ function handleStart() {
+ if (isSessionStarting()) return;
+ var configuration = state.configuration;
+ var token = configuration.token;
+ WaveService.updateSession(token, configuration, function () {
+ WaveService.updateLabels(token, configuration.labels, function () {
+ WaveService.startSession(token, function () {
+ openResultsPage(token);
+ });
+ });
+ });
+ state.isStarting = true;
+ }
+
+ function handleDiscardChanges() {
+ state.configuration = utils.copyObject(state.configurationBackup);
+ }
+
+ function handleExpiration() {
+ state.expired = true;
+ renderSessionConfiguration();
+ renderResumeView();
+ }
+
+ function openResultsPage(token) {
+ location.href = WEB_ROOT + "results.html?token=" + token;
+ }
+
+ function handleAddExludedTestsRaw() {
+ var excludedTestsTextArea = UI.getElement("excluded-tests-text");
+ var tests = excludedTestsTextArea.value.split("\n");
+ var configuration = state.configuration;
+ var excludedTests = configuration.tests.exclude;
+ for (var test of tests) {
+ if (!test) continue;
+ if (test.startsWith("#")) continue;
+ if (excludedTests.indexOf(test) !== -1) continue;
+ excludedTests.push(test);
+ }
+
+ excludedTestsTextArea.value = "";
+ renderExcludedTests();
+ }
+
+ function handleAddExludedTestsMalfunctioning() {
+ var excludedTestsTextArea = UI.getElement("excluded-tests-text");
+ var token = excludedTestsTextArea.value;
+ var tokenRegExp = new RegExp(
+ "^[a-f0-9]{8}(-[a-f0-9]{0,4}|$)(-[a-f0-9]{0,4}|$)(-[a-f0-9]{0,4}|$)(-[a-f0-9]{0,12}|$)"
+ );
+ var configuration = state.configuration;
+ var excludedTests = configuration.tests.exclude;
+ if (tokenRegExp.test(token)) {
+ WaveService.findToken(
+ token,
+ function (token) {
+ WaveService.readMalfunctioningTests(token, function (
+ malfunctioningTests
+ ) {
+ for (var test of malfunctioningTests) {
+ if (!test) continue;
+ if (excludedTests.indexOf(test) !== -1) continue;
+ excludedTests.push(test);
+ }
+ renderExcludedTests();
+ });
+ },
+ function () {
+ state.excludedTestError = "Session not found";
+ renderExcludedTests();
+ }
+ );
+ } else {
+ state.excludedTestError = "Invalid session token";
+ renderExcludedTests();
+ }
+ }
+
+ function handleAddExludedTestsExcluded() {
+ var excludedTestsTextArea = UI.getElement("excluded-tests-text");
+ var token = excludedTestsTextArea.value;
+ var tokenRegExp = new RegExp(
+ "^[a-f0-9]{8}(-[a-f0-9]{0,4}|$)(-[a-f0-9]{0,4}|$)(-[a-f0-9]{0,4}|$)(-[a-f0-9]{0,12}|$)"
+ );
+ var configuration = state.configuration;
+ var excludedTests = configuration.tests.exclude;
+ if (tokenRegExp.test(token)) {
+ WaveService.findToken(
+ token,
+ function (token) {
+ WaveService.readSession(token, function (sessionConfig) {
+ var prevExcludedTests = sessionConfig.tests.exclude;
+ for (var test of prevExcludedTests) {
+ if (!test) continue;
+ if (excludedTests.indexOf(test) !== -1) continue;
+ excludedTests.push(test);
+ }
+ renderExcludedTests();
+ });
+ },
+ function () {
+ state.excludedTestError = "Session not found";
+ renderExcludedTests();
+ }
+ );
+ } else {
+ state.excludedTestError = "Invalid session token";
+ renderExcludedTests();
+ }
+ }
+
+ function handleRemoveExcludedTest(test) {
+ var configuration = state.configuration;
+ var excludedTests = configuration.tests.exclude;
+ var index = excludedTests.indexOf(test);
+ excludedTests.splice(index, 1);
+ renderExcludedTests();
+ }
+
+ function handleExcludeInputChange(type) {
+ if (state.activeExcludeInput === type) {
+ state.activeExcludeInput = null;
+ } else {
+ state.activeExcludeInput = type;
+ }
+ renderExcludedTests();
+ }
+
+ function showAddLabel() {
+ state.addLabelVisible = true;
+ renderLabelsField();
+ UI.getElement("session-label-input").focus();
+ }
+
+ function hideAddLabel() {
+ state.addLabelVisible = false;
+ renderLabelsField();
+ }
+
+ function addLabel() {
+ var label = UI.getElement("session-label-input").value;
+ if (!label) return;
+ state.configuration.labels.push(label);
+ renderLabelsField();
+ UI.getElement("session-label-input").focus();
+ }
+
+ function removeLabel(index) {
+ const { configuration } = state;
+ configuration.labels.splice(index, 1);
+ renderLabelsField();
+ }
+
+ function resumeSession() {
+ var resumeToken = UI.getElement("resume-token").value;
+ if (!resumeToken) return;
+
+ WaveService.resumeSession(
+ state.configuration.token,
+ resumeToken,
+ function () {
+ openResultsPage(resumeToken);
+ }
+ );
+ }
+
+ function render() {
+ const configurationView = UI.createElement({
+ element: "section",
+ className: "section",
+ children: [
+ {
+ className: "container",
+ style: "margin-bottom: 2em",
+ children: [
+ {
+ element: "img",
+ src: "res/wavelogo_2016.jpg",
+ className: "site-logo",
+ },
+ { className: "title", text: "Session Configuration" },
+ ],
+ },
+ {
+ id: "session-configuration",
+ },
+ {
+ id: "resume-view",
+ className: "container",
+ style: "margin-bottom: 2em",
+ },
+ ],
+ });
+ const root = UI.getRoot();
+ root.innerHTML = "";
+ root.appendChild(configurationView);
+ renderSessionConfiguration();
+ renderResumeView();
+ }
+
+ function renderSessionConfiguration() {
+ var configuration = state.configuration;
+ var status = state.status;
+ var sessionConfigurationView = UI.createElement({});
+ var sessionConfiguration = UI.getElement("session-configuration");
+ sessionConfiguration.innerHTML = "";
+
+ if (state.expired) {
+ var expiredIndicator = UI.createElement({
+ className: "level container",
+ style: "max-width: 500px",
+ children: {
+ element: "span",
+ className: "level-item field column",
+ children: [
+ {
+ element: "article",
+ className: "message is-danger",
+ id: "find-error",
+ children: [
+ {
+ text:
+ "Could not find any sessions! Try adding more characters of the token.",
+ className: "message-body",
+ },
+ ],
+ style: "display: none",
+ },
+ {
+ className: "label has-text-weight-normal",
+ text: "Session token:",
+ },
+ {
+ className: "field-body",
+ children: {
+ className: "field",
+ children: {
+ className: "control",
+ children: {
+ style: "display: flex; margin-bottom: 10px;",
+ children: [
+ {
+ element: "input",
+ inputType: "text",
+ className: "input is-family-monospace",
+ id: "token-fragment",
+ placeholder:
+ "First 8 characters or more of session token",
+ onKeyDown: function (event) {
+ if (event.key === "Enter") {
+ handleConfigureSession();
+ }
+ },
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ className: "field is-grouped is-grouped-right",
+ children: {
+ className: "control",
+ children: {
+ className: "button is-dark is-outlined",
+ children: [
+ {
+ element: "span",
+ className: "icon",
+ children: [
+ {
+ element: "i",
+ className: "fas fa-cog",
+ },
+ ],
+ },
+ { text: "Configure Session", element: "span" },
+ ],
+ onclick: function () {
+ handleConfigureSession();
+ },
+ },
+ },
+ },
+ ],
+ },
+ });
+ sessionConfigurationView.appendChild(expiredIndicator);
+ sessionConfiguration.appendChild(sessionConfigurationView);
+ return;
+ }
+
+ if (!configuration) {
+ var loadingIndicator = createLoadingIndicator(
+ "Loading configuration ..."
+ );
+ sessionConfigurationView.appendChild(loadingIndicator);
+ sessionConfiguration.appendChild(sessionConfigurationView);
+ return;
+ }
+
+ sessionConfiguration.parentNode.replaceChild(
+ UI.createElement({
+ id: "session-configuration",
+ className: "container",
+ style: "margin-bottom: 2em",
+ children: [
+ {
+ id: "token-field",
+ },
+ {
+ id: "expiration-field",
+ },
+ {
+ id: "labels-field",
+ },
+ {
+ id: "apis-field",
+ },
+ {
+ id: "exclude-field",
+ },
+ {
+ id: "types-field",
+ },
+ {
+ id: "references-field",
+ },
+ {
+ id: "buttons-field",
+ },
+ ],
+ }),
+ sessionConfiguration
+ );
+
+ renderTokenField();
+ renderExpirationField();
+ renderLabelsField();
+ renderApisField();
+ renderExcludeField();
+ renderTypesField();
+ renderReferencesField();
+ renderButtonsField();
+ }
+
+ function renderTokenField() {
+ var configuration = state.configuration;
+ var tokenField = UI.getElement("token-field");
+ tokenField.parentNode.replaceChild(
+ UI.createElement({
+ id: "token-field",
+ className: "field is-horizontal",
+ children: [
+ {
+ className: "field-label",
+ children: { className: "label", text: "Token" },
+ },
+ {
+ className: "field-body",
+ children: {
+ className: "field",
+ children: {
+ className: "control",
+ text: configuration.token,
+ },
+ },
+ },
+ ],
+ }),
+ tokenField
+ );
+ }
+
+ function renderExpirationField() {
+ var status = state.status;
+ var expirationField = UI.getElement("expiration-field");
+ expirationField.parentNode.replaceChild(
+ UI.createElement({
+ id: "expiration-field",
+ className: "field is-horizontal",
+ children: [
+ {
+ className: "field-label",
+ children: { className: "label", text: "Expires" },
+ },
+ {
+ className: "field-body",
+ children: {
+ className: "field",
+ children: {
+ className: "control",
+ text: status.expirationDate.toLocaleString(),
+ },
+ },
+ },
+ ],
+ }),
+ expirationField
+ );
+ }
+
+ function renderLabelsField() {
+ var addLabelVisible = state.addLabelVisible;
+ var configuration = state.configuration;
+ var labelsField = UI.getElement("labels-field");
+
+ labelsField.parentNode.replaceChild(
+ UI.createElement({
+ id: "labels-field",
+ className: "field is-horizontal",
+ children: [
+ {
+ className: "field-label",
+ children: { className: "label", text: "Labels" },
+ },
+ {
+ className: "field-body",
+ children: {
+ className: "field is-grouped is-grouped-multiline",
+ children: configuration.labels
+ .map((label, index) => ({
+ className: "control",
+ children: {
+ className: "tags has-addons",
+ children: [
+ {
+ element: "span",
+ className: "tag is-info",
+ text: label,
+ },
+ {
+ element: "a",
+ className: "tag is-delete",
+ onClick: () => removeLabel(index),
+ },
+ ],
+ },
+ }))
+ .concat(
+ addLabelVisible
+ ? [
+ {
+ className: "control field is-grouped",
+ children: [
+ {
+ element: "input",
+ className: "input is-small control",
+ style: "width: 10rem",
+ id: "session-label-input",
+ type: "text",
+ onKeyUp: (event) =>
+ event.keyCode === 13 ? addLabel() : null,
+ },
+ {
+ className:
+ "button is-dark is-outlined is-small is-rounded control",
+ text: "save",
+ onClick: addLabel,
+ },
+ {
+ className:
+ "button is-dark is-outlined is-small is-rounded control",
+ text: "cancel",
+ onClick: hideAddLabel,
+ },
+ ],
+ },
+ ]
+ : [
+ {
+ className: "button is-rounded is-small",
+ text: "Add",
+ onClick: showAddLabel,
+ },
+ ]
+ ),
+ },
+ },
+ ],
+ }),
+ labelsField
+ );
+ }
+
+ function renderApisField() {
+ var apisField = UI.getElement("apis-field");
+ apisField.parentNode.replaceChild(
+ UI.createElement({
+ id: "apis-field",
+ className: "field is-horizontal",
+ children: [
+ {
+ className: "field-label",
+ children: [
+ { className: "label", text: "APIs" },
+ createSelectDeselectButtons(
+ function () {
+ selectAllTests();
+ renderApisField();
+ },
+ function () {
+ deselectAllTests();
+ renderApisField();
+ }
+ ),
+ ],
+ },
+ {
+ className: "field-body",
+ children: {
+ className: "field",
+ children: {
+ className: "control",
+ children: [
+ {
+ id: "api-error",
+ },
+ {
+ element: "ul",
+ className: "menu-list",
+ children: apis.map(function (api) {
+ return UI.createElement({
+ element: "li",
+ id: api.title,
+ });
+ }),
+ },
+ ],
+ },
+ },
+ },
+ ],
+ }),
+ apisField
+ );
+ renderApisList(apis);
+ checkApiList();
+ }
+
+ function renderApisList(apis) {
+ for (var api of apis) {
+ renderApiList(api);
+ }
+ }
+
+ function renderApiList(api) {
+ var listItem = UI.getElement(api.title);
+ var includedRatio = getIncludedRatio(api.path);
+ var apiListItem = {
+ element: "a",
+ onClick: function (event) {
+ if (!testFileSelectionEnabled) return;
+ if (!state.expandedApis) state.expandedApis = {};
+ state.expandedApis[api.path] = !state.expandedApis[api.path];
+ renderApiList(api);
+ },
+ children: [
+ {
+ element: "input",
+ type: "checkbox",
+ style: "width: 1.3em; height: 1.3em;vertical-align: middle;",
+ checked: includedRatio > 0,
+ indeterminate: includedRatio > 0 && includedRatio < 1,
+ onclick: function (event) {
+ event.stopPropagation();
+ if (includedRatio > 0) {
+ handleRemoveIncludedTest(api.path);
+ } else {
+ handleAddIncludedTest(api.path);
+ }
+ renderApiList(api);
+ },
+ },
+ testFileSelectionEnabled
+ ? {
+ element: "span",
+ style:
+ "display: inline-block;vertical-align: middle;margin-left:0.3em;width: 0.7em",
+ children: {
+ element: "i",
+ className:
+ state.expandedApis && state.expandedApis[api.path]
+ ? "fas fa-angle-down"
+ : "fas fa-angle-right",
+ },
+ }
+ : null,
+ {
+ style:
+ "display: inline-block;vertical-align: middle;margin-left:0.3em;width: 90%",
+ text: api.title,
+ },
+ ],
+ };
+ listItem.innerHTML = "";
+ listItem.appendChild(UI.createElement(apiListItem));
+ if (state.expandedApis && state.expandedApis[api.path]) {
+ listItem.appendChild(createApiTestsList(api));
+ }
+ checkApiList();
+ }
+
+ function createApiTestsList(api) {
+ if (!state.tests) {
+ WaveService.readTestList(
+ function (readTests) {
+ state.tests = readTests;
+ for (var api in state.tests) {
+ if (hasIncludedTest("/" + api)) {
+ handleRemoveIncludedTest("/" + api);
+ handleAddIncludedTest("/" + api);
+ }
+ }
+ renderApiList(this.api);
+ }.bind({ api: api })
+ );
+ return createLoadingIndicator("Loading tests ...");
+ } else {
+ var tests = state.tests[api.path.substr(1)];
+ var testListView = {
+ element: "ul",
+ children: [],
+ };
+
+ testListView.children = testListView.children.concat(
+ tests
+ .sort()
+ .map(function (test) {
+ return {
+ element: "li",
+ onclick: function (event) {
+ handleIncludedTestToggle(test);
+ renderApiList(api);
+ },
+ children: [
+ {
+ element: "a",
+ children: [
+ {
+ element: "input",
+ type: "checkbox",
+ style:
+ "width: 1.3em; height: 1.3em;vertical-align: middle;",
+ checked: hasIncludedTest(test),
+ },
+ {
+ style:
+ "display: inline-block;vertical-align: middle;margin-left:0.3em;max-width: 90%",
+ text: test,
+ },
+ ],
+ },
+ ],
+ };
+ })
+ );
+ return UI.createElement(testListView);
+ }
+ }
+
+ function renderExcludeField() {
+ var excludeField = UI.getElement("exclude-field");
+ excludeField.parentNode.replaceChild(
+ UI.createElement({
+ id: "exclude-field",
+ className: "field is-horizontal",
+ children: [
+ {
+ className: "field-label",
+ children: { className: "label", text: "Excluded Tests" },
+ },
+ {
+ className: "field-body",
+ children: {
+ className: "field",
+ children: {
+ className: "control",
+ children: { id: "excluded-tests-view" },
+ },
+ },
+ },
+ ],
+ }),
+ excludeField
+ );
+ renderExcludedTests();
+ }
+
+ function renderTypesField() {
+ if (!testTypeSelectionEnabled) return;
+ var typesField = UI.getElement("types-field");
+ typesField.parentNode.replaceChild(
+ UI.createElement({
+ id: "types-field",
+ className: "field is-horizontal",
+ children: [
+ {
+ className: "field-label",
+ children: { className: "label", text: "Test Types" },
+ },
+ {
+ className: "field-body",
+ children: {
+ className: "field",
+ children: {
+ className: "control",
+ children: [
+ isTestTypeListValid()
+ ? null
+ : createErrorMessage("Select at least one test type"),
+ ].concat(createTestTypeList(types)),
+ },
+ },
+ },
+ ],
+ }),
+ typesField
+ );
+ }
+
+ function renderReferencesField() {
+ if (referenceSessions.length === 0) {
+ return;
+ }
+ var referencesField = UI.getElement("references-field");
+ referencesField.parentNode.replaceChild(
+ UI.createElement({
+ id: "references-field",
+ className: "field is-horizontal",
+ children: [
+ {
+ className: "field-label",
+ children: [
+ { className: "label", text: "Reference Browsers" },
+ createSelectDeselectButtons(
+ function () {
+ selectAllRefSessions();
+ renderReferencesField();
+ },
+ function () {
+ deselectAllRefSessions();
+ renderReferencesField();
+ }
+ ),
+ ],
+ },
+ {
+ className: "field-body",
+ children: {
+ className: "field",
+ children: {
+ className: "control",
+ children: createRefSessionsList(referenceSessions),
+ },
+ },
+ },
+ ],
+ }),
+ referencesField
+ );
+ }
+
+ function renderButtonsField() {
+ var buttonsField = UI.getElement("buttons-field");
+ buttonsField.parentNode.replaceChild(
+ UI.createElement({
+ id: "buttons-field",
+ className: "level level-right",
+ children: [
+ {
+ element: "button",
+ className: "button is-success",
+ style: "margin-right: 0.3em",
+ disabled: !isConfigurationValid(),
+ onClick: function () {
+ handleStart();
+ renderButtonsField();
+ },
+ children: [
+ {
+ element: "span",
+ className: "icon",
+ children: [
+ {
+ element: "i",
+ className: isSessionStarting()
+ ? "fas fa-spinner fa-pulse"
+ : "fas fa-play",
+ },
+ ],
+ },
+ {
+ element: "span",
+ text: isSessionStarting()
+ ? "Starting Session ..."
+ : "Start Session",
+ },
+ ],
+ },
+ {
+ element: "button",
+ className: "button",
+ onClick: function () {
+ handleDiscardChanges();
+ renderSessionConfiguration();
+ },
+ disabled: isSessionStarting(),
+ children: [
+ {
+ element: "span",
+ className: "icon",
+ children: [
+ {
+ element: "i",
+ className: "fas fa-times",
+ },
+ ],
+ },
+ {
+ element: "span",
+ text: "Discard Changes",
+ },
+ ],
+ },
+ ],
+ }),
+ buttonsField
+ );
+ }
+
+ function renderExcludedTests() {
+ var excludedTestsView = UI.getElement("excluded-tests-view");
+ if (!excludedTestsView) return;
+ excludedTestsView.innerHTML = "";
+
+ var errorMessage = state.excludedTestError;
+ if (errorMessage) {
+ var error = createErrorMessage(errorMessage);
+ excludedTestsView.appendChild(UI.createElement(error));
+ }
+
+ var excludeInputs = [
+ { title: "Add Raw", type: "raw" },
+ { title: "Add Malfunctioning", type: "malfunc" },
+ { title: "Add Previous Excluded", type: "excluded" },
+ ];
+
+ var activeExcludeInput = state.activeExcludeInput;
+
+ var excludedTestInputSwitch = UI.createElement({
+ className: "tabs is-centered is-toggle is-small",
+ children: {
+ element: "ul",
+ children: excludeInputs.map(function (input) {
+ return {
+ element: "li",
+ onClick: function () {
+ handleExcludeInputChange(input.type);
+ },
+ className: (function () {
+ if (activeExcludeInput === input.type) return "is-active";
+ return "";
+ })(),
+ children: { element: "a", text: input.title },
+ };
+ }),
+ },
+ });
+ excludedTestsView.appendChild(excludedTestInputSwitch);
+
+ if (activeExcludeInput === "raw") {
+ var rawInput = UI.createElement({
+ children: [
+ {
+ className: "is-size-7",
+ style: "margin-bottom: 20px",
+ text:
+ "Provide paths to test files or directories to exclude them from the session. One path per line, lines starting with # are omitted.",
+ },
+ {
+ element: "textarea",
+ className: "textarea",
+ id: "excluded-tests-text",
+ },
+ {
+ style: "margin-top: 10px",
+ onClick: function () {
+ handleAddExludedTestsRaw();
+ },
+ children: [
+ {
+ element: "button",
+ className: "button",
+ style: "margin-bottom: 20px",
+ text: "Add",
+ },
+ ],
+ },
+ ],
+ });
+ excludedTestsView.appendChild(rawInput);
+ } else if (
+ activeExcludeInput === "malfunc" ||
+ activeExcludeInput === "excluded"
+ ) {
+ var malfuncInput = UI.createElement({
+ style: "margin-bottom: 1em",
+ children: [
+ {
+ className: "is-size-7",
+ style: "margin-bottom: 1em",
+ text:
+ activeExcludeInput === "malfunc"
+ ? "Add malfunctioning tests from past sessions by providing at least the first eight characters of the session's token."
+ : "Add excluded tests from past sessions by providing at least the first eight characters of the session's token.",
+ },
+ {
+ className: "field is-horizontal",
+ children: [
+ {
+ className: "field-label",
+ children: { className: "label", text: "Session Token" },
+ },
+ {
+ className: "field-body",
+ children: {
+ className: "field is-grouped is-multiline",
+ children: [
+ {
+ id: "excluded-tests-text",
+ className: "input",
+ element: "input",
+ type: "text",
+ },
+ {
+ className: "button",
+ style: "margin-left: 1em",
+ text: "Add",
+ onClick: function () {
+ if (activeExcludeInput === "malfunc") {
+ handleAddExludedTestsMalfunctioning();
+ } else {
+ handleAddExludedTestsExcluded();
+ }
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ });
+ excludedTestsView.appendChild(malfuncInput);
+ }
+
+ var excludedTestsTable = createExcludedTestsTable();
+ var tableWrapper = UI.createElement({
+ style: "max-height: 250px; overflow: auto; margin-bottom: 10px",
+ });
+ tableWrapper.appendChild(excludedTestsTable);
+ excludedTestsView.appendChild(tableWrapper);
+ }
+
+ function renderResumeView() {
+ var query = utils.parseQuery(location.search);
+ var resumeToken = query.resume;
+ if (!resumeToken) resumeToken = "";
+
+ var renderResumeElement = UI.getElement("resume-view");
+ renderResumeElement.innerHTML = "";
+ if (state.expired) return;
+
+ var heading = UI.createElement({
+ element: "h2",
+ className: "title is-5",
+ text: "Resume session",
+ });
+ renderResumeElement.appendChild(heading);
+
+ var resumeControls = UI.createElement({
+ className: "columns",
+ children: [
+ {
+ className: "column",
+ children: {
+ className: "field",
+ children: [
+ {
+ element: "label",
+ className: "label",
+ text: "Token (first 8 characters or more)",
+ },
+ {
+ className: "control",
+ children: {
+ element: "input",
+ id: "resume-token",
+ className: "input is-family-monospace tabbable",
+ type: "text",
+ style: "max-width: 30em",
+ value: resumeToken,
+ },
+ },
+ ],
+ },
+ },
+ {
+ className: "column",
+ style:
+ "display: flex; align-items: flex-end; justify-content: flex-end",
+ children: {
+ className: "button",
+ onClick: function () {
+ resumeSession();
+ },
+ children: [
+ {
+ element: "span",
+ className: "icon",
+ children: { element: "i", className: "fas fa-redo-alt" },
+ },
+ {
+ element: "span",
+ text: "Resume",
+ },
+ ],
+ },
+ },
+ ],
+ });
+ renderResumeElement.appendChild(resumeControls);
+ }
+
+ function createExcludedTestsTable() {
+ var excludedTests = state.configuration.tests.exclude;
+ if (excludedTests.length === 0) {
+ return UI.createElement({
+ style: "text-align: center",
+ text: "- No Excluded Tests -",
+ });
+ }
+ var table = UI.createElement({
+ element: "table",
+ className: "table",
+ style: "width: 100%",
+ children: excludedTests.map(function (test) {
+ return {
+ element: "tr",
+ children: [
+ { element: "td", style: "width: 100%;", text: test },
+ {
+ element: "td",
+ children: {
+ element: "button",
+ className: "button is-small",
+ onClick: function () {
+ handleRemoveExcludedTest(test);
+ },
+ children: {
+ element: "span",
+ className: "icon",
+ children: {
+ element: "i",
+ className: "fas fa-trash-alt",
+ },
+ },
+ },
+ },
+ ],
+ };
+ }),
+ });
+ return table;
+ }
+
+ function createTestTypeList(types) {
+ return types.map((type) => ({
+ element: "button",
+ style: "margin-right: 0.3em; margin-bottom: 0.3em",
+ className: "button" + (hasTestType(type.value) ? " is-info" : ""),
+ text: type.title,
+ onClick: function (event) {
+ handleTestTypeToggle(type.value);
+ renderTypesField();
+ },
+ }));
+ }
+
+ function createRefSessionsList(referenceSessions) {
+ return referenceSessions.map((session) => ({
+ element: "button",
+ className: "button" + (hasRefSession(session) ? " is-info" : ""),
+ style: "margin-right: 0.3em; margin-bottom: 0.3em; height: auto",
+ onClick: function () {
+ handleRefSessionToggle(session);
+ renderReferencesField();
+ },
+ children: [
+ {
+ element: "span",
+ className: "icon",
+ children: [{ element: "i", className: session.icon }],
+ },
+ {
+ element: "span",
+ children: [
+ { text: session.title },
+ {
+ text: session.engine,
+ style: "font-size: 0.8em",
+ },
+ ],
+ },
+ ],
+ }));
+ }
+
+ function createSelectDeselectButtons(onSelect, onDeselect) {
+ return {
+ style: "margin-top: 0.3em",
+ children: [
+ {
+ element: "button",
+ style: "margin-right: 0.3em",
+ className: "button is-rounded is-small",
+ text: "All",
+ onClick: onSelect,
+ },
+ {
+ element: "button",
+ className: "button is-rounded is-small",
+ text: "None",
+ onClick: onDeselect,
+ },
+ ],
+ };
+ }
+
+ function createErrorMessage(message) {
+ return {
+ element: "article",
+ className: "message is-danger",
+ children: [
+ {
+ className: "message-body",
+ text: message,
+ },
+ ],
+ };
+ }
+
+ function createLoadingIndicator(text) {
+ return UI.createElement({
+ className: "level",
+ children: {
+ element: "span",
+ className: "level-item",
+ children: [
+ {
+ element: "i",
+ className: "fas fa-spinner fa-pulse",
+ },
+ {
+ style: "margin-left: 0.4em;",
+ text: text,
+ },
+ ],
+ },
+ });
+ }
+ }
+ </script>
+ </body>
+</html>