/** * Copyright 2018 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { compare } from 'playwright-core/lib/image_tools/compare'; import { PNG } from 'playwright-core/lib/utilsBundle'; import { expect, playwrightTest as it } from '../config/browserTest'; it.use({ headless: false }); it('should have default url when launching browser @smoke', async ({ launchPersistent }) => { const { context } = await launchPersistent(); const urls = context.pages().map(page => page.url()); expect(urls).toEqual(['about:blank']); }); it('should close browser with beforeunload page', async ({ launchPersistent, server }) => { it.slow(); const { context } = await launchPersistent(); const page = await context.newPage(); await page.goto(server.PREFIX + '/beforeunload.html'); // We have to interact with a page so that 'beforeunload' handlers // fire. await page.click('body'); await context.close(); }); it('should close browsercontext with pending beforeunload dialog', async ({ server, context }) => { const page = await context.newPage(); await page.goto(server.PREFIX + '/beforeunload.html'); // We have to interact with a page so that 'beforeunload' handlers // fire. await page.click('body'); await Promise.all([ page.waitForEvent('dialog'), page.close({ runBeforeUnload: true }), ]); await context.close(); }); it('should not crash when creating second context', async ({ browser }) => { { const browserContext = await browser.newContext(); await browserContext.newPage(); await browserContext.close(); } { const browserContext = await browser.newContext(); await browserContext.newPage(); await browserContext.close(); } }); it('should click when viewport size is larger than screen', async ({ page }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/22082' }); await page.setViewportSize({ width: 3000, height: 3000, }); await page.setContent(` `); await page.locator('button').click(); }); it('should dispatch click events to oversized viewports', async ({ page }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/22082' }); // Some prime numbers for width/height. const width = 2971; const height = 3067; await page.setViewportSize({ width, height }); await page.evaluate(() => { window['events'] = []; window.addEventListener('click', event => window['events'].push({ x: event.clientX, y: event.clientY }), false); }); const expectedEvents = []; // Allow a little padding from the edges of viewport. for (let i = 3; i < 23; ++i) { const x = width - i; const y = height - i; expectedEvents.push({ x, y }); await page.mouse.move(x, y); await page.mouse.down(); await page.mouse.up(); } const actualEvents = await page.evaluate(() => window['events']); expect(expectedEvents).toEqual(actualEvents); }); it('should click background tab', async ({ page, server }) => { await page.setContent(`empty.html`); await page.click('a'); await page.click('button'); }); it('should close browser after context menu was triggered', async ({ browserType, server }) => { const browser = await browserType.launch(); const page = await browser.newPage(); await page.goto(server.PREFIX + '/grid.html'); await page.click('body', { button: 'right' }); await browser.close(); }); it('should(not) block third party cookies', async ({ page, server, allowsThirdParty }) => { await page.goto(server.EMPTY_PAGE); await page.evaluate(src => { let fulfill; const promise = new Promise(x => fulfill = x); const iframe = document.createElement('iframe'); document.body.appendChild(iframe); iframe.onload = fulfill; iframe.src = src; return promise; }, server.CROSS_PROCESS_PREFIX + '/grid.html'); const documentCookie = await page.frames()[1].evaluate(() => { document.cookie = 'username=John Doe'; return document.cookie; }); await page.waitForTimeout(2000); expect(documentCookie).toBe(allowsThirdParty ? 'username=John Doe' : ''); const cookies = await page.context().cookies(server.CROSS_PROCESS_PREFIX + '/grid.html'); if (allowsThirdParty) { expect(cookies).toEqual([ { 'domain': '127.0.0.1', 'expires': -1, 'httpOnly': false, 'name': 'username', 'path': '/', 'sameSite': 'None', 'secure': false, 'value': 'John Doe' } ]); } else { expect(cookies).toEqual([]); } }); it('should not block third party SameSite=None cookies', async ({ httpsServer, browserName, browser }) => { it.skip(browserName === 'webkit', 'No third party cookies in WebKit'); const page = await browser.newPage({ ignoreHTTPSErrors: true, }); httpsServer.setRoute('/empty.html', (req, res) => { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(``); }); httpsServer.setRoute('/grid.html', (req, res) => { res.writeHead(200, { 'Set-Cookie': ['a=b; Path=/; Max-Age=3600; SameSite=None; Secure'], 'Content-Type': 'text/html' }); res.end(`Hello world `); }); const cookie = new Promise(f => { httpsServer.setRoute('/json', (req, res) => { f(req.headers.cookie); res.end(); }); }); await page.goto(httpsServer.EMPTY_PAGE); expect(await cookie).toBe('a=b'); await page.close(); }); it('should not override viewport size when passed null', async function({ browserName, server, browser }) { it.fixme(browserName === 'webkit', 'Our WebKit embedder does not respect window features'); const context = await browser.newContext({ viewport: null }); const page = await context.newPage(); await page.goto(server.EMPTY_PAGE); const [popup] = await Promise.all([ page.waitForEvent('popup'), page.evaluate(() => { const win = window.open(window.location.href, 'Title', 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=300,top=0,left=0'); win.resizeTo(500, 450); }), ]); await popup.waitForLoadState(); await popup.waitForFunction(() => window.outerWidth === 500 && window.outerHeight === 450); await context.close(); }); it('Page.bringToFront should work', async ({ browser }) => { const page1 = await browser.newPage(); await page1.setContent('Page1'); const page2 = await browser.newPage(); await page2.setContent('Page2'); await page1.bringToFront(); expect(await page1.evaluate('document.visibilityState')).toBe('visible'); expect(await page2.evaluate('document.visibilityState')).toBe('visible'); await page2.bringToFront(); expect(await page1.evaluate('document.visibilityState')).toBe('visible'); expect(await page2.evaluate('document.visibilityState')).toBe( 'visible' ); await page1.close(); await page2.close(); }); it('should click in OOPIF', async ({ browserName, launchPersistent, server }) => { it.fixme(browserName === 'chromium', 'Click is offset by the infobar height'); server.setRoute('/empty.html', (req, res) => { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(``); }); server.setRoute('/iframe.html', (req, res) => { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(` `); }); const { page } = await launchPersistent(); const consoleLog: string[] = []; page.on('console', m => consoleLog.push(m.text())); await page.goto(server.EMPTY_PAGE); await page.frames()[1].click('text=Submit'); expect(consoleLog).toContain('ok'); }); it('should click bottom row w/ infobar in OOPIF', async ({ browserName, launchPersistent, server }) => { it.fixme(browserName === 'chromium', 'Click is offset by the infobar height'); server.setRoute('/empty.html', (req, res) => { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(` `); }); server.setRoute('/iframe.html', (req, res) => { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(` `); }); const { page } = await launchPersistent(); await page.goto(server.EMPTY_PAGE); // Chrome bug! Investigate what's happening in the oopif router. const consoleLog: string[] = []; page.on('console', m => consoleLog.push(m.text())); while (!consoleLog.includes('ok')) { await page.waitForTimeout(100); await page.frames()[1].click('text=Submit'); } }); it('headless and headful should use same default fonts', async ({ page, browserName, browserType }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/11177' }); it.skip(browserName === 'firefox', 'Text is misaligned in headed vs headless'); const genericFontFamilies = [ 'standard', 'serif', 'sans-serif', 'monospace', 'cursive', 'fantasy', 'emoji' ]; const headlessBrowser = await browserType.launch({ headless: true }); const headlessPage = await headlessBrowser.newPage(); for (const family of genericFontFamilies) { const content = `