Bug 1556471 [wpt PR 17146] - Initial implementation of std-toast, a=testonly

Automatic update from web-platform-tests
Initial implementation of std-toast

Intent to Implement: https://groups.google.com/a/chromium.org/forum/?utm_source=digest&utm_medium=email#!topic/blink-dev/Gl7FIKM5IFw

BUG=972945

Follow-ups will align with std-switch in elements and de-duplicate the .eslintrc.js files between toast and kv-storage.

Change-Id: Ib5837ccf8c9ea03fd2f1f2bd581e443a2936f693
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1635867
Commit-Queue: Jack Steinberg <jacksteinberg@chromium.org>
Commit-Queue: Fergal Daly <fergal@chromium.org>
Reviewed-by: Kouhei Ueno <kouhei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#670383}

--

wpt-commits: 17de974a80b0d9a6ff48dc24796441057afad5a0
wpt-pr: 17146
This commit is contained in:
Jack Steinberg 2019-07-19 12:35:52 +00:00 коммит произвёл James Graham
Родитель 4b03795d44
Коммит 99eb349595
8 изменённых файлов: 624 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,5 @@
spec: https://github.com/jackbsteinberg/std-toast
suggested_reviewers:
- domenic
- fergald
- jackbsteinberg

Просмотреть файл

@ -0,0 +1,116 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Toast: attribute tests</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<main></main>
<script type="module">
import { testToastElement, assertToastShown, assertToastNotShown, testToastElementAsync } from './resources/helpers.js';
testToastElement((toast) => {
toast.setAttribute('open', '');
assertToastShown(toast);
}, 'setting `open` on a hidden toast shows the toast');
testToastElement((toast) => {
toast.setAttribute('open', false);
assertToastShown(toast);
}, 'setting `open` to false on a hidden toast shows the toast, because of string conversion');
testToastElement((toast) => {
toast.show();
toast.setAttribute('open', 'test');
assertToastShown(toast);
}, 'setting `open` on a shown toast does nothing');
testToastElement((toast) => {
toast.show();
toast.setAttribute('open', 'test');
toast.setAttribute('open', 'test');
assertToastShown(toast);
}, 'resetting `open` on a shown toast does nothing');
testToastElement((toast) => {
toast.show();
toast.setAttribute('open', false);
assertToastShown(toast);
}, 'setting `open` to false on a shown toast does nothing, because of string conversion');
testToastElement((toast) => {
toast.show();
toast.removeAttribute('open');
assertToastNotShown(toast);
}, 'removing `open` hides the toast');
testToastElement((toast) => {
toast.show();
assert_true(toast.hasAttribute('open'));
}, 'showing the toast adds open attribute');
testToastElement((toast) => {
toast.show();
toast.hide();
assert_false(toast.hasAttribute('open'));
}, 'hiding the toast removes open attribute');
testToastElement((toast) => {
toast.toggleAttribute('open');
assert_true(toast.hasAttribute('open'));
}, 'toggling `open` on a hidden toast sets the open attribute');
testToastElement((toast) => {
toast.toggleAttribute('open');
toast.toggleAttribute('open');
assert_false(toast.hasAttribute('open'));
}, 'toggling `open` twice leaves the toast with no open attribute');
testToastElement((toast) => {
assert_false(toast.open);
}, 'the `toast.open` boolean is false for a hidden toast');
testToastElement((toast) => {
toast.show();
assert_true(toast.open);
}, 'the `toast.open` boolean is true for a shown toast');
testToastElement((toast) => {
toast.open = true;
assertToastShown(toast);
assert_equals(toast.getAttribute('open'), '');
}, 'setting `toast.open` to true on a hidden toast will show the toast');
testToastElement((toast) => {
toast.show();
toast.open = false;
assertToastNotShown(toast);
}, 'setting `toast.open` to false on a shown toast will hide the toast');
testToastElement((toast) => {
toast.open = 'truthy!';
assertToastShown(toast);
assert_equals(toast.getAttribute('open'), '');
}, 'setting `toast.open` to some truthy value on a hidden toast will show the toast');
testToastElement((toast) => {
toast.show();
toast.open = '';
assertToastNotShown(toast);
}, 'setting `toast.open` to some falsy value on a shown toast will hide the toast');
testToastElement((toast) => {
toast.toggleAttribute('open');
assert_true(toast.open);
}, 'toggling `open` on a hidden toast sets `toast.open` to true');
testToastElementAsync((t, toast) => {
toast.toggleAttribute('open', true);
t.step_timeout(() => {
assertToastShown(toast);
t.done();
}, 2000);
}, 'toggling open attribute does not start timeout');
</script>

