import { expect } from 'chai';
import { Serializable } from 'puppeteer';
import { PageObjectElement } from './page_object_element';

/**
 * A test bed for PageObjectElement test cases that must run both in-browser and on Puppeteer.
 *
 * The methods in this interface allow writing PageObjectElement test cases in an
 * environment-independent way. Each environment (i.e. the in-browser and Puppeteer test suites)
 * must provide its own implementation.
 */
export interface TestBed {
  /**
   * Injects the given HTML into a test page, and returns a new PageObjectElement wrapping the
   * top-level element in said HTML.
   *
   * The HTML must have exactly one top-level element.
   *
   * @example
   * "<div>Hello, world!</div>"                // Valid example.
   * "<span>Hello</span> <span>World!</span>"  // Invalid example.
   */
  setUpPageObjectElement(html: string): Promise<PageObjectElement>;

  /**
   * Evaluates the given function inside the test page, passing as the first argument the
   * HTMLElement wrapped by the PageObjectElement returned by the most recent call to
   * setUpPageObjectElement().
   */
  evaluate<T extends Serializable | void = void>(fn: (el: HTMLElement)=> T): Promise<T>;
}

/**
 * Sets up the PageObjectElement test cases shared by its in-browser and Puppeteer test suites.
 *
 * Any test cases for behaviors that apply to both the in-browser and Puppeteer environments should
 * be place here. Test cases for environment-specific behaviors, if any, should be placed in
 * page_object_element_karma_test.ts or page_object_element_nodejs_test.ts.
 */
