mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Travis: add scripts to test if headless Chrome runs properly
This commit is contained in:
parent
492fd004af
commit
0a5ed2b4a5
|
@ -39,6 +39,11 @@ install:
|
||||||
- npm config set prefix=$HOME/.node_modules
|
- npm config set prefix=$HOME/.node_modules
|
||||||
- npm install
|
- npm install
|
||||||
- npm run build
|
- npm run build
|
||||||
|
- google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 index.html &
|
||||||
|
- BROWSER_PID=$!
|
||||||
|
- node start.js test
|
||||||
|
- node ./bin/test-chrome.js
|
||||||
|
- kill $BROWSER_PID
|
||||||
- popd
|
- popd
|
||||||
- rm -rf tools/idea/idea-artifacts/dependencies
|
- rm -rf tools/idea/idea-artifacts/dependencies
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ function tryConnect() {
|
||||||
let ws = new WebSocket("ws://localhost:9090");
|
let ws = new WebSocket("ws://localhost:9090");
|
||||||
|
|
||||||
ws.onopen = () => {
|
ws.onopen = () => {
|
||||||
console.log("Connected established");
|
console.log("Connection established");
|
||||||
listen(ws);
|
listen(ws);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,6 +30,10 @@ function tryConnect() {
|
||||||
tryConnect();
|
tryConnect();
|
||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ws.onerror = err => {
|
||||||
|
console.log("Could not connect WebSocket", err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function listen(ws) {
|
function listen(ws) {
|
||||||
|
@ -58,12 +62,14 @@ function runTests(ws, suiteId, tests, index) {
|
||||||
|
|
||||||
function runSingleTest(test, callback) {
|
function runSingleTest(test, callback) {
|
||||||
console.log("Running test " + test.name + " consisting of " + test.files);
|
console.log("Running test " + test.name + " consisting of " + test.files);
|
||||||
let iframe = document.getElementById("test");
|
let iframe = document.createElement("iframe");
|
||||||
|
document.body.appendChild(iframe);
|
||||||
let handshakeListener = () => {
|
let handshakeListener = () => {
|
||||||
window.removeEventListener("message", handshakeListener);
|
window.removeEventListener("message", handshakeListener);
|
||||||
|
|
||||||
let listener = event => {
|
let listener = event => {
|
||||||
window.removeEventListener("message", listener);
|
window.removeEventListener("message", listener);
|
||||||
|
document.body.removeChild(iframe);
|
||||||
callback(event.data);
|
callback(event.data);
|
||||||
};
|
};
|
||||||
window.addEventListener("message", listener);
|
window.addEventListener("message", listener);
|
||||||
|
|
|
@ -21,6 +21,5 @@
|
||||||
<script src="client.js"></script>
|
<script src="client.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe id="test" src="frame.html"></iframe>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
118
tests/src/test/js/src/cdp.js
Normal file
118
tests/src/test/js/src/cdp.js
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
import * as http from "http";
|
||||||
|
import { client as WebSocketClient } from "websocket";
|
||||||
|
|
||||||
|
function httpGetJson(url) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
http.request(url, resp => {
|
||||||
|
if (resp.statusCode !== 200) {
|
||||||
|
reject(new Error(`HTTP status: ${resp.statusCode}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let data = "";
|
||||||
|
resp.on('data', (chunk) => {
|
||||||
|
data += chunk;
|
||||||
|
});
|
||||||
|
resp.on('end', () => {
|
||||||
|
resolve(JSON.parse(data));
|
||||||
|
});
|
||||||
|
}).on("error", err => {
|
||||||
|
reject(new Error(`HTTP error: ${err.message}`));
|
||||||
|
}).end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function connectWs(url) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const client = new WebSocketClient();
|
||||||
|
client.on("connectFailed", error => reject(new Error('Connect Error: ' + error)));
|
||||||
|
client.on("connect", resolve);
|
||||||
|
client.connect(url);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class CDP {
|
||||||
|
constructor(conn) {
|
||||||
|
this.idGenerator = 1;
|
||||||
|
this.pendingCalls = Object.create(null);
|
||||||
|
this.eventHandlers = Object.create(null);
|
||||||
|
this.conn = conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.conn.on("message", message => {
|
||||||
|
if (message.type === 'utf8') {
|
||||||
|
const messageObj = JSON.parse(message.utf8Data);
|
||||||
|
if (messageObj.id !== void 0) {
|
||||||
|
const pendingCall = this.pendingCalls[messageObj.id];
|
||||||
|
delete this.pendingCalls[messageObj.id];
|
||||||
|
if (messageObj.error) {
|
||||||
|
pendingCall.reject(new Error(`Error calling CDP method ${messageObj.error}`));
|
||||||
|
} else {
|
||||||
|
pendingCall.resolve(messageObj.result);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const handlers = this.eventHandlers[messageObj.method];
|
||||||
|
if (handlers) {
|
||||||
|
for (const handler of handlers) {
|
||||||
|
handler(messageObj.params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.conn.on("close", () => {
|
||||||
|
for (const key in Object.getOwnPropertyNames(this.pendingCalls)) {
|
||||||
|
this.pendingCalls[key].reject(new Error("Connection closed before result received"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.conn.on("error", err => {
|
||||||
|
console.error("WS error: %j", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
call(method, params = undefined) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const id = this.idGenerator++;
|
||||||
|
this.pendingCalls[id] = { resolve, reject };
|
||||||
|
this.conn.send(JSON.stringify({ id, method, params }));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async on(eventName, handler) {
|
||||||
|
let handlers = this.eventHandlers[eventName];
|
||||||
|
if (handlers === void 0) {
|
||||||
|
handlers = [];
|
||||||
|
this.eventHandlers[eventName] = handlers;
|
||||||
|
}
|
||||||
|
handlers.push(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async connect(url) {
|
||||||
|
const targets = await httpGetJson(url + "/json/list");
|
||||||
|
const wsUrl = targets.find(target => target.type === "page").webSocketDebuggerUrl;
|
||||||
|
console.log("Connected to Chrome");
|
||||||
|
const wsConn = await connectWs(wsUrl);
|
||||||
|
console.log(`Connected to WS endpoint: ${wsUrl}`);
|
||||||
|
return wsConn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { CDP };
|
48
tests/src/test/js/src/log-chrome.js
Normal file
48
tests/src/test/js/src/log-chrome.js
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
import { CDP } from "./cdp.js";
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
const wsConn = await CDP.connect("http://localhost:9222");
|
||||||
|
const cdp = new CDP(wsConn);
|
||||||
|
const waitForLog = new Promise(resolve => {
|
||||||
|
let timeout = setTimeout(resolve, 500);
|
||||||
|
cdp.on("Runtime.consoleAPICalled", event => {
|
||||||
|
const value = event.args.filter(arg => arg.type === "string").map(arg => arg.value).join("");
|
||||||
|
if (value !== "") {
|
||||||
|
console.log("[LOG] " + new Date(event.timestamp) + ": " + value);
|
||||||
|
}
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(resolve, 500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
cdp.start();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await cdp.call("Runtime.enable");
|
||||||
|
await waitForLog;
|
||||||
|
} finally {
|
||||||
|
wsConn.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run().catch(e => {
|
||||||
|
console.error("Error", e);
|
||||||
|
});
|
|
@ -192,7 +192,7 @@ class TestRunner {
|
||||||
|
|
||||||
const resultPromises = [];
|
const resultPromises = [];
|
||||||
|
|
||||||
this.timeout = createRefreshableTimeoutPromise(10000);
|
this.timeout = createRefreshableTimeoutPromise(20000);
|
||||||
for (let i = 0; i < suite.testCases.length; ++i) {
|
for (let i = 0; i < suite.testCases.length; ++i) {
|
||||||
resultPromises.push(new Promise(resolve => {
|
resultPromises.push(new Promise(resolve => {
|
||||||
this.pendingRequests[request.id + "-" + i] = resolve;
|
this.pendingRequests[request.id + "-" + i] = resolve;
|
||||||
|
|
95
tests/src/test/js/src/test-chrome.js
Normal file
95
tests/src/test/js/src/test-chrome.js
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
import { CDP } from "./cdp.js";
|
||||||
|
|
||||||
|
function waitForTest(cdp) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let stage = 'initial';
|
||||||
|
let requestId = null;
|
||||||
|
cdp.on("Runtime.consoleAPICalled", event => {
|
||||||
|
const value = event.args.filter(arg => arg.type === "string").map(arg => arg.value).join("");
|
||||||
|
switch (stage) {
|
||||||
|
case 'initial':
|
||||||
|
if (value === 'Connection established') {
|
||||||
|
stage = 'connected';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'connected': {
|
||||||
|
const result = /Request #([0-9]+) received/.exec(value);
|
||||||
|
if (result) {
|
||||||
|
requestId = result[1];
|
||||||
|
stage = 'sent';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'sent':
|
||||||
|
if (value === "Running test only simple consisting of http://localhost:9090//only/test.js") {
|
||||||
|
stage = 'ran';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'ran':
|
||||||
|
if (value === "Sending response #" + requestId) {
|
||||||
|
stage = 'received';
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function timeout(time) {
|
||||||
|
let timer;
|
||||||
|
return {
|
||||||
|
promise: new Promise((resolve, reject) => {
|
||||||
|
timer = setTimeout(() => { reject(new Error("Timeout expired")); }, time);
|
||||||
|
}),
|
||||||
|
cancel: () => clearTimeout(timer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
const wsConn = await CDP.connect("http://localhost:9222");
|
||||||
|
const cdp = new CDP(wsConn);
|
||||||
|
cdp.on("Runtime.consoleAPICalled", event => {
|
||||||
|
const value = event.args.filter(arg => arg.type === "string").map(arg => arg.value).join("");
|
||||||
|
if (value !== "") {
|
||||||
|
console.log("[LOG] " + new Date(event.timestamp) + ": " + value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const wait = waitForTest(cdp);
|
||||||
|
let timer;
|
||||||
|
cdp.start();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await cdp.call("Runtime.enable");
|
||||||
|
timer = timeout(10000);
|
||||||
|
await Promise.race([wait, timer.promise]);
|
||||||
|
} finally {
|
||||||
|
if (timer) {
|
||||||
|
timer.cancel();
|
||||||
|
}
|
||||||
|
wsConn.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run().catch(e => {
|
||||||
|
console.error("Error", e);
|
||||||
|
});
|
19
tests/src/test/js/test/only/test.js
Normal file
19
tests/src/test/js/test/only/test.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function main(args, callback) {
|
||||||
|
callback();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user