Skip to content

Commit 43cdbf1

Browse files
committed
Improve coverage
1 parent 8764d82 commit 43cdbf1

File tree

16 files changed

+988
-203
lines changed

16 files changed

+988
-203
lines changed

examples/new/newtab/scripts.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
console.log('Hello from the new tab page!')
1+
console.log('Hello from the new tab page')
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import logo from '../images/logo.svg'
2+
3+
let unmount
4+
5+
if (import.meta.webpackHot) {
6+
import.meta.webpackHot?.accept()
7+
import.meta.webpackHot?.dispose(() => unmount?.())
8+
}
9+
10+
console.log('hello from content_scripts')
11+
12+
if (document.readyState === 'complete') {
13+
unmount = initial() || (() => {})
14+
} else {
15+
document.addEventListener('readystatechange', () => {
16+
if (document.readyState === 'complete') unmount = initial() || (() => {})
17+
})
18+
}
19+
20+
function initial() {
21+
const rootDiv = document.createElement('div')
22+
rootDiv.id = 'extension-root'
23+
document.body.appendChild(rootDiv)
24+
25+
// Injecting content_scripts inside a shadow dom
26+
// prevents conflicts with the host page's styles.
27+
// This way, styles from the extension won't leak into the host page.
28+
const shadowRoot = rootDiv.attachShadow({mode: 'open'})
29+
30+
const styleElement = document.createElement('style')
31+
shadowRoot.appendChild(styleElement)
32+
fetchCSS().then((response) => (styleElement.textContent = response))
33+
34+
if (import.meta.webpackHot) {
35+
import.meta.webpackHot?.accept('./styles.css', () => {
36+
fetchCSS().then((response) => (styleElement.textContent = response))
37+
})
38+
}
39+
40+
// Create container div
41+
const contentDiv = document.createElement('div')
42+
contentDiv.className = 'content_script'
43+
44+
// Create and append logo image
45+
const img = document.createElement('img')
46+
img.className = 'content_logo'
47+
img.src = logo
48+
contentDiv.appendChild(img)
49+
50+
// Create and append title
51+
const title = document.createElement('h1')
52+
title.className = 'content_title'
53+
title.textContent = 'Welcome to your Special Folders (Scripts) Extension'
54+
contentDiv.appendChild(title)
55+
56+
// Create and append description paragraph
57+
const desc = document.createElement('p')
58+
desc.className = 'content_description'
59+
desc.innerHTML = 'Learn more about creating cross-browser extensions at '
60+
61+
const link = document.createElement('a')
62+
63+
link.href = 'https://extension.js.org'
64+
link.target = '_blank'
65+
link.textContent = 'https://extension.js.org'
66+
67+
desc.appendChild(link)
68+
contentDiv.appendChild(desc)
69+
70+
// Append the content div to shadow root
71+
shadowRoot.appendChild(contentDiv)
72+
73+
return () => {
74+
rootDiv.remove()
75+
}
76+
}
77+
78+
async function fetchCSS() {
79+
const cssUrl = new URL('./styles.css', import.meta.url)
80+
const response = await fetch(cssUrl)
81+
const text = await response.text()
82+
return response.ok ? text : Promise.reject(text)
83+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
.content_script {
2+
color: #c9c9c9;
3+
background-color: #0a0c10;
4+
position: fixed;
5+
right: 0;
6+
bottom: 0;
7+
z-index: 9;
8+
width: 315px;
9+
margin: 1rem;
10+
padding: 2rem 1rem;
11+
display: flex;
12+
flex-direction: column;
13+
gap: 1em;
14+
border-radius: 6px;
15+
z-index: 9999;
16+
}
17+
18+
.content_logo {
19+
width: 72px;
20+
}
21+
22+
.content_title {
23+
font-size: 1.85em;
24+
line-height: 1.1;
25+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
26+
'Helvetica Neue', Arial, 'Noto Sans', sans-serif;
27+
font-weight: 700;
28+
margin: 0;
29+
}
30+
31+
.content_description {
32+
font-size: small;
33+
margin: 0;
34+
}
35+
36+
.content_description a {
37+
text-decoration: none;
38+
border-bottom: 2px solid #c9c9c9;
39+
color: #e5e7eb;
40+
margin: 0;
41+
}
Lines changed: 3 additions & 0 deletions
Loading

examples/special-folders-scripts/manifest.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,20 @@
77
"icons": {
88
"48": "images/extension_48.png"
99
},
10+
"content_scripts": [
11+
{
12+
"matches": ["<all_urls>"],
13+
"js": ["content/scripts.js"]
14+
}
15+
],
1016
"background": {
1117
"chromium:service_worker": "background.js",
1218
"firefox:scripts": ["background.js"]
1319
},
1420
"permissions": ["scripting", "webNavigation", "storage"],
1521
"host_permissions": ["https://extension.js.org/*"],
16-
"action": {}
22+
"action": {},
23+
"user_scripts": {
24+
"api_script": "user_scripts/api-script.js"
25+
}
1726
}
Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
{
2-
"private": true,
3-
"name": "special-folders-scripts",
4-
"description": "An Extension.js example.",
5-
"version": "0.0.1",
6-
"author": {
7-
"name": "Cezar Augusto",
8-
"email": "boss@cezaraugusto.net",
9-
"url": "https://cezaraugusto.com"
2+
"name": "scripts-plugin-test",
3+
"version": "1.0.0",
4+
"description": "Test fixture for ScriptsPlugin",
5+
"scripts": {
6+
"build": "extension.js build",
7+
"dev": "extension.js dev"
108
},
11-
"license": "MIT",
12-
"type": "module"
9+
"devDependencies": {
10+
"@extension.js/webpack-plugin": "workspace:*"
11+
}
1312
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
1+
// Included script with HMR
2+
if (module.hot) {
3+
module.hot.accept()
4+
}
5+
6+
console.log('Included script loaded')
7+
18
const text = `Your browser extension injected this script`
29
alert(text)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// User script with HMR
2+
if (module.hot) {
3+
module.hot.accept()
4+
}
5+
6+
console.log('User script loaded')
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest'
2+
import {AddScripts} from '../steps/add-scripts'
3+
import {type Compiler} from '@rspack/core'
4+
import * as fs from 'fs'
5+
import * as path from 'path'
6+
7+
// Mock fs module
8+
vi.mock('fs', () => ({
9+
readFileSync: vi.fn(),
10+
existsSync: vi.fn()
11+
}))
12+
13+
// Mock path module
14+
vi.mock('path', () => ({
15+
join: vi.fn(),
16+
dirname: vi.fn()
17+
}))
18+
19+
describe('AddScripts', () => {
20+
const mockManifestPath = '/path/to/manifest.json'
21+
const mockManifest = {
22+
content_scripts: [
23+
{
24+
matches: ['<all_urls>'],
25+
js: ['content.js']
26+
}
27+
],
28+
background: {
29+
service_worker: 'background.js'
30+
}
31+
}
32+
33+
beforeEach(() => {
34+
vi.clearAllMocks()
35+
// Mock process.exit to prevent test termination
36+
vi.spyOn(process, 'exit').mockImplementation((code) => {
37+
throw new Error(`process.exit called with code ${code}`)
38+
})
39+
vi.mocked(fs.existsSync).mockReturnValue(true)
40+
vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify(mockManifest))
41+
vi.mocked(path.dirname).mockReturnValue('/path/to')
42+
vi.mocked(path.join).mockImplementation((...args) => args.join('/'))
43+
})
44+
45+
afterEach(() => {
46+
vi.restoreAllMocks()
47+
})
48+
49+
it('should process content scripts from manifest', () => {
50+
const compiler = {
51+
options: {
52+
entry: {}
53+
}
54+
} as unknown as Compiler
55+
56+
const addScripts = new AddScripts({manifestPath: mockManifestPath})
57+
addScripts.apply(compiler)
58+
59+
expect(fs.existsSync).toHaveBeenCalledWith(mockManifestPath)
60+
expect(fs.readFileSync).toHaveBeenCalledWith(mockManifestPath, 'utf8')
61+
expect(compiler.options.entry).toHaveProperty('content_scripts/content-0')
62+
})
63+
64+
it('should process background service worker', () => {
65+
const compiler = {
66+
options: {
67+
entry: {}
68+
}
69+
} as unknown as Compiler
70+
71+
const addScripts = new AddScripts({manifestPath: mockManifestPath})
72+
addScripts.apply(compiler)
73+
74+
expect(fs.existsSync).toHaveBeenCalledWith(mockManifestPath)
75+
expect(fs.readFileSync).toHaveBeenCalledWith(mockManifestPath, 'utf8')
76+
expect(compiler.options.entry).toHaveProperty('background/service_worker')
77+
})
78+
})

0 commit comments

Comments
 (0)