/**
 * Copyright 2017 Google Inc. All rights reserved.
 * Modifications 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 as it, expect } from './pageTest';
async function giveItAChanceToResolve(page) {
  for (let i = 0; i < 5; i++)
    await page.evaluate(() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f))));
}
it('should select single option @smoke', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/input/select.html');
  await page.selectOption('select', 'blue');
  expect(await page.evaluate(() => window['result'].onInput)).toEqual(['blue']);
  expect(await page.evaluate(() => window['result'].onChange)).toEqual(['blue']);
});
it('should select single option by value', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/input/select.html');
  await page.selectOption('select', { value: 'blue' });
  expect(await page.evaluate(() => window['result'].onInput)).toEqual(['blue']);
  expect(await page.evaluate(() => window['result'].onChange)).toEqual(['blue']);
});
it('should select single option by label', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/input/select.html');
  await page.selectOption('select', { label: 'Indigo' });
  expect(await page.evaluate(() => window['result'].onInput)).toEqual(['indigo']);
  expect(await page.evaluate(() => window['result'].onChange)).toEqual(['indigo']);
});
it('should select single option by handle', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/input/select.html');
  await page.selectOption('select', await page.$('[id=whiteOption]'));
  expect(await page.evaluate(() => window['result'].onInput)).toEqual(['white']);
  expect(await page.evaluate(() => window['result'].onChange)).toEqual(['white']);
});
it('should select single option by index', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/input/select.html');
  await page.selectOption('select', { index: 2 });
  expect(await page.evaluate(() => window['result'].onInput)).toEqual(['brown']);
  expect(await page.evaluate(() => window['result'].onChange)).toEqual(['brown']);
});
it('should select single option by multiple attributes', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/input/select.html');
  await page.selectOption('select', { value: 'green', label: 'Green' });
  expect(await page.evaluate(() => window['result'].onInput)).toEqual(['green']);
  expect(await page.evaluate(() => window['result'].onChange)).toEqual(['green']);
});
it('should not select single option when some attributes do not match', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/input/select.html');
  await page.$eval('select', s => s.value = undefined);
  try {
    await page.selectOption('select', { value: 'green', label: 'Brown' }, { timeout: 1000 });
  } catch (e) {
    expect(e.message).toContain('Timeout');
  }
  expect(await page.evaluate(() => document.querySelector('select').value)).toEqual('');
});
it('should select only first option', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/input/select.html');
  await page.selectOption('select', ['blue', 'green', 'red']);
  expect(await page.evaluate(() => window['result'].onInput)).toEqual(['blue']);
  expect(await page.evaluate(() => window['result'].onChange)).toEqual(['blue']);
});
it('should not throw when select causes navigation', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/input/select.html');
  await page.$eval('select', select => select.addEventListener('input', () => window.location.href = '/empty.html'));
  await Promise.all([
    page.selectOption('select', 'blue'),
    page.waitForNavigation(),
  ]);
  expect(page.url()).toContain('empty.html');
});
it('should select multiple options', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/input/select.html');
  await page.evaluate(() => window['makeMultiple']());
  await page.selectOption('select', ['blue', 'green', 'red']);
  expect(await page.evaluate(() => window['result'].onInput)).toEqual(['blue', 'green', 'red']);
  expect(await page.evaluate(() => window['result'].onChange)).toEqual(['blue', 'green', 'red']);
});
it('should select multiple options with attributes', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/input/select.html');
  await page.evaluate(() => window['makeMultiple']());
  await page.selectOption('select', [{ value: 'blue' }, { label: 'Green' }, { index: 4 }]);
  expect(await page.evaluate(() => window['result'].onInput)).toEqual(['blue', 'gray', 'green']);
  expect(await page.evaluate(() => window['result'].onChange)).toEqual(['blue', 'gray', 'green']);
});
it('should select options with sibling label', async ({ page, server }) => {
  await page.setContent(`
    `);
  await page.selectOption('text=Choose a pet', 'cat');
  expect(await page.$eval('select', select => select.options[select.selectedIndex].text)).toEqual('Cat');
});
it('should select options with outer label', async ({ page, server }) => {
  await page.setContent(``);
  await page.selectOption('text=Choose a pet', 'cat');
  expect(await page.$eval('select', select => select.options[select.selectedIndex].text)).toEqual('Cat');
});
it('should respect event bubbling', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/input/select.html');
  await page.selectOption('select', 'blue');
  expect(await page.evaluate(() => window['result'].onBubblingInput)).toEqual(['blue']);
  expect(await page.evaluate(() => window['result'].onBubblingChange)).toEqual(['blue']);
});
it('should throw when element is not a