chore: update changelog, bump versions and refine tests

This commit is contained in:
Tommy D. Rossi
2025-11-22 11:59:48 +01:00
parent d52d591155
commit 71c1c75359
7 changed files with 52 additions and 652 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "mcp-extension",
"version": "0.0.48",
"version": "0.0.49",
"description": "Playwright MCP Browser Extension",
"private": true,
"repository": {
+14
View File
@@ -1,5 +1,19 @@
# Changelog
## 0.0.9
### Patch Changes
- Added `tabs` permission to extension manifest to fix `chrome.tabs` access issues
- Implemented `toggleExtensionForActiveTab` global helper in extension background script
- Automated extension loading and toggling in MCP tests using `chromium.launchPersistentContext`
- Added comprehensive tests for extension lifecycle:
- Toggling extension on new and existing pages
- Verifying direct CDP connection to relay
- Handling Playwright connection before extension attachment
- Fixed `getCdpUrl` utility usage in tests
- Updated tests to use unique URLs for better debugging
## 0.0.8
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "playwriter",
"description": "",
"version": "0.0.8",
"version": "0.0.9",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
+24 -29
View File
@@ -2,15 +2,27 @@ import { createMCPClient } from './mcp-client.js'
import { describe, it, expect, beforeAll, afterAll } from 'vitest'
import { exec } from 'node:child_process'
import { promisify } from 'node:util'
import { chromium } from 'playwright-core'
import { chromium, BrowserContext } from 'playwright-core'
import path from 'node:path'
import fs from 'node:fs'
import os from 'node:os'
import { getCdpUrl } from './utils.js'
import { spawn } from 'node:child_process'
const execAsync = promisify(exec)
async function getExtensionServiceWorker(context: BrowserContext) {
let serviceWorker = context.serviceWorkers().find(sw => sw.url().startsWith('chrome-extension://'))
if (!serviceWorker) {
serviceWorker = await context.waitForEvent('serviceworker', {
predicate: (sw) => sw.url().startsWith('chrome-extension://')
})
}
return serviceWorker
}
function js(strings: TemplateStringsArray, ...values: any[]): string {
return strings.reduce(
(result, str, i) => result + str + (values[i] || ''),
@@ -52,7 +64,7 @@ describe('MCP Server Tests', () => {
cwd: process.cwd(),
stdio: 'inherit'
})
// Wait for port 19988 to be ready
await new Promise<void>((resolve, reject) => {
let retries = 0
@@ -73,7 +85,7 @@ describe('MCP Server Tests', () => {
}
}, 1000)
})
const result = await createMCPClient()
client = result.client
cleanup = result.cleanup
@@ -98,7 +110,7 @@ describe('MCP Server Tests', () => {
// Create a page to attach to
const page = await browserContext.newPage()
await page.goto('about:blank')
// Connect the tab
await serviceWorker.evaluate(async () => {
// @ts-ignore
@@ -115,7 +127,7 @@ describe('MCP Server Tests', () => {
relayServerProcess.kill()
}
await killProcessOnPort(19988)
if (userDataDir) {
try {
fs.rmSync(userDataDir, { recursive: true, force: true })
@@ -264,21 +276,15 @@ describe('MCP Server Tests', () => {
if (!browserContext) throw new Error('Browser not initialized')
// Find the correct service worker by URL
const extensionPath = path.resolve('../extension/dist')
let serviceWorker = browserContext.serviceWorkers().find(sw => sw.url().startsWith('chrome-extension://'))
if (!serviceWorker) {
serviceWorker = await browserContext.waitForEvent('serviceworker', {
predicate: (sw) => sw.url().startsWith('chrome-extension://')
})
}
const serviceWorker = await getExtensionServiceWorker(browserContext)
// 1. Create a new page
const page = await browserContext.newPage()
const testUrl = 'https://example.com/'
const testUrl = 'https://example.com/toggling'
await page.goto(testUrl)
await page.bringToFront()
// 2. Enable extension on this new tab
// Since it's a new page, extension is not connected yet
const result = await serviceWorker.evaluate(async () => {
@@ -288,8 +294,7 @@ describe('MCP Server Tests', () => {
expect(result.isConnected).toBe(true)
// 3. Verify we can connect via direct CDP and see the page
const randomId = Math.random().toString(36).substring(7)
const cdpUrl = `ws://localhost:19988/cdp/${randomId}`
const cdpUrl = getCdpUrl()
let directBrowser = await chromium.connectOverCDP(cdpUrl)
let contexts = directBrowser.contexts()
let pages = contexts[0].pages()
@@ -310,23 +315,15 @@ describe('MCP Server Tests', () => {
// 5. Try to connect/use the page.
// connecting to relay will succeed, but listing pages should NOT show our page
// OR if we try to send command to the previous targetId (via session), it should fail
// Connect to relay again
directBrowser = await chromium.connectOverCDP(cdpUrl)
contexts = directBrowser.contexts()
pages = contexts[0].pages() // this calls Target.getTargets internally via contexts() or pages()?
// Actually contexts() just returns what it knows.
// If relay sent detachedFromTarget, the page should be gone from the context.
pages = contexts[0].pages()
foundPage = pages.find(p => p.url() === testUrl)
expect(foundPage).toBeUndefined()
// Also try to send a command to the old target ID if possible?
// Hard to do with high-level Playwright API on the browser object.
// We can try to use a raw CDPSession on the browser target if we knew how to route it.
// But checking it's gone is good enough for "connection disabled".
await directBrowser.close()
// 6. Re-enable extension
@@ -337,9 +334,6 @@ describe('MCP Server Tests', () => {
expect(resultEnabled.isConnected).toBe(true)
// 7. Verify page is back
// Note: targetId might have changed! Fetch it again just in case, or rely on relay to update routing.
// But relay routing is based on `sessionId`. New session ID generated on attach.
// The URL path param `targetId` is just a label.
directBrowser = await chromium.connectOverCDP(cdpUrl)
// Wait a bit for targets to populate
@@ -359,6 +353,7 @@ describe('MCP Server Tests', () => {
await directBrowser.close()
await page.close()
})
})
function tryJsonParse(str: string) {
try {
+1 -1
View File
@@ -383,7 +383,7 @@ server.tool(
responseText += 'Code executed successfully (no output)'
}
const MAX_LENGTH = 1000
const MAX_LENGTH = 5000
let finalText = responseText.trim()
if (finalText.length > MAX_LENGTH) {
finalText = finalText.slice(0, MAX_LENGTH) + `\n\n[Truncated to ${MAX_LENGTH} characters. Better manage your logs or paginate them to read the full logs]`
@@ -1,318 +1,23 @@
Return value:
- table [ref=e3]:
- rowgroup [ref=e4]:
- row "Hacker Newsnew | threads | past | comments | ask | show | jobs | submit xmorse (70) | logout" [ref=e5]:
- cell "Hacker Newsnew | threads | past | comments | ask | show | jobs | submit xmorse (70) | logout" [ref=e6]:
- row "Hacker Newsnew | past | comments | ask | show | jobs | submit login" [ref=e5]:
- cell "Hacker Newsnew | past | comments | ask | show | jobs | submit login" [ref=e6]:
- table [ref=e7]:
- rowgroup [ref=e8]:
- row "Hacker Newsnew | threads | past | comments | ask | show | jobs | submit xmorse (70) | logout" [ref=e9]:
- row "Hacker Newsnew | past | comments | ask | show | jobs | submit login" [ref=e9]:
- cell [ref=e10]:
- link [ref=e11] [cursor=pointer]:
- /url: https://news.ycombinator.com
- img [ref=e12]
- cell "Hacker Newsnew | threads | past | comments | ask | show | jobs | submit" [ref=e13]:
- cell "Hacker Newsnew | past | comments | ask | show | jobs | submit" [ref=e13]:
- generic [ref=e14]:
- link "Hacker News" [ref=e16] [cursor=pointer]:
- /url: news
- link "new" [ref=e17] [cursor=pointer]:
- /url: newest
- text: "|"
- link "threads" [ref=e18] [cursor=pointer]:
- /url: threads?id=xmorse
- text: "|"
- link "past" [ref=e19] [cursor=pointer]:
- /url: front
- text: "|"
- link "comments" [ref=e20] [cursor=pointer]:
- /url: newcomments
- text: "|"
- link "ask" [ref=e21] [cursor=pointer]:
- /url: ask
- text: "|"
- link "show" [ref=e22] [cursor=pointer]:
- /url: show
- text: "|"
- link "jobs" [ref=e23] [cursor=pointer]:
- /url: jobs
- text: "|"
- link "submit" [ref=e24] [cursor=pointer]:
- /url: submit
- cell "xmorse (70) | logout" [ref=e25]:
- generic [ref=e26]:
- link "xmorse" [ref=e27] [cursor=pointer]:
- /url: user?id=xmorse
- text: (70) |
- link "logout" [ref=e28] [cursor=pointer]:
- /url: logout?auth=227f860372905c327e92615af914e1e41ec43fff&goto=item%3Fid%3D1
- row [ref=e29]
- row [ref=e30]:
- cell [ref=e31]:
- table [ref=e32]:
- rowgroup [ref=e33]:
- row "upvote Y Combinator (ycombinator.com)" [ref=e34]:
- cell [ref=e35]
- cell "upvote" [ref=e36]:
- link "upvote" [ref=e38] [cursor=pointer]:
- /url: vote?id=1&how=up&auth=e52b391ec392eb381ace51126fd80e19d48c1d7b&goto=item%3Fid%3D1
- generic "upvote" [ref=e39]
- cell "Y Combinator (ycombinator.com)" [ref=e40]:
- generic [ref=e41]:
- link "Y Combinator" [ref=e42] [cursor=pointer]:
- /url: http://ycombinator.com
- generic [ref=e43]:
- text: (
- link "ycombinator.com" [ref=e44] [cursor=pointer]:
- /url: from?site=ycombinator.com
- text: )
- row "57 points by pg on Oct 9, 2006 | hide | past | favorite | 16 comments" [ref=e45]:
- cell [ref=e46]
- cell "57 points by pg on Oct 9, 2006 | hide | past | favorite | 16 comments" [ref=e47]:
- generic [ref=e48]:
- text: 57 points by
- link "pg" [ref=e49] [cursor=pointer]:
- /url: user?id=pg
- generic "2006-10-09T18:21:51 1160418111" [ref=e50]:
- link "on Oct 9, 2006" [ref=e51] [cursor=pointer]:
- /url: item?id=1
- text: "|"
- link "hide" [ref=e52] [cursor=pointer]:
- /url: hide?id=1&auth=e52b391ec392eb381ace51126fd80e19d48c1d7b&goto=item%3Fid%3D1
- text: "|"
- link "past" [ref=e53] [cursor=pointer]:
- /url: https://hn.algolia.com/?query=Y%20Combinator&type=story&dateRange=all&sort=byDate&storyText=false&prefix&page=0
- text: "|"
- link "favorite" [ref=e54] [cursor=pointer]:
- /url: fave?id=1&auth=e52b391ec392eb381ace51126fd80e19d48c1d7b
- text: "|"
- link "16 comments" [ref=e55] [cursor=pointer]:
- /url: item?id=1
- row [ref=e56]:
- cell [ref=e57]
- cell [ref=e58]
- table [ref=e59]:
- rowgroup [ref=e60]:
- row "upvote sama on Oct 9, 2006 | [] \"the rising star of venture capital\" -unknown VC eating lunch on SHR" [ref=e61]:
- cell "upvote sama on Oct 9, 2006 | [] \"the rising star of venture capital\" -unknown VC eating lunch on SHR" [ref=e62]:
- table [ref=e63]:
- rowgroup [ref=e64]:
- row "upvote sama on Oct 9, 2006 | [] \"the rising star of venture capital\" -unknown VC eating lunch on SHR" [ref=e65]:
- cell [ref=e66]:
- img
- cell "upvote" [ref=e67]:
- link "upvote" [ref=e69] [cursor=pointer]:
- /url: vote?id=15&how=up&auth=709295bd69cc8638fcf14a7b807bb0efabd69a2d&goto=item%3Fid%3D1#15
- generic "upvote" [ref=e70]
- cell "sama on Oct 9, 2006 | [] \"the rising star of venture capital\" -unknown VC eating lunch on SHR" [ref=e71]:
- generic [ref=e73]:
- link "sama" [ref=e74] [cursor=pointer]:
- /url: user?id=sama
- generic "2006-10-09T19:51:01 1160423461" [ref=e75]:
- link "on Oct 9, 2006" [ref=e76] [cursor=pointer]:
- /url: item?id=15
- generic [ref=e77]:
- text: "|"
- link [ref=e78] [cursor=pointer]:
- /url: "#487171"
- text: next
- link "[]" [ref=e79] [cursor=pointer]:
- /url: javascript:void(0)
- generic [ref=e80]:
- generic [ref=e81]: "\"the rising star of venture capital\" -unknown VC eating lunch on SHR"
- generic:
- paragraph
- row "upvote pg on Oct 9, 2006 | | [] Is there anywhere to eat on Sandhill Road?" [ref=e82]:
- cell "upvote pg on Oct 9, 2006 | | [] Is there anywhere to eat on Sandhill Road?" [ref=e83]:
- table [ref=e84]:
- rowgroup [ref=e85]:
- row "upvote pg on Oct 9, 2006 | | [] Is there anywhere to eat on Sandhill Road?" [ref=e86]:
- cell [ref=e87]:
- img [ref=e88]
- cell "upvote" [ref=e89]:
- link "upvote" [ref=e91] [cursor=pointer]:
- /url: vote?id=17&how=up&auth=3c24b126f8f812f8c3a24a0b9143eac42ca15476&goto=item%3Fid%3D1#17
- generic "upvote" [ref=e92]
- cell "pg on Oct 9, 2006 | | [] Is there anywhere to eat on Sandhill Road?" [ref=e93]:
- generic [ref=e95]:
- link "pg" [ref=e96] [cursor=pointer]:
- /url: user?id=pg
- generic "2006-10-09T19:52:45 1160423565" [ref=e97]:
- link "on Oct 9, 2006" [ref=e98] [cursor=pointer]:
- /url: item?id=17
- generic [ref=e99]:
- text: "|"
- link [ref=e100] [cursor=pointer]:
- /url: "#15"
- text: parent
- text: "|"
- link [ref=e101] [cursor=pointer]:
- /url: "#487171"
- text: next
- link "[]" [ref=e102] [cursor=pointer]:
- /url: javascript:void(0)
- generic [ref=e103]:
- generic [ref=e104]: Is there anywhere to eat on Sandhill Road?
- generic:
- paragraph
- row "upvote dmon on Feb 25, 2007 | | | [] sure" [ref=e105]:
- cell "upvote dmon on Feb 25, 2007 | | | [] sure" [ref=e106]:
- table [ref=e107]:
- rowgroup [ref=e108]:
- row "upvote dmon on Feb 25, 2007 | | | [] sure" [ref=e109]:
- cell [ref=e110]:
- img [ref=e111]
- cell "upvote" [ref=e112]:
- link "upvote" [ref=e114] [cursor=pointer]:
- /url: vote?id=1079&how=up&auth=851f0b1e178c46300e9d2218764827726415a50d&goto=item%3Fid%3D1#1079
- generic "upvote" [ref=e115]
- cell "dmon on Feb 25, 2007 | | | [] sure" [ref=e116]:
- generic [ref=e118]:
- link "dmon" [ref=e119] [cursor=pointer]:
- /url: user?id=dmon
- generic "2007-02-25T22:18:23 1172441903" [ref=e120]:
- link "on Feb 25, 2007" [ref=e121] [cursor=pointer]:
- /url: item?id=1079
- generic [ref=e122]:
- text: "|"
- link [ref=e123] [cursor=pointer]:
- /url: "#15"
- text: root
- text: "|"
- link [ref=e124] [cursor=pointer]:
- /url: "#17"
- text: parent
- text: "|"
- link [ref=e125] [cursor=pointer]:
- /url: "#487171"
- text: next
- link "[]" [ref=e126] [cursor=pointer]:
- /url: javascript:void(0)
- generic [ref=e127]:
- generic [ref=e128]: sure
- generic:
- paragraph
- row "jacquesm on Feb 19, 2009 [dead] | | [] So, just to see how hard it is to make the longest span between article and comment :) Congratulations on your second birthday YC, and thanks to Paul Graham for writing this forum. I had a really good look at the good a few days ago and I was quite impressed with how elegant the whole thing is put together. Lisp would not be my language of choice for a website like this, and yet, after seeing how concise it was I'm tempted to play around with lisp in a web environment." [ref=e129]:
- cell "jacquesm on Feb 19, 2009 [dead] | | [] So, just to see how hard it is to make the longest span between article and comment :) Congratulations on your second birthday YC, and thanks to Paul Graham for writing this forum. I had a really good look at the good a few days ago and I was quite impressed with how elegant the whole thing is put together. Lisp would not be my language of choice for a website like this, and yet, after seeing how concise it was I'm tempted to play around with lisp in a web environment." [ref=e130]:
- table [ref=e131]:
- rowgroup [ref=e132]:
- row "jacquesm on Feb 19, 2009 [dead] | | [] So, just to see how hard it is to make the longest span between article and comment :) Congratulations on your second birthday YC, and thanks to Paul Graham for writing this forum. I had a really good look at the good a few days ago and I was quite impressed with how elegant the whole thing is put together. Lisp would not be my language of choice for a website like this, and yet, after seeing how concise it was I'm tempted to play around with lisp in a web environment." [ref=e133]:
- cell [ref=e134]:
- img
- cell [ref=e135]:
- img [ref=e137]
- cell "jacquesm on Feb 19, 2009 [dead] | | [] So, just to see how hard it is to make the longest span between article and comment :) Congratulations on your second birthday YC, and thanks to Paul Graham for writing this forum. I had a really good look at the good a few days ago and I was quite impressed with how elegant the whole thing is put together. Lisp would not be my language of choice for a website like this, and yet, after seeing how concise it was I'm tempted to play around with lisp in a web environment." [ref=e138]:
- generic [ref=e140]:
- link "jacquesm" [ref=e141] [cursor=pointer]:
- /url: user?id=jacquesm
- generic "2009-02-19T12:21:23 1235046083" [ref=e142]:
- link "on Feb 19, 2009" [ref=e143] [cursor=pointer]:
- /url: item?id=487171
- text: "[dead]"
- generic [ref=e144]:
- text: "|"
- link [ref=e145] [cursor=pointer]:
- /url: "#15"
- text: prev
- text: "|"
- link [ref=e146] [cursor=pointer]:
- /url: "#234509"
- text: next
- link "[]" [ref=e147] [cursor=pointer]:
- /url: javascript:void(0)
- generic [ref=e148]:
- generic [ref=e149]:
- text: So, just to see how hard it is to make the longest span between article and comment :)
- paragraph [ref=e150]: Congratulations on your second birthday YC, and thanks to Paul Graham for writing this forum. I had a really good look at the good a few days ago and I was quite impressed with how elegant the whole thing is put together.
- paragraph [ref=e151]: Lisp would not be my language of choice for a website like this, and yet, after seeing how concise it was I'm tempted to play around with lisp in a web environment.
- generic:
- paragraph
- row "kleevr on July 2, 2008 [dead] | | [11 more]" [ref=e152]:
- cell "kleevr on July 2, 2008 [dead] | | [11 more]" [ref=e153]:
- table [ref=e154]:
- rowgroup [ref=e155]:
- row "kleevr on July 2, 2008 [dead] | | [11 more]" [ref=e156]:
- cell [ref=e157]:
- img
- cell "kleevr on July 2, 2008 [dead] | | [11 more]" [ref=e158]:
- generic [ref=e160]:
- link "kleevr" [ref=e161] [cursor=pointer]:
- /url: user?id=kleevr
- generic "2008-07-02T20:29:48 1215030588" [ref=e162]:
- link "on July 2, 2008" [ref=e163] [cursor=pointer]:
- /url: item?id=234509
- text: "[dead]"
- generic [ref=e164]:
- text: "|"
- link [ref=e165] [cursor=pointer]:
- /url: "#487171"
- text: prev
- text: "|"
- link [ref=e166] [cursor=pointer]:
- /url: "#82729"
- text: next
- link "[11 more]" [ref=e167] [cursor=pointer]:
- /url: javascript:void(0)
- row "vice on Nov 22, 2007 [dead] | [] I'm nX 1 too ;)" [ref=e168]:
- cell "vice on Nov 22, 2007 [dead] | [] I'm nX 1 too ;)" [ref=e169]:
- table [ref=e170]:
- rowgroup [ref=e171]:
- row "vice on Nov 22, 2007 [dead] | [] I'm nX 1 too ;)" [ref=e172]:
- cell [ref=e173]:
- img
- cell [ref=e174]:
- img [ref=e176]
- cell "vice on Nov 22, 2007 [dead] | [] I'm nX 1 too ;)" [ref=e177]:
- generic [ref=e179]:
- link "vice" [ref=e180] [cursor=pointer]:
- /url: user?id=vice
- generic "2007-11-22T12:50:54 1195735854" [ref=e181]:
- link "on Nov 22, 2007" [ref=e182] [cursor=pointer]:
- /url: item?id=82729
- text: "[dead]"
- generic [ref=e183]:
- text: "|"
- link [ref=e184] [cursor=pointer]:
- /url: "#234509"
- text: prev
- link "[]" [ref=e185] [cursor=pointer]:
- /url: javascript:void(0)
- generic [ref=e186]:
- generic [ref=e187]:
- text: I'm nX 1 too
- paragraph [ref=e188]: ;)
- generic:
- paragraph
- row "Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact Search:" [ref=e189]:
- cell "Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact Search:" [ref=e190]:
- img
- table [ref=e191]:
- rowgroup [ref=e192]:
- row [ref=e193]:
- cell [ref=e194]
- generic [ref=e195]:
- generic [ref=e196]:
- link "Guidelines" [ref=e197] [cursor=pointer]:
- /url: newsguidelines.html
- text: "|"
- link "FAQ" [ref=e198] [cursor=pointer]:
- /url: newsfaq.html
- text: "|"
- link "Lists" [ref=e199] [cursor=pointer]:
- /url: lists
- text: "|"
- link "API" [ref=e200] [cursor=pointer]:
- /url: https://github.com/HackerNews/API
- text: "|"
- link "Security" [ref=e201] [cursor=pointer]:
- /url: security.html
- text: "|"
- link "Legal" [ref=e202] [cursor=pointer]:
- /url: https://www.ycombinator.com/legal/
- text: "|"
- link "Apply to YC" [ref=e203] [cursor=pointer]:
- /url: https://www.ycombinator.com/apply/
- text: "|"
- link "Contact" [ref=e204] [cursor=pointer]:
- /url: mailto:hn@ycombinator.com
- generic [ref=e205]:
- text: "Search:"
- textbox [ref=e206]
- link "past" [ref=e18] [cursor=pointer]:
[Truncated to 1000 characters. Better manage your logs or paginate them to read the full logs]
@@ -24,320 +24,6 @@ Return value:
- /url: /colors
- generic [ref=e16]:
- button "Search documentation... ⌘ K" [ref=e18]:
- generic [ref=e19]: Search documentation...
- generic [ref=e21]:
- generic: ⌘
- generic: K
- link "99.8k" [ref=e22] [cursor=pointer]:
- /url: https://github.com/shadcn-ui/ui
- img
- generic [ref=e23]: 99.8k
- button "Toggle layout" [ref=e24]:
- generic [ref=e25]: Toggle layout
- img
- button "Toggle theme" [ref=e26]:
- img
- generic [ref=e27]: Toggle theme
- main [ref=e28]:
- generic [ref=e29]:
- generic [ref=e32]:
- 'link "New New Components: Field, Input Group, Item and more" [ref=e33] [cursor=pointer]':
- /url: /docs/changelog
- generic "New" [ref=e34]
- text: "New Components: Field, Input Group, Item and more"
- img
- heading "The Foundation for your Design System" [level=1] [ref=e35]
- paragraph [ref=e36]: A set of beautifully designed components that you can customize, extend, and build on. Start here then make it your own. Open Source. Open Code.
- generic [ref=e37]:
- link "Get Started" [ref=e38] [cursor=pointer]:
- /url: /docs/installation
- link "View Components" [ref=e39] [cursor=pointer]:
- /url: /docs/components
- generic [ref=e41]:
- generic [ref=e46]:
- link "Examples" [ref=e47] [cursor=pointer]:
- /url: /
- link "Dashboard" [ref=e48] [cursor=pointer]:
- /url: /examples/dashboard
- link "Tasks" [ref=e49] [cursor=pointer]:
- /url: /examples/tasks
- link "Playground" [ref=e50] [cursor=pointer]:
- /url: /examples/playground
- link "Authentication" [ref=e51] [cursor=pointer]:
- /url: /examples/authentication
- generic [ref=e52]:
- generic [ref=e53]: Theme
- combobox "Theme" [ref=e54]:
- generic [ref=e55]: "Theme:"
- generic: Neutral
- img
- button "Copy Code" [ref=e56]:
- img
- generic [ref=e57]: Copy Code
- generic [ref=e61]:
- generic [ref=e65]:
- group "Payment Method" [ref=e66]:
- generic [ref=e67]: Payment Method
- paragraph [ref=e68]: All transactions are secure and encrypted
- generic [ref=e69]:
- group [ref=e70]:
- generic [ref=e71]: Name on Card
- textbox "Name on Card" [ref=e72]:
- /placeholder: John Doe
- generic [ref=e73]:
- group [ref=e74]:
- generic [ref=e75]: Card Number
- textbox "Card Number" [ref=e76]:
- /placeholder: 1234 5678 9012 3456
- paragraph [ref=e77]: Enter your 16-digit number.
- group [ref=e78]:
- generic [ref=e79]: CVV
- textbox "CVV" [ref=e80]:
- /placeholder: "123"
- generic [ref=e81]:
- group [ref=e82]:
- generic [ref=e83]: Month
- combobox "Month" [ref=e84]:
- generic: MM
- img
- combobox [ref=e85]
- group [ref=e86]:
- generic [ref=e87]: Year
- combobox "Year" [ref=e88]:
- generic: YYYY
- img
- combobox [ref=e89]
- group "Billing Address" [ref=e91]:
- generic [ref=e92]: Billing Address
- paragraph [ref=e93]: The billing address associated with your payment method
- group [ref=e95]:
- checkbox "Same as shipping address" [checked] [ref=e96]:
- generic:
- img
- checkbox [checked]
- generic [ref=e97]: Same as shipping address
- group [ref=e99]:
- group [ref=e101]:
- generic [ref=e102]: Comments
- textbox "Comments" [ref=e103]:
- /placeholder: Add any additional comments
- group [ref=e104]:
- button "Submit" [ref=e105]
- button "Cancel" [ref=e106]
- generic [ref=e107]:
- generic [ref=e108]:
- generic [ref=e109]:
- generic [ref=e111]:
- img "@shadcn" [ref=e113]
- img "@maxleiter" [ref=e115]
- img "@evilrabbit" [ref=e117]
- generic [ref=e118]: No Team Members
- generic [ref=e119]: Invite your team to collaborate on this project.
- button "Invite Members" [ref=e121]:
- img
- text: Invite Members
- generic [ref=e122]:
- generic [ref=e123]:
- status "Loading"
- text: Syncing
- generic [ref=e124]:
- status "Loading"
- text: Updating
- generic [ref=e125]:
- status "Loading"
- text: Loading
- group [ref=e126]:
- group [ref=e127]:
- button "Add" [ref=e128]:
- img
- group [ref=e129]:
- group [ref=e130]:
- textbox "Send a message..." [ref=e131]
- group [ref=e132]:
- button "Voice Mode" [ref=e133]:
- img
- group [ref=e135]:
- generic [ref=e136]: Price Range
- paragraph [ref=e137]: Set your budget range ($200 - 800).
- generic "Price Range" [ref=e138]:
- slider "Minimum" [ref=e142]
- slider "Maximum" [ref=e144]
- generic [ref=e145]:
- group [ref=e146]:
- textbox "Search..." [ref=e147]
- group [ref=e148]:
- img [ref=e149]
- group [ref=e152]: 12 results
- group [ref=e153]:
- textbox "example.com" [ref=e154]
- group [ref=e155]:
- generic [ref=e156]: https://
- group [ref=e157]:
- button "Info" [ref=e158]:
- img
- group [ref=e159]:
- textbox "Ask, Search or Chat..." [ref=e160]
- group [ref=e161]:
- button "Add" [ref=e162]:
- img
- button "Auto" [ref=e163]
- generic [ref=e164]: 52% used
- button "Send" [ref=e165]:
- img
- generic [ref=e166]: Send
- group [ref=e167]:
- textbox "@shadcn" [ref=e168]
- group [ref=e169]:
- img [ref=e171]
- generic [ref=e173]:
- generic [ref=e174]:
- generic [ref=e175]: Input Secure
- group [ref=e176]:
- textbox "Input Secure" [ref=e177]
- group [ref=e178]:
- button "Info" [ref=e179]:
- img
- group [ref=e180]: https://
- group [ref=e181]:
- button "Favorite" [ref=e182]:
- img
- generic [ref=e183]:
- generic [ref=e184]:
- generic [ref=e185]:
- generic [ref=e186]: Two-factor authentication
- paragraph [ref=e187]: Verify via email or phone number.
- button "Enable" [ref=e189]
- link "Your profile has been verified." [ref=e190] [cursor=pointer]:
- /url: "#"
- generic [ref=e191]:
- img
- generic [ref=e193]: Your profile has been verified.
- img [ref=e195]
- generic [ref=e198]: Appearance Settings
- group [ref=e199]:
- generic [ref=e200]:
- group "Compute Environment" [ref=e201]:
- generic [ref=e202]: Compute Environment
- paragraph [ref=e203]: Select the compute environment for your cluster.
- radiogroup [ref=e204]:
- group [ref=e206]:
- generic [ref=e207]:
- generic [ref=e208]: Kubernetes
- paragraph [ref=e209]: Run GPU workloads on a K8s configured cluster. This is the default.
- radio "Kubernetes" [checked] [ref=e210]:
- img [ref=e211]
- group [ref=e214]:
- generic [ref=e215]:
- generic [ref=e216]: Virtual Machine
- paragraph [ref=e217]: Access a VM configured cluster to run workloads. (Coming soon)
- radio "Virtual Machine" [ref=e218]
- group [ref=e220]:
- generic [ref=e221]:
- generic [ref=e222]: Number of GPUs
- paragraph [ref=e223]: You can add more later.
- group [ref=e224]:
- textbox "Number of GPUs" [ref=e225]: "8"
- button "Decrement" [ref=e226]:
- img
- button "Increment" [ref=e227]:
- img
- group [ref=e229]:
- generic [ref=e230]:
- generic [ref=e231]: Wallpaper Tinting
- paragraph [ref=e232]: Allow the wallpaper to be tinted.
- switch "Wallpaper Tinting" [checked] [ref=e233]
- generic [ref=e234]:
- group [ref=e236]:
- generic [ref=e237]: Prompt
- group [ref=e238]:
- textbox "Prompt" [ref=e239]:
- /placeholder: Ask, search, or make anything...
- group [ref=e240]:
- button "Add context" [ref=e241]:
- img
- text: Add context
- group [ref=e243]:
- button "Attach file" [ref=e244]:
- img
- button "Auto" [ref=e245]
- button "All Sources" [ref=e246]:
- img
- text: All Sources
- button "Send" [ref=e247]:
- img
- group [ref=e248]:
- group [ref=e249]:
- button "Go Back" [ref=e250]:
- img
- group [ref=e251]:
- button "Archive" [ref=e252]
- button "Report" [ref=e253]
- group [ref=e254]:
- button "Snooze" [ref=e255]
- button "More Options" [ref=e256]:
- img
- group [ref=e258]:
- checkbox "I agree to the terms and conditions" [checked] [ref=e259]:
- generic:
- img
- generic [ref=e260]: I agree to the terms and conditions
- generic [ref=e261]:
- group [ref=e262]:
- group [ref=e263]:
- button "1" [ref=e264]
- button "2" [ref=e265]
- button "3" [ref=e266]
- group [ref=e267]:
- button "Previous" [ref=e268]:
- img
- button "Next" [ref=e269]:
- img
- group [ref=e270]:
- button "Copilot" [ref=e271]:
- img
- text: Copilot
- button "Open Popover" [ref=e272]:
- img
- group "How did you hear about us?" [ref=e277]:
- generic [ref=e278]: How did you hear about us?
- paragraph [ref=e279]: Select the option that best describes how you heard about us.
- generic [ref=e280]:
- group [ref=e282]:
- checkbox "Social Media" [checked] [ref=e283]:
- generic:
- img
- checkbox [checked]
- generic [ref=e284]: Social Media
- group [ref=e286]:
- checkbox "Search Engine" [ref=e287]
- checkbox
- generic [ref=e288]: Search Engine
- group [ref=e290]:
- checkbox "Referral" [ref=e291]
- checkbox
- generic [ref=e292]: Referral
- group [ref=e294]:
- checkbox "Other" [ref=e295]
- checkbox
- generic [ref=e296]: Other
- generic [ref=e297]:
- generic [ref=e298]:
- generic [ref=e299]:
- status "Loading"
- generic [ref=e300]: Processing your request
- generic [ref=e301]: Please wait while we process your request. Do not refresh the page.
- button "Cancel" [ref=e303]
- contentinfo [ref=e304]:
- generic [ref=e307]:
- text: Built by
- link "shadcn" [ref=e308] [cursor=pointer]:
- /url: https://twitter.com/shadcn
- text: at
- link "Vercel" [ref=e309] [cursor=pointer]:
- /url: https://vercel.com/new?utm_source=shadcn_site&utm_medium=web&utm_campaign=docs_cta_deploy_now_callout
- text: . The source code is available on
- link "GitHub" [ref=e310] [cursor=pointer]:
- /url: https://github.com/shadcn-ui/ui
- text: .
- region "Notifications alt+T"
- alert [ref=e311]
- generic [re
[Truncated to 1000 characters. Better manage your logs or paginate them to read the full logs]