Skip to content

Commit 0071b32

Browse files
authored
Update all templates to prepare for v2.0.0-rc.0 (#256)
1 parent 53b4f59 commit 0071b32

File tree

174 files changed

+4158
-648
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

174 files changed

+4158
-648
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,4 @@ __TEST__
6767
/playwright/.cache/
6868
/e2e-report/
6969
_examples
70-
specs/
70+
specs/

examples-v2/data.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {type Template} from './types'
2+
3+
const ALL_TEMPLATES: Template[] = [
4+
{
5+
name: 'javascript',
6+
uiContext: ['content'],
7+
uiFramework: undefined,
8+
css: 'css',
9+
hasBackground: false,
10+
hasEnv: false,
11+
configFiles: undefined
12+
},
13+
{
14+
name: 'typescript',
15+
uiContext: ['content'],
16+
uiFramework: undefined,
17+
css: 'css',
18+
hasBackground: false,
19+
hasEnv: false,
20+
configFiles: ['tsconfig.json']
21+
},
22+
{
23+
name: 'react',
24+
uiContext: ['content'],
25+
uiFramework: 'react',
26+
css: 'css',
27+
hasBackground: false,
28+
hasEnv: false,
29+
configFiles: ['postcss.config.js', 'tailwind.config.js', 'tsconfig.json']
30+
},
31+
{
32+
name: 'preact',
33+
uiContext: ['content'],
34+
uiFramework: 'preact',
35+
css: 'css',
36+
hasBackground: false,
37+
hasEnv: false,
38+
configFiles: ['postcss.config.js', 'tailwind.config.js', 'tsconfig.json']
39+
},
40+
{
41+
name: 'vue',
42+
uiContext: ['content'],
43+
uiFramework: 'vue',
44+
css: 'css',
45+
hasBackground: false,
46+
hasEnv: false,
47+
configFiles: ['postcss.config.js', 'tailwind.config.js', 'tsconfig.json']
48+
},
49+
{
50+
name: 'svelte',
51+
uiContext: ['content'],
52+
uiFramework: 'svelte',
53+
css: 'css',
54+
hasBackground: false,
55+
hasEnv: false,
56+
configFiles: ['postcss.config.js', 'tailwind.config.js', 'tsconfig.json']
57+
}
58+
]
59+
60+
const SUPPORTED_BROWSERS: string[] = ['chrome', 'edge', 'firefox']
61+
62+
export {SUPPORTED_BROWSERS, ALL_TEMPLATES}

examples-v2/extension-fixtures.mjs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import {
2+
test as base,
3+
chromium,
4+
} from '@playwright/test'
5+
6+
/**
7+
* @typedef {import('@playwright/test').BrowserContext} BrowserContext
8+
*/
9+
const extensionFixtures = (
10+
/** @type {string} */ pathToExtension,
11+
/** @type {boolean} */ headless
12+
/** @returns {import('@playwright/test').TestModifier<{}, {context: BrowserContext, extensionId: string}>} */
13+
) => {
14+
return base.extend({
15+
/** @type {() => Promise<BrowserContext>} */
16+
// eslint-disable-next-line no-empty-pattern
17+
context: async ({}, use) => {
18+
const context = await chromium.launchPersistentContext('', {
19+
headless: false,
20+
args: [
21+
headless ? `--headless=new` : '',
22+
`--disable-extensions-except=${pathToExtension}`,
23+
`--load-extension=${pathToExtension}`,
24+
'--no-first-run', // Disable Chrome's native first run experience.
25+
'--disable-client-side-phishing-detection', // Disables client-side phishing detection
26+
'--disable-component-extensions-with-background-pages', // Disable some built-in extensions that aren't affected by '--disable-extensions'
27+
'--disable-default-apps', // Disable installation of default apps
28+
'--disable-features=InterestFeedContentSuggestions', // Disables the Discover feed on NTP
29+
'--disable-features=Translate', // Disables Chrome translation, both the manual option and the popup prompt when a page with differing language is detected.
30+
'--hide-scrollbars', // Hide scrollbars from screenshots.
31+
'--mute-audio', // Mute any audio
32+
'--no-default-browser-check', // Disable the default browser check, do not prompt to set it as such
33+
'--no-first-run', // Skip first run wizards
34+
'--ash-no-nudges', // Avoids blue bubble "user education" nudges (eg., "… give your browser a new look", Memory Saver)
35+
'--disable-search-engine-choice-screen', // Disable the 2023+ search engine choice screen
36+
'--disable-features=MediaRoute', // Avoid the startup dialog for `Do you want the application “Chromium.app” to accept incoming network connections?`. Also disables the Chrome Media Router which creates background networking activity to discover cast targets. A superset of disabling DialMediaRouteProvider.
37+
'--use-mock-keychain', // Use mock keychain on Mac to prevent the blocking permissions dialog about "Chrome wants to use your confidential information stored in your keychain"
38+
'--disable-background-networking', // Disable various background network services, including extension updating, safe browsing service, upgrade detector, translate, UMA
39+
'--disable-breakpad', // Disable crashdump collection (reporting is already disabled in Chromium)
40+
'--disable-component-update', // Don't update the browser 'components' listed at chrome://components/
41+
'--disable-domain-reliability', // Disables Domain Reliability Monitoring, which tracks whether the browser has difficulty contacting Google-owned sites and uploads reports to Google.
42+
'--disable-features=AutofillServerCommunicatio', // Disables autofill server communication. This feature isn't disabled via other 'parent' flags.
43+
'--disable-features=CertificateTransparencyComponentUpdate',
44+
'--disable-sync', // Disable syncing to a Google account
45+
'--disable-features=OptimizationHints', // Used for turning on Breakpad crash reporting in a debug environment where crash reporting is typically compiled but disabled. Disable the Chrome Optimization Guide and networking with its service API
46+
'--disable-features=DialMediaRouteProvider', // A weaker form of disabling the MediaRouter feature. See that flag's details.
47+
'--no-pings', // Don't send hyperlink auditing pings
48+
'--enable-features=SidePanelUpdates' // Ensure the side panel is visible. This is used for testing the side panel feature.
49+
].filter((arg) => !!arg)
50+
})
51+
await use(context)
52+
await context.close()
53+
},
54+
/** @type {() => Promise<string>} */
55+
extensionId: async ({context}, use) => {
56+
/*
57+
// for manifest v2:
58+
let [background] = context.backgroundPages()
59+
if (!background)
60+
background = await context.waitForEvent('backgroundpage')
61+
*/
62+
63+
// for manifest v3:
64+
let [background] = context.serviceWorkers()
65+
if (!background) background = await context.waitForEvent('serviceworker')
66+
67+
const extensionId = background.url().split('/')[2]
68+
await use(extensionId)
69+
}
70+
})
71+
}
72+
73+
// Screenshot function
74+
async function takeScreenshot(page, screenshotPath) {
75+
await page.screenshot({path: screenshotPath})
76+
}
77+
78+
export {extensionFixtures, takeScreenshot}
79+
80+
/**
81+
* Utility to access elements inside the Shadow DOM.
82+
* @param page The Playwright Page object.
83+
* @param shadowHostSelector The selector for the Shadow DOM host element.
84+
* @param innerSelector The selector for the element inside the Shadow DOM.
85+
* @returns A Promise resolving to an ElementHandle for the inner element or null if not found.
86+
*/
87+
export async function getShadowRootElement(
88+
page,
89+
shadowHostSelector,
90+
innerSelector
91+
) {
92+
const shadowHost = page.locator(shadowHostSelector)
93+
const shadowRootHandle = await shadowHost.evaluateHandle(
94+
(host) => host.shadowRoot
95+
)
96+
97+
const innerElement = await shadowRootHandle.evaluateHandle(
98+
(shadowRoot, selector) =>
99+
shadowRoot.querySelector(selector),
100+
innerSelector
101+
)
102+
103+
return innerElement.asElement()
104+
}

examples-v2/extension-fixtures.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import {
2+
test as base,
3+
chromium,
4+
type Page,
5+
type BrowserContext,
6+
type ElementHandle
7+
} from '@playwright/test'
8+
9+
export const extensionFixtures = (
10+
pathToExtension: string,
11+
headless: boolean
12+
) => {
13+
return base.extend<{
14+
context: BrowserContext
15+
extensionId: string
16+
}>({
17+
context: async ({}, use) => {
18+
const context = await chromium.launchPersistentContext('', {
19+
headless: false,
20+
args: [
21+
headless ? `--headless=new` : '',
22+
`--disable-extensions-except=${pathToExtension}`,
23+
`--load-extension=${pathToExtension}`,
24+
'--no-first-run', // Disable Chrome's native first run experience.
25+
'--disable-client-side-phishing-detection', // Disables client-side phishing detection
26+
'--disable-component-extensions-with-background-pages', // Disable some built-in extensions that aren't affected by '--disable-extensions'
27+
'--disable-default-apps', // Disable installation of default apps
28+
'--disable-features=InterestFeedContentSuggestions', // Disables the Discover feed on NTP
29+
'--disable-features=Translate', // Disables Chrome translation, both the manual option and the popup prompt when a page with differing language is detected.
30+
'--hide-scrollbars', // Hide scrollbars from screenshots.
31+
'--mute-audio', // Mute any audio
32+
'--no-default-browser-check', // Disable the default browser check, do not prompt to set it as such
33+
'--no-first-run', // Skip first run wizards
34+
'--ash-no-nudges', // Avoids blue bubble "user education" nudges (eg., "… give your browser a new look", Memory Saver)
35+
'--disable-search-engine-choice-screen', // Disable the 2023+ search engine choice screen
36+
'--disable-features=MediaRoute', // Avoid the startup dialog for `Do you want the application “Chromium.app” to accept incoming network connections?`. Also disables the Chrome Media Router which creates background networking activity to discover cast targets. A superset of disabling DialMediaRouteProvider.
37+
'--use-mock-keychain', // Use mock keychain on Mac to prevent the blocking permissions dialog about "Chrome wants to use your confidential information stored in your keychain"
38+
'--disable-background-networking', // Disable various background network services, including extension updating, safe browsing service, upgrade detector, translate, UMA
39+
'--disable-breakpad', // Disable crashdump collection (reporting is already disabled in Chromium)
40+
'--disable-component-update', // Don't update the browser 'components' listed at chrome://components/
41+
'--disable-domain-reliability', // Disables Domain Reliability Monitoring, which tracks whether the browser has difficulty contacting Google-owned sites and uploads reports to Google.
42+
'--disable-features=AutofillServerCommunicatio', // Disables autofill server communication. This feature isn't disabled via other 'parent' flags.
43+
'--disable-features=CertificateTransparencyComponentUpdate',
44+
'--disable-sync', // Disable syncing to a Google account
45+
'--disable-features=OptimizationHints', // Used for turning on Breakpad crash reporting in a debug environment where crash reporting is typically compiled but disabled. Disable the Chrome Optimization Guide and networking with its service API
46+
'--disable-features=DialMediaRouteProvider', // A weaker form of disabling the MediaRouter feature. See that flag's details.
47+
'--no-pings', // Don't send hyperlink auditing pings
48+
'--enable-features=SidePanelUpdates' // Ensure the side panel is visible. This is used for testing the side panel feature.
49+
].filter((arg) => !!arg)
50+
})
51+
await use(context)
52+
await context.close()
53+
},
54+
extensionId: async ({context}, use) => {
55+
/*
56+
// for manifest v2:
57+
let [background] = context.backgroundPages()
58+
if (!background)
59+
background = await context.waitForEvent('backgroundpage')
60+
*/
61+
62+
// for manifest v3:
63+
let [background] = context.serviceWorkers()
64+
if (!background) background = await context.waitForEvent('serviceworker')
65+
66+
const extensionId = background.url().split('/')[2]
67+
await use(extensionId)
68+
}
69+
})
70+
}
71+
72+
// Screenshot function
73+
export async function takeScreenshot(page: any, screenshotPath: string) {
74+
await page.screenshot({path: screenshotPath})
75+
}
76+
77+
/**
78+
* Utility to access elements inside the Shadow DOM.
79+
* @param page The Playwright Page object.
80+
* @param shadowHostSelector The selector for the Shadow DOM host element.
81+
* @param innerSelector The selector for the element inside the Shadow DOM.
82+
* @returns A Promise resolving to an ElementHandle for the inner element or null if not found.
83+
*/
84+
export async function getShadowRootElement(
85+
page: Page,
86+
shadowHostSelector: string,
87+
innerSelector: string
88+
): Promise<ElementHandle<HTMLElement> | null> {
89+
// Wait for shadow host to be present first
90+
await page.waitForSelector(shadowHostSelector, {timeout: 15000})
91+
92+
// Get the shadow host element
93+
const shadowHost = await page.$(shadowHostSelector)
94+
if (!shadowHost) return null
95+
96+
// Get its shadow root
97+
const shadowRoot = await page.evaluateHandle(
98+
(host) => host.shadowRoot,
99+
shadowHost
100+
)
101+
if (!shadowRoot) return null
102+
103+
// Find element within shadow root
104+
const element = await page.evaluateHandle(
105+
(root) => root?.querySelector(innerSelector),
106+
shadowRoot
107+
)
108+
109+
return element.asElement() as ElementHandle<HTMLElement> | null
110+
}

examples-v2/javascript/.gitignore

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
node_modules
5+
6+
# testing
7+
coverage
8+
9+
# production
10+
dist
11+
12+
# misc
13+
.DS_Store
14+
15+
# local env files
16+
.env.local
17+
.env.development.local
18+
.env.test.local
19+
.env.production.local
20+
21+
# lock files
22+
yarn.lock
23+
package-lock.json
24+
25+
# debug files
26+
npm-debug.log*
27+
yarn-debug.log*
28+
yarn-error.log*
29+
30+
# extension.js
31+
extension-env.d.ts

examples-v2/javascript/background.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log('Hello from the background script!')
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import logo from '../images/logo.svg'
2+
3+
console.log('hello from content_scripts')
4+
5+
if (document.readyState === 'complete') {
6+
initial()
7+
} else {
8+
document.addEventListener('readystatechange', () => {
9+
if (document.readyState === 'complete') initial()
10+
})
11+
}
12+
13+
function initial() {
14+
const rootDiv = document.createElement('div')
15+
rootDiv.id = 'extension-root'
16+
document.body.appendChild(rootDiv)
17+
18+
// Injecting content_scripts inside a shadow dom
19+
// prevents conflicts with the host page's styles.
20+
// This way, styles from the extension won't leak into the host page.
21+
const shadowRoot = rootDiv.attachShadow({mode: 'open'})
22+
23+
// Inform Extension.js that the shadow root is available.
24+
window.__EXTENSION_SHADOW_ROOT__ = shadowRoot
25+
26+
shadowRoot.innerHTML = `
27+
<div class="content_script">
28+
<img class="content_logo" src="${logo}" />
29+
<h1 class="content_title">
30+
Welcome to your Content Script Extension
31+
</h1>
32+
<p class="content_description">
33+
Learn more about creating cross-browser extensions at <a
34+
className="underline hover:no-underline"
35+
href="https://extension.js.org"
36+
target="_blank"
37+
>
38+
https://extension.js.org
39+
</a>
40+
</p>
41+
</div>
42+
`
43+
}

0 commit comments

Comments
 (0)