Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/components/Package/SkillsModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ function getWarningTooltip(skill: SkillListItem): string | undefined {
</code>
<button
type="button"
class="absolute top-0 inset-ie-0 px-2 py-0.5 font-mono text-xs text-fg-muted bg-bg-subtle/80 border border-border rounded transition-colors duration-200 opacity-0 group-hover/cmd:opacity-100 hover:(text-fg border-border-hover) active:scale-95 focus-visible:opacity-100 focus-visible:outline-accent/70"
class="absolute top-0 inset-ie-0 px-2 py-0.5 font-mono text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
:aria-label="$t('package.get_started.copy_command')"
@click.stop="copyCommand"
>
Expand Down
2 changes: 1 addition & 1 deletion app/components/Terminal/Execute.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const copyExecuteCommand = () => copyExecute(getFullExecuteCommand())
>
<button
type="button"
class="px-2 py-0.5 font-mono text-xs text-fg-muted bg-bg-subtle/80 border border-border rounded transition-colors duration-200 opacity-0 group-hover/executecmd:opacity-100 hover:(text-fg border-border-hover) active:scale-95 focus-visible:opacity-100 focus-visible:outline-accent/70"
class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
:aria-label="$t('package.get_started.copy_command')"
@click.stop="copyExecuteCommand"
>
Expand Down
6 changes: 3 additions & 3 deletions app/components/Terminal/Install.vue
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ const copyCreateCommand = () => copyCreate(getFullCreateCommand())
>
<button
type="button"
class="px-2 py-0.5 font-mono text-xs text-fg-muted bg-bg-subtle/80 border border-border rounded transition-colors duration-200 opacity-0 group-hover/installcmd:opacity-100 hover:(text-fg border-border-hover) active:scale-95 focus-visible:opacity-100 focus-visible:outline-accent/70 select-none"
class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
:aria-label="$t('package.get_started.copy_command')"
@click.stop="copyInstallCommand"
>
Expand Down Expand Up @@ -185,7 +185,7 @@ const copyCreateCommand = () => copyCreate(getFullCreateCommand())
>
<button
type="button"
class="px-2 py-0.5 font-mono text-xs text-fg-muted bg-bg-subtle/80 border border-border rounded transition-colors duration-200 opacity-0 group-hover/runcmd:opacity-100 hover:(text-fg border-border-hover) active:scale-95 focus-visible:opacity-100 focus-visible:outline-accent/70 select-none"
class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
@click.stop="copyRunCommand(executableInfo?.primaryCommand)"
>
{{ runCopied ? $t('common.copied') : $t('common.copy') }}
Expand Down Expand Up @@ -230,7 +230,7 @@ const copyCreateCommand = () => copyCreate(getFullCreateCommand())
>
<button
type="button"
class="px-2 py-0.5 font-mono text-xs text-fg-muted bg-bg-subtle/80 border border-border rounded transition-colors duration-200 opacity-0 group-hover/createcmd:opacity-100 hover:(text-fg border-border-hover) active:scale-95 focus-visible:opacity-100 focus-visible:outline-accent/70 select-none"
class="px-2 py-0.5 font-mono ms-auto text-xs text-fg-muted bg-bg-subtle/80 border border-border border-solid rounded transition-colors duration-200 hover:(text-fg border-border-hover) active:scale-95 focus-visible:outline-accent/70"
:aria-label="$t('package.create.copy_command')"
@click.stop="copyCreateCommand"
>
Expand Down
79 changes: 56 additions & 23 deletions test/e2e/create-command.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ test.describe('Create Command', () => {
})

test.describe('Copy Functionality', () => {
test('hovering create command shows copy button', async ({ page, goto }) => {
test('copy button is always visible', async ({ page, goto }) => {
await goto('/package/vite', { waitUntil: 'hydration' })

await expect(page.locator('h1')).toContainText('vite', { timeout: 15000 })
Expand All @@ -75,14 +75,8 @@ test.describe('Create Command', () => {
const createCommandContainer = page.locator('.group\\/createcmd').first()
await expect(createCommandContainer).toBeVisible({ timeout: 20000 })

// Copy button should initially be hidden (opacity-0)
// Copy button should always be visible
const copyButton = createCommandContainer.locator('button')
await expect(copyButton).toHaveCSS('opacity', '0')

// Hover over the container
await createCommandContainer.hover()

// Copy button should become visible
await expect(copyButton).toHaveCSS('opacity', '1')
})

Expand All @@ -104,9 +98,6 @@ test.describe('Create Command', () => {
const createCommandContainer = page.locator('.group\\/createcmd').first()
await expect(createCommandContainer).toBeVisible({ timeout: 20000 })

await createCommandContainer.hover()

// Click the copy button
const copyButton = createCommandContainer.locator('button')
await copyButton.click()

Expand All @@ -123,21 +114,15 @@ test.describe('Create Command', () => {
})

test.describe('Install Command Copy', () => {
test('hovering install command shows copy button', async ({ page, goto }) => {
test('copy button is always visible', async ({ page, goto }) => {
await goto('/package/is-odd', { waitUntil: 'hydration' })

// Find the install command container
const installCommandContainer = page.locator('.group\\/installcmd').first()
await expect(installCommandContainer).toBeVisible()

// Copy button should initially be hidden
// Copy button should always be visible
const copyButton = installCommandContainer.locator('button')
await expect(copyButton).toHaveCSS('opacity', '0')

// Hover over the container
await installCommandContainer.hover()

// Copy button should become visible
await expect(copyButton).toHaveCSS('opacity', '1')
})

Expand All @@ -151,11 +136,7 @@ test.describe('Create Command', () => {

await goto('/package/is-odd', { waitUntil: 'hydration' })

// Find and hover over the install command container
const installCommandContainer = page.locator('.group\\/installcmd').first()
await installCommandContainer.hover()

// Click the copy button
const copyButton = installCommandContainer.locator('button')
await copyButton.click()

Expand All @@ -170,4 +151,56 @@ test.describe('Create Command', () => {
await expect(copyButton).not.toContainText(/copied/i)
})
})

test.describe('Run Command Copy', () => {
test('copy button is always visible', async ({ page, goto }) => {
await goto('/package/vite', { waitUntil: 'hydration' })

await expect(page.locator('h1')).toContainText('vite', { timeout: 15000 })

await expect(page.locator('main header').locator('text=/v\\d+\\.\\d+/')).toBeVisible({
timeout: 15000,
})

// Find the run command container
const runCommandContainer = page.locator('.group\\/runcmd').first()
await expect(runCommandContainer).toBeVisible({ timeout: 20000 })

// Copy button should always be visible
const copyButton = runCommandContainer.locator('button')
await expect(copyButton).toHaveCSS('opacity', '1')
})

test('clicking copy button copies run command and shows confirmation', async ({
page,
goto,
context,
}) => {
// Grant clipboard permissions
await context.grantPermissions(['clipboard-read', 'clipboard-write'])

await goto('/package/vite', { waitUntil: 'hydration' })
await expect(page.locator('h1')).toContainText('vite', { timeout: 15000 })

await expect(page.locator('main header').locator('text=/v\\d+\\.\\d+/')).toBeVisible({
timeout: 15000,
})

const runCommandContainer = page.locator('.group\\/runcmd').first()
await expect(runCommandContainer).toBeVisible({ timeout: 20000 })

const copyButton = runCommandContainer.locator('button')
await copyButton.click()

// Button text should change to "copied!"
await expect(copyButton).toContainText(/copied/i)

// Verify clipboard content contains the run command
const clipboardContent = await page.evaluate(() => navigator.clipboard.readText())
expect(clipboardContent).toMatch(/npx vite/i)

await expect(copyButton).toContainText(/copy/i, { timeout: 5000 })
await expect(copyButton).not.toContainText(/copied/i)
})
})
})
Loading