Skip to content

PostMessage Cleanup - TodoMVC example (experimental) #509

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
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];
}
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
@@ -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,10 @@
import { BenchmarkConnector } from "./speedometer-utils/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();
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;
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
@@ -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;
}
Loading