Просмотреть файл

@ -0,0 +1,73 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Toast: Event tests</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<main></main>
<script type="module">
import { testToastElement, EventCollector } from './resources/helpers.js';
testToastElement((toast) => {
const counter = new EventCollector();
toast.addEventListener('show', (e) => {
counter.getCallback()(e);
});
toast.open = true;
assert_equals(counter.getCount(), 1);
}, 'setting open to true on a hidden toast triggers the `show` event');
testToastElement((toast) => {
const counter = new EventCollector();
toast.open = true;
toast.addEventListener('show', counter.getCallback());
toast.open = true;
assert_equals(counter.getCount(), 0);
}, 'setting open to true on a shown toast does not trigger the `show` event');
testToastElement((toast) => {
const counter = new EventCollector();
toast.addEventListener('hide', counter.getCallback());
toast.open = false;
assert_equals(counter.getCount(), 0);
}, 'setting open to false on a hidden toast does not trigger the `hide` event');
testToastElement((toast) => {
const counter = new EventCollector();
toast.show();
toast.addEventListener('hide', counter.getCallback());
toast.open = false;
assert_equals(counter.getCount(), 1);
}, 'setting open to false on a shown toast triggers the `hide` event');
testToastElement((toast) => {
const counter = new EventCollector();
toast.addEventListener('show', counter.getCallback());
toast.open = true;
toast.open = true;
assert_equals(counter.getCount(), 1);
}, 'setting open to true twice only triggers the `show` event once');
testToastElement((toast) => {
const counter = new EventCollector();
toast.show();
toast.addEventListener('hide', counter.getCallback());
toast.open = false;
toast.open = false;
assert_equals(counter.getCount(), 1);
}, 'setting open to false twice only triggers the `hide` event once');
</script>

Просмотреть файл

@ -0,0 +1,98 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Toast: Event tests</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<main></main>
<script type="module">
import { testToastElement, EventCollector } from './resources/helpers.js';
testToastElement((toast) => {
const counter = new EventCollector();
toast.addEventListener('show', counter.getCallback());
toast.show();
assert_equals(counter.getCount(), 1);
}, 'calling `show()` on a hidden toast triggers the `show` event');
testToastElement((toast) => {
const counter = new EventCollector();
toast.show();
toast.addEventListener('show', counter.getCallback());
toast.show();
assert_equals(counter.getCount(), 0);
}, 'calling `show()` on a shown toast does not trigger the `show` event');
testToastElement((toast) => {
const counter = new EventCollector();
toast.addEventListener('hide', counter.getCallback());
toast.hide();
assert_equals(counter.getCount(), 0);
}, 'calling `hide()` on a hidden toast does not trigger the `hide` event');
testToastElement((toast) => {
const counter = new EventCollector();
toast.show();
toast.addEventListener('hide', counter.getCallback());
toast.hide();
assert_equals(counter.getCount(), 1);
}, 'calling `hide()` on a shown toast triggers the `hide` event');
testToastElement((toast) => {
const counter = new EventCollector();
toast.addEventListener('show', counter.getCallback());
toast.show();
toast.show();
assert_equals(counter.getCount(), 1);
}, 'calling `show()` twice only triggers the `show` event once');
testToastElement((toast) => {
const counter = new EventCollector();
toast.show();
toast.addEventListener('hide', counter.getCallback());
toast.hide();
toast.hide();
assert_equals(counter.getCount(), 1);
}, 'calling `hide()` twice only triggers the `hide` event once');
testToastElement((toast) => {
const events = new EventCollector();
toast.addEventListener('show', events.getCallback());
toast.show();
toast.hide();
toast.show();
assert_equals(events.getCount(), 2);
assert_not_equals(events.getEvents()[0], events.getEvents()[1]);
}, "separate openings trigger different `show` events");
testToastElement((toast) => {
const events = new EventCollector();
toast.addEventListener('hide', events.getCallback());
toast.show();
toast.hide();
toast.show();
toast.hide();
assert_equals(events.getCount(), 2);
assert_not_equals(events.getEvents()[0], events.getEvents()[1]);
}, "separate closings trigger different `hide` events");
</script>

