electron/spec-main/content-script-spec.ts

149 lines
5.3 KiB
TypeScript

import { expect } from 'chai'
import * as path from 'path'
import { closeWindow } from './window-helpers'
import { emittedNTimes } from './events-helpers'
import { BrowserWindow, ipcMain, WebContents } from 'electron'
describe('chrome extension content scripts', () => {
const fixtures = path.resolve(__dirname, 'fixtures')
const extensionPath = path.resolve(fixtures, 'extensions')
const addExtension = (name: string) => BrowserWindow.addExtension(path.resolve(extensionPath, name))
const removeAllExtensions = () => {
Object.keys(BrowserWindow.getExtensions()).map(extName => {
BrowserWindow.removeExtension(extName)
})
}
let responseIdCounter = 0
const executeJavaScriptInFrame = (webContents: WebContents, frameRoutingId: number, code: string) => {
return new Promise(resolve => {
const responseId = responseIdCounter++
ipcMain.once(`executeJavaScriptInFrame_${responseId}`, (event, result) => {
resolve(result)
})
webContents.send('executeJavaScriptInFrame', frameRoutingId, code, responseId)
})
}
const generateTests = (sandboxEnabled: boolean, contextIsolationEnabled: boolean) => {
describe(`with sandbox ${sandboxEnabled ? 'enabled' : 'disabled'} and context isolation ${contextIsolationEnabled ? 'enabled' : 'disabled'}`, () => {
let w: BrowserWindow
describe('supports "run_at" option', () => {
beforeEach(async () => {
await closeWindow(w)
w = new BrowserWindow({
show: false,
width: 400,
height: 400,
webPreferences: {
contextIsolation: contextIsolationEnabled,
sandbox: sandboxEnabled
}
})
})
afterEach(() => {
removeAllExtensions()
return closeWindow(w).then(() => { w = null as unknown as BrowserWindow })
})
it('should run content script at document_start', () => {
addExtension('content-script-document-start')
w.webContents.once('dom-ready', async () => {
const result = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor')
expect(result).to.equal('red')
})
w.loadURL('about:blank')
})
it('should run content script at document_idle', async () => {
addExtension('content-script-document-idle')
w.loadURL('about:blank')
const result = await w.webContents.executeJavaScript('document.body.style.backgroundColor')
expect(result).to.equal('red')
})
it('should run content script at document_end', () => {
addExtension('content-script-document-end')
w.webContents.once('did-finish-load', async () => {
const result = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor')
expect(result).to.equal('red')
})
w.loadURL('about:blank')
})
})
describe('supports "all_frames" option', () => {
const contentScript = path.resolve(fixtures, 'extensions/content-script')
// Computed style values
const COLOR_RED = `rgb(255, 0, 0)`
const COLOR_BLUE = `rgb(0, 0, 255)`
const COLOR_TRANSPARENT = `rgba(0, 0, 0, 0)`
before(() => {
BrowserWindow.addExtension(contentScript)
})
after(() => {
BrowserWindow.removeExtension('content-script-test')
})
beforeEach(() => {
w = new BrowserWindow({
show: false,
webPreferences: {
// enable content script injection in subframes
nodeIntegrationInSubFrames: true,
preload: path.join(contentScript, 'all_frames-preload.js')
}
})
})
afterEach(() =>
closeWindow(w).then(() => {
w = null as unknown as BrowserWindow
})
)
it('applies matching rules in subframes', async () => {
const detailsPromise = emittedNTimes(w.webContents, 'did-frame-finish-load', 2)
w.loadFile(path.join(contentScript, 'frame-with-frame.html'))
const frameEvents = await detailsPromise
await Promise.all(
frameEvents.map(async frameEvent => {
const [, isMainFrame, , frameRoutingId] = frameEvent
const result: any = await executeJavaScriptInFrame(
w.webContents,
frameRoutingId,
`(() => {
const a = document.getElementById('all_frames_enabled')
const b = document.getElementById('all_frames_disabled')
return {
enabledColor: getComputedStyle(a).backgroundColor,
disabledColor: getComputedStyle(b).backgroundColor
}
})()`
)
expect(result.enabledColor).to.equal(COLOR_RED)
if (isMainFrame) {
expect(result.disabledColor).to.equal(COLOR_BLUE)
} else {
expect(result.disabledColor).to.equal(COLOR_TRANSPARENT) // null color
}
})
)
})
})
})
}
generateTests(false, false)
generateTests(false, true)
generateTests(true, false)
generateTests(true, true)
})