fix(next): live preview device position when using zoom (#6665)
This commit is contained in:
@@ -10,16 +10,20 @@ export const DeviceContainer: React.FC<{
|
||||
const { children } = props
|
||||
|
||||
const deviceFrameRef = React.useRef<HTMLDivElement>(null)
|
||||
const outerFrameRef = React.useRef<HTMLDivElement>(null)
|
||||
|
||||
const { breakpoint, setMeasuredDeviceSize, size, zoom } = useLivePreviewContext()
|
||||
const { breakpoint, setMeasuredDeviceSize, size: desiredSize, zoom } = useLivePreviewContext()
|
||||
|
||||
// Keep an accurate measurement of the actual device size as it is truly rendered
|
||||
// This is helpful when `sizes` are non-number units like percentages, etc.
|
||||
const { size: measuredDeviceSize } = useResize(deviceFrameRef)
|
||||
const { size: measuredDeviceSize } = useResize(deviceFrameRef.current)
|
||||
const { size: outerFrameSize } = useResize(outerFrameRef.current)
|
||||
|
||||
let deviceIsLargerThanFrame: boolean = false
|
||||
|
||||
// Sync the measured device size with the context so that other components can use it
|
||||
// This happens from the bottom up so that as this component mounts and unmounts,
|
||||
// Its size is freshly populated again upon re-mounting, i.e. going from iframe->popup->iframe
|
||||
// its size is freshly populated again upon re-mounting, i.e. going from iframe->popup->iframe
|
||||
useEffect(() => {
|
||||
if (measuredDeviceSize) {
|
||||
setMeasuredDeviceSize(measuredDeviceSize)
|
||||
@@ -34,13 +38,34 @@ export const DeviceContainer: React.FC<{
|
||||
|
||||
if (
|
||||
typeof zoom === 'number' &&
|
||||
typeof size.width === 'number' &&
|
||||
typeof size.height === 'number'
|
||||
typeof desiredSize.width === 'number' &&
|
||||
typeof desiredSize.height === 'number' &&
|
||||
typeof measuredDeviceSize.width === 'number' &&
|
||||
typeof measuredDeviceSize.height === 'number'
|
||||
) {
|
||||
const scaledWidth = size.width / zoom
|
||||
const difference = scaledWidth - size.width
|
||||
x = `${difference / 2}px`
|
||||
margin = '0 auto'
|
||||
const scaledDesiredWidth = desiredSize.width / zoom
|
||||
const scaledDeviceWidth = measuredDeviceSize.width * zoom
|
||||
const scaledDeviceDifferencePixels = scaledDesiredWidth - desiredSize.width
|
||||
deviceIsLargerThanFrame = scaledDeviceWidth > outerFrameSize.width
|
||||
|
||||
if (deviceIsLargerThanFrame) {
|
||||
if (zoom > 1) {
|
||||
const differenceFromDeviceToFrame = measuredDeviceSize.width - outerFrameSize.width
|
||||
if (differenceFromDeviceToFrame < 0) x = `${differenceFromDeviceToFrame / 2}px`
|
||||
else x = '0'
|
||||
} else {
|
||||
x = '0'
|
||||
}
|
||||
} else {
|
||||
if (zoom >= 1) {
|
||||
x = `${scaledDeviceDifferencePixels / 2}px`
|
||||
} else {
|
||||
const differenceFromDeviceToFrame = outerFrameSize.width - scaledDeviceWidth
|
||||
x = `${differenceFromDeviceToFrame / 2}px`
|
||||
margin = '0'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,21 +73,29 @@ export const DeviceContainer: React.FC<{
|
||||
let height = zoom ? `${100 / zoom}%` : '100%'
|
||||
|
||||
if (breakpoint !== 'responsive') {
|
||||
width = `${size?.width / (typeof zoom === 'number' ? zoom : 1)}px`
|
||||
height = `${size?.height / (typeof zoom === 'number' ? zoom : 1)}px`
|
||||
width = `${desiredSize?.width / (typeof zoom === 'number' ? zoom : 1)}px`
|
||||
height = `${desiredSize?.height / (typeof zoom === 'number' ? zoom : 1)}px`
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={deviceFrameRef}
|
||||
ref={outerFrameRef}
|
||||
style={{
|
||||
height,
|
||||
margin,
|
||||
transform: `translate3d(${x}, 0, 0)`,
|
||||
width,
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
<div
|
||||
ref={deviceFrameRef}
|
||||
style={{
|
||||
height,
|
||||
margin,
|
||||
transform: `translate3d(${x}, 0, 0)`,
|
||||
width,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
/* eslint-disable no-shadow */
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
type Intersect = [setNode: React.Dispatch<Element>, entry: IntersectionObserverEntry]
|
||||
type Intersect = [
|
||||
setNode: React.Dispatch<HTMLElement>,
|
||||
entry: IntersectionObserverEntry,
|
||||
node: HTMLElement,
|
||||
]
|
||||
|
||||
export const useIntersect = (
|
||||
{ root = null, rootMargin = '0px', threshold = 0 } = {},
|
||||
@@ -33,5 +37,5 @@ export const useIntersect = (
|
||||
return () => currentObserver.disconnect()
|
||||
}, [node, disable])
|
||||
|
||||
return [setNode, entry]
|
||||
return [setNode, entry, node]
|
||||
}
|
||||
|
||||
@@ -12,15 +12,13 @@ interface Resize {
|
||||
size?: Size
|
||||
}
|
||||
|
||||
export const useResize = (ref: React.MutableRefObject<HTMLElement>): Resize => {
|
||||
export const useResize = (element: HTMLElement): Resize => {
|
||||
const [size, setSize] = useState<Size>()
|
||||
|
||||
useEffect(() => {
|
||||
let observer: any // eslint-disable-line
|
||||
|
||||
const { current: currentRef } = ref
|
||||
|
||||
if (currentRef) {
|
||||
if (element) {
|
||||
observer = new ResizeObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
const {
|
||||
@@ -53,15 +51,15 @@ export const useResize = (ref: React.MutableRefObject<HTMLElement>): Resize => {
|
||||
})
|
||||
})
|
||||
|
||||
observer.observe(currentRef)
|
||||
observer.observe(element)
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (observer) {
|
||||
observer.unobserve(currentRef)
|
||||
observer.unobserve(element)
|
||||
}
|
||||
}
|
||||
}, [ref])
|
||||
}, [element])
|
||||
|
||||
return {
|
||||
size,
|
||||
|
||||
@@ -11,6 +11,7 @@ import { Footer } from './globals/Footer.js'
|
||||
import { Header } from './globals/Header.js'
|
||||
import { seed } from './seed/index.js'
|
||||
import {
|
||||
desktopBreakpoint,
|
||||
mobileBreakpoint,
|
||||
pagesSlug,
|
||||
postsSlug,
|
||||
@@ -25,7 +26,7 @@ export default buildConfigWithDefaults({
|
||||
// You can define any of these properties on a per collection or global basis
|
||||
// The Live Preview config cascades from the top down, properties are inherited from here
|
||||
url: formatLivePreviewURL,
|
||||
breakpoints: [mobileBreakpoint],
|
||||
breakpoints: [mobileBreakpoint, desktopBreakpoint],
|
||||
collections: [pagesSlug, postsSlug, ssrPagesSlug, ssrAutosavePagesSlug],
|
||||
globals: ['header', 'footer'],
|
||||
},
|
||||
|
||||
@@ -8,19 +8,29 @@ import {
|
||||
ensureAutoLoginAndCompilationIsDone,
|
||||
exactText,
|
||||
initPageConsoleErrorCatch,
|
||||
navigateToListCellLink,
|
||||
saveDocAndAssert,
|
||||
} from '../helpers.js'
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
|
||||
import { initPayloadE2ENoConfig } from '../helpers/initPayloadE2ENoConfig.js'
|
||||
import { POLL_TOPASS_TIMEOUT, TEST_TIMEOUT_LONG } from '../playwright.config.js'
|
||||
import {
|
||||
ensureDeviceIsCentered,
|
||||
ensureDeviceIsLeftAligned,
|
||||
goToCollectionLivePreview,
|
||||
goToDoc,
|
||||
goToGlobalLivePreview,
|
||||
selectLivePreviewBreakpoint,
|
||||
selectLivePreviewZoom,
|
||||
} from './helpers.js'
|
||||
import {
|
||||
desktopBreakpoint,
|
||||
mobileBreakpoint,
|
||||
pagesSlug,
|
||||
renderedPageTitleID,
|
||||
ssrAutosavePagesSlug,
|
||||
ssrPagesSlug,
|
||||
} from './shared.js'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
@@ -34,25 +44,6 @@ describe('Live Preview', () => {
|
||||
let ssrPagesURLUtil: AdminUrlUtil
|
||||
let ssrAutosavePostsURLUtil: AdminUrlUtil
|
||||
|
||||
const goToDoc = async (page: Page, urlUtil: AdminUrlUtil) => {
|
||||
await page.goto(urlUtil.list)
|
||||
await page.waitForURL(urlUtil.list)
|
||||
await navigateToListCellLink(page)
|
||||
}
|
||||
|
||||
const goToCollectionPreview = async (page: Page, urlUtil: AdminUrlUtil): Promise<void> => {
|
||||
await goToDoc(page, urlUtil)
|
||||
await page.goto(`${page.url()}/preview`)
|
||||
await page.waitForURL(`**/preview`)
|
||||
}
|
||||
|
||||
const goToGlobalPreview = async (page: Page, slug: string): Promise<void> => {
|
||||
const global = new AdminUrlUtil(serverURL, slug)
|
||||
const previewURL = `${global.global(slug)}/preview`
|
||||
await page.goto(previewURL)
|
||||
await page.waitForURL(previewURL)
|
||||
}
|
||||
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
;({ serverURL } = await initPayloadE2ENoConfig({ dirname }))
|
||||
@@ -88,18 +79,18 @@ describe('Live Preview', () => {
|
||||
})
|
||||
|
||||
test('collection — has route', async () => {
|
||||
await goToCollectionPreview(page, pagesURLUtil)
|
||||
await goToCollectionLivePreview(page, pagesURLUtil)
|
||||
await expect(page.locator('.live-preview')).toBeVisible()
|
||||
})
|
||||
|
||||
test('collection — renders iframe', async () => {
|
||||
await goToCollectionPreview(page, pagesURLUtil)
|
||||
await goToCollectionLivePreview(page, pagesURLUtil)
|
||||
const iframe = page.locator('iframe.live-preview-iframe')
|
||||
await expect(iframe).toBeVisible()
|
||||
})
|
||||
|
||||
test('collection — re-renders iframe client-side when form state changes', async () => {
|
||||
await goToCollectionPreview(page, pagesURLUtil)
|
||||
await goToCollectionLivePreview(page, pagesURLUtil)
|
||||
|
||||
const titleField = page.locator('#field-title')
|
||||
const frame = page.frameLocator('iframe.live-preview-iframe').first()
|
||||
@@ -129,7 +120,7 @@ describe('Live Preview', () => {
|
||||
})
|
||||
|
||||
test('collection ssr — re-render iframe when save is made', async () => {
|
||||
await goToCollectionPreview(page, ssrPagesURLUtil)
|
||||
await goToCollectionLivePreview(page, ssrPagesURLUtil)
|
||||
|
||||
const titleField = page.locator('#field-title')
|
||||
const frame = page.frameLocator('iframe.live-preview-iframe').first()
|
||||
@@ -159,7 +150,7 @@ describe('Live Preview', () => {
|
||||
})
|
||||
|
||||
test('collection ssr — re-render iframe when autosave is made', async () => {
|
||||
await goToCollectionPreview(page, ssrAutosavePostsURLUtil)
|
||||
await goToCollectionLivePreview(page, ssrAutosavePostsURLUtil)
|
||||
|
||||
const titleField = page.locator('#field-title')
|
||||
const frame = page.frameLocator('iframe.live-preview-iframe').first()
|
||||
@@ -189,12 +180,12 @@ describe('Live Preview', () => {
|
||||
})
|
||||
|
||||
test('collection — should show live-preview view-level action in live-preview view', async () => {
|
||||
await goToCollectionPreview(page, pagesURLUtil)
|
||||
await goToCollectionLivePreview(page, pagesURLUtil)
|
||||
await expect(page.locator('.app-header .collection-live-preview-button')).toHaveCount(1)
|
||||
})
|
||||
|
||||
test('global — should show live-preview view-level action in live-preview view', async () => {
|
||||
await goToGlobalPreview(page, 'footer')
|
||||
await goToGlobalLivePreview(page, 'footer', serverURL)
|
||||
await expect(page.locator('.app-header .global-live-preview-button')).toHaveCount(1)
|
||||
})
|
||||
|
||||
@@ -220,7 +211,7 @@ describe('Live Preview', () => {
|
||||
|
||||
test('global — has route', async () => {
|
||||
const url = page.url()
|
||||
await goToGlobalPreview(page, 'header')
|
||||
await goToGlobalLivePreview(page, 'header', serverURL)
|
||||
|
||||
await expect(() => expect(page.url()).toBe(`${url}/preview`)).toPass({
|
||||
timeout: POLL_TOPASS_TIMEOUT,
|
||||
@@ -228,13 +219,13 @@ describe('Live Preview', () => {
|
||||
})
|
||||
|
||||
test('global — renders iframe', async () => {
|
||||
await goToGlobalPreview(page, 'header')
|
||||
await goToGlobalLivePreview(page, 'header', serverURL)
|
||||
const iframe = page.locator('iframe.live-preview-iframe')
|
||||
await expect(iframe).toBeVisible()
|
||||
})
|
||||
|
||||
test('global — can edit fields', async () => {
|
||||
await goToGlobalPreview(page, 'header')
|
||||
await goToGlobalLivePreview(page, 'header', serverURL)
|
||||
const field = page.locator('input#field-navItems__0__link__newTab') //field-navItems__0__link__newTab
|
||||
await expect(field).toBeVisible()
|
||||
await expect(field).toBeEnabled()
|
||||
@@ -242,14 +233,14 @@ describe('Live Preview', () => {
|
||||
await saveDocAndAssert(page)
|
||||
})
|
||||
|
||||
test('properly measures iframe and displays size', async () => {
|
||||
test('device — properly measures size', async () => {
|
||||
await page.goto(pagesURLUtil.create)
|
||||
await page.waitForURL(pagesURLUtil.create)
|
||||
await page.locator('#field-title').fill('Title 3')
|
||||
await page.locator('#field-slug').fill('slug-3')
|
||||
|
||||
await saveDocAndAssert(page)
|
||||
await goToCollectionPreview(page, pagesURLUtil)
|
||||
await goToCollectionLivePreview(page, pagesURLUtil)
|
||||
|
||||
const iframe = page.locator('iframe')
|
||||
|
||||
@@ -291,37 +282,16 @@ describe('Live Preview', () => {
|
||||
})
|
||||
})
|
||||
|
||||
test('resizes iframe to specified breakpoint', async () => {
|
||||
test('device — resizes to specified breakpoint', async () => {
|
||||
await page.goto(pagesURLUtil.create)
|
||||
await page.waitForURL(pagesURLUtil.create)
|
||||
await page.locator('#field-title').fill('Title 4')
|
||||
await page.locator('#field-slug').fill('slug-4')
|
||||
|
||||
await saveDocAndAssert(page)
|
||||
await goToCollectionPreview(page, pagesURLUtil)
|
||||
await goToCollectionLivePreview(page, pagesURLUtil)
|
||||
|
||||
// Check that the breakpoint select is present
|
||||
const breakpointSelector = page.locator(
|
||||
'.live-preview-toolbar-controls__breakpoint button.popup-button',
|
||||
)
|
||||
|
||||
await expect(() => expect(breakpointSelector).toBeTruthy()).toPass({
|
||||
timeout: POLL_TOPASS_TIMEOUT,
|
||||
})
|
||||
|
||||
// Select the mobile breakpoint
|
||||
await breakpointSelector.first().click()
|
||||
await page
|
||||
.locator(`.live-preview-toolbar-controls__breakpoint button.popup-button-list__button`)
|
||||
.filter({ hasText: mobileBreakpoint.label })
|
||||
.click()
|
||||
|
||||
// Make sure the value has been set
|
||||
await expect(breakpointSelector).toContainText(mobileBreakpoint.label)
|
||||
const option = page.locator(
|
||||
'.live-preview-toolbar-controls__breakpoint button.popup-button-list__button--selected',
|
||||
)
|
||||
await expect(option).toHaveText(mobileBreakpoint.label)
|
||||
await selectLivePreviewBreakpoint(page, mobileBreakpoint.label)
|
||||
|
||||
// Measure the size of the iframe against the specified breakpoint
|
||||
const iframe = page.locator('iframe')
|
||||
@@ -382,4 +352,34 @@ describe('Live Preview', () => {
|
||||
timeout: POLL_TOPASS_TIMEOUT,
|
||||
})
|
||||
})
|
||||
|
||||
test('device — centers device when smaller than frame despite zoom', async () => {
|
||||
await goToCollectionLivePreview(page, pagesURLUtil)
|
||||
await selectLivePreviewBreakpoint(page, mobileBreakpoint.label)
|
||||
await ensureDeviceIsCentered(page)
|
||||
await selectLivePreviewZoom(page, '75%')
|
||||
await ensureDeviceIsCentered(page)
|
||||
await selectLivePreviewZoom(page, '50%')
|
||||
await ensureDeviceIsCentered(page)
|
||||
await selectLivePreviewZoom(page, '125%')
|
||||
await ensureDeviceIsCentered(page)
|
||||
await selectLivePreviewZoom(page, '200%')
|
||||
await ensureDeviceIsCentered(page)
|
||||
expect(true).toBeTruthy()
|
||||
})
|
||||
|
||||
test('device — left-aligns device when larger than frame despite zoom', async () => {
|
||||
await goToCollectionLivePreview(page, pagesURLUtil)
|
||||
await selectLivePreviewBreakpoint(page, desktopBreakpoint.label)
|
||||
await ensureDeviceIsLeftAligned(page)
|
||||
await selectLivePreviewZoom(page, '75%')
|
||||
await ensureDeviceIsLeftAligned(page)
|
||||
await selectLivePreviewZoom(page, '50%')
|
||||
await ensureDeviceIsLeftAligned(page)
|
||||
await selectLivePreviewZoom(page, '125%')
|
||||
await ensureDeviceIsLeftAligned(page)
|
||||
await selectLivePreviewZoom(page, '200%')
|
||||
await ensureDeviceIsLeftAligned(page)
|
||||
expect(true).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
||||
122
test/live-preview/helpers.ts
Normal file
122
test/live-preview/helpers.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import type { Page } from '@playwright/test'
|
||||
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { exactText, navigateToListCellLink } from '../helpers.js'
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
|
||||
import { POLL_TOPASS_TIMEOUT } from '../playwright.config.js'
|
||||
|
||||
export const goToDoc = async (page: Page, urlUtil: AdminUrlUtil) => {
|
||||
await page.goto(urlUtil.list)
|
||||
await page.waitForURL(urlUtil.list)
|
||||
await navigateToListCellLink(page)
|
||||
}
|
||||
|
||||
export const goToCollectionLivePreview = async (
|
||||
page: Page,
|
||||
urlUtil: AdminUrlUtil,
|
||||
): Promise<void> => {
|
||||
await goToDoc(page, urlUtil)
|
||||
await page.goto(`${page.url()}/preview`)
|
||||
await page.waitForURL(`**/preview`)
|
||||
}
|
||||
|
||||
export const goToGlobalLivePreview = async (
|
||||
page: Page,
|
||||
slug: string,
|
||||
serverURL: string,
|
||||
): Promise<void> => {
|
||||
const global = new AdminUrlUtil(serverURL, slug)
|
||||
const previewURL = `${global.global(slug)}/preview`
|
||||
await page.goto(previewURL)
|
||||
await page.waitForURL(previewURL)
|
||||
}
|
||||
|
||||
export const selectLivePreviewBreakpoint = async (page: Page, breakpointLabel: string) => {
|
||||
const breakpointSelector = page.locator(
|
||||
'.live-preview-toolbar-controls__breakpoint button.popup-button',
|
||||
)
|
||||
|
||||
await expect(() => expect(breakpointSelector).toBeTruthy()).toPass({
|
||||
timeout: POLL_TOPASS_TIMEOUT,
|
||||
})
|
||||
|
||||
await breakpointSelector.first().click()
|
||||
|
||||
await page
|
||||
.locator(`.live-preview-toolbar-controls__breakpoint button.popup-button-list__button`)
|
||||
.filter({ hasText: breakpointLabel })
|
||||
.click()
|
||||
|
||||
await expect(breakpointSelector).toContainText(breakpointLabel)
|
||||
|
||||
const option = page.locator(
|
||||
'.live-preview-toolbar-controls__breakpoint button.popup-button-list__button--selected',
|
||||
)
|
||||
|
||||
await expect(option).toHaveText(breakpointLabel)
|
||||
}
|
||||
|
||||
export const selectLivePreviewZoom = async (page: Page, zoomLabel: string) => {
|
||||
const zoomSelector = page.locator('.live-preview-toolbar-controls__zoom button.popup-button')
|
||||
|
||||
await expect(() => expect(zoomSelector).toBeTruthy()).toPass({
|
||||
timeout: POLL_TOPASS_TIMEOUT,
|
||||
})
|
||||
|
||||
await zoomSelector.first().click()
|
||||
|
||||
const zoomOption = page.locator(
|
||||
'.live-preview-toolbar-controls__zoom button.popup-button-list__button',
|
||||
{
|
||||
hasText: exactText(zoomLabel),
|
||||
},
|
||||
)
|
||||
|
||||
expect(zoomOption).toBeTruthy()
|
||||
await zoomOption.click()
|
||||
|
||||
await expect(zoomSelector).toContainText(zoomLabel)
|
||||
|
||||
const option = page.locator(
|
||||
'.live-preview-toolbar-controls__zoom button.popup-button-list__button--selected',
|
||||
)
|
||||
|
||||
await expect(option).toHaveText(zoomLabel)
|
||||
}
|
||||
|
||||
export const ensureDeviceIsCentered = async (page: Page) => {
|
||||
const main = page.locator('.live-preview-window__main')
|
||||
const iframe = page.locator('iframe.live-preview-iframe')
|
||||
const mainBoxAfterZoom = await main.boundingBox()
|
||||
const iframeBoxAfterZoom = await iframe.boundingBox()
|
||||
const distanceFromIframeLeftToMainLeftAfterZoom = Math.abs(
|
||||
mainBoxAfterZoom?.x - iframeBoxAfterZoom?.x,
|
||||
)
|
||||
const distanceFromIFrameRightToMainRightAfterZoom = Math.abs(
|
||||
mainBoxAfterZoom?.x +
|
||||
mainBoxAfterZoom?.width -
|
||||
iframeBoxAfterZoom?.x -
|
||||
iframeBoxAfterZoom?.width,
|
||||
)
|
||||
await expect(() =>
|
||||
expect(distanceFromIframeLeftToMainLeftAfterZoom).toBe(
|
||||
distanceFromIFrameRightToMainRightAfterZoom,
|
||||
),
|
||||
).toPass({
|
||||
timeout: POLL_TOPASS_TIMEOUT,
|
||||
})
|
||||
}
|
||||
|
||||
export const ensureDeviceIsLeftAligned = async (page: Page) => {
|
||||
const main = page.locator('.live-preview-window__main > div')
|
||||
const iframe = page.locator('iframe.live-preview-iframe')
|
||||
const mainBoxAfterZoom = await main.boundingBox()
|
||||
const iframeBoxAfterZoom = await iframe.boundingBox()
|
||||
const distanceFromIframeLeftToMainLeftAfterZoom = Math.abs(
|
||||
mainBoxAfterZoom?.x - iframeBoxAfterZoom?.x,
|
||||
)
|
||||
await expect(() => expect(distanceFromIframeLeftToMainLeftAfterZoom).toBe(0)).toPass({
|
||||
timeout: POLL_TOPASS_TIMEOUT,
|
||||
})
|
||||
}
|
||||
@@ -15,4 +15,11 @@ export const mobileBreakpoint = {
|
||||
height: 667,
|
||||
}
|
||||
|
||||
export const desktopBreakpoint = {
|
||||
label: 'Desktop',
|
||||
name: 'desktop',
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
}
|
||||
|
||||
export const renderedPageTitleID = 'rendered-page-title'
|
||||
|
||||
Reference in New Issue
Block a user