Source code
Revision control
Copy as Markdown
Other Tools
<!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>