/**
 * Copyright (c) Microsoft Corporation.
 *
 * 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 { test, expect } from './pageTest';
test('should detect roles', async ({ page }) => {
  await page.setContent(`
    Hello 
    
Heading 
    Hello I am a dialog
  `);
  expect(await page.locator(`role=button`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello `,
  ]);
  expect(await page.locator(`role=listbox`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Heading `,
  ]);
  expect(await page.locator(`role=group`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello I am a dialog
`,
  ]);
  expect(await page.locator(`role=menuitem`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
  ]);
  expect(await page.getByRole('menuitem').evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
  ]);
});
test('should support selected', async ({ page }) => {
  await page.setContent(`
    
      Hi 
      Hello 
     
    
  `);
  expect(await page.locator(`role=option[selected]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello `,
    `Hi
`,
  ]);
  expect(await page.locator(`role=option[selected=true]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello `,
    `Hi
`,
  ]);
  expect(await page.getByRole('option', { selected: true }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello `,
    `Hi
`,
  ]);
  expect(await page.locator(`role=option[selected=false]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
    `Hello
`,
  ]);
  expect(await page.getByRole('option', { selected: false }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
    `Hello
`,
  ]);
});
test('should support checked', async ({ page }) => {
  await page.setContent(`
    Hi
    Hello
    Unknown
  `);
  await page.$eval('[indeterminate]', input => (input as HTMLInputElement).indeterminate = true);
  expect(await page.locator(`role=checkbox[checked]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi
`,
  ]);
  expect(await page.locator(`role=checkbox[checked=true]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi
`,
  ]);
  expect(await page.getByRole('checkbox', { checked: true }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi
`,
  ]);
  expect(await page.locator(`role=checkbox[checked=false]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello
`,
    `Unknown
`,
  ]);
  expect(await page.getByRole('checkbox', { checked: false }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello
`,
    `Unknown
`,
  ]);
  expect(await page.locator(`role=checkbox[checked="mixed"]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi
`,
    `Hello
`,
    `Unknown
`,
  ]);
});
test('should support pressed', async ({ page }) => {
  await page.setContent(`
    Hi 
    Hello 
    Bye 
    Mixed 
  `);
  expect(await page.locator(`role=button[pressed]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello `,
  ]);
  expect(await page.locator(`role=button[pressed=true]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello `,
  ]);
  expect(await page.getByRole('button', { pressed: true }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello `,
  ]);
  expect(await page.locator(`role=button[pressed=false]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
    `Bye `,
  ]);
  expect(await page.getByRole('button', { pressed: false }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
    `Bye `,
  ]);
  expect(await page.locator(`role=button[pressed="mixed"]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Mixed `,
  ]);
  expect(await page.locator(`role=button`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
    `Hello `,
    `Bye `,
    `Mixed `,
  ]);
});
test('should support expanded', async ({ page }) => {
  await page.setContent(`
    Hi
    Hello
    Bye
  `);
  expect(await page.locator('role=treeitem').evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi
`,
    `Hello
`,
    `Bye
`,
  ]);
  expect(await page.getByRole('treeitem').evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi
`,
    `Hello
`,
    `Bye
`,
  ]);
  expect(await page.locator(`role=treeitem[expanded]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello
`,
  ]);
  expect(await page.locator(`role=treeitem[expanded=true]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello
`,
  ]);
  expect(await page.getByRole('treeitem', { expanded: true }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello
`,
  ]);
  expect(await page.locator(`role=treeitem[expanded=false]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Bye
`,
  ]);
  expect(await page.getByRole('treeitem', { expanded: false }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Bye
`,
  ]);
  // Workaround for expanded="none".
  expect(await page.locator(`[role=treeitem]:not([aria-expanded])`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi
`,
  ]);
});
test('should support disabled', async ({ page }) => {
  await page.setContent(`
    Hi 
    Bye 
    Hello 
    Oh 
    
      Yay 
     
  `);
  expect(await page.locator(`role=button[disabled]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Bye `,
    `Hello `,
    `Yay `,
  ]);
  expect(await page.locator(`role=button[disabled=true]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Bye `,
    `Hello `,
    `Yay `,
  ]);
  expect(await page.getByRole('button', { disabled: true }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Bye `,
    `Hello `,
    `Yay `,
  ]);
  expect(await page.locator(`role=button[disabled=false]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
    `Oh `,
  ]);
  expect(await page.getByRole('button', { disabled: false }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
    `Oh `,
  ]);
});
test('should support level', async ({ page }) => {
  await page.setContent(`
    Hello 
    Hi 
    Bye
  `);
  expect(await page.locator(`role=heading[level=1]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello `,
  ]);
  expect(await page.getByRole('heading', { level: 1 }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hello `,
  ]);
  expect(await page.locator(`role=heading[level=3]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
  ]);
  expect(await page.getByRole('heading', { level: 3 }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
  ]);
  expect(await page.locator(`role=heading[level=5]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Bye
`,
  ]);
});
test('should filter hidden, unless explicitly asked for', async ({ page }) => {
  await page.setContent(`
    Hi 
    Hello 
    Yay 
    Nay 
    Bye 
    
      Oh 
    
    
      Still here 
    
    Never 
    
    
    
      Open form 
      
         Label
          
     
    
      One 
      Two 
      Three 
     
    
  `);
  expect(await page.locator(`role=button`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
    `Nay `,
    `Still here `,
    `Shadow1 `,
  ]);
  expect(await page.locator(`role=button[include-hidden]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
    `Hello `,
    `Yay `,
    `Nay `,
    `Bye `,
    `Oh `,
    `Still here `,
    `Never `,
    `Shadow1 `,
    `Shadow2 `,
  ]);
  expect(await page.locator(`role=button[include-hidden=true]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
    `Hello `,
    `Yay `,
    `Nay `,
    `Bye `,
    `Oh `,
    `Still here `,
    `Never `,
    `Shadow1 `,
    `Shadow2 `,
  ]);
  expect(await page.locator(`role=button[include-hidden=false]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `Hi `,
    `Nay `,
    `Still here `,
    `Shadow1 `,
  ]);
  expect(await page.locator(`role=textbox`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `One `,
    `Three `,
  ]);
});
test('should support name', async ({ page }) => {
  await page.setContent(`
    
    
    
    
    
  `);
  expect(await page.locator(`role=button[name="Hello"]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
  ]);
  expect(await page.locator(`role=button[name=" \n Hello "]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
  ]);
  expect(await page.getByRole('button', { name: 'Hello' }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
  ]);
  expect(await page.locator(`role=button[name*="all"]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
  ]);
  expect(await page.locator(`role=button[name=/^H[ae]llo$/]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
    `
`,
  ]);
  expect(await page.getByRole('button', { name: /^H[ae]llo$/ }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
    `
`,
  ]);
  expect(await page.locator(`role=button[name=/h.*o/i]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
    `
`,
  ]);
  expect(await page.getByRole('button', { name: /h.*o/i }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
    `
`,
  ]);
  expect(await page.locator(`role=button[name="Hello"][include-hidden]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
    `
`,
  ]);
  expect(await page.getByRole('button', { name: 'Hello', includeHidden: true }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
    `
`,
  ]);
  expect(await page.getByRole('button', { name: 'hello', includeHidden: true }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
    `
`,
  ]);
  expect(await page.locator(`role=button[name=Hello]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
  ]);
  expect(await page.locator(`role=button[name=123][include-hidden]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
  ]);
  expect(await page.getByRole('button', { name: '123', includeHidden: true }).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `
`,
  ]);
});
test('errors', async ({ page }) => {
  const e0 = await page.$('role=[bar]').catch(e => e);
  expect(e0.message).toContain(`Role must not be empty`);
  const e1 = await page.$('role=foo[sElected]').catch(e => e);
  expect(e1.message).toContain(`Unknown attribute "sElected", must be one of "checked", "disabled", "expanded", "include-hidden", "level", "name", "pressed", "selected"`);
  const e2 = await page.$('role=foo[bar . qux=true]').catch(e => e);
  expect(e2.message).toContain(`Unknown attribute "bar.qux"`);
  const e3 = await page.$('role=heading[level="bar"]').catch(e => e);
  expect(e3.message).toContain(`"level" attribute must be compared to a number`);
  const e4 = await page.$('role=checkbox[checked="bar"]').catch(e => e);
  expect(e4.message).toContain(`"checked" must be one of true, false, "mixed"`);
  const e5 = await page.$('role=checkbox[checked~=true]').catch(e => e);
  expect(e5.message).toContain(`cannot use ~= in attribute with non-string matching value`);
  const e6 = await page.$('role=button[level=3]').catch(e => e);
  expect(e6.message).toContain(`"level" attribute is only supported for roles: "heading", "listitem", "row", "treeitem"`);
  const e7 = await page.$('role=button[name]').catch(e => e);
  expect(e7.message).toContain(`"name" attribute must have a value`);
  const e8 = await page.$('role=treeitem[expanded="none"]').catch(e => e);
  expect(e8.message).toContain(`"expanded" must be one of true, false`);
});
test('hidden with shadow dom slots', async ({ page }) => {
  await page.setContent(`
    
      hidden1 
    
    
      hidden2 
    
    
      visible1 
    
    
      visible2 
    
  `);
  expect(await page.locator(`role=button`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `visible1 `,
    `visible2 `,
  ]);
  expect(await page.locator(`role=button[include-hidden]`).evaluateAll(els => els.map(e => e.outerHTML))).toEqual([
    `hidden1 `,
    `hidden2 `,
    `visible1 `,
    `visible2 `,
  ]);
});