blob: 2b46398657ff0d0b77a6191f31ac0b86241167e6 [file] [log] [blame]
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']);
});
});
};