Просмотреть файл

@ -0,0 +1,125 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Toast: method tests</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<main></main>
<div></div>
<script type="module">
import { testToastElement, assertToastShown, assertToastNotShown, testToastElementAsync } from './resources/helpers.js';
testToastElement((toast) => {
toast.show();
assertToastShown(toast);
}, 'calling `show()` on a hidden toast opens and displays it');
testToastElement((toast) => {
toast.toggleAttribute('open');
toast.show();
assertToastShown(toast);
}, 'calling `show()` on a shown toast does nothing');
testToastElement((toast) => {
toast.toggleAttribute('open');
toast.hide();
assertToastNotShown(toast);
}, 'calling `hide()` on a shown toast hides the toast');
testToastElement((toast) => {
toast.hide();
assertToastNotShown(toast);
}, 'calling `hide()` on a hidden toast does nothing');
testToastElement((toast) => {
toast.toggle();
assertToastShown(toast);
}, 'calling `toggle()` on a hidden toast shows the toast');
testToastElement((toast) => {
toast.show();
toast.toggle();
assertToastNotShown(toast);
}, 'calling `toggle()` on a shown toast hides the toast');
testToastElement((toast) => {
toast.toggle(true);
assertToastShown(toast);
}, 'calling `toggle()` with `force` parameter set to true on a hidden opens the toast');
testToastElement((toast) => {
toast.show();
toast.toggle(true);
assertToastShown(toast);
}, 'calling `toggle()` with `force` parameter set to true on a shown toast does not close the toast');
testToastElement((toast) => {
toast.toggle(false);
assertToastNotShown(toast);
}, 'calling `toggle()` with `force` parameter set to false on a hidden toast does not open the toast');
testToastElement((toast) => {
toast.show();
toast.toggle(false);
assertToastNotShown(toast);
}, 'calling `toggle()` with `force` parameter set to false on a shown toast closes the toast');
testToastElementAsync((t, toast) => {
toast.show();
// time = 999
t.step_timeout(() => {
assertToastShown(toast);
toast.show();
// time = 2000
t.step_timeout(() => {
assertToastShown(toast);
// time = 3000
t.step_timeout(() => {
assertToastNotShown(toast);
t.done();
}, 1000);
}, 1001);
}, 999);
}, 'calling `show()` twice resets the timeout');
testToastElementAsync((t, toast) => {
toast.show();
// time = 999
t.step_timeout(() => {
assertToastShown(toast);
toast.hide();
// time = 1000
t.step_timeout(() => {
assertToastNotShown(toast);
// time = 1500
t.step_timeout(() => {
toast.show();
// time = 2500
t.step_timeout(() => {
assertToastShown(toast);
t.done();
}, 1000);
}, 500);
}, 1);
}, 999);
}, 'calling `hide()` clears the timeout');
</script>

Просмотреть файл

