Skip to content

Commit

Permalink
test: add routine for Violentmonkey
Browse files Browse the repository at this point in the history
  • Loading branch information
guansss committed Aug 30, 2023
1 parent 137f350 commit 4d5e60c
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 48 deletions.
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
TEST_PORT=8081
EXT=
TEST_PORT=8888
TEST_BROWSER_CASE_TIMEOUT=30000
TEST_PUPPETEER_TIMEOUT=5000
10 changes: 8 additions & 2 deletions jest-puppeteer.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
const { availableExtensions } = require("./tests/extensions/available-extensions")
const { getExtension } = require("./tests/extensions/extensions")

const extensions = []

try {
extensions.push(getExtension(process.env.EXT).dir)
} catch (ignored) {}

/** @type {import('jest-environment-puppeteer').JestPuppeteerConfig} */
module.exports = {
Expand All @@ -7,7 +13,7 @@ module.exports = {
devtools: process.env.HEADLESS === "false",
headless: process.env.HEADLESS !== "false" ? "new" : false,
args: [
...availableExtensions().flatMap((dir) => [
...extensions.flatMap((dir) => [
`--load-extension=${dir}`,
`--disable-extensions-except=${dir}`,
]),
Expand Down
13 changes: 9 additions & 4 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@
* https://jestjs.io/docs/configuration
*/

const { getExtension } = require("./tests/extensions/extensions")

require("dotenv").config()

const timeoutScale = process.env.CI ? 5 : 1

if (process.env.EXT) {
console.log(`============= Testing with ${getExtension(process.env.EXT).name} =============`)
}

module.exports = {
// All imported modules in your tests should be mocked automatically
// automock: false,
Expand Down Expand Up @@ -70,6 +76,7 @@ module.exports = {

// A set of global variables that need to be available in all test environments
globals: {
__EXT__: process.env.EXT,
__PORT__: parseInt(process.env.TEST_PORT),
__BROWSER_CASE_TIMEOUT__: parseInt(process.env.TEST_BROWSER_CASE_TIMEOUT) * timeoutScale,
__PUPPETEER_TIMEOUT__: parseInt(process.env.TEST_PUPPETEER_TIMEOUT) * timeoutScale,
Expand Down Expand Up @@ -102,7 +109,7 @@ module.exports = {
},

// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
modulePathIgnorePatterns: ['dist'],
modulePathIgnorePatterns: ["dist"],

// Activates notifications for test results
// notify: false,
Expand Down Expand Up @@ -146,9 +153,7 @@ module.exports = {
// setupFiles: [],

// A list of paths to modules that run some code to configure or set up the testing framework before each test
setupFilesAfterEnv: [
"<rootDir>/tests/jest-setup-after-env.ts",
],
setupFilesAfterEnv: ["<rootDir>/tests/jest-setup-after-env.ts"],

// The number of seconds after which a test is considered as slow and reported as such in the results.
// slowTestThreshold: 5,
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@
"check-deps": "ts-node scripts/check-deps.ts",
"prepublishOnly": "npm run check-deps",
"examples": "ts-node scripts/update-examples.ts",
"test": "jest --runInBand",
"test:u": "npm run test -- --updateSnapshot",
"test:h": "cross-env HEADLESS=false npm run test"
"test": "jest --runInBand && npm run test:ext",
"test:u": "jest --runInBand --updateSnapshot",
"test:tm": "cross-env EXT=tm jest --runInBand -t '\\[browser\\]'",
"test:vm": "cross-env EXT=vm jest --runInBand -t '\\[browser\\]'",
"test:tm:h": "cross-env HEADLESS=false npm run test:tm",
"test:vm:h": "cross-env HEADLESS=false npm run test:vm",
"test:ext": "npm run test:tm && npm run test:vm"
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
Expand Down
9 changes: 2 additions & 7 deletions scripts/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@ const axios = require("axios")
const fs = require("fs")
const JSZip = require("jszip")
const path = require("path")

const extensionInfos = {
tampermonkey: {
url: "https://data.tampermonkey.net/tampermonkey_stable.crx",
},
}
const { extensionInfos } = require("../tests/extensions/extensions")

const extensionDir = path.resolve(__dirname, "../tests/extensions")

Expand All @@ -29,7 +24,7 @@ async function installExtensions() {
if (fs.existsSync(outDir)) {
if (fs.readdirSync(outDir).length > 0) {
console.warn(
`Extension directory ${outDir} already exists, skipping to avoid overwrite. If you want to reinstall it, please delete the directory first.`
`Warning: extension directory ${outDir} already exists, skipping to avoid overwriting. If you want to reinstall it, please delete the directory first.`
)
return
}
Expand Down
1 change: 1 addition & 0 deletions src/env-dev.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/// <reference types="webpack/module" />
/// <reference types="webpack-dev-server" />

declare const __EXT__: string
declare const __PORT__: number
declare const __BROWSER_CASE_TIMEOUT__: number

Expand Down
12 changes: 7 additions & 5 deletions tests/cases/hot/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Server from "webpack-dev-server"
import { merge } from "webpack-merge"
import { monkey } from "../../../src"
import { DEV_SCRIPT } from "../../../src/shared/constants"
import { installWithTampermonkey } from "../../utils/tampermonkey"
import { installScript } from "../../utils/extensions"
import {
testBuild,
usingDevServerHot,
Expand All @@ -31,12 +31,12 @@ const config = withCommonConfig({

it("build", () => testBuild(monkey(withMiniCssExtract(config))))

describe("hot reload", () => {
it.browser("modules", async () => {
describe("hot reload JS", () => {
it.browser("dependencies", async () => {
await usingDevServerHot(
{ config: monkey(withMiniCssExtract(config)) },
async (server, { replacers }) => {
await installWithTampermonkey(browser, page, `http://localhost:${__PORT__}/${DEV_SCRIPT}`)
await installScript(browser, page, `http://localhost:${__PORT__}/${DEV_SCRIPT}`)
await page.goto(`http://localhost:${__PORT__}/webpack-dev-server/`)

const expectExactlyOnes = async (classes: string[]) => {
Expand Down Expand Up @@ -74,15 +74,17 @@ describe("hot reload", () => {
}
)
})
})

describe("hot reload CSS", () => {
it.browser.each([
["css with mini-css-extract", withMiniCssExtract()],
// ["css with style-loader", withStyleLoader()],
])("%s", async (_, cssConfig) => {
await usingDevServerHot(
{ config: monkey(merge({}, config, cssConfig)) },
async (server, { replacers }) => {
await installWithTampermonkey(browser, page, `http://localhost:${__PORT__}/${DEV_SCRIPT}`)
await installScript(browser, page, `http://localhost:${__PORT__}/${DEV_SCRIPT}`)
await page.goto(`http://localhost:${__PORT__}/webpack-dev-server/`)
await page.waitForSelector(".index1")

Expand Down
16 changes: 0 additions & 16 deletions tests/extensions/available-extensions.js

This file was deleted.

43 changes: 43 additions & 0 deletions tests/extensions/extensions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const glob = require("glob")
const _ = require("lodash")
const path = require("path")

const extensionInfos = {
tampermonkey: {
id: "tm",
name: "Tampermonkey",
url: "https://data.tampermonkey.net/tampermonkey_stable.crx",
},
violentmonkey: {
id: "vm",
name: "Violentmonkey",
url: "https://github.com/violentmonkey/violentmonkey/releases/download/v2.15.0/Violentmonkey-webext-v2.15.0.zip",
},
}

const getInstalledExtensions = _.memoize(() => {
const dirs = glob.sync("*/", { cwd: __dirname, absolute: true })

if (dirs.length === 0) {
throw new Error("No extensions found, please run `npm run setup` to install the extensions.")
}

return dirs
})

function getExtension(id) {
const ext = Object.values(extensionInfos).find((ext) => ext.id === id)
if (!ext) {
throw new Error(`No extension found for "${id}"`)
}
return {
...ext,
dir: getInstalledExtensions().find((dir) => extensionInfos[path.basename(dir)] === ext),
}
}

module.exports = {
extensionInfos,
getInstalledExtensions,
getExtension,
}
31 changes: 22 additions & 9 deletions tests/jest-setup-after-env.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as matchers from "jest-extended"
import { noop } from "lodash"

expect.extend(matchers)

Expand Down Expand Up @@ -27,6 +28,10 @@ it.browser.todo = wrapIt(it.todo)
it.browser.concurrent = wrapIt(it.concurrent)
it.browser.each = wrapEach(it.each)

function getBrowserTestName(baseName: string) {
return `[browser] ${baseName}`
}

function wrapIt(original: jest.It): jest.It {
type ItFunction = {
[K in keyof jest.It]: K extends "each"
Expand All @@ -37,24 +42,32 @@ function wrapIt(original: jest.It): jest.It {
}[keyof jest.It]

const itWrapper: ItFunction = (name, fn, timeout = defaultBrowserCaseTimeout) => {
original(`[browser] ${name}`, fn && wrapFn(fn), timeout)
if (process.env.EXT) {
return original(getBrowserTestName(name), fn && wrapFn(fn), timeout)
} else {
return original.skip(getBrowserTestName(name), noop)
}
}

return itWrapper as jest.It
}

function wrapEach(original: jest.Each) {
const eachWrapper: jest.Each = (...args: any[]) => {
const originalReturn = original.apply(globalThis, args as any)
if (process.env.EXT) {
const originalReturn = original.apply(globalThis, args as any)

const eachReturnWrapper: typeof originalReturn = (
name,
fn,
timeout = defaultBrowserCaseTimeout
) => {
originalReturn(`[browser] ${name}`, wrapFn(fn), timeout)
const eachReturnWrapper: typeof originalReturn = (
name,
fn,
timeout = defaultBrowserCaseTimeout
) => {
originalReturn(getBrowserTestName(name), wrapFn(fn), timeout)
}
return eachReturnWrapper
}
return eachReturnWrapper

return it.skip.each.apply(globalThis, args as any)
}
return eachWrapper
}
Expand Down
23 changes: 22 additions & 1 deletion tests/utils/tampermonkey.ts → tests/utils/extensions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Browser, Page, Target } from "puppeteer"

export async function installWithTampermonkey(browser: Browser, page: Page, scriptUrl: string) {
export async function installScript(browser: Browser, page: Page, scriptUrl: string) {
try {
await page.goto(scriptUrl)
} catch (e) {
Expand All @@ -11,6 +11,16 @@ export async function installWithTampermonkey(browser: Browser, page: Page, scri
}
}

if (__EXT__ === "tm") {
return installWithTampermonkey(browser)
} else if (__EXT__ === "vm") {
return installWithViolentmonkey(browser)
} else {
throw new Error(`Unknown extension type: "${__EXT__}"`)
}
}

async function installWithTampermonkey(browser: Browser) {
const installerTarget = await browser.waitForTarget((target) =>
/extension:.+ask\.html/.test(target.url())
)
Expand Down Expand Up @@ -46,3 +56,14 @@ export async function installWithTampermonkey(browser: Browser, page: Page, scri
})
}
}

async function installWithViolentmonkey(browser: Browser) {
const installerTarget = await browser.waitForTarget((target) =>
/extension:.+confirm\/index\.html/.test(target.url())
)
const installerPage = (await installerTarget.page())!
const installBtn = await installerPage.waitForSelector("#confirm")
await installBtn!.click()
await installerPage.waitForSelector("#confirm[disabled]")
await installerPage.close()
}

0 comments on commit 4d5e60c

Please sign in to comment.