| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Copyright 2017 Google Inc. All rights reserved. | 
					
						
							| 
									
										
										
										
											2019-12-10 13:21:51 -08:00
										 |  |  |  * Modifications copyright (c) Microsoft Corporation. | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const path = require('path'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const FILE_TO_UPLOAD = path.join(__dirname, '/assets/file-to-upload.txt'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-18 17:11:45 -08:00
										 |  |  | module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROME, WEBKIT}) { | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |   const {describe, xdescribe, fdescribe} = testRunner; | 
					
						
							| 
									
										
										
										
											2019-12-19 15:47:35 -08:00
										 |  |  |   const {it, fit, xit, dit} = testRunner; | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |   const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; | 
					
						
							| 
									
										
										
										
											2019-12-11 22:43:06 -08:00
										 |  |  |   describe('input', function() { | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |     it('should upload the file', async({page, server}) => { | 
					
						
							|  |  |  |       await page.goto(server.PREFIX + '/input/fileupload.html'); | 
					
						
							|  |  |  |       const filePath = path.relative(process.cwd(), FILE_TO_UPLOAD); | 
					
						
							|  |  |  |       const input = await page.$('input'); | 
					
						
							| 
									
										
										
										
											2019-11-26 14:29:21 -08:00
										 |  |  |       await input.setInputFiles(filePath); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |       expect(await page.evaluate(e => e.files[0].name, input)).toBe('file-to-upload.txt'); | 
					
						
							|  |  |  |       expect(await page.evaluate(e => { | 
					
						
							|  |  |  |         const reader = new FileReader(); | 
					
						
							|  |  |  |         const promise = new Promise(fulfill => reader.onload = fulfill); | 
					
						
							|  |  |  |         reader.readAsText(e.files[0]); | 
					
						
							|  |  |  |         return promise.then(() => reader.result); | 
					
						
							|  |  |  |       }, input)).toBe('contents of the file'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-27 13:50:24 -08:00
										 |  |  |   describe('Page.waitForFileChooser', function() { | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |     it('should emit event', async({page, server}) => { | 
					
						
							|  |  |  |       await page.setContent(`<input type=file>`); | 
					
						
							|  |  |  |       const [chooser] = await Promise.all([ | 
					
						
							|  |  |  |         new Promise(f => page.once('filechooser', f)), | 
					
						
							|  |  |  |         page.click('input'), | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  |       expect(chooser).toBeTruthy(); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |     it('should work when file input is attached to DOM', async({page, server}) => { | 
					
						
							|  |  |  |       await page.setContent(`<input type=file>`); | 
					
						
							|  |  |  |       const [chooser] = await Promise.all([ | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |         page.waitForEvent('filechooser'), | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |         page.click('input'), | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  |       expect(chooser).toBeTruthy(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     it('should work when file input is not attached to DOM', async({page, server}) => { | 
					
						
							|  |  |  |       const [chooser] = await Promise.all([ | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |         page.waitForEvent('filechooser'), | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |         page.evaluate(() => { | 
					
						
							|  |  |  |           const el = document.createElement('input'); | 
					
						
							|  |  |  |           el.type = 'file'; | 
					
						
							|  |  |  |           el.click(); | 
					
						
							|  |  |  |         }), | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  |       expect(chooser).toBeTruthy(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     it('should respect timeout', async({page, server}) => { | 
					
						
							|  |  |  |       let error = null; | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |       await page.waitForEvent('filechooser', {timeout: 1}).catch(e => error = e); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |       expect(error).toBeInstanceOf(playwright.errors.TimeoutError); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     it('should respect default timeout when there is no custom timeout', async({page, server}) => { | 
					
						
							|  |  |  |       page.setDefaultTimeout(1); | 
					
						
							|  |  |  |       let error = null; | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |       await page.waitForEvent('filechooser').catch(e => error = e); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |       expect(error).toBeInstanceOf(playwright.errors.TimeoutError); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     it('should prioritize exact timeout over default timeout', async({page, server}) => { | 
					
						
							|  |  |  |       page.setDefaultTimeout(0); | 
					
						
							|  |  |  |       let error = null; | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |       await page.waitForEvent('filechooser', {timeout: 1}).catch(e => error = e); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |       expect(error).toBeInstanceOf(playwright.errors.TimeoutError); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     it('should work with no timeout', async({page, server}) => { | 
					
						
							|  |  |  |       const [chooser] = await Promise.all([ | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |         page.waitForEvent('filechooser', {timeout: 0}), | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |         page.evaluate(() => setTimeout(() => { | 
					
						
							|  |  |  |           const el = document.createElement('input'); | 
					
						
							|  |  |  |           el.type = 'file'; | 
					
						
							|  |  |  |           el.click(); | 
					
						
							|  |  |  |         }, 50)) | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  |       expect(chooser).toBeTruthy(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     it('should return the same file chooser when there are many watchdogs simultaneously', async({page, server}) => { | 
					
						
							|  |  |  |       await page.setContent(`<input type=file>`); | 
					
						
							|  |  |  |       const [fileChooser1, fileChooser2] = await Promise.all([ | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |         page.waitForEvent('filechooser'), | 
					
						
							|  |  |  |         page.waitForEvent('filechooser'), | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |         page.$eval('input', input => input.click()), | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  |       expect(fileChooser1 === fileChooser2).toBe(true); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     it('should accept single file', async({page, server}) => { | 
					
						
							|  |  |  |       await page.setContent(`<input type=file oninput='javascript:console.timeStamp()'>`); | 
					
						
							| 
									
										
										
										
											2019-11-27 16:18:04 -08:00
										 |  |  |       const [{ element }] = await Promise.all([ | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |         page.waitForEvent('filechooser'), | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |         page.click('input'), | 
					
						
							|  |  |  |       ]); | 
					
						
							| 
									
										
										
										
											2019-11-27 16:18:04 -08:00
										 |  |  |       await element.setInputFiles(FILE_TO_UPLOAD); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |       expect(await page.$eval('input', input => input.files.length)).toBe(1); | 
					
						
							|  |  |  |       expect(await page.$eval('input', input => input.files[0].name)).toBe('file-to-upload.txt'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     it('should be able to read selected file', async({page, server}) => { | 
					
						
							|  |  |  |       await page.setContent(`<input type=file>`); | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |       page.waitForEvent('filechooser').then(({element}) => element.setInputFiles(FILE_TO_UPLOAD)); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |       expect(await page.$eval('input', async picker => { | 
					
						
							|  |  |  |         picker.click(); | 
					
						
							|  |  |  |         await new Promise(x => picker.oninput = x); | 
					
						
							|  |  |  |         const reader = new FileReader(); | 
					
						
							|  |  |  |         const promise = new Promise(fulfill => reader.onload = fulfill); | 
					
						
							|  |  |  |         reader.readAsText(picker.files[0]); | 
					
						
							|  |  |  |         return promise.then(() => reader.result); | 
					
						
							|  |  |  |       })).toBe('contents of the file'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     it('should be able to reset selected files with empty file list', async({page, server}) => { | 
					
						
							|  |  |  |       await page.setContent(`<input type=file>`); | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |       page.waitForEvent('filechooser').then(({element}) => element.setInputFiles(FILE_TO_UPLOAD)); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |       expect(await page.$eval('input', async picker => { | 
					
						
							|  |  |  |         picker.click(); | 
					
						
							|  |  |  |         await new Promise(x => picker.oninput = x); | 
					
						
							|  |  |  |         return picker.files.length; | 
					
						
							|  |  |  |       })).toBe(1); | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |       page.waitForEvent('filechooser').then(({element}) => element.setInputFiles()); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |       expect(await page.$eval('input', async picker => { | 
					
						
							|  |  |  |         picker.click(); | 
					
						
							|  |  |  |         await new Promise(x => picker.oninput = x); | 
					
						
							|  |  |  |         return picker.files.length; | 
					
						
							|  |  |  |       })).toBe(0); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     it('should not accept multiple files for single-file input', async({page, server}) => { | 
					
						
							|  |  |  |       await page.setContent(`<input type=file>`); | 
					
						
							| 
									
										
										
										
											2019-11-27 16:18:04 -08:00
										 |  |  |       const [{ element }] = await Promise.all([ | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |         page.waitForEvent('filechooser'), | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |         page.click('input'), | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  |       let error = null; | 
					
						
							| 
									
										
										
										
											2019-11-27 16:18:04 -08:00
										 |  |  |       await element.setInputFiles( | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |         path.relative(process.cwd(), __dirname + '/assets/file-to-upload.txt'), | 
					
						
							| 
									
										
										
										
											2019-11-27 16:18:04 -08:00
										 |  |  |         path.relative(process.cwd(), __dirname + '/assets/pptr.png')).catch(e => error = e); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |       expect(error).not.toBe(null); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-27 16:18:04 -08:00
										 |  |  |   describe('Page.waitForFileChooser isMultiple', () => { | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |     it('should work for single file pick', async({page, server}) => { | 
					
						
							|  |  |  |       await page.setContent(`<input type=file>`); | 
					
						
							| 
									
										
										
										
											2019-11-27 16:18:04 -08:00
										 |  |  |       const [{ multiple }] = await Promise.all([ | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |         page.waitForEvent('filechooser'), | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |         page.click('input'), | 
					
						
							|  |  |  |       ]); | 
					
						
							| 
									
										
										
										
											2019-11-27 16:18:04 -08:00
										 |  |  |       expect(multiple).toBe(false); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  |     it('should work for "multiple"', async({page, server}) => { | 
					
						
							|  |  |  |       await page.setContent(`<input multiple type=file>`); | 
					
						
							| 
									
										
										
										
											2019-11-27 16:18:04 -08:00
										 |  |  |       const [{ multiple }] = await Promise.all([ | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |         page.waitForEvent('filechooser'), | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |         page.click('input'), | 
					
						
							|  |  |  |       ]); | 
					
						
							| 
									
										
										
										
											2019-11-27 16:18:04 -08:00
										 |  |  |       expect(multiple).toBe(true); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  |     it('should work for "webkitdirectory"', async({page, server}) => { | 
					
						
							|  |  |  |       await page.setContent(`<input multiple webkitdirectory type=file>`); | 
					
						
							| 
									
										
										
										
											2019-11-27 16:18:04 -08:00
										 |  |  |       const [{ multiple }] = await Promise.all([ | 
					
						
							| 
									
										
										
										
											2019-12-17 17:34:32 -08:00
										 |  |  |         page.waitForEvent('filechooser'), | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |         page.click('input'), | 
					
						
							|  |  |  |       ]); | 
					
						
							| 
									
										
										
										
											2019-11-27 16:18:04 -08:00
										 |  |  |       expect(multiple).toBe(true); | 
					
						
							| 
									
										
										
										
											2019-11-18 18:18:28 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }; |