@ -0,0 +1,74 @@
<!DOCTYPE html>
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Toast: showToast tests</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
</body>
<script type="module">
import { showToast, StdToastElement } from 'std:toast';
import { assertToastNotShown, assertToastShown } from './resources/helpers.js';
// message
test(() => {
const toast = new StdToastElement(false);
document.body.appendChild(toast);
assert_equals(toast.textContent, 'false');
}), 'passing false as message converts to the string `false`';
test(() => {
const toast = new StdToastElement('<p>rich text</p>');
document.body.appendChild(toast);
assert_equals(toast.textContent, '<p>rich text</p>');
assert_equals(toast.querySelector('p'), null);
}, 'passing markup to the constructor does not pass through the markup behaviors');
test(() => {
const toastString = '<std-toast id="test">test</std-toast>';
document.body.innerHTML = toastString;
const toast = document.body.querySelector('#test');
assert_equals(toast.textContent, 'test');
}, 'HTML created toast has `test` as its text content');
// duration
async_test(t => {
const toast = showToast('message');
t.step_timeout(() => {
assertToastShown(toast);
}, 1999);
t.step_timeout(() => {
assertToastNotShown(toast);
t.done();
}, 2000);
t.add_cleanup(function() {
toast.remove();
});
}, 'showToast closes after default duration of 2000ms');
async_test(t => {
const toast = showToast('message', {duration: 1000});
t.step_timeout(() => {
assertToastShown(toast);
}, 999);
t.step_timeout(() => {
assertToastNotShown(toast);
t.done();
}, 1000);
t.add_cleanup(function() {
toast.remove();
});
}, 'showToast closes after user specified 1000ms');
</script>

Просмотреть файл

@ -0,0 +1,70 @@
import { showToast, StdToastElement } from 'std:toast';
// helper functions to keep tests from bleeding into each other
const runTest = (testFn, name, toast) => {
try {
test(() => {
testFn(toast);
}, name);
} finally {
toast.remove();
}
};
const runTestAsync = (testFn, name, toast) => {
async_test(t => {
testFn(t, toast);
t.add_cleanup(() => {
toast.remove();
});
}, name);
};
export const testToastElement = (testFn, name) => {
const toast = new StdToastElement('Message', {});
document.querySelector('main').appendChild(toast);
runTest(testFn, name, toast);
};
export const testToastElementAsync = (testFn, name) => {
const toast = new StdToastElement('Message', {});
document.querySelector('main').appendChild(toast);
runTestAsync(testFn, name, toast);
};
export const testShowToast = (testFn, name) => {
const toast = showToast("message");
runTest(testFn, name, toast);
};
export const assertToastShown = (toast) => {
assert_not_equals(window.getComputedStyle(toast).display, 'none');
assert_true(toast.hasAttribute('open'));
assert_true(toast.open);
};
export const assertToastNotShown = (toast) => {
assert_equals(window.getComputedStyle(toast).display, 'none');
assert_false(toast.hasAttribute('open'));
assert_false(toast.open);
};
export class EventCollector {
events = [];
getCallback() {
return (e) => {this.events.push(e)};
}
getCount() {
return this.events.length;
}
getEvents() {
return this.events;
}
}

Просмотреть файл

@ -0,0 +1,63 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Toast: showToast tests</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
</body>
<script type="module">
import { showToast, StdToastElement } from 'std:toast';
import { testShowToast, assertToastNotShown, assertToastShown } from './resources/helpers.js';
testShowToast((toast) => {
assert_true(toast != null);
assert_true(toast instanceof StdToastElement);
}, 'showToast creates and returns a toast');
testShowToast((toast) => {
assert_true(document.querySelector('std-toast') === toast);
}, 'showToast puts the toast in the DOM');
testShowToast((toast) => {
assertToastShown(toast);
}, 'showToast displays the toast by default');
testShowToast((toast) => {
toast.hide();
assertToastNotShown(toast);
}, 'hiding showToast immediately does not display it');
testShowToast((toast) => {
toast.show();
assertToastShown(toast);
}, 'calling show after showToast does nothing');
testShowToast((toast) => {
let toast2;
try {
toast2 = showToast('message2');
assert_not_equals(toast, toast2);
}
finally {
toast2.remove();
}
}, 'calling showToast multiple times creates multiple different toasts');
test(() => {
const toast = showToast('test');
assert_equals(toast.textContent, 'test');
}, 'showToast created toast has `test` as its text content');
test(() => {
const toast = showToast('<p>rich text</p>');
assert_equals(toast.textContent, '<p>rich text</p>');
assert_equals(toast.querySelector('p'), null);
}, 'passing markup to showToast does not pass through the markup behaviors');
</script>