export const describePageObjectElement = (testBed: TestBed) => {
  it('supports isEmpty', async () => {
    const poe = await testBed.setUpPageObjectElement('<div>Hello, world!</div>');
    expect(await poe.isEmpty()).to.be.false;
    const nullPromise = new Promise<null>((resolve) => resolve(null));
    expect(await (new PageObjectElement(nullPromise)).isEmpty()).to.be.true;
  });

  it('supports innerText', async () => {
    const poe = await testBed.setUpPageObjectElement('<div>Hello, world!</div>');
    expect(await poe.innerText).to.equal('Hello, world!');
  });

  it('supports isInnerTextEqualTo', async () => {
    const poe = await testBed.setUpPageObjectElement('<div>Hello, world!</div>');
    expect(await poe.isInnerTextEqualTo('Hello, world!')).to.be.true;
    expect(await poe.isInnerTextEqualTo(' Hello, world!')).to.be.false;
    expect(await poe.isInnerTextEqualTo('Hello, world! ')).to.be.false;
    expect(await poe.isInnerTextEqualTo('Goodbye')).to.be.false;
  });

  it('supports className', async () => {
    const poe = await testBed.setUpPageObjectElement('<div class="hello world"></div>');
    expect(await poe.className).to.equal('hello world');
  });

  it('supports hasClassName', async () => {
    const poe = await testBed.setUpPageObjectElement('<div class="hello world"></div>');
    expect(await poe.hasClassName('hello')).to.be.true;
    expect(await poe.hasClassName('world')).to.be.true;
    expect(await poe.hasClassName('goodbye')).to.be.false;
  });

  it('supports focus', async () => {
    const poe = await testBed.setUpPageObjectElement('<button>Hello, world!</button>');
    const isFocused = () => testBed.evaluate((el) => document.activeElement === el);

    expect(await isFocused()).to.be.false;
    await poe.focus();
    expect(await isFocused()).to.be.true;
  });

  it('supports click', async () => {
    const poe = await testBed.setUpPageObjectElement(
      '<button onclick="this.setAttribute(\'clicked\', true)">Click me!</button>',
    );
    const wasClicked = () => testBed.evaluate((el: HTMLElement) => el.hasAttribute('clicked'));

    expect(await wasClicked()).to.be.false;
    await poe.click();
    expect(await wasClicked()).to.be.true;
  });

  it('supports hasAttribute', async () => {
    let poe = await testBed.setUpPageObjectElement('<div></div>');
    expect(await poe.hasAttribute('hello')).to.be.false;

    poe = await testBed.setUpPageObjectElement('<div hello></div>');
    expect(await poe.hasAttribute('hello')).to.be.true;
  });

  it('supports getAttribute', async () => {
    let poe = await testBed.setUpPageObjectElement('<a>Click me!</a>');
    expect(await poe.getAttribute('href')).to.be.null;

    poe = await testBed.setUpPageObjectElement('<a href="/hello-world">Click me!</a>');
    expect(await poe.getAttribute('href')).to.equal('/hello-world');
  });

  it('supports value', async () => {
    const poe = await testBed.setUpPageObjectElement('<input type="text" value="hello"/>');
    expect(await poe.value).to.equal('hello');
  });

  it('supports enterValue', async () => {
    const poe = await testBed.setUpPageObjectElement(`
      <input type="text"
             oninput="this.setAttribute('input-event-dispatched', true)"
             onchange="this.setAttribute('change-event-dispatched', true)"/>`);

    const wasInputEventDispatched = () => testBed.evaluate((el: HTMLElement) => el.hasAttribute('input-event-dispatched'));
    const wasChangeEventDispatched = () => testBed.evaluate((el: HTMLElement) => el.hasAttribute('change-event-dispatched'));

    expect(await wasInputEventDispatched()).to.be.false;
    expect(await wasChangeEventDispatched()).to.be.false;
    await poe.enterValue('hello');
    expect(await testBed.evaluate((el) => (el as HTMLInputElement).value)).to.equal('hello');
    expect(await wasInputEventDispatched()).to.be.true;
    expect(await wasChangeEventDispatched()).to.be.true;
  });

  it('supports typeKey', async () => {
    const poe = await testBed.setUpPageObjectElement(`
      <input type="text"
             onkeydown="this.setAttribute('keydown-event-key', event.key)"
             onkeypress="this.setAttribute('keypress-event-key', event.key)"
             onkeyup="this.setAttribute('keyup-event-key', event.key)"/>`);

    const keydownEventKey = () => testBed.evaluate((el: HTMLElement) => el.getAttribute('keydown-event-key'));
    const keypressEventKey = () => testBed.evaluate((el: HTMLElement) => el.getAttribute('keypress-event-key'));
    const keyupEventKey = () => testBed.evaluate((el: HTMLElement) => el.getAttribute('keyup-event-key'));

    expect(await keydownEventKey()).to.be.null;
    expect(await keypressEventKey()).to.be.null;
    expect(await keyupEventKey()).to.be.null;
    await poe.typeKey('a');
    expect(await keydownEventKey()).to.equal('a');
    expect(await keypressEventKey()).to.equal('a');
    expect(await keyupEventKey()).to.equal('a');
  });

  it('supports applyFnToDOMNode', async () => {
    const poe = await testBed.setUpPageObjectElement('<div>Hello, world!</div>');
    const result = await poe.applyFnToDOMNode(
      (el, prefix, suffix) => `${prefix}${el.innerText}${suffix}`,
      'The contents are: "',
      '". That is all.',
    );
    expect(result).to.equal('The contents are: "Hello, world!". That is all.');
  });

  describe('selector functions', () => {
    let poe: PageObjectElement;

    beforeEach(async () => {
      poe = await testBed.setUpPageObjectElement(`
        <div>
          <span class=salutation>Hello</span>,
          <span class=name>World</span>!
        </div>
      `);
    });

    it('supports bySelector', async () => {
      expect(await poe.bySelector('p').isEmpty()).to.be.true;
      expect(await poe.bySelector('span').isEmpty()).to.be.false;
      expect(await poe.bySelector('span.name').innerText).to.equal('World');
    });

    it('supports bySelectorAll', async () => {
      expect(await poe.bySelectorAll('p').length).to.equal(0);
      expect(await poe.bySelectorAll('span').length).to.equal(2);
      expect(await poe.bySelectorAll('span').map((el) => el.innerText))
        .to.deep.equal(['Hello', 'World']);
    });
  });
};
