feat: make React and Vue selectors experimental (#8106)
This commit is contained in:
		
							parent
							
								
									792986c92d
								
							
						
					
					
						commit
						4975f4179e
					
				|  | @ -179,40 +179,40 @@ methods accept [`param: selector`] as their first argument. | ||||||
|   await page.ClickAsync("xpath=//button"); |   await page.ClickAsync("xpath=//button"); | ||||||
|   ``` |   ``` | ||||||
|   Learn more about [XPath selector][xpath]. |   Learn more about [XPath selector][xpath]. | ||||||
| - React selector | - React selector (experimental) | ||||||
|   ```js |   ```js | ||||||
|   await page.click('react=ListItem[text *= "milk" i]'); |   await page.click('_react=ListItem[text *= "milk" i]'); | ||||||
|   ``` |   ``` | ||||||
|   ```java |   ```java | ||||||
|   page.click("react=ListItem[text *= 'milk' i]"); |   page.click("_react=ListItem[text *= 'milk' i]"); | ||||||
|   ``` |   ``` | ||||||
|   ```python async |   ```python async | ||||||
|   await page.click("react=ListItem[text *= 'milk' i]") |   await page.click("_react=ListItem[text *= 'milk' i]") | ||||||
|   ``` |   ``` | ||||||
|   ```python sync |   ```python sync | ||||||
|   page.click("react=ListItem[text *= 'milk' i]") |   page.click("_react=ListItem[text *= 'milk' i]") | ||||||
|   ``` |   ``` | ||||||
|   ```csharp |   ```csharp | ||||||
|   await page.ClickAsync("react=ListItem[text *= 'milk' i]"); |   await page.ClickAsync("_react=ListItem[text *= 'milk' i]"); | ||||||
|   ``` |   ``` | ||||||
|   Learn more about [React selector][react]. |   Learn more about [React selectors][react]. | ||||||
| - Vue selector | - Vue selector (experimental) | ||||||
|   ```js |   ```js | ||||||
|   await page.click('vue=list-item[text *= "milk" i]'); |   await page.click('_vue=list-item[text *= "milk" i]'); | ||||||
|   ``` |   ``` | ||||||
|   ```java |   ```java | ||||||
|   page.click("vue=list-item[text *= 'milk' i]"); |   page.click("_vue=list-item[text *= 'milk' i]"); | ||||||
|   ``` |   ``` | ||||||
|   ```python async |   ```python async | ||||||
|   await page.click("vue=list-item[text *= "milk" i]") |   await page.click("_vue=list-item[text *= "milk" i]") | ||||||
|   ``` |   ``` | ||||||
|   ```python sync |   ```python sync | ||||||
|   page.click("vue=list-item[text *= 'milk' i]") |   page.click("_vue=list-item[text *= 'milk' i]") | ||||||
|   ``` |   ``` | ||||||
|   ```csharp |   ```csharp | ||||||
|   await page.ClickAsync("vue=list-item[text *= 'milk' i]"); |   await page.ClickAsync("_vue=list-item[text *= 'milk' i]"); | ||||||
|   ``` |   ``` | ||||||
|   Learn more about [Vue selector][vue]. |   Learn more about [Vue selectors][vue]. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -663,22 +663,26 @@ converts `'//html/body'` to `'xpath=//html/body'`. | ||||||
| 
 | 
 | ||||||
| ## React selectors | ## React selectors | ||||||
| 
 | 
 | ||||||
|  | :::note | ||||||
|  | React selectors are experimental and prefixed with `_`. The functionality might change in future. | ||||||
|  | ::: | ||||||
|  | 
 | ||||||
| React selectors allow selecting elements by its component name and property values. The syntax is very similar to [attribute selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) and supports all attribute selector operators. | React selectors allow selecting elements by its component name and property values. The syntax is very similar to [attribute selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) and supports all attribute selector operators. | ||||||
| 
 | 
 | ||||||
| In react selectors, component names are transcribed with **CamelCase**. | In react selectors, component names are transcribed with **CamelCase**. | ||||||
| 
 | 
 | ||||||
| Selector examples: | Selector examples: | ||||||
| 
 | 
 | ||||||
| - match by **component**: `react=BookItem` | - match by **component**: `_react=BookItem` | ||||||
| - match by component and **exact property value**, case-sensetive: `react=BookItem[author = "Steven King"]` | - match by component and **exact property value**, case-sensetive: `_react=BookItem[author = "Steven King"]` | ||||||
| - match by property value only, **case-insensetive**: `react=[author = "steven king" i]` | - match by property value only, **case-insensetive**: `_react=[author = "steven king" i]` | ||||||
| - match by component and **truthy property value**: `react=MyButton[enabled]` | - match by component and **truthy property value**: `_react=MyButton[enabled]` | ||||||
| - match by component and **boolean value**: `react=MyButton[enabled = false]` | - match by component and **boolean value**: `_react=MyButton[enabled = false]` | ||||||
| - match by property **value substring**: `react=[author *= "King"]` | - match by property **value substring**: `_react=[author *= "King"]` | ||||||
| - match by component and **multiple properties**: `react=BookItem[author *= "king" i][year = 1990]` | - match by component and **multiple properties**: `_react=BookItem[author *= "king" i][year = 1990]` | ||||||
| - match by **nested** property value: `react=[some.nested.value = 12]` | - match by **nested** property value: `_react=[some.nested.value = 12]` | ||||||
| - match by component and property value **prefix**: `react=BookItem[author ^= "Steven"]` | - match by component and property value **prefix**: `_react=BookItem[author ^= "Steven"]` | ||||||
| - match by component and property value **suffix**: `react=BookItem[author $= "Steven"]` | - match by component and property value **suffix**: `_react=BookItem[author $= "Steven"]` | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -695,22 +699,26 @@ React selectors, as well as [React DevTools](https://chrome.google.com/webstore/ | ||||||
| 
 | 
 | ||||||
| ## Vue selectors | ## Vue selectors | ||||||
| 
 | 
 | ||||||
|  | :::note | ||||||
|  | Vue selectors are experimental and prefixed with `_`. The functionality might change in future. | ||||||
|  | ::: | ||||||
|  | 
 | ||||||
| Vue selectors allow selecting elements by its component name and property values. The syntax is very similar to [attribute selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) and supports all attribute selector operators. | Vue selectors allow selecting elements by its component name and property values. The syntax is very similar to [attribute selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) and supports all attribute selector operators. | ||||||
| 
 | 
 | ||||||
| In vue selectors, component names are transcribed with **kebab-case**. | In vue selectors, component names are transcribed with **kebab-case**. | ||||||
| 
 | 
 | ||||||
| Selector examples: | Selector examples: | ||||||
| 
 | 
 | ||||||
| - match by **component**: `vue=book-item` | - match by **component**: `_vue=book-item` | ||||||
| - match by component and **exact property value**, case-sensetive: `vue=book-item[author = "Steven King"]` | - match by component and **exact property value**, case-sensetive: `_vue=book-item[author = "Steven King"]` | ||||||
| - match by property value only, **case-insensetive**: `vue=[author = "steven king" i]` | - match by property value only, **case-insensetive**: `_vue=[author = "steven king" i]` | ||||||
| - match by component and **truthy property value**: `vue=my-button[enabled]` | - match by component and **truthy property value**: `_vue=my-button[enabled]` | ||||||
| - match by component and **boolean value**: `vue=my-button[enabled = false]` | - match by component and **boolean value**: `_vue=my-button[enabled = false]` | ||||||
| - match by property **value substring**: `vue=[author *= "King"]` | - match by property **value substring**: `_vue=[author *= "King"]` | ||||||
| - match by component and **multiple properties**: `vue=book-item[author *= "king" i][year = 1990]` | - match by component and **multiple properties**: `_vue=book-item[author *= "king" i][year = 1990]` | ||||||
| - match by **nested** property value: `vue=[some.nested.value = 12]` | - match by **nested** property value: `_vue=[some.nested.value = 12]` | ||||||
| - match by component and property value **prefix**: `vue=book-item[author ^= "Steven"]` | - match by component and property value **prefix**: `_vue=book-item[author ^= "Steven"]` | ||||||
| - match by component and property value **suffix**: `vue=book-item[author $= "Steven"]` | - match by component and property value **suffix**: `_vue=book-item[author $= "Steven"]` | ||||||
| 
 | 
 | ||||||
| To find Vue element names in a tree use [Vue DevTools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=en). | To find Vue element names in a tree use [Vue DevTools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=en). | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -64,8 +64,8 @@ export class InjectedScript { | ||||||
|     this._engines = new Map(); |     this._engines = new Map(); | ||||||
|     this._engines.set('xpath', XPathEngine); |     this._engines.set('xpath', XPathEngine); | ||||||
|     this._engines.set('xpath:light', XPathEngine); |     this._engines.set('xpath:light', XPathEngine); | ||||||
|     this._engines.set('react', ReactEngine); |     this._engines.set('_react', ReactEngine); | ||||||
|     this._engines.set('vue', VueEngine); |     this._engines.set('_vue', VueEngine); | ||||||
|     this._engines.set('text', this._createTextEngine(true)); |     this._engines.set('text', this._createTextEngine(true)); | ||||||
|     this._engines.set('text:light', this._createTextEngine(false)); |     this._engines.set('text:light', this._createTextEngine(false)); | ||||||
|     this._engines.set('id', this._createAttributeEngine('id', true)); |     this._engines.set('id', this._createAttributeEngine('id', true)); | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ export class Selectors { | ||||||
|     this._builtinEngines = new Set([ |     this._builtinEngines = new Set([ | ||||||
|       'css', 'css:light', |       'css', 'css:light', | ||||||
|       'xpath', 'xpath:light', |       'xpath', 'xpath:light', | ||||||
|       'react', 'vue', |       '_react', '_vue', | ||||||
|       'text', 'text:light', |       'text', 'text:light', | ||||||
|       'id', 'id:light', |       'id', 'id:light', | ||||||
|       'data-testid', 'data-testid:light', |       'data-testid', 'data-testid:light', | ||||||
|  | @ -48,7 +48,7 @@ export class Selectors { | ||||||
|       '_visible', '_nth' |       '_visible', '_nth' | ||||||
|     ]); |     ]); | ||||||
|     this._builtinEnginesInMainWorld = new Set([ |     this._builtinEnginesInMainWorld = new Set([ | ||||||
|       'react', 'vue', |       '_react', '_vue', | ||||||
|     ]); |     ]); | ||||||
|     this._engines = new Map(); |     this._engines = new Map(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -30,79 +30,79 @@ for (const [name, url] of Object.entries(reacts)) { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should work with single-root elements', async ({page}) => { |     it('should work with single-root elements', async ({page}) => { | ||||||
|       expect(await page.$$eval(`react=BookList`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=BookList`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`react=BookItem`, els => els.length)).toBe(3); |       expect(await page.$$eval(`_react=BookItem`, els => els.length)).toBe(3); | ||||||
|       expect(await page.$$eval(`react=BookList >> react=BookItem`, els => els.length)).toBe(3); |       expect(await page.$$eval(`_react=BookList >> _react=BookItem`, els => els.length)).toBe(3); | ||||||
|       expect(await page.$$eval(`react=BookItem >> react=BookList`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_react=BookItem >> _react=BookList`, els => els.length)).toBe(0); | ||||||
| 
 | 
 | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should work with multi-root elements (fragments)', async ({page}) => { |     it('should work with multi-root elements (fragments)', async ({page}) => { | ||||||
|       it.skip(name === 'react15', 'React 15 does not support fragments'); |       it.skip(name === 'react15', 'React 15 does not support fragments'); | ||||||
|       expect(await page.$$eval(`react=App`, els => els.length)).toBe(14); |       expect(await page.$$eval(`_react=App`, els => els.length)).toBe(14); | ||||||
|       expect(await page.$$eval(`react=AppHeader`, els => els.length)).toBe(2); |       expect(await page.$$eval(`_react=AppHeader`, els => els.length)).toBe(2); | ||||||
|       expect(await page.$$eval(`react=NewBook`, els => els.length)).toBe(2); |       expect(await page.$$eval(`_react=NewBook`, els => els.length)).toBe(2); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should not crash when there is no match', async ({page}) => { |     it('should not crash when there is no match', async ({page}) => { | ||||||
|       expect(await page.$$eval(`react=Apps`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_react=Apps`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`react=BookLi`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_react=BookLi`, els => els.length)).toBe(0); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should compose', async ({page}) => { |     it('should compose', async ({page}) => { | ||||||
|       expect(await page.$eval(`react=NewBook >> react=button`, el => el.textContent)).toBe('new book'); |       expect(await page.$eval(`_react=NewBook >> _react=button`, el => el.textContent)).toBe('new book'); | ||||||
|       expect(await page.$eval(`react=NewBook >> react=input`, el => el.tagName)).toBe('INPUT'); |       expect(await page.$eval(`_react=NewBook >> _react=input`, el => el.tagName)).toBe('INPUT'); | ||||||
|       expect(await page.$eval(`react=BookItem >> text=Gatsby`, el => el.textContent)).toBe('The Great Gatsby'); |       expect(await page.$eval(`_react=BookItem >> text=Gatsby`, el => el.textContent)).toBe('The Great Gatsby'); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should query by props combinations', async ({page}) => { |     it('should query by props combinations', async ({page}) => { | ||||||
|       expect(await page.$$eval(`react=BookItem[name="The Great Gatsby"]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=BookItem[name="The Great Gatsby"]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`react=BookItem[name="the great gatsby" i]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=BookItem[name="the great gatsby" i]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`react=ColorButton[nested.index = 0]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=ColorButton[nested.index = 0]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`react=ColorButton[nested.nonexisting.index = 0]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_react=ColorButton[nested.nonexisting.index = 0]`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`react=ColorButton[nested.index.nonexisting = 0]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_react=ColorButton[nested.index.nonexisting = 0]`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`react=ColorButton[nested.index.nonexisting = 1]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_react=ColorButton[nested.index.nonexisting = 1]`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`react=ColorButton[nested.value = 4.1]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=ColorButton[nested.value = 4.1]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`react=ColorButton[enabled = false]`, els => els.length)).toBe(4); |       expect(await page.$$eval(`_react=ColorButton[enabled = false]`, els => els.length)).toBe(4); | ||||||
|       expect(await page.$$eval(`react=ColorButton[enabled = true] `, els => els.length)).toBe(5); |       expect(await page.$$eval(`_react=ColorButton[enabled = true] `, els => els.length)).toBe(5); | ||||||
|       expect(await page.$$eval(`react=ColorButton[enabled = true][color = "red"]`, els => els.length)).toBe(2); |       expect(await page.$$eval(`_react=ColorButton[enabled = true][color = "red"]`, els => els.length)).toBe(2); | ||||||
|       expect(await page.$$eval(`react=ColorButton[enabled = true][color = "red"i][nested.index =  6]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=ColorButton[enabled = true][color = "red"i][nested.index =  6]`, els => els.length)).toBe(1); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should exact match by props', async ({page}) => { |     it('should exact match by props', async ({page}) => { | ||||||
|       expect(await page.$eval(`react=BookItem[name = "The Great Gatsby"]`, el => el.textContent)).toBe('The Great Gatsby'); |       expect(await page.$eval(`_react=BookItem[name = "The Great Gatsby"]`, el => el.textContent)).toBe('The Great Gatsby'); | ||||||
|       expect(await page.$$eval(`react=BookItem[name = "The Great Gatsby"]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=BookItem[name = "The Great Gatsby"]`, els => els.length)).toBe(1); | ||||||
|       // case sensetive by default
 |       // case sensetive by default
 | ||||||
|       expect(await page.$$eval(`react=BookItem[name = "the great gatsby"]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_react=BookItem[name = "the great gatsby"]`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`react=BookItem[name = "the great gatsby" s]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_react=BookItem[name = "the great gatsby" s]`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`react=BookItem[name = "the great gatsby" S]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_react=BookItem[name = "the great gatsby" S]`, els => els.length)).toBe(0); | ||||||
|       // case insensetive with flag
 |       // case insensetive with flag
 | ||||||
|       expect(await page.$$eval(`react=BookItem[name = "the great gatsby" i]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=BookItem[name = "the great gatsby" i]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`react=BookItem[name = "the great gatsby" I]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=BookItem[name = "the great gatsby" I]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`react=BookItem[name = "  The Great Gatsby  "]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_react=BookItem[name = "  The Great Gatsby  "]`, els => els.length)).toBe(0); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should partially match by props', async ({page}) => { |     it('should partially match by props', async ({page}) => { | ||||||
|       // Check partial matching
 |       // Check partial matching
 | ||||||
|       expect(await page.$eval(`react=BookItem[name *= "Gatsby"]`, el => el.textContent)).toBe('The Great Gatsby'); |       expect(await page.$eval(`_react=BookItem[name *= "Gatsby"]`, el => el.textContent)).toBe('The Great Gatsby'); | ||||||
|       expect(await page.$$eval(`react=BookItem[name *= "Gatsby"]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=BookItem[name *= "Gatsby"]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`react=[name *= "Gatsby"]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=[name *= "Gatsby"]`, els => els.length)).toBe(1); | ||||||
| 
 | 
 | ||||||
|       expect(await page.$$eval(`react=BookItem[name = "Gatsby"]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_react=BookItem[name = "Gatsby"]`, els => els.length)).toBe(0); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should support all string operators', async ({page}) => { |     it('should support all string operators', async ({page}) => { | ||||||
|       expect(await page.$$eval(`react=ColorButton[color = "red"]`, els => els.length)).toBe(3); |       expect(await page.$$eval(`_react=ColorButton[color = "red"]`, els => els.length)).toBe(3); | ||||||
|       expect(await page.$$eval(`react=ColorButton[color |= "red"]`, els => els.length)).toBe(3); |       expect(await page.$$eval(`_react=ColorButton[color |= "red"]`, els => els.length)).toBe(3); | ||||||
|       expect(await page.$$eval(`react=ColorButton[color $= "ed"]`, els => els.length)).toBe(3); |       expect(await page.$$eval(`_react=ColorButton[color $= "ed"]`, els => els.length)).toBe(3); | ||||||
|       expect(await page.$$eval(`react=ColorButton[color ^= "gr"]`, els => els.length)).toBe(3); |       expect(await page.$$eval(`_react=ColorButton[color ^= "gr"]`, els => els.length)).toBe(3); | ||||||
|       expect(await page.$$eval(`react=ColorButton[color ~= "e"]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_react=ColorButton[color ~= "e"]`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`react=BookItem[name ~= "gatsby" i]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=BookItem[name ~= "gatsby" i]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`react=BookItem[name *= " gatsby" i]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_react=BookItem[name *= " gatsby" i]`, els => els.length)).toBe(1); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should support truthy querying', async ({page}) => { |     it('should support truthy querying', async ({page}) => { | ||||||
|       expect(await page.$$eval(`react=ColorButton[enabled]`, els => els.length)).toBe(5); |       expect(await page.$$eval(`_react=ColorButton[enabled]`, els => els.length)).toBe(5); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -29,77 +29,77 @@ for (const [name, url] of Object.entries(vues)) { | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should work with single-root elements', async ({page}) => { |     it('should work with single-root elements', async ({page}) => { | ||||||
|       expect(await page.$$eval(`vue=book-list`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=book-list`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`vue=book-item`, els => els.length)).toBe(3); |       expect(await page.$$eval(`_vue=book-item`, els => els.length)).toBe(3); | ||||||
|       expect(await page.$$eval(`vue=book-list >> vue=book-item`, els => els.length)).toBe(3); |       expect(await page.$$eval(`_vue=book-list >> _vue=book-item`, els => els.length)).toBe(3); | ||||||
|       expect(await page.$$eval(`vue=book-item >> vue=book-list`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_vue=book-item >> _vue=book-list`, els => els.length)).toBe(0); | ||||||
| 
 | 
 | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should work with multi-root elements (fragments)', async ({page}) => { |     it('should work with multi-root elements (fragments)', async ({page}) => { | ||||||
|       it.skip(name === 'vue2', 'vue2 does not support fragments'); |       it.skip(name === 'vue2', 'vue2 does not support fragments'); | ||||||
|       expect(await page.$$eval(`vue=Root`, els => els.length)).toBe(14); |       expect(await page.$$eval(`_vue=Root`, els => els.length)).toBe(14); | ||||||
|       expect(await page.$$eval(`vue=app-header`, els => els.length)).toBe(2); |       expect(await page.$$eval(`_vue=app-header`, els => els.length)).toBe(2); | ||||||
|       expect(await page.$$eval(`vue=new-book`, els => els.length)).toBe(2); |       expect(await page.$$eval(`_vue=new-book`, els => els.length)).toBe(2); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should not crash when there is no match', async ({page}) => { |     it('should not crash when there is no match', async ({page}) => { | ||||||
|       expect(await page.$$eval(`vue=apps`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_vue=apps`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`vue=book-li`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_vue=book-li`, els => els.length)).toBe(0); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should compose', async ({page}) => { |     it('should compose', async ({page}) => { | ||||||
|       expect(await page.$eval(`vue=book-item >> text=Gatsby`, el => el.textContent.trim())).toBe('The Great Gatsby'); |       expect(await page.$eval(`_vue=book-item >> text=Gatsby`, el => el.textContent.trim())).toBe('The Great Gatsby'); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should query by props combinations', async ({page}) => { |     it('should query by props combinations', async ({page}) => { | ||||||
|       expect(await page.$$eval(`vue=book-item[name="The Great Gatsby"]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=book-item[name="The Great Gatsby"]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`vue=book-item[name="the great gatsby" i]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=book-item[name="the great gatsby" i]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`vue=color-button[nested.index = 0]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=color-button[nested.index = 0]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`vue=color-button[nested.nonexisting.index = 0]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_vue=color-button[nested.nonexisting.index = 0]`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`vue=color-button[nested.index.nonexisting = 0]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_vue=color-button[nested.index.nonexisting = 0]`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`vue=color-button[nested.index.nonexisting = 1]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_vue=color-button[nested.index.nonexisting = 1]`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`vue=color-button[nested.value = 4.1]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=color-button[nested.value = 4.1]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`vue=color-button[enabled = false]`, els => els.length)).toBe(4); |       expect(await page.$$eval(`_vue=color-button[enabled = false]`, els => els.length)).toBe(4); | ||||||
|       expect(await page.$$eval(`vue=color-button[enabled = true] `, els => els.length)).toBe(5); |       expect(await page.$$eval(`_vue=color-button[enabled = true] `, els => els.length)).toBe(5); | ||||||
|       expect(await page.$$eval(`vue=color-button[enabled = true][color = "red"]`, els => els.length)).toBe(2); |       expect(await page.$$eval(`_vue=color-button[enabled = true][color = "red"]`, els => els.length)).toBe(2); | ||||||
|       expect(await page.$$eval(`vue=color-button[enabled = true][color = "red"i][nested.index =  6]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=color-button[enabled = true][color = "red"i][nested.index =  6]`, els => els.length)).toBe(1); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should exact match by props', async ({page}) => { |     it('should exact match by props', async ({page}) => { | ||||||
|       expect(await page.$eval(`vue=book-item[name = "The Great Gatsby"]`, el => el.textContent)).toBe('The Great Gatsby'); |       expect(await page.$eval(`_vue=book-item[name = "The Great Gatsby"]`, el => el.textContent)).toBe('The Great Gatsby'); | ||||||
|       expect(await page.$$eval(`vue=book-item[name = "The Great Gatsby"]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=book-item[name = "The Great Gatsby"]`, els => els.length)).toBe(1); | ||||||
|       // case sensetive by default
 |       // case sensetive by default
 | ||||||
|       expect(await page.$$eval(`vue=book-item[name = "the great gatsby"]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_vue=book-item[name = "the great gatsby"]`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`vue=book-item[name = "the great gatsby" s]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_vue=book-item[name = "the great gatsby" s]`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`vue=book-item[name = "the great gatsby" S]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_vue=book-item[name = "the great gatsby" S]`, els => els.length)).toBe(0); | ||||||
|       // case insensetive with flag
 |       // case insensetive with flag
 | ||||||
|       expect(await page.$$eval(`vue=book-item[name = "the great gatsby" i]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=book-item[name = "the great gatsby" i]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`vue=book-item[name = "the great gatsby" I]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=book-item[name = "the great gatsby" I]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`vue=book-item[name = "  The Great Gatsby  "]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_vue=book-item[name = "  The Great Gatsby  "]`, els => els.length)).toBe(0); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should partially match by props', async ({page}) => { |     it('should partially match by props', async ({page}) => { | ||||||
|       // Check partial matching
 |       // Check partial matching
 | ||||||
|       expect(await page.$eval(`vue=book-item[name *= "Gatsby"]`, el => el.textContent)).toBe('The Great Gatsby'); |       expect(await page.$eval(`_vue=book-item[name *= "Gatsby"]`, el => el.textContent)).toBe('The Great Gatsby'); | ||||||
|       expect(await page.$$eval(`vue=book-item[name *= "Gatsby"]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=book-item[name *= "Gatsby"]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`vue=[name *= "Gatsby"]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=[name *= "Gatsby"]`, els => els.length)).toBe(1); | ||||||
| 
 | 
 | ||||||
|       expect(await page.$$eval(`vue=book-item[name = "Gatsby"]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_vue=book-item[name = "Gatsby"]`, els => els.length)).toBe(0); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should support all string operators', async ({page}) => { |     it('should support all string operators', async ({page}) => { | ||||||
|       expect(await page.$$eval(`vue=color-button[color = "red"]`, els => els.length)).toBe(3); |       expect(await page.$$eval(`_vue=color-button[color = "red"]`, els => els.length)).toBe(3); | ||||||
|       expect(await page.$$eval(`vue=color-button[color |= "red"]`, els => els.length)).toBe(3); |       expect(await page.$$eval(`_vue=color-button[color |= "red"]`, els => els.length)).toBe(3); | ||||||
|       expect(await page.$$eval(`vue=color-button[color $= "ed"]`, els => els.length)).toBe(3); |       expect(await page.$$eval(`_vue=color-button[color $= "ed"]`, els => els.length)).toBe(3); | ||||||
|       expect(await page.$$eval(`vue=color-button[color ^= "gr"]`, els => els.length)).toBe(3); |       expect(await page.$$eval(`_vue=color-button[color ^= "gr"]`, els => els.length)).toBe(3); | ||||||
|       expect(await page.$$eval(`vue=color-button[color ~= "e"]`, els => els.length)).toBe(0); |       expect(await page.$$eval(`_vue=color-button[color ~= "e"]`, els => els.length)).toBe(0); | ||||||
|       expect(await page.$$eval(`vue=book-item[name ~= "gatsby" i]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=book-item[name ~= "gatsby" i]`, els => els.length)).toBe(1); | ||||||
|       expect(await page.$$eval(`vue=book-item[name *= " gatsby" i]`, els => els.length)).toBe(1); |       expect(await page.$$eval(`_vue=book-item[name *= " gatsby" i]`, els => els.length)).toBe(1); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should support truthy querying', async ({page}) => { |     it('should support truthy querying', async ({page}) => { | ||||||
|       expect(await page.$$eval(`vue=color-button[enabled]`, els => els.length)).toBe(5); |       expect(await page.$$eval(`_vue=color-button[enabled]`, els => els.length)).toBe(5); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue