feat: 新增包文件

This commit is contained in:
duanshuwen
2025-11-15 22:41:50 +08:00
parent 7b65193e5c
commit 7ada85f175
104 changed files with 11273 additions and 1 deletions

View File

@@ -0,0 +1,299 @@
import { expect } from 'chai'
import { app, BrowserWindow } from 'electron'
import { emittedOnce } from './events-helpers'
import { useExtensionBrowser, useServer } from './hooks'
import { ChromeExtensionImpl } from '../dist/types/browser/impl'
describe('chrome.tabs', () => {
let assignTabDetails: ChromeExtensionImpl['assignTabDetails']
const server = useServer()
const browser = useExtensionBrowser({
url: server.getUrl,
extensionName: 'rpc',
assignTabDetails(details, tab) {
assignTabDetails?.(details, tab)
},
})
afterEach(() => {
assignTabDetails = undefined
})
describe('get()', () => {
it('returns tab details', async () => {
const tabId = browser.window.webContents.id
const result = await browser.crx.exec('tabs.get', tabId)
expect(result).to.be.an('object')
expect(result.id).to.equal(tabId)
expect(result.windowId).to.equal(browser.window.id)
})
})
describe('getCurrent()', () => {
it('gets details of the active tab', async () => {
const result = await browser.crx.exec('tabs.getCurrent')
expect(result).to.be.an('object')
})
})
describe('create()', () => {
it('creates a tab', async () => {
const wcPromise = emittedOnce(app, 'web-contents-created')
const tabInfo = await browser.crx.exec('tabs.create', { url: server.getUrl() })
const [, wc] = await wcPromise
expect(tabInfo).to.be.an('object')
expect(tabInfo.id).to.equal(wc.id)
expect(tabInfo.active).to.equal(true)
expect(tabInfo.url).to.equal(server.getUrl())
expect(tabInfo.windowId).to.equal(browser.window.id)
expect(tabInfo.title).to.be.a('string')
})
// TODO: Navigating to chrome-extension:// receives ERR_BLOCKED_BY_CLIENT (-20)
it.skip('resolves relative URL', async () => {
const relativeUrl = './options.html'
const tabInfo = await browser.crx.exec('tabs.create', { url: relativeUrl })
const url = new URL(relativeUrl, browser.extension.url).href
expect(tabInfo).to.be.an('object')
expect(tabInfo.url).to.equal(url)
})
it('fails on chrome:// URLs', async () => {
const tabInfo = await browser.crx.exec('tabs.create', { url: 'chrome://kill' })
expect(tabInfo).to.be.a('null')
})
it('fails on javascript: URLs', async () => {
const tabInfo = browser.crx.exec('tabs.create', { url: "javascript:alert('hacked')" })
expect(await tabInfo).to.be.a('null')
})
})
describe('query()', () => {
it('gets the active tab', async () => {
const result = await browser.crx.exec('tabs.query', { active: true })
expect(result).to.be.an('array')
expect(result).to.be.length(1)
expect(result[0].id).to.be.equal(browser.window.webContents.id)
expect(result[0].windowId).to.be.equal(browser.window.id)
})
it('gets the active tab of multiple windows', async () => {
const secondWindow = new BrowserWindow({
show: false,
webPreferences: {
session: browser.session,
nodeIntegration: false,
contextIsolation: true,
},
})
browser.extensions.addTab(secondWindow.webContents, secondWindow)
const result = await browser.crx.exec('tabs.query', { active: true })
expect(result).to.be.an('array')
expect(result).to.be.length(2)
expect(result[0].windowId).to.be.equal(browser.window.id)
expect(result[1].windowId).to.be.equal(secondWindow.id)
})
it('matches exact title', async () => {
const results = await browser.crx.exec('tabs.query', { title: 'title' })
expect(results).to.be.an('array')
expect(results).to.be.length(1)
expect(results[0].title).to.be.equal('title')
})
it('matches title pattern', async () => {
const results = await browser.crx.exec('tabs.query', { title: '*' })
expect(results).to.be.an('array')
expect(results).to.be.length(1)
expect(results[0].title).to.be.equal('title')
})
it('matches exact url', async () => {
const url = server.getUrl()
const results = await browser.crx.exec('tabs.query', { url })
expect(results).to.be.an('array')
expect(results).to.be.length(1)
expect(results[0].url).to.be.equal(url)
})
it('matches wildcard url pattern', async () => {
const url = 'http://*/*'
const results = await browser.crx.exec('tabs.query', { url })
expect(results).to.be.an('array')
expect(results).to.be.length(1)
expect(results[0].url).to.be.equal(server.getUrl())
})
it('matches either url pattern', async () => {
const patterns = ['http://foo.bar/*', `${server.getUrl()}*`]
const results = await browser.crx.exec('tabs.query', { url: patterns })
expect(results).to.be.an('array')
expect(results).to.be.length(1)
expect(results[0].url).to.be.equal(server.getUrl())
})
})
describe('reload()', () => {
it('reloads the active tab', async () => {
const navigatePromise = emittedOnce(browser.window.webContents, 'did-navigate')
browser.crx.exec('tabs.reload')
await navigatePromise
})
it('reloads a specified tab', async () => {
const tabId = browser.window.webContents.id
const navigatePromise = emittedOnce(browser.window.webContents, 'did-navigate')
browser.crx.exec('tabs.reload', tabId)
await navigatePromise
})
})
describe('update()', () => {
it('navigates the tab', async () => {
const tabId = browser.window.webContents.id
const updateUrl = `${server.getUrl()}foo`
const navigatePromise = emittedOnce(browser.window.webContents, 'did-navigate')
browser.crx.exec('tabs.update', tabId, { url: updateUrl })
await navigatePromise
expect(browser.window.webContents.getURL()).to.equal(updateUrl)
})
it('navigates the active tab', async () => {
const updateUrl = `${server.getUrl()}foo`
const navigatePromise = emittedOnce(browser.window.webContents, 'did-navigate')
browser.crx.exec('tabs.update', { url: updateUrl })
await navigatePromise
expect(browser.window.webContents.getURL()).to.equal(updateUrl)
})
it('fails on chrome:// URLs', async () => {
const tabId = browser.webContents.id
const tabInfo = await browser.crx.exec('tabs.update', tabId, { url: 'chrome://kill' })
expect(tabInfo).to.be.a('null')
})
})
describe('goForward()', () => {
it('navigates the active tab forward', async () => {
const initialUrl = browser.window.webContents.getURL()
const targetUrl = `${server.getUrl()}foo`
await browser.window.webContents.loadURL(targetUrl)
expect(browser.window.webContents.navigationHistory.canGoBack()).to.be.true
browser.window.webContents.navigationHistory.goBack()
await emittedOnce(browser.window.webContents, 'did-navigate')
expect(browser.window.webContents.navigationHistory.canGoForward()).to.be.true
expect(browser.window.webContents.getURL()).to.equal(initialUrl)
const navigatePromise = emittedOnce(browser.window.webContents, 'did-navigate')
browser.crx.exec('tabs.goForward')
await navigatePromise
expect(browser.window.webContents.getURL()).to.equal(targetUrl)
})
it('navigates a specified tab forward', async () => {
const tabId = browser.window.webContents.id
const initialUrl = browser.window.webContents.getURL()
const targetUrl = `${server.getUrl()}foo`
await browser.window.webContents.loadURL(targetUrl)
expect(browser.window.webContents.navigationHistory.canGoBack()).to.be.true
browser.window.webContents.navigationHistory.goBack()
await emittedOnce(browser.window.webContents, 'did-navigate')
expect(browser.window.webContents.navigationHistory.canGoForward()).to.be.true
expect(browser.window.webContents.getURL()).to.equal(initialUrl)
const navigatePromise = emittedOnce(browser.window.webContents, 'did-navigate')
browser.crx.exec('tabs.goForward', tabId)
await navigatePromise
expect(browser.window.webContents.getURL()).to.equal(targetUrl)
})
})
describe('goBack()', () => {
it('navigates the active tab back', async () => {
const initialUrl = browser.window.webContents.getURL()
await browser.window.webContents.loadURL(`${server.getUrl()}foo`)
expect(browser.window.webContents.navigationHistory.canGoBack()).to.be.true
const navigatePromise = emittedOnce(browser.window.webContents, 'did-navigate')
browser.crx.exec('tabs.goBack')
await navigatePromise
expect(browser.window.webContents.getURL()).to.equal(initialUrl)
})
it('navigates a specified tab back', async () => {
const tabId = browser.window.webContents.id
const initialUrl = browser.window.webContents.getURL()
await browser.window.webContents.loadURL(`${server.getUrl()}foo`)
expect(browser.window.webContents.canGoBack()).to.be.true
const navigatePromise = emittedOnce(browser.window.webContents, 'did-navigate')
browser.crx.exec('tabs.goBack', tabId)
await navigatePromise
expect(browser.window.webContents.getURL()).to.equal(initialUrl)
})
})
describe('executeScript()', () => {
it('injects code into a tab', async () => {
const tabId = browser.window.webContents.id
const [result] = await browser.crx.exec('tabs.executeScript', tabId, {
code: 'location.href',
})
expect(result).to.equal(browser.window.webContents.getURL())
})
it('injects code into the active tab', async () => {
const [result] = await browser.crx.exec('tabs.executeScript', { code: 'location.href' })
expect(result).to.equal(browser.window.webContents.getURL())
})
})
describe('onCreated', () => {
it('emits when tab is added', async () => {
const p = browser.crx.eventOnce('tabs.onCreated')
const secondWindow = new BrowserWindow({
show: false,
webPreferences: {
session: browser.session,
nodeIntegration: false,
contextIsolation: true,
},
})
const secondTab = secondWindow.webContents
const url = `${server.getUrl()}foo`
await secondWindow.loadURL(url)
browser.extensions.addTab(secondTab, secondWindow)
const [tabDetails] = await p
expect(tabDetails).to.be.an('object')
expect(tabDetails.id).to.equal(secondTab.id)
expect(tabDetails.windowId).to.equal(secondWindow.id)
expect(tabDetails.url).to.equal(secondTab.getURL())
})
})
describe('onUpdated', () => {
it('emits on "tab-updated" event', async () => {
const p = browser.crx.eventOnce('tabs.onUpdated')
// Wait for tabs.onUpdated listener to be set
await new Promise((resolve) => setTimeout(resolve, 10))
assignTabDetails = (details) => {
details.discarded = true
}
browser.webContents.emit('tab-updated')
const [_tabId, changeInfo, _tabDetails] = await p
expect(changeInfo).to.be.an('object')
expect(Object.keys(changeInfo)).to.have.lengthOf(1)
expect(changeInfo).to.haveOwnProperty('discarded')
expect(changeInfo.discarded).to.equal(true)
})
})
})