Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(browser): add browser iframe mouse interaction #5815

Merged
merged 5 commits into from
Jun 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 packages/browser/src/client/orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ function createIframe(container: HTMLDivElement, file: string) {

iframe.style.display = 'block'
iframe.style.border = 'none'
iframe.style.pointerEvents = 'none'
iframe.setAttribute('allowfullscreen', 'true')
iframe.setAttribute('allow', 'clipboard-write;')

iframes.set(file, iframe)
container.className = 'testing'
container.appendChild(iframe)
return iframe
}
Expand Down
40 changes: 34 additions & 6 deletions packages/ui/client/components/BrowserIframe.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
<script setup lang="ts">
const viewport = ref('custom')
import { recalculateDetailPanels } from '~/composables/navigation'
import { registerResizingListener } from '~/composables/client/resizing'

const sizes = {
type ViewportSize = 'small-mobile' | 'large-mobile' | 'tablet' | 'custom'

const sizes: Record<ViewportSize, [width: string, height: string]> = {
'small-mobile': ['320px', '568px'],
'large-mobile': ['414px', '896px'],
tablet: ['834px', '1112px'],
custom: ['100%', '100%'],
}

async function changeViewport(name: string) {
const testerRef = ref<HTMLDivElement>()
const viewport = ref<ViewportSize>('custom')

async function changeViewport(name: ViewportSize) {
if (viewport.value === name) {
viewport.value = 'custom'
} else {
viewport.value = name
}

const iframe = document.querySelector('#tester-ui iframe[data-vitest]')
const iframe = document.querySelector<HTMLIFrameElement>('#tester-ui iframe[data-vitest]')
if (!iframe) {
console.warn('Iframe not found')
return
Expand All @@ -31,6 +36,17 @@ async function changeViewport(name: string) {

recalculateDetailPanels()
}

function onResizing(isResizing: boolean) {
const tester = testerRef.value
if (!tester)
return

tester.style.pointerEvents = isResizing ? 'none' : ''
}
onMounted(() => {
registerResizingListener(onResizing)
})
</script>

<template>
Expand Down Expand Up @@ -84,10 +100,22 @@ async function changeViewport(name: string) {
@click="changeViewport('tablet')"
/>
</div>
<div flex-auto overflow-auto>
<div id="tester-ui" class="flex h-full justify-center items-center font-light op70" style="overflow: auto; width: 100%; height: 100%">
<div flex-auto class="scrolls">
<div id="tester-ui" ref="testerRef" style="overflow: auto; width: 100%; height: 100%">
Select a test to run
</div>
</div>
</div>
</template>

<style>
#tester-ui {
userquin marked this conversation as resolved.
Show resolved Hide resolved
@apply flex h-full justify-center items-center font-light op70;
}
/* DO NOT REMOVE: class added in browser orchestrator when adding the iframe */
#tester-ui.testing {
display: unset !important;
font-family: unset !important;
opacity: unset;
}
</style>
24 changes: 24 additions & 0 deletions packages/ui/client/composables/client/resizing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export type ResizingListener = (isResizing: boolean) => void

const resizingSymbol = Symbol.for('resizing')

export function registerResizingListener(listener: ResizingListener) {
inject<(listener: ResizingListener) => void>(resizingSymbol)?.(listener)
}

export function provideResizing() {
const listeners = new Set<ResizingListener>()

function addResizeListener(listener: ResizingListener) {
listeners.add(listener)
}

function notifyResizing(isResizing: boolean) {
for (const listener of listeners)
listener(isResizing)
}

provide(resizingSymbol, addResizeListener)

return { notifyResizing }
}
8 changes: 6 additions & 2 deletions packages/ui/client/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
// @ts-expect-error missing types
import { Pane, Splitpanes } from 'splitpanes'
import { browserState } from '~/composables/client';
import { coverageUrl, coverageVisible, initializeNavigation, detailSizes } from '../composables/navigation'
import { coverageUrl, coverageVisible, initializeNavigation, detailSizes } from '~/composables/navigation'
import { provideResizing } from '~/composables/client/resizing'

const { notifyResizing } = provideResizing()
const dashboardVisible = initializeNavigation()

const mainSizes = useLocalStorage<[left: number, right: number]>('vitest-ui_splitpanes-mainSizes', [33, 67], {
initOnMounted: true,
})
Expand All @@ -18,6 +21,7 @@ const onModuleResized = useDebounceFn((event: { size: number }[]) => {
event.forEach((e, i) => {
detailSizes.value[i] = e.size
})
notifyResizing(false)
}, 0)

function resizeMain() {
Expand All @@ -41,7 +45,7 @@ function resizeMain() {
<Coverage v-else-if="coverageVisible" key="coverage" :src="coverageUrl" />
<FileDetails v-else />
</transition>
<Splitpanes v-else key="detail" id="details-splitpanes" @resized="onModuleResized">
<Splitpanes v-else key="detail" id="details-splitpanes" @resize="notifyResizing(true)" @resized="onModuleResized">
<Pane :size="detailSizes[0]">
<BrowserIframe v-once />
</Pane>
Expand Down
Loading