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
101 changes: 70 additions & 31 deletions packages/runtime/src/components/Badge.ce.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed } from 'vue'
import { computed, ref } from 'vue'

const props = withDefaults(
defineProps<{
Expand Down Expand Up @@ -34,48 +34,88 @@ const bgColorClass = computed(() => {
return 'summary-success'
})

// $: calcBgColorClass = () => {
// if (!summary) return ''
// if (summary.errorCount > 0) return 'summary-error'
// if (summary.warningCount > 0) return 'summary-warning'
// return 'summary-success'
// }

// $: bgColorClass = calcBgColorClass()
const isCopied = ref(false)
const onCopy = async () => {
const text = props.checkerResults
.map((result) => {
return result.diagnostics
.map((d: any) => {
return `[${result.checkerId}] ${d.message}${d.id ? ` (${d.id})` : ''}${
d.loc ? `\n${d.loc.file}:${d.loc.line}:${d.loc.column}` : ''
}${d.frame ? `\n${d.frame}` : ''}`
})
.join('\n\n')
})
.join('\n\n---\n\n')

try {
await navigator.clipboard.writeText(text)
isCopied.value = true
setTimeout(() => {
isCopied.value = false
}, 2000)
} catch (err) {
console.error('Failed to copy: ', err)
}
}
</script>

<template>
<button
:class="[
'badge-base',
collapsed ? `to-uncollpase ${bgColorClass}` : 'to-collpase',
`badge-${position}`,
]"
:style="badgeStyle"
@click="onClick"
>
<template v-if="collapsed">
<span class="summary"><span class="emoji">❗️</span>{{ summary.errorCount }}</span>
<span class="summary"><span class="emoji">⚠️</span>{{ summary.warningCount }}</span>
</template>
<template v-else>
<span>Close</span>
</template>
</button>
<div :class="['badge-container', `badge-${position}`]" :style="badgeStyle">
<button v-if="!collapsed" class="badge-button copy-button" @click="onCopy">
{{ isCopied ? 'Copied!' : 'Copy' }}
</button>
<button
:class="[
'badge-button',
'action-button',
collapsed ? `to-uncollpase ${bgColorClass}` : 'to-collpase',
]"
@click="onClick"
>
<template v-if="collapsed">
<span class="summary"><span class="emoji">❗️</span>{{ summary.errorCount }}</span>
<span class="summary"><span class="emoji">⚠️</span>{{ summary.warningCount }}</span>
</template>
<template v-else>
<span>Close</span>
</template>
</button>
</div>
</template>

<style>
.badge-base {
.badge-container {
display: flex;
gap: 0.5em;
position: fixed;
z-index: 99999;
margin: 0.5em;
border-radius: 0.3em;
}

.badge-button {
appearance: none;
font-size: 0.9em;
font-weight: bold;
border: 0px;
border-radius: 0.3em;
padding: 0.5em;
cursor: pointer;
position: fixed;
z-index: 99999;
margin: 0.5em;
color: white;
}

.copy-button {
background: rgb(63, 78, 96);
border: 1px solid rgba(255, 255, 255, 0.1);
}

.copy-button:hover {
background: rgb(73, 88, 106);
}

.action-button {
background: transparent;
}

.badge-bl {
Expand All @@ -99,7 +139,6 @@ const bgColorClass = computed(() => {
}

.to-collpase {
color: white;
background: rgb(63, 78, 96);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('config-initialIsOpen-false', () => {
await getHmrOverlayText()
} catch (e) {
expect((e as any).toString()).toContain(
'Invariant failed: <vite-plugin-checker-error-overlay> shadow dom is expected to be found, but got null'
'Invariant failed: .message-body is expected in shadow root'
)
}
}
Expand Down
47 changes: 47 additions & 0 deletions playground/config-overlay-changes/__tests__/test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
getHmrOverlay,
getHmrOverlayText,
isServe,
page,
pollingUntil,
sleep,
sleepForEdit,
Expand All @@ -20,6 +21,50 @@ describe('config-overlay-changes', () => {
expect(file1).toMatchSnapshot()
expect(frame1).toMatchSnapshot()

console.log('-- copy diagnostics to clipboard --')
const overlay = page.locator('vite-plugin-checker-error-overlay')
const actionButton = overlay.locator('.action-button')
await actionButton.waitFor({ state: 'visible' })

// Expand overlay if collapsed
const isCollapsed = await actionButton.evaluate(
(el) => (el as HTMLElement).querySelector('.summary') !== null
)
if (isCollapsed) {
await actionButton.click()
await sleep(500) // Wait for expansion
}

const copyButton = overlay.locator('.copy-button')
await copyButton.waitFor({ state: 'visible' })

// Mock clipboard API
await page.evaluate(() => {
;(window as any).__lastCopiedText = ''
Object.defineProperty(window.Navigator.prototype, 'clipboard', {
get: () => ({
writeText: (text: string) => {
;(window as any).__lastCopiedText = text
return Promise.resolve()
},
}),
configurable: true,
})
})

await copyButton.click()

// Check visual feedback
await pollingUntil(
async () => await copyButton.innerText(),
(text) => text === 'Copied!'
)

// Check "clipboard" content
const copiedText = await page.evaluate(() => (window as any).__lastCopiedText)
expect(copiedText).toContain('[eslint]')
expect(copiedText).toContain('var hello')

console.log('-- overlay update after edit --')
editFile('src/main.ts', (code) => code.replace('Hello', 'Hello1'))
await sleepForEdit()
Expand All @@ -37,3 +82,5 @@ describe('config-overlay-changes', () => {
})
})
})


Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('config-overlay-position-style', () => {
it('find badge in right top corner and customized by badgeStyle', async () => {
await sleepForServerReady()
const shadowRoot = await getHmrOverlay()
const badge = await shadowRoot!.$('.badge-base')
const badge = await shadowRoot!.$('.badge-container')

const { bgColor, top, right } = await badge!.evaluate((el) => {
const bgColor = window.getComputedStyle(el).getPropertyValue('background-color')
Expand Down
Loading