Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -724,3 +724,12 @@ export const defaultTodoText = {
ru: "Кое-что сделать",
emoji: "Something to do 😊",
};

export const numberOfItemsToAdd = 100;
export const defaultLanguage = "en";

export function getTodoText(lang = "en", index) {
const todosSelection = todos[lang];
const currentIndex = index % todosSelection.length;
return todosSelection[currentIndex];
}
1 change: 1 addition & 0 deletions resources/shared/workload-testing-utils.mjs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./helpers.mjs";
export * from "./benchmark.mjs";
export * from "./translations.mjs";
23 changes: 13 additions & 10 deletions resources/tests.mjs
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
import { BenchmarkTestStep } from "./benchmark-runner.mjs";
import { todos } from "./translations.mjs";

const numberOfItemsToAdd = 100;
const defaultLanguage = "en";

function getTodoText(lang, index) {
const todosSelection = todos[lang] ?? todos[defaultLanguage];
const currentIndex = index % todosSelection.length;
return todosSelection[currentIndex];
}
import { getTodoText, numberOfItemsToAdd, defaultLanguage } from "./shared/translations.mjs";

export const Suites = [];

Expand Down Expand Up @@ -274,6 +265,18 @@ Suites.push({
],
});

Suites.push({
name: "TodoMVC-WebComponents-PostMessage",
url: "resources/todomvc/vanilla-examples/javascript-web-components/dist/index.html",
tags: ["experimental", "todomvc", "webcomponents"],
disabled: true,
async prepare() {},
type: "remote",
/* config: {
name: "default", // optional param to target non-default tests locally
}, */
});

