-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
1,577 additions
and
135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { describe, it, beforeEach } from 'moonshiner'; | ||
import { I, assert, fixture } from '../helpers'; | ||
|
||
describe('Actions | #blur(selector?)', () => { | ||
beforeEach(() => { | ||
fixture(` | ||
<h1 tabindex="0">Foo</h1> | ||
<button>Bar</button> | ||
`); | ||
}); | ||
|
||
it('blurs the current element', async () => { | ||
let $foo = document.querySelector('h1'); | ||
let $bar = document.querySelector('button'); | ||
|
||
$foo.focus(); | ||
await I.blur('Foo'); | ||
await assert(document.activeElement !== $foo, | ||
'Expected "Foo" to not be focused'); | ||
|
||
$bar.focus(); | ||
await I.find('Bar').then.blur(); | ||
await assert(document.activeElement !== $bar, | ||
'Expected "Bar" to not be focused'); | ||
}); | ||
|
||
it('asserts the element is focused', async () => { | ||
await assert.throws(I.blur('Foo'), | ||
'"Foo" is not focused'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import { describe, it } from 'moonshiner'; | ||
import { I, assert, fixture, listen } from '../helpers'; | ||
|
||
describe('Actions | #click(selector?)', () => { | ||
it('clicks the current element', async () => { | ||
fixture('<button>Foo</button>'); | ||
let event = listen('button', 'click'); | ||
|
||
await I.click('Foo'); | ||
await assert(event.calls.length === 1, | ||
'Expected to click "Foo"'); | ||
|
||
await I.find('Foo').then.click(); | ||
await assert(event.calls.length === 2, | ||
'Expected to click "Foo" a second time'); | ||
}); | ||
|
||
it('asserts the element is not disabled', async () => { | ||
fixture('<button disabled>Bar</button>'); | ||
let event = listen('button', 'click'); | ||
|
||
await assert.throws(I.click('Bar'), | ||
'"Bar" is disabled'); | ||
await assert(event.calls.length === 0, | ||
'Expected "Bar" to not be clicked'); | ||
}); | ||
|
||
it('checks and unchecks checkbox and radio elements', async () => { | ||
fixture(` | ||
<input id="check" type="checkbox" /> | ||
<label for="check">Baz</label> | ||
<input name="radios" id="radio-1" type="radio" /> | ||
<label for="radio-1">Qux</label> | ||
<input name="radios" id="radio-2" type="radio" /> | ||
<label for="radio-2">Xyzzy</label> | ||
`); | ||
|
||
await I.click('Baz'); | ||
await assert(document.getElementById('check').checked === true, | ||
'Expected "Baz" to be checked'); | ||
|
||
await I.click('Baz'); | ||
await assert(document.getElementById('check').checked === false, | ||
'Expected "Baz" to not be checked'); | ||
|
||
await I.click('Qux'); | ||
await assert(document.getElementById('radio-1').checked === true, | ||
'Expected "Qux" to be checked'); | ||
await assert(document.getElementById('radio-2').checked === false, | ||
'Expected "Xyzzy" to not be checked'); | ||
|
||
await I.click('Xyzzy'); | ||
await assert(document.getElementById('radio-1').checked === false, | ||
'Expected "Qux" to not be checked'); | ||
await assert(document.getElementById('radio-2').checked === true, | ||
'Expected "Xyzzy" to be checked'); | ||
}); | ||
|
||
it('selects options within select elements', async () => { | ||
fixture(` | ||
<select> | ||
<option disabled>Choose</option> | ||
<option>Foo</option> | ||
<option>Bar</option> | ||
</select> | ||
`); | ||
|
||
let input = listen('select', 'input'); | ||
let change = listen('select', 'change'); | ||
|
||
await I.click('Foo'); | ||
await assert(input.$.value === 'Foo', | ||
'Expected "Foo" to be selected'); | ||
|
||
await I.click('Bar'); | ||
await assert(input.$.value === 'Bar', | ||
'Expected "Bar" to be selected'); | ||
|
||
await assert(input.calls.length === 2, | ||
'Expected input events when selecting options'); | ||
await assert(change.calls.length === 2, | ||
'Expected change events when selecting options'); | ||
}); | ||
|
||
it('asserts the option select element is not disabled', async () => { | ||
fixture(` | ||
<select disabled> | ||
<option disabled>Choose</option> | ||
<option>Foo</option> | ||
<option>Bar</option> | ||
</select> | ||
`); | ||
|
||
let event = listen('select', 'change'); | ||
|
||
await assert.throws(I.click('Foo'), | ||
'"Foo" select is disabled'); | ||
await assert(event.calls.length === 0, | ||
'Expected change event not to be triggered'); | ||
}); | ||
|
||
it('selects and deselects options within multi-select elements', async () => { | ||
fixture(` | ||
<select multiple> | ||
<option>Foo</option> | ||
<option>Bar</option> | ||
</select> | ||
`); | ||
|
||
let event = listen('select', 'change'); | ||
|
||
await I.click('Foo'); | ||
await I.click('Bar'); | ||
|
||
await assert( | ||
event.$.selectedOptions[0].value === 'Foo' && | ||
event.$.selectedOptions[1].value === 'Bar', | ||
'Expected "Foo" and "Bar" to be selected'); | ||
|
||
await I.click('Foo'); | ||
|
||
await assert( | ||
event.$.selectedOptions[0].value === 'Bar' && | ||
!event.$.selectedOptions[1], | ||
'Expected only "Bar" to be selected'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { describe, it, beforeEach } from 'moonshiner'; | ||
import { I, assert, fixture } from '../helpers'; | ||
|
||
describe('Actions | #focus(selector?)', () => { | ||
beforeEach(() => { | ||
fixture(` | ||
<h1 tabindex="0">Foo</h1> | ||
<button>Bar</button> | ||
<label>Baz</label> | ||
`); | ||
}); | ||
|
||
it('focuses the current element', async () => { | ||
let $foo = document.querySelector('h1'); | ||
let $bar = document.querySelector('button'); | ||
|
||
await I.focus('Foo'); | ||
await assert(document.activeElement === $foo, | ||
'Expected "Foo" to have focus'); | ||
|
||
await I.find('Bar').then.focus(); | ||
await assert(document.activeElement === $bar, | ||
'Expected "Bar" to have focus'); | ||
}); | ||
|
||
it('asserts the element is focusable', async () => { | ||
await assert.throws(I.focus('Baz'), | ||
'"Baz" is not focusable'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
import { describe, it } from 'moonshiner'; | ||
import { I, assert, fixture, listen } from '../helpers'; | ||
|
||
describe('Actions | #press(keys, options?)', () => { | ||
it('triggers keyboard events for the current element', async () => { | ||
fixture('<div class="foo">Foo</div>'); | ||
|
||
let events = { | ||
keydown: listen('.foo', 'keydown'), | ||
beforeinput: listen('.foo', 'beforeinput'), | ||
input: listen('.foo', 'input'), | ||
keyup: listen('.foo', 'keyup') | ||
}; | ||
|
||
await I.find('Foo') | ||
.then.press('Delete'); | ||
|
||
for (let event in events) { | ||
if (event === 'keydown' || event === 'keyup') { | ||
await assert( | ||
events[event].calls.length === 1 && | ||
events[event].calls[0][0].key === 'Delete', | ||
`Expected \`${event}\` event for "Delete"`); | ||
} else { | ||
await assert(events[event].calls.length === 0, | ||
`Unexpected \`${event}\` event for "Delete"`); | ||
} | ||
} | ||
}); | ||
|
||
it('triggers input events for the current input element', async () => { | ||
fixture('<input placeholder="Bar" />'); | ||
|
||
let events = { | ||
keydown: listen('input', 'keydown'), | ||
beforeinput: listen('input', 'beforeinput', e => { | ||
if (e.key === 'C') e.preventDefault(); | ||
}), | ||
input: listen('input', 'input'), | ||
keyup: listen('input', 'keyup') | ||
}; | ||
|
||
await I.find('Bar') | ||
.then.press('B'); | ||
|
||
for (let event in events) { | ||
await assert( | ||
events[event].calls.length === 1 && | ||
events[event].calls[0][0].key === 'B', | ||
`Expected \`${event}\` event for "B"`); | ||
} | ||
|
||
await I.find('Bar') | ||
.then.press('C'); | ||
|
||
await assert(events.beforeinput.calls.length === 2, | ||
'Expected a second beforeinput event'); | ||
await assert(events.input.calls.length === 1, | ||
'Expected second input event to be canceled'); | ||
}); | ||
|
||
it('does not accept arbitrary key names', async () => { | ||
await assert.throws(() => I.press('KeyFoo'), | ||
'Unknown key `KeyFoo`'); | ||
}); | ||
|
||
it('can insert or replace text within relevant elements', async () => { | ||
fixture('<div contenteditable>Fo</div>'); | ||
let $ = document.querySelector('[contenteditable]'); | ||
|
||
await I.find($) | ||
.then.press('KeyO'); | ||
|
||
await assert($.innerText === 'Foo', | ||
'Expected content editable text to be "Foo"'); | ||
|
||
await I.find($) | ||
.then.press('!', { replace: true }); | ||
|
||
await assert($.innerText === '!', | ||
'Expected content editable text to be "!"'); | ||
|
||
$.innerText = 'Bar'; | ||
|
||
await I.find($) | ||
.then.press('z', { range: [2, 3] }); | ||
|
||
await assert($.innerText === 'Baz', | ||
'Expected content editable text to be "Baz"'); | ||
}); | ||
|
||
it('replaces any existing text selection', async () => { | ||
fixture('<div contenteditable>Qoox</div>'); | ||
let $ = document.querySelector('[contenteditable]'); | ||
|
||
let range = document.createRange(); | ||
range.setStart($.firstChild, 1); | ||
range.setEnd($.firstChild, 3); | ||
let sel = window.getSelection(); | ||
sel.removeAllRanges(); | ||
sel.addRange(range); | ||
|
||
await I.find($) | ||
.then.press('u'); | ||
|
||
await assert($.innerText === 'Qux', | ||
'Expected content editable text to be "Qux"'); | ||
}); | ||
|
||
it('can delete text within relevant elements', async () => { | ||
fixture('<input placeholder="Foo" value="FFooo" />'); | ||
|
||
await I.find('Foo') | ||
.then.press('Backspace') | ||
.then.press('Delete', { range: 0 }); | ||
|
||
await assert(document.querySelector('input').value === 'Foo', | ||
'Expected "Foo" value to be "Foo"'); | ||
}); | ||
|
||
it('can hold a key in an interaction until the next press', async () => { | ||
fixture('<input placeholder="Baz" />'); | ||
|
||
await I.find('Baz') | ||
.then.press('Shift', { hold: true }) | ||
.then.press('KeyB') | ||
.then.press('Shift') | ||
.then.press(['KeyA', 'KeyZ']) | ||
.then.press(['Shift', 'Digit1']); | ||
|
||
await assert(document.querySelector('input').value === 'Baz!', | ||
'Expected "Baz" to have a value of "Baz!"'); | ||
}); | ||
|
||
it('retains any custom value descriptors for relevant elements', async () => { | ||
fixture('<input placeholder="Qux" />'); | ||
let $input = document.querySelector('input'); | ||
let value = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); | ||
|
||
Object.defineProperty($input, 'value', { | ||
...value, get: () => value.get.apply($input) + 'oo' | ||
}); | ||
|
||
await I.find('Qux') | ||
.then.press('KeyF'); | ||
|
||
await assert($input.value === 'foo', | ||
'Expected "Qux" value to be "foo"'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { describe, it, beforeEach } from 'moonshiner'; | ||
import { I, assert, fixture, listen } from '../helpers'; | ||
|
||
describe('Actions | #trigger(eventName, options?)', () => { | ||
beforeEach(() => { | ||
fixture('<div class="foo">Foo</div>'); | ||
}); | ||
|
||
it('triggers an arbitrary event on the current element', async () => { | ||
let event = listen('.foo', 'foobar'); | ||
|
||
await I.find('Foo') | ||
.then.trigger('foobar'); | ||
|
||
await assert(event.calls.length === 1, | ||
'Expected "foobar" event to be triggered'); | ||
}); | ||
|
||
it('bubbles and is cancelable by default', async () => { | ||
let event = listen('.foo', 'xyzzy'); | ||
|
||
await I.find('Foo') | ||
.then.trigger('xyzzy', { foo: 'bar' }) | ||
.then.trigger('xyzzy', { bubbles: null, cancelable: false }); | ||
|
||
await assert(event.calls[0][0].foo === 'bar', | ||
'Expected "xyzzy" event to include event properties'); | ||
await assert(event.calls[0][0].bubbles && event.calls[0][0].cancelable, | ||
'Expected "xyzzy" event to bubble and be cancelable'); | ||
await assert(!event.calls[1][0].bubbles && !event.calls[1][0].cancelable, | ||
'Expected "xyzzy" event to not bubble and not be cancelable'); | ||
}); | ||
}); |
Oops, something went wrong.