1/** 2 * Copyright 2018 Google Inc. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17import expect from 'expect'; 18import { 19 getTestState, 20 setupTestBrowserHooks, 21 itFailsFirefox, 22} from './mocha-utils'; // eslint-disable-line import/extensions 23import utils from './utils.js'; 24 25describe('BrowserContext', function () { 26 setupTestBrowserHooks(); 27 it('should have default context', async () => { 28 const { browser } = getTestState(); 29 expect(browser.browserContexts().length).toEqual(1); 30 const defaultContext = browser.browserContexts()[0]; 31 expect(defaultContext.isIncognito()).toBe(false); 32 let error = null; 33 await defaultContext.close().catch((error_) => (error = error_)); 34 expect(browser.defaultBrowserContext()).toBe(defaultContext); 35 expect(error.message).toContain('cannot be closed'); 36 }); 37 it('should create new incognito context', async () => { 38 const { browser } = getTestState(); 39 40 expect(browser.browserContexts().length).toBe(1); 41 const context = await browser.createIncognitoBrowserContext(); 42 expect(context.isIncognito()).toBe(true); 43 expect(browser.browserContexts().length).toBe(2); 44 expect(browser.browserContexts().indexOf(context) !== -1).toBe(true); 45 await context.close(); 46 expect(browser.browserContexts().length).toBe(1); 47 }); 48 it('should close all belonging targets once closing context', async () => { 49 const { browser } = getTestState(); 50 51 expect((await browser.pages()).length).toBe(1); 52 53 const context = await browser.createIncognitoBrowserContext(); 54 await context.newPage(); 55 expect((await browser.pages()).length).toBe(2); 56 expect((await context.pages()).length).toBe(1); 57 58 await context.close(); 59 expect((await browser.pages()).length).toBe(1); 60 }); 61 it('window.open should use parent tab context', async () => { 62 const { browser, server } = getTestState(); 63 64 const context = await browser.createIncognitoBrowserContext(); 65 const page = await context.newPage(); 66 await page.goto(server.EMPTY_PAGE); 67 const [popupTarget] = await Promise.all([ 68 utils.waitEvent(browser, 'targetcreated'), 69 page.evaluate<(url: string) => void>( 70 (url) => window.open(url), 71 server.EMPTY_PAGE 72 ), 73 ]); 74 expect(popupTarget.browserContext()).toBe(context); 75 await context.close(); 76 }); 77 it('should fire target events', async () => { 78 const { browser, server } = getTestState(); 79 80 const context = await browser.createIncognitoBrowserContext(); 81 const events = []; 82 context.on('targetcreated', (target) => 83 events.push('CREATED: ' + target.url()) 84 ); 85 context.on('targetchanged', (target) => 86 events.push('CHANGED: ' + target.url()) 87 ); 88 context.on('targetdestroyed', (target) => 89 events.push('DESTROYED: ' + target.url()) 90 ); 91 const page = await context.newPage(); 92 await page.goto(server.EMPTY_PAGE); 93 await page.close(); 94 expect(events).toEqual([ 95 'CREATED: about:blank', 96 `CHANGED: ${server.EMPTY_PAGE}`, 97 `DESTROYED: ${server.EMPTY_PAGE}`, 98 ]); 99 await context.close(); 100 }); 101 it('should wait for a target', async () => { 102 const { browser, puppeteer, server } = getTestState(); 103 104 const context = await browser.createIncognitoBrowserContext(); 105 let resolved = false; 106 107 const targetPromise = context.waitForTarget( 108 (target) => target.url() === server.EMPTY_PAGE 109 ); 110 targetPromise 111 .then(() => (resolved = true)) 112 .catch((error) => { 113 resolved = true; 114 if (error instanceof puppeteer.errors.TimeoutError) { 115 console.error(error); 116 } else throw error; 117 }); 118 const page = await context.newPage(); 119 expect(resolved).toBe(false); 120 await page.goto(server.EMPTY_PAGE); 121 try { 122 const target = await targetPromise; 123 expect(await target.page()).toBe(page); 124 } catch (error) { 125 if (error instanceof puppeteer.errors.TimeoutError) { 126 console.error(error); 127 } else throw error; 128 } 129 await context.close(); 130 }); 131 132 it('should timeout waiting for a non-existent target', async () => { 133 const { browser, puppeteer, server } = getTestState(); 134 135 const context = await browser.createIncognitoBrowserContext(); 136 const error = await context 137 .waitForTarget((target) => target.url() === server.EMPTY_PAGE, { 138 timeout: 1, 139 }) 140 .catch((error_) => error_); 141 expect(error).toBeInstanceOf(puppeteer.errors.TimeoutError); 142 await context.close(); 143 }); 144 145 it('should isolate localStorage and cookies', async () => { 146 const { browser, server } = getTestState(); 147 148 // Create two incognito contexts. 149 const context1 = await browser.createIncognitoBrowserContext(); 150 const context2 = await browser.createIncognitoBrowserContext(); 151 expect(context1.targets().length).toBe(0); 152 expect(context2.targets().length).toBe(0); 153 154 // Create a page in first incognito context. 155 const page1 = await context1.newPage(); 156 await page1.goto(server.EMPTY_PAGE); 157 await page1.evaluate(() => { 158 localStorage.setItem('name', 'page1'); 159 document.cookie = 'name=page1'; 160 }); 161 162 expect(context1.targets().length).toBe(1); 163 expect(context2.targets().length).toBe(0); 164 165 // Create a page in second incognito context. 166 const page2 = await context2.newPage(); 167 await page2.goto(server.EMPTY_PAGE); 168 await page2.evaluate(() => { 169 localStorage.setItem('name', 'page2'); 170 document.cookie = 'name=page2'; 171 }); 172 173 expect(context1.targets().length).toBe(1); 174 expect(context1.targets()[0]).toBe(page1.target()); 175 expect(context2.targets().length).toBe(1); 176 expect(context2.targets()[0]).toBe(page2.target()); 177 178 // Make sure pages don't share localstorage or cookies. 179 expect(await page1.evaluate(() => localStorage.getItem('name'))).toBe( 180 'page1' 181 ); 182 expect(await page1.evaluate(() => document.cookie)).toBe('name=page1'); 183 expect(await page2.evaluate(() => localStorage.getItem('name'))).toBe( 184 'page2' 185 ); 186 expect(await page2.evaluate(() => document.cookie)).toBe('name=page2'); 187 188 // Cleanup contexts. 189 await Promise.all([context1.close(), context2.close()]); 190 expect(browser.browserContexts().length).toBe(1); 191 }); 192 193 it('should work across sessions', async () => { 194 const { browser, puppeteer } = getTestState(); 195 196 expect(browser.browserContexts().length).toBe(1); 197 const context = await browser.createIncognitoBrowserContext(); 198 expect(browser.browserContexts().length).toBe(2); 199 const remoteBrowser = await puppeteer.connect({ 200 browserWSEndpoint: browser.wsEndpoint(), 201 }); 202 const contexts = remoteBrowser.browserContexts(); 203 expect(contexts.length).toBe(2); 204 remoteBrowser.disconnect(); 205 await context.close(); 206 }); 207}); 208