Suites.push({
name: "TodoMVC-WebComponents-Complex-DOM",
url: "resources/todomvc/vanilla-examples/javascript-web-components-complex/dist/index.html",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
<link rel="stylesheet" href="styles/header.css" />
<link rel="stylesheet" href="styles/footer.css" />
<!-- load these first, so that they are registered by the time the app components needs them -->
<script type="module" src="components/todo-topbar/todo-topbar.component.js"></script>
<script type="module" src="components/todo-list/todo-list.component.js"></script>
<script type="module" src="components/todo-bottombar/todo-bottombar.component.js"></script>
<script type="module" src="components/todo-app/todo-app.component.js"></script>
<script type="module" src="src/components/todo-topbar/todo-topbar.component.js"></script>
<script type="module" src="src/components/todo-list/todo-list.component.js"></script>
<script type="module" src="src/components/todo-bottombar/todo-bottombar.component.js"></script>
<script type="module" src="src/components/todo-app/todo-app.component.js"></script>
</head>

<body>
Expand All @@ -26,5 +26,6 @@
<p class="footer-text">Press 'enter' to add the todo.</p>
<p class="footer-text">Double-click to edit a todo</p>
</footer>
<script type="module" src="src/index.js"></script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/* eslint-disable no-case-declarations */
import { TestRunner } from "./test-runner.mjs";
import { Params } from "./params.mjs";

/**
* BenchmarkStep
*
* A single test step, with a common interface to interact with.
*/
export class BenchmarkStep {
constructor(name, run) {
this.name = name;
this.run = run;
}

async runAndRecord(params, suite, test, callback) {
const testRunner = new TestRunner(null, null, params, suite, test, callback);
const result = await testRunner.runTest();
return result;
}
}

/**
* BenchmarkSuite
*
* A single test suite that contains one or more test steps.
*/
export class BenchmarkSuite {
constructor(name, tests) {
this.name = name;
this.tests = tests;
}

record(_test, syncTime, asyncTime) {
const total = syncTime + asyncTime;
const results = {
tests: { Sync: syncTime, Async: asyncTime },
total: total,
};

return results;
}

async runAndRecord(params, onProgress) {
const measuredValues = {
tests: {},
total: 0,
};
const suiteStartLabel = `suite-${this.name}-start`;
const suiteEndLabel = `suite-${this.name}-end`;

performance.mark(suiteStartLabel);

for (const test of this.tests) {
const result = await test.runAndRecord(params, this, test, this.record);
measuredValues.tests[test.name] = result;
measuredValues.total += result.total;
onProgress?.(test.name);
}

performance.mark(suiteEndLabel);
performance.measure(`suite-${this.name}`, suiteStartLabel, suiteEndLabel);

return {
type: "suite-tests-complete",
status: "success",
result: measuredValues,
suitename: this.name,
};
}
}

/** **********************************************************************
* BenchmarkConnector
*
* postMessage is used to communicate between app and benchmark.
* When the app is ready, an 'app-ready' message is sent to signal that the app can receive instructions.
*
* A prepare script within the apps appends window.name and window.version from the package.json file.
* The appId is build by appending name-version
* It's used as an additional safe-guard to ensure the correct app responds to a message.
*************************************************************************/
export class BenchmarkConnector {
constructor(suites, name, version) {
this.suites = suites;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use private variables?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a benefit in refactoring? Maybe that's a larger conversation if we want to prefer private variables in our code and might be better to tackle in a separate discussion. This is consistent with the previous example that uses the postMessage api and I rather want to avoid larger changes in a single pr.

this.name = name;
this.version = version;

if (!name || !version)
console.warn("No name or version supplied, to create a unique appId");

this.appId = name && version ? `${name}-${version}` : -1;
this.onMessage = this.onMessage.bind(this);
}

async onMessage(event) {
if (event.data.id !== this.appId || event.data.key !== "benchmark-connector")
return;

switch (event.data.type) {
case "benchmark-suite":
const params = new Params(new URLSearchParams(window.location.search));
const suite = this.suites[event.data.name];
if (!suite)
console.error(`Suite with the name of "${event.data.name}" not found!`);
const { result } = await suite.runAndRecord(params, (test) => this.sendMessage({ type: "step-complete", status: "success", appId: this.appId, name: this.name, test }));
this.sendMessage({ type: "suite-complete", status: "success", appId: this.appId, result });
this.disconnect();
break;
default:
console.error(`Message data type not supported: ${event.data.type}`);
}
}

sendMessage(message) {
window.top.postMessage(message, "*");
}

connect() {
window.addEventListener("message", this.onMessage);
this.sendMessage({ type: "app-ready", status: "success", appId: this.appId });
}

disconnect() {
window.removeEventListener("message", this.onMessage);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import template from "./todo-app.template.js";
import { useRouter } from "../../hooks/useRouter.js";

import globalStyles from "../../styles/global.constructable.js";
import appStyles from "../../styles/app.constructable.js";
import mainStyles from "../../styles/main.constructable.js";
import globalStyles from "../../../styles/global.constructable.js";
import appStyles from "../../../styles/app.constructable.js";
import mainStyles from "../../../styles/main.constructable.js";
class TodoApp extends HTMLElement {
#isReady = false;
#data = [];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import template from "./todo-bottombar.template.js";

import globalStyles from "../../styles/global.constructable.js";
import bottombarStyles from "../../styles/bottombar.constructable.js";
import globalStyles from "../../../styles/global.constructable.js";
import bottombarStyles from "../../../styles/bottombar.constructable.js";

class TodoBottombar extends HTMLElement {
static get observedAttributes() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import template from "./todo-item.template.js";
import { useDoubleClick } from "../../hooks/useDoubleClick.js";
import { useKeyListener } from "../../hooks/useKeyListener.js";

import globalStyles from "../../styles/global.constructable.js";
import itemStyles from "../../styles/todo-item.constructable.js";
import globalStyles from "../../../styles/global.constructable.js";
import itemStyles from "../../../styles/todo-item.constructable.js";

class TodoItem extends HTMLElement {
static get observedAttributes() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import template from "./todo-list.template.js";
import TodoItem from "../todo-item/todo-item.component.js";

import globalStyles from "../../styles/global.constructable.js";
import listStyles from "../../styles/todo-list.constructable.js";
import globalStyles from "../../../styles/global.constructable.js";
import listStyles from "../../../styles/todo-list.constructable.js";

class TodoList extends HTMLElement {
static get observedAttributes() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import template from "./todo-topbar.template.js";
import { useKeyListener } from "../../hooks/useKeyListener.js";
import { nanoid } from "../../utils/nanoid.js";

import globalStyles from "../../styles/global.constructable.js";
import topbarStyles from "../../styles/topbar.constructable.js";
import globalStyles from "../../../styles/global.constructable.js";
import topbarStyles from "../../../styles/topbar.constructable.js";

class TodoTopbar extends HTMLElement {
static get observedAttributes() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Helper Methods
*
* Various methods that are extracted from the Page class.
*/
export function getParent(lookupStartNode, path) {
lookupStartNode = lookupStartNode.shadowRoot ?? lookupStartNode;
const parent = path.reduce((root, selector) => {
const node = root.querySelector(selector);
return node.shadowRoot ?? node;
}, lookupStartNode);

return parent;
}

export function getElement(selector, path = [], lookupStartNode = document) {
const element = getParent(lookupStartNode, path).querySelector(selector);
return element;
}

export function getAllElements(selector, path = [], lookupStartNode = document) {
const elements = Array.from(getParent(lookupStartNode, path).querySelectorAll(selector));
return elements;
}

export function forceLayout() {
const rect = document.body.getBoundingClientRect();
const e = document.elementFromPoint((rect.width / 2) | 0, (rect.height / 2) | 0);
return e;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { BenchmarkConnector } from "./benchmark.mjs";
import suites, { appName, appVersion } from "./workload-test.mjs";

/*
Paste below into dev console for manual testing:
window.addEventListener("message", (event) => console.log(event.data));
window.postMessage({ id: "todomvc-postmessage-1.0.0", key: "benchmark-connector", type: "benchmark-suite", name: "default" }, "*");
*/
const benchmarkConnector = new BenchmarkConnector(suites, appName, appVersion);
benchmarkConnector.connect();
Loading