-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4bd864a
commit c6127cb
Showing
7 changed files
with
1,896 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import { FlowplayerUMD} from "@flowplayer/player" | ||
import type { FlowplayerUMD} from "@flowplayer/player" | ||
declare global { | ||
var flowplayer: FlowplayerUMD; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export default { | ||
files: ["./test/puppeteer/**/*.spec.mjs"], | ||
require: ["./test/puppeteer/_setup/helpers.mjs"], | ||
timeout: "5m", | ||
concurrency: 3 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
import pug from "pug" | ||
import os, {tmpdir} from "os" | ||
import fs from "fs/promises" | ||
import path from "path" | ||
import puppeteer from "puppeteer" | ||
import HttpServer from "http-server" | ||
import "dotenv/config" | ||
import mkdirp from "mkdirp" | ||
import {PuppeteerScreenRecorder} from "puppeteer-screen-recorder" | ||
|
||
const debug = (...args) => process.env.DEBUG && console.log(...args) | ||
const _dirname = path.dirname(import.meta.url) | ||
const tmpDir = path.join(os.tmpdir(), "puppeteer-native", "html") | ||
|
||
export function compilePug(name) { | ||
const fileName = path.join(_dirname, name + ".pug").slice(5) | ||
return pug.compileFile(fileName, {}) | ||
} | ||
|
||
const Templates = {local: compilePug("local")} | ||
|
||
export async function createServer(t) { | ||
return new Promise((resolve) => { | ||
const server = HttpServer.createServer({root: tmpDir}) | ||
server.listen(0, "localhost", () => { | ||
Object.assign(t.context, {server, ...server.server.address()}) | ||
Object.assign(t.context, {address: "localhost"}) | ||
debug("server / up / %s:%s", t.context.address, t.context.port) | ||
resolve() | ||
}) | ||
}) | ||
} | ||
|
||
export async function destroyServer(t) { | ||
if (!t.context.server) return | ||
t.context.server.close() | ||
t.context.server = void 0 | ||
} | ||
|
||
export async function loadComponent(componentName) { | ||
const component = await fs.readFile( | ||
path.join("dist", `${componentName}.js`) | ||
) | ||
|
||
return component.toString() | ||
} | ||
|
||
export async function writeTempFile(fileName, contents) { | ||
const fullName = path.join(tmpDir, fileName) | ||
debug("created: %s", fullName) | ||
await fs.writeFile(fullName, contents) | ||
return fullName | ||
} | ||
|
||
export function titleToFile(title, suffix = ".html") { | ||
const fileName = title | ||
.toLowerCase() | ||
.replaceAll(/\s+/g, "-") | ||
.replaceAll(/[/]/g, "-") | ||
.replaceAll(/,/g, "-") | ||
.replaceAll(/-{2,}/g, "-") | ||
.replaceAll(/=/g, "-") | ||
.replaceAll(/_/g, "-") | ||
return fileName + suffix | ||
} | ||
|
||
export async function compileLocalTest(t, {config, components: componentNames}) { | ||
const components = await Promise.all(componentNames.map((name) => loadComponent(name))) | ||
|
||
const compiled = Templates.local({ | ||
Test: { | ||
components, | ||
config: config | ||
} | ||
}) | ||
const fileName = titleToFile(t.title) | ||
const filePath = await writeTempFile(fileName, compiled) | ||
return {fileName, filePath} | ||
} | ||
|
||
const { | ||
PUPPETEER_PRODUCT: puppeteerProduct, | ||
CHROME_PATH: chromePath = "/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome", | ||
FIREFOX_PATH: firefoxPath = "/usr/bin/firefox" | ||
} = process.env | ||
|
||
const headless = !!process.env.CI || !!process.env.PUPPETEER_HEADLESS | ||
|
||
const executablePath = puppeteerProduct === "firefox" ? firefoxPath : chromePath | ||
|
||
export async function makePuppeteerSession(t, args) { | ||
args = args || [] | ||
if (process.env.CI) args.push("--no-sandbox") | ||
|
||
const browser = await puppeteer.launch({ | ||
headless, | ||
executablePath, | ||
slowMo: !headless ? 50 : 200, | ||
userDataDir: path.join(tmpdir(), `puppeteer-ci-${Date.now()}`), | ||
args | ||
}) | ||
const page = await browser.newPage({timeout: 120 * 1000}) | ||
const recorder = new PuppeteerScreenRecorder(page) | ||
page.on("console", (msg) => { | ||
if (!process.env.DEBUG) return | ||
for (let i = 0; i < msg.args().length; ++i) | ||
debug(`console / ${t.title} / ${i}: ${msg.args()[i]}`) | ||
}) | ||
return {browser, page, recorder} | ||
} | ||
|
||
async function getPlayer( | ||
t, | ||
components, | ||
config, | ||
token, | ||
puppeteer, | ||
recorder, | ||
setup, | ||
host, | ||
page | ||
) { | ||
const context = {host, page} | ||
if (typeof setup == "function") { | ||
await setup(context) | ||
} | ||
const recordingFile = | ||
"/tmp/puppeteer-native/components/recordings/" + titleToFile(t.title, ".mp4") | ||
|
||
if (!process.env.DEBUG) await recorder.start(recordingFile) | ||
const {fileName, filePath} = await compileLocalTest(t, { | ||
config: JSON.stringify(config).replaceAll(":host:", host), | ||
components, | ||
}) | ||
const testDocument = `${context.host}/${fileName}` //host + fileName | ||
await page.goto(testDocument, puppeteer || {waitUntil: "networkidle2", timeout: 120 * 1000} | ||
) | ||
const player = await page.$(".fp-engine") | ||
return {player, filePath, recordingFile} | ||
} | ||
|
||
export function withPlayer({components, config, token, files, puppeteer, args}, setup) { | ||
return async function (t, run) { | ||
await mkdirp(tmpDir) | ||
await mkdirp("/tmp/puppeteer-native/components/recordings/") | ||
if (!t.context.address) await createServer(t) | ||
const host = `http://localhost:${t.context.port}` | ||
if (files) | ||
await Promise.all( | ||
Object.entries(files).map(([fileName, contents]) => | ||
writeTempFile(fileName, contents) | ||
) | ||
) | ||
|
||
const {browser, page, recorder} = await makePuppeteerSession(t, args) | ||
|
||
const {player, filePath, recordingFile} = await getPlayer( | ||
t, | ||
components, | ||
config, | ||
token, | ||
puppeteer, | ||
recorder, | ||
setup, | ||
host, | ||
page | ||
) | ||
|
||
t.assert(player) | ||
try { | ||
try { | ||
await run(t, page, player) | ||
} catch (err) { | ||
// todo: open an issue with ava.js about this | ||
t.fail(err.message) | ||
} | ||
} finally { | ||
await destroyServer(t) | ||
if (!process.env.DEBUG) await recorder.stop() | ||
if (t.passed) { | ||
const testFiles = Object.keys(files || {}).map((fileName) => | ||
path.join(tmpDir, fileName) | ||
) | ||
const rm = async (f) => { | ||
if (process.env.KEEP) return | ||
if (process.env.DEBUG) debug("cleaning up file %s", f) | ||
if (await fs.stat(f)) { | ||
return await fs.rm(f) | ||
} | ||
} | ||
const removals = [rm(recordingFile), rm(filePath), ...testFiles.map(rm)] | ||
await Promise.all(removals) | ||
} | ||
if (!process.env.KEEP) await browser.close() | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
html(lang="en") | ||
meta(charset="utf-8") | ||
head | ||
link(rel="stylesheet" href="https://cdn.flowplayer.com/releases/native/3/stable/style/flowplayer.css") | ||
script(src = "https://cdn.flowplayer.com/releases/native/3/stable/flowplayer.min.js") | ||
script(src = "https://cdn.flowplayer.com/releases/native/3/stable/plugins/hls.min.js") | ||
script(src = "https://cdn.flowplayer.com/releases/native/3/stable/plugins/ovp.min.js") | ||
script(src = "https://cdn.flowplayer.com/releases/native/3/stable/plugins/qsel.min.js") | ||
script(src = "https://cdn.flowplayer.com/releases/native/3/stable/plugins/speed.min.js") | ||
script(src = "https://cdn.flowplayer.com/releases/native/3/stable/plugins/vtsel.min.js") | ||
body | ||
div(id = "player") | ||
//inject components | ||
each component in Test.components | ||
script!= component | ||
|
||
script | ||
| localStorage["flowplayer/debug"] = ".*" | ||
| window.Errors = [] | ||
| window.onerror = function(messageOrEvent, source, lineno, colno, error) { window.Errors.push([...arguments]) } | ||
| window.__FLOWPLAYER_TOKEN = "eyJraWQiOiJiRDJrSnhuTkppT1AiLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJjIjoie1wiYWNsXCI6NixcImlkXCI6XCJiRDJrSnhuTkppT1BcIn0iLCJpc3MiOiJGbG93cGxheWVyIn0.6SS-jLJb338KVYAsj4SFVBzbah-auDeQjeBqjJL6SRa_vJKt4xW7-lSlZGjqsKAqhXFso2UF_BaBkJZ1S1SQFg" | ||
| window.player = flowplayer("#player", !{Test.config}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import test from "ava" | ||
import {createServer, destroyServer, withPlayer} from "../_setup/helpers.mjs" | ||
|
||
test.before("setting up server...", createServer) | ||
test.after("shutting down server...", destroyServer) | ||
|
||
|
||
const Player = withPlayer({ | ||
components: ["combined-menu-control"], config: { | ||
src: "https://fp-eu-w1-nnarhinen.s3.eu-west-1.amazonaws.com/multi-angle-hls/playlist.m3u8" | ||
} | ||
}) | ||
|
||
test("dummy test", Player, async (t, page, player) => { | ||
setTimeout(() => console.log(player), 20_000) | ||
}) |
Oops, something went wrong.