fix: live preview device position when using zoom (#6667)
This commit is contained in:
@@ -101,6 +101,13 @@ export const selectTableRow = async (page: Page, title: string): Promise<void> =
|
||||
expect(await page.locator(selector).isChecked()).toBe(true)
|
||||
}
|
||||
|
||||
export async function navigateToListCellLink(page: Page, selector = '.cell-id') {
|
||||
const cellLink = page.locator(`${selector} a`).first()
|
||||
const linkURL = await cellLink.getAttribute('href')
|
||||
await cellLink.click()
|
||||
await page.waitForURL(`**${linkURL}`)
|
||||
}
|
||||
|
||||
export const findTableCell = async (
|
||||
page: Page,
|
||||
fieldName: string,
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Users } from './collections/Users'
|
||||
import { Footer } from './globals/Footer'
|
||||
import { Header } from './globals/Header'
|
||||
import { seed } from './seed'
|
||||
import { mobileBreakpoint } from './shared'
|
||||
import { desktopBreakpoint, mobileBreakpoint } from './shared'
|
||||
import { formatLivePreviewURL } from './utilities/formatLivePreviewURL'
|
||||
|
||||
const mockModulePath = path.resolve(__dirname, './mocks/mockFSModule.js')
|
||||
@@ -21,7 +21,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: ['pages', 'posts'],
|
||||
globals: ['header', 'footer'],
|
||||
},
|
||||
|
||||
@@ -5,7 +5,14 @@ import { expect, test } from '@playwright/test'
|
||||
import { exactText, initPageConsoleErrorCatch, saveDocAndAssert } from '../helpers'
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil'
|
||||
import { initPayloadE2E } from '../helpers/configHelpers'
|
||||
import { mobileBreakpoint } from './shared'
|
||||
import {
|
||||
ensureDeviceIsCentered,
|
||||
ensureDeviceIsLeftAligned,
|
||||
goToCollectionLivePreview,
|
||||
selectLivePreviewBreakpoint,
|
||||
selectLivePreviewZoom,
|
||||
} from './helpers'
|
||||
import { desktopBreakpoint, mobileBreakpoint } from './shared'
|
||||
import { startLivePreviewDemo } from './startLivePreviewDemo'
|
||||
|
||||
const { beforeAll, describe } = test
|
||||
@@ -216,4 +223,34 @@ describe('Live Preview', () => {
|
||||
const height = parseInt(heightInputValue)
|
||||
expect(height).toBe(mobileBreakpoint.height)
|
||||
})
|
||||
|
||||
test('device — centers device when smaller than frame despite zoom', async () => {
|
||||
await goToCollectionLivePreview(page, url)
|
||||
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, url)
|
||||
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()
|
||||
})
|
||||
})
|
||||
|
||||
124
test/live-preview/helpers.ts
Normal file
124
test/live-preview/helpers.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
import type { Page } from '@playwright/test'
|
||||
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { exactText, navigateToListCellLink } from '../helpers.js'
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
|
||||
|
||||
export const EXPECT_TIMEOUT = 8000
|
||||
export const POLL_TOPASS_TIMEOUT = EXPECT_TIMEOUT * 4
|
||||
|
||||
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,
|
||||
})
|
||||
}
|
||||
@@ -8,3 +8,10 @@ export const mobileBreakpoint = {
|
||||
width: 375,
|
||||
height: 667,
|
||||
}
|
||||
|
||||
export const desktopBreakpoint = {
|
||||
label: 'Desktop',
|
||||
name: 'desktop',
|
||||
width: 1920,
|
||||
height: 1024,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user