Add visual testing for layout rendering

This commit is contained in:
wooferzfg
2020-02-21 23:09:08 -06:00
parent 1470503958
commit 0a4158b564
12 changed files with 1492 additions and 0 deletions
+2
View File
@@ -3,3 +3,5 @@ dist
npm-debug.log
src/livesplit_core.wasm
src/livesplit-core
test/screenshots
+520
View File
@@ -0,0 +1,520 @@
{
"components": [
{
"CurrentComparison": {
"background": {
"Vertical": [
[
1,
1,
1,
0.06
],
[
1,
1,
1,
0.005
]
]
},
"display_two_rows": false,
"label_color": null,
"value_color": null
}
},
{
"CurrentPace": {
"background": {
"Vertical": [
[
1,
1,
1,
0.06
],
[
1,
1,
1,
0.005
]
]
},
"comparison_override": null,
"display_two_rows": false,
"label_color": null,
"value_color": null,
"accuracy": "Seconds"
}
},
{
"Delta": {
"background": {
"Vertical": [
[
1,
1,
1,
0.06
],
[
1,
1,
1,
0.005
]
]
},
"comparison_override": null,
"display_two_rows": false,
"label_color": null,
"drop_decimals": true,
"accuracy": "Tenths"
}
},
{
"DetailedTimer": {
"background": "Transparent",
"comparison1": null,
"comparison2": "Best Segments",
"hide_second_comparison": false,
"timer": {
"background": "Transparent",
"timing_method": null,
"height": 40,
"color_override": null,
"show_gradient": true,
"digits_format": "SingleDigitSeconds",
"accuracy": "Hundredths",
"is_segment_timer": false
},
"segment_timer": {
"background": "Transparent",
"timing_method": null,
"height": 25,
"color_override": [
0.6666667,
0.6666667,
0.6666667,
1
],
"show_gradient": true,
"digits_format": "SingleDigitSeconds",
"accuracy": "Hundredths",
"is_segment_timer": true
},
"display_icon": false,
"show_segment_name": false
}
},
{
"Graph": {
"comparison_override": null,
"show_best_segments": false,
"live_graph": true,
"flip_graph": false,
"behind_background_color": [
0.4509804,
0.15686275,
0.15686275,
1
],
"ahead_background_color": [
0.15686275,
0.4509804,
0.20392157,
1
],
"grid_lines_color": [
0,
0,
0,
0.15
],
"graph_lines_color": [
1,
1,
1,
1
],
"partial_fill_color": [
1,
1,
1,
0.25
],
"complete_fill_color": [
1,
1,
1,
0.4
],
"height": 80
}
},
{
"PbChance": {
"background": {
"Vertical": [
[
1,
1,
1,
0.06
],
[
1,
1,
1,
0.005
]
]
},
"display_two_rows": false,
"label_color": null,
"value_color": null
}
},
{
"PossibleTimeSave": {
"background": {
"Vertical": [
[
1,
1,
1,
0.06
],
[
1,
1,
1,
0.005
]
]
},
"comparison_override": null,
"display_two_rows": false,
"total_possible_time_save": false,
"label_color": null,
"value_color": null,
"accuracy": "Hundredths"
}
},
{
"PreviousSegment": {
"background": {
"Vertical": [
[
1,
1,
1,
0.06
],
[
1,
1,
1,
0.005
]
]
},
"comparison_override": null,
"display_two_rows": false,
"label_color": null,
"drop_decimals": true,
"accuracy": "Tenths",
"show_possible_time_save": false
}
},
{
"SegmentTime": {
"background": {
"Vertical": [
[
1,
1,
1,
0.06
],
[
1,
1,
1,
0.005
]
]
},
"comparison_override": null,
"display_two_rows": false,
"label_color": null,
"value_color": null,
"accuracy": "Hundredths"
}
},
{
"Splits": {
"background": {
"Alternating": [
[
0,
0,
0,
0
],
[
1,
1,
1,
0.04
]
]
},
"visual_split_count": 16,
"split_preview_count": 1,
"show_thin_separators": true,
"separator_last_split": true,
"always_show_last_split": true,
"fill_with_blank_space": true,
"display_two_rows": false,
"current_split_gradient": {
"Vertical": [
[
0.2,
0.4509804,
0.95686275,
1
],
[
0.08235294,
0.20784314,
0.45490196,
1
]
]
},
"show_column_labels": false,
"columns": [
{
"name": "Time",
"start_with": "ComparisonTime",
"update_with": "SplitTime",
"update_trigger": "OnEndingSegment",
"comparison_override": null,
"timing_method": null
},
{
"name": "+/",
"start_with": "Empty",
"update_with": "Delta",
"update_trigger": "Contextual",
"comparison_override": null,
"timing_method": null
}
]
}
},
{
"SumOfBest": {
"background": {
"Vertical": [
[
1,
1,
1,
0.06
],
[
1,
1,
1,
0.005
]
]
},
"display_two_rows": false,
"label_color": null,
"value_color": null,
"accuracy": "Seconds"
}
},
{
"Text": {
"background": {
"Vertical": [
[
1,
1,
1,
0.06
],
[
1,
1,
1,
0.005
]
]
},
"display_two_rows": false,
"left_center_color": null,
"right_color": null,
"text": {
"Center": ""
}
}
},
{
"Timer": {
"background": "Transparent",
"timing_method": null,
"height": 60,
"color_override": null,
"show_gradient": true,
"digits_format": "SingleDigitSeconds",
"accuracy": "Hundredths",
"is_segment_timer": false
}
},
{
"Title": {
"background": {
"Vertical": [
[
1,
1,
1,
0.13
],
[
1,
1,
1,
0
]
]
},
"text_color": null,
"show_game_name": true,
"show_category_name": true,
"show_finished_runs_count": false,
"show_attempt_count": true,
"text_alignment": "Auto",
"display_as_single_line": false,
"display_game_icon": true,
"show_region": false,
"show_platform": false,
"show_variables": true
}
},
{
"TotalPlaytime": {
"background": {
"Vertical": [
[
1,
1,
1,
0.06
],
[
1,
1,
1,
0.005
]
]
},
"display_two_rows": false,
"show_days": true,
"label_color": null,
"value_color": null
}
},
{
"BlankSpace": {
"background": "Transparent",
"size": 24
}
},
"Separator"
],
"general": {
"direction": "Vertical",
"background": {
"Plain": [
0.06,
0.06,
0.06,
1
]
},
"best_segment_color": [
1,
0.8333333,
0,
1
],
"ahead_gaining_time_color": [
0,
0.8,
0.21333332,
1
],
"ahead_losing_time_color": [
0.38000003,
0.82000005,
0.49733335,
1
],
"behind_gaining_time_color": [
0.82000005,
0.38000003,
0.38000003,
1
],
"behind_losing_time_color": [
0.8,
0,
0,
1
],
"not_running_color": [
0.67,
0.67,
0.67,
1
],
"personal_best_color": [
0.08000004,
0.64733326,
1,
1
],
"paused_color": [
0.48,
0.48,
0.48,
1
],
"thin_separators_color": [
1,
1,
1,
0.09
],
"separators_color": [
1,
1,
1,
0.35
],
"text_color": [
1,
1,
1,
1
]
}
}
+212
View File
@@ -0,0 +1,212 @@
{
"components": [
{
"Title": {
"background": {
"Vertical": [
[
1,
1,
1,
0.13
],
[
1,
1,
1,
0
]
]
},
"text_color": null,
"show_game_name": true,
"show_category_name": true,
"show_finished_runs_count": false,
"show_attempt_count": true,
"text_alignment": "Auto",
"display_as_single_line": false,
"display_game_icon": true,
"show_region": false,
"show_platform": false,
"show_variables": true
}
},
{
"Splits": {
"background": {
"Alternating": [
[
0,
0,
0,
0
],
[
1,
1,
1,
0.04
]
]
},
"visual_split_count": 16,
"split_preview_count": 1,
"show_thin_separators": true,
"separator_last_split": true,
"always_show_last_split": true,
"fill_with_blank_space": true,
"display_two_rows": false,
"current_split_gradient": {
"Vertical": [
[
0.2,
0.4509804,
0.95686275,
1
],
[
0.08235294,
0.20784314,
0.45490196,
1
]
]
},
"show_column_labels": false,
"columns": [
{
"name": "Time",
"start_with": "ComparisonTime",
"update_with": "SplitTime",
"update_trigger": "OnEndingSegment",
"comparison_override": null,
"timing_method": null
},
{
"name": "+/",
"start_with": "Empty",
"update_with": "Delta",
"update_trigger": "Contextual",
"comparison_override": null,
"timing_method": null
}
]
}
},
{
"Timer": {
"background": "Transparent",
"timing_method": null,
"height": 60,
"color_override": null,
"show_gradient": true,
"digits_format": "SingleDigitSeconds",
"accuracy": "Hundredths",
"is_segment_timer": false
}
},
{
"PreviousSegment": {
"background": {
"Vertical": [
[
1,
1,
1,
0.06
],
[
1,
1,
1,
0.005
]
]
},
"comparison_override": null,
"display_two_rows": false,
"label_color": null,
"drop_decimals": true,
"accuracy": "Tenths",
"show_possible_time_save": false
}
}
],
"general": {
"direction": "Vertical",
"background": {
"Plain": [
0.06,
0.06,
0.06,
1
]
},
"best_segment_color": [
1,
0.8333333,
0,
1
],
"ahead_gaining_time_color": [
0,
0.8,
0.21333332,
1
],
"ahead_losing_time_color": [
0.38000003,
0.82000005,
0.49733335,
1
],
"behind_gaining_time_color": [
0.82000005,
0.38000003,
0.38000003,
1
],
"behind_losing_time_color": [
0.8,
0,
0,
1
],
"not_running_color": [
0.67,
0.67,
0.67,
1
],
"personal_best_color": [
0.08000004,
0.64733326,
1,
1
],
"paused_color": [
0.48,
0.48,
0.48,
1
],
"thin_separators_color": [
1,
1,
1,
0.09
],
"separators_color": [
1,
1,
1,
0.35
],
"text_color": [
1,
1,
1,
1
]
}
}
+143
View File
@@ -0,0 +1,143 @@
{
"components": [
{
"Splits": {
"background": {
"Alternating": [
[
0,
0,
0,
0
],
[
1,
1,
1,
0.04
]
]
},
"visual_split_count": 12,
"split_preview_count": 1,
"show_thin_separators": true,
"separator_last_split": true,
"always_show_last_split": true,
"fill_with_blank_space": true,
"display_two_rows": true,
"current_split_gradient": {
"Vertical": [
[
0.2,
0.4509804,
0.95686275,
1
],
[
0.08235294,
0.20784314,
0.45490196,
1
]
]
},
"show_column_labels": false,
"columns": [
{
"name": "Time",
"start_with": "ComparisonTime",
"update_with": "SplitTime",
"update_trigger": "OnEndingSegment",
"comparison_override": null,
"timing_method": null
},
{
"name": "+/",
"start_with": "Empty",
"update_with": "Delta",
"update_trigger": "Contextual",
"comparison_override": null,
"timing_method": null
}
]
}
}
],
"general": {
"direction": "Vertical",
"background": {
"Plain": [
0.06,
0.06,
0.06,
1
]
},
"best_segment_color": [
1,
0.8333333,
0,
1
],
"ahead_gaining_time_color": [
0,
0.8,
0.21333332,
1
],
"ahead_losing_time_color": [
0.38000003,
0.82000005,
0.49733335,
1
],
"behind_gaining_time_color": [
0.82000005,
0.38000003,
0.38000003,
1
],
"behind_losing_time_color": [
0.8,
0,
0,
1
],
"not_running_color": [
0.67,
0.67,
0.67,
1
],
"personal_best_color": [
0.08000004,
0.64733326,
1,
1
],
"paused_color": [
0.48,
0.48,
0.48,
1
],
"thin_separators_color": [
1,
1,
1,
0.09
],
"separators_color": [
1,
1,
1,
0.35
],
"text_color": [
1,
1,
1,
1
]
}
}
+143
View File
@@ -0,0 +1,143 @@
{
"components": [
{
"Splits": {
"background": {
"Alternating": [
[
0,
0,
0,
0
],
[
1,
1,
1,
0.04
]
]
},
"visual_split_count": 3,
"split_preview_count": 1,
"show_thin_separators": true,
"separator_last_split": true,
"always_show_last_split": true,
"fill_with_blank_space": true,
"display_two_rows": false,
"current_split_gradient": {
"Vertical": [
[
0.2,
0.4509804,
0.95686275,
1
],
[
0.08235294,
0.20784314,
0.45490196,
1
]
]
},
"show_column_labels": true,
"columns": [
{
"name": "Time",
"start_with": "ComparisonTime",
"update_with": "SplitTime",
"update_trigger": "OnEndingSegment",
"comparison_override": null,
"timing_method": null
},
{
"name": "+/",
"start_with": "Empty",
"update_with": "Delta",
"update_trigger": "Contextual",
"comparison_override": null,
"timing_method": null
}
]
}
}
],
"general": {
"direction": "Vertical",
"background": {
"Plain": [
0.06,
0.06,
0.06,
1
]
},
"best_segment_color": [
1,
0.8333333,
0,
1
],
"ahead_gaining_time_color": [
0,
0.8,
0.21333332,
1
],
"ahead_losing_time_color": [
0.38000003,
0.82000005,
0.49733335,
1
],
"behind_gaining_time_color": [
0.82000005,
0.38000003,
0.38000003,
1
],
"behind_losing_time_color": [
0.8,
0,
0,
1
],
"not_running_color": [
0.67,
0.67,
0.67,
1
],
"personal_best_color": [
0.08000004,
0.64733326,
1,
1
],
"paused_color": [
0.48,
0.48,
0.48,
1
],
"thin_separators_color": [
1,
1,
1,
0.09
],
"separators_color": [
1,
1,
1,
0.35
],
"text_color": [
1,
1,
1,
1
]
}
}
@@ -0,0 +1,112 @@
{
"components": [
{
"Title": {
"background": {
"Vertical": [
[
1,
1,
1,
0.13
],
[
1,
1,
1,
0
]
]
},
"text_color": null,
"show_game_name": true,
"show_category_name": true,
"show_finished_runs_count": false,
"show_attempt_count": true,
"text_alignment": "Center",
"display_as_single_line": false,
"display_game_icon": false,
"show_region": false,
"show_platform": false,
"show_variables": true
}
}
],
"general": {
"direction": "Vertical",
"background": {
"Plain": [
0.06,
0.06,
0.06,
1
]
},
"best_segment_color": [
1,
0.8333333,
0,
1
],
"ahead_gaining_time_color": [
0,
0.8,
0.21333332,
1
],
"ahead_losing_time_color": [
0.38000003,
0.82000005,
0.49733335,
1
],
"behind_gaining_time_color": [
0.82000005,
0.38000003,
0.38000003,
1
],
"behind_losing_time_color": [
0.8,
0,
0,
1
],
"not_running_color": [
0.67,
0.67,
0.67,
1
],
"personal_best_color": [
0.08000004,
0.64733326,
1,
1
],
"paused_color": [
0.48,
0.48,
0.48,
1
],
"thin_separators_color": [
1,
1,
1,
0.09
],
"separators_color": [
1,
1,
1,
0.35
],
"text_color": [
1,
1,
1,
1
]
}
}
@@ -0,0 +1,112 @@
{
"components": [
{
"Title": {
"background": {
"Vertical": [
[
1,
1,
1,
0.13
],
[
1,
1,
1,
0
]
]
},
"text_color": null,
"show_game_name": true,
"show_category_name": true,
"show_finished_runs_count": false,
"show_attempt_count": true,
"text_alignment": "Center",
"display_as_single_line": false,
"display_game_icon": true,
"show_region": false,
"show_platform": false,
"show_variables": true
}
}
],
"general": {
"direction": "Vertical",
"background": {
"Plain": [
0.06,
0.06,
0.06,
1
]
},
"best_segment_color": [
1,
0.8333333,
0,
1
],
"ahead_gaining_time_color": [
0,
0.8,
0.21333332,
1
],
"ahead_losing_time_color": [
0.38000003,
0.82000005,
0.49733335,
1
],
"behind_gaining_time_color": [
0.82000005,
0.38000003,
0.38000003,
1
],
"behind_losing_time_color": [
0.8,
0,
0,
1
],
"not_running_color": [
0.67,
0.67,
0.67,
1
],
"personal_best_color": [
0.08000004,
0.64733326,
1,
1
],
"paused_color": [
0.48,
0.48,
0.48,
1
],
"thin_separators_color": [
1,
1,
1,
0.09
],
"separators_color": [
1,
1,
1,
0.35
],
"text_color": [
1,
1,
1,
1
]
}
}
@@ -0,0 +1,112 @@
{
"components": [
{
"Title": {
"background": {
"Vertical": [
[
1,
1,
1,
0.13
],
[
1,
1,
1,
0
]
]
},
"text_color": null,
"show_game_name": true,
"show_category_name": true,
"show_finished_runs_count": false,
"show_attempt_count": false,
"text_alignment": "Left",
"display_as_single_line": false,
"display_game_icon": false,
"show_region": false,
"show_platform": false,
"show_variables": true
}
}
],
"general": {
"direction": "Vertical",
"background": {
"Plain": [
0.06,
0.06,
0.06,
1
]
},
"best_segment_color": [
1,
0.8333333,
0,
1
],
"ahead_gaining_time_color": [
0,
0.8,
0.21333332,
1
],
"ahead_losing_time_color": [
0.38000003,
0.82000005,
0.49733335,
1
],
"behind_gaining_time_color": [
0.82000005,
0.38000003,
0.38000003,
1
],
"behind_losing_time_color": [
0.8,
0,
0,
1
],
"not_running_color": [
0.67,
0.67,
0.67,
1
],
"personal_best_color": [
0.08000004,
0.64733326,
1,
1
],
"paused_color": [
0.48,
0.48,
0.48,
1
],
"thin_separators_color": [
1,
1,
1,
0.09
],
"separators_color": [
1,
1,
1,
0.35
],
"text_color": [
1,
1,
1,
1
]
}
}
+133
View File
@@ -0,0 +1,133 @@
const fs = require("fs");
const path = require("path");
const { fork } = require("child_process");
const {
Builder,
By,
until,
} = require("selenium-webdriver");
const chrome = require("selenium-webdriver/chrome");
const chromedriver = require("chromedriver");
const imghash = require("imghash");
const hex64 = require("hex64");
const pixelmatch = require("pixelmatch");
const PNG = require("pngjs").PNG;
describe("Layout Rendering Tests", () => {
let driver, serverProcess;
const LAYOUTS_FOLDER = "test/layouts";
const SCREENSHOTS_FOLDER = "test/screenshots";
const SPLITS_FOLDER = "test/splits";
const findElement = async (selector) => {
return driver.wait(until.elementLocated(selector));
};
const clickElement = async (selector) => {
const element = await driver.wait(until.elementLocated(selector));
await element.click();
}
const loadFile = async (filePath) => {
const inputElement = await findElement(By.id("file-input"));
await inputElement.sendKeys(path.resolve(filePath));
}
before(async () => {
serverProcess = fork("./node_modules/webpack-dev-server/bin/webpack-dev-server.js");
const service = new chrome.ServiceBuilder(chromedriver.path).build();
chrome.setDefaultService(service);
const options = new chrome.Options().windowSize({ width: 1200, height: 2400 }).headless();
driver = await new Builder().forBrowser("chrome").setChromeOptions(options).build();
await driver.get("http://localhost:8080");
await driver.executeScript(() => {
HTMLInputElement.prototype.click = function() {
const existingFileInput = document.getElementById("file-input");
if (existingFileInput) {
existingFileInput.remove();
}
this.style.display = "none";
this.id = "file-input";
document.body.appendChild(this);
}
});
if (!fs.existsSync(SCREENSHOTS_FOLDER)) {
fs.mkdirSync(SCREENSHOTS_FOLDER);
}
});
const testRendering = (layoutName, splitsName, expectedHash) => {
it(`Renders the ${layoutName} layout with the ${splitsName} splits correctly`, async () => {
await clickElement(By.xpath(".//button[contains(text(), 'Layout')]"));
await clickElement(By.xpath(".//button[contains(text(), 'Import')]"));
await loadFile(`${LAYOUTS_FOLDER}/${layoutName}.ls1l`);
await clickElement(By.xpath(".//button[contains(text(), 'Back')]"));
await clickElement(By.xpath(".//button[contains(text(), 'Splits')]"));
await clickElement(By.xpath(".//button[contains(text(), 'Import')]"));
await loadFile(`${SPLITS_FOLDER}/${splitsName}.lss`);
await clickElement(By.xpath(".//button[contains(text(), 'Back')]"));
const layoutElement = await findElement(By.className("layout"));
const layoutScreenshot = await layoutElement.takeScreenshot();
const tempFilePath = `${SCREENSHOTS_FOLDER}/${layoutName}.png`;
fs.writeFileSync(tempFilePath, layoutScreenshot, "base64");
const actualHashHex = await imghash.hash(tempFilePath, 12);
const actualHash = hex64.encode(actualHashHex);
const actualScreenshotPath = `${SCREENSHOTS_FOLDER}/${layoutName}_${splitsName}_${actualHash.replace("/", "$")}.png`;
const expectedScreenshotPath = `${SCREENSHOTS_FOLDER}/${layoutName}_${splitsName}_${expectedHash.replace("/", "$")}.png`;
fs.renameSync(tempFilePath, actualScreenshotPath);
if (actualHash !== expectedHash) {
let showWarning = false;
try {
if (fs.existsSync(expectedScreenshotPath)) {
const actualImage = PNG.sync.read(fs.readFileSync(actualScreenshotPath));
const expectedImage = PNG.sync.read(fs.readFileSync(expectedScreenshotPath));
const { width, height } = actualImage;
const diff = new PNG({ width, height });
const numPixelsDifferent = pixelmatch(actualImage.data, expectedImage.data, diff.data, width, height);
if (numPixelsDifferent === 0) {
showWarning = true;
}
fs.writeFileSync(`${SCREENSHOTS_FOLDER}/${layoutName}_${splitsName}_diff.png`, PNG.sync.write(diff));
}
}
finally {
if (showWarning) {
console.warn(`Render match despite mismatching hashes! Expected hash: ${expectedHash}, actual hash: ${actualHash}`);
} else {
throw Error(`Render mismatch! Expected hash: ${expectedHash}, actual hash: ${actualHash}`)
}
}
}
});
}
testRendering("all_components", "default", "8AAD____-BAAAAAAAALABv_j");
testRendering("all_components", "pmw3", "8AAD__8A-B_DuDvDLDACRP-_");
testRendering("default", "default", "__wBAAAAAAAAAAAAAAAAAP__");
testRendering("default", "pmw3", "_4uBiDvDODPDvDLDPDrDAP-H");
testRendering("splits_two_rows", "celeste", "-D-D0B_DyB8D0B_D1D_jxDwD");
testRendering("splits_with_labels", "celeste", "AKAL__8D8DkAgBsD-D6D-DOD");
testRendering("title_centered_no_game_icon", "celeste", "__BgDw__BwAAAwDxDx__DwAA");
testRendering("title_centered_with_game_icon", "celeste", "__AwRw__wwwAwYx5x5__x4AA");
testRendering("title_left_no_attempt_count", "celeste", "__4A4A__4AAAMA8A8A__cAAA");
after(async () => {
await driver.quit();
serverProcess.kill();
});
});
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><Run version="1.8.0"><GameIcon/><GameName>Game</GameName><CategoryName>Category</CategoryName><Metadata><Run id=""/><Platform usesEmulator="False"/><Region/><SpeedrunComVariables/><CustomVariables/></Metadata><Offset>00:00:00.0000000</Offset><AttemptCount>0</AttemptCount><AttemptHistory/><Segments><Segment><Name>Time</Name><Icon/><SplitTimes><SplitTime name="Personal Best"/></SplitTimes><BestSegmentTime/><SegmentHistory/></Segment></Segments><AutoSplitterSettings/></Run>
File diff suppressed because one or more lines are too long