summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/battery-status
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/battery-status')
-rw-r--r--testing/web-platform/tests/battery-status/META.yml4
-rw-r--r--testing/web-platform/tests/battery-status/api-defined.https.html30
-rw-r--r--testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html28
-rw-r--r--testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy-attribute.https.sub.html27
-rw-r--r--testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy.https.sub.html28
-rw-r--r--testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy.https.sub.html.headers1
-rw-r--r--testing/web-platform/tests/battery-status/battery-allowed-in-same-origin-iframe.https.html26
-rw-r--r--testing/web-platform/tests/battery-status/battery-charging-manual.https.html54
-rw-r--r--testing/web-platform/tests/battery-status/battery-default-permissions-policy.https.sub.html28
-rw-r--r--testing/web-platform/tests/battery-status/battery-disabled-by-permissions-policy.https.sub.html28
-rw-r--r--testing/web-platform/tests/battery-status/battery-disabled-by-permissions-policy.https.sub.html.headers1
-rw-r--r--testing/web-platform/tests/battery-status/battery-disallowed-in-cross-origin-iframe.https.sub.html27
-rw-r--r--testing/web-platform/tests/battery-status/battery-discharging-manual.https.html54
-rw-r--r--testing/web-platform/tests/battery-status/battery-full-manual.https.html44
-rw-r--r--testing/web-platform/tests/battery-status/battery-plugging-in-manual.https.html127
-rw-r--r--testing/web-platform/tests/battery-status/battery-promise-window.https.html30
-rw-r--r--testing/web-platform/tests/battery-status/battery-promise.https.html20
-rw-r--r--testing/web-platform/tests/battery-status/battery-unplugging-manual.https.html112
-rw-r--r--testing/web-platform/tests/battery-status/idlharness.https.window.js20
-rw-r--r--testing/web-platform/tests/battery-status/multiple-promises-after-resolve.https.html23
-rw-r--r--testing/web-platform/tests/battery-status/multiple-promises.https.html22
-rw-r--r--testing/web-platform/tests/battery-status/no-leak-on-detached-use.https.html48
-rw-r--r--testing/web-platform/tests/battery-status/page-visibility.https.html38
-rw-r--r--testing/web-platform/tests/battery-status/promise-with-eventlisteners.https.html36
-rw-r--r--testing/web-platform/tests/battery-status/resources/battery-status-helpers.js34
-rw-r--r--testing/web-platform/tests/battery-status/resources/support-iframe.html5
-rw-r--r--testing/web-platform/tests/battery-status/resources/support-window-open.html10
-rw-r--r--testing/web-platform/tests/battery-status/resources/window-postmessage-open-close.html9
-rw-r--r--testing/web-platform/tests/battery-status/restricted-level-precision.https.html22
29 files changed, 936 insertions, 0 deletions
diff --git a/testing/web-platform/tests/battery-status/META.yml b/testing/web-platform/tests/battery-status/META.yml
new file mode 100644
index 0000000000..77d19a828d
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/META.yml
@@ -0,0 +1,4 @@
+spec: https://w3c.github.io/battery/
+suggested_reviewers:
+ - anssiko
+ - Honry
diff --git a/testing/web-platform/tests/battery-status/api-defined.https.html b/testing/web-platform/tests/battery-status/api-defined.https.html
new file mode 100644
index 0000000000..9fe41d4b49
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/api-defined.https.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/test-only-api.js"></script>
+<script src="resources/battery-status-helpers.js"></script>
+</head>
+<body>
+<script>
+battery_status_test(async (t, mockBatteryMonitor) => {
+ mockBatteryMonitor.setBatteryStatus(false, 10, 20, 0.5);
+ const battery = await navigator.getBattery();
+
+ assert_not_equals(battery, undefined);
+ assert_equals(typeof battery.charging, 'boolean');
+ assert_equals(typeof battery.chargingTime, 'number');
+ assert_equals(typeof battery.dischargingTime, 'number');
+ assert_equals(typeof battery.level, 'number');
+
+ mockBatteryMonitor.verifyBatteryStatus(battery);
+
+ assert_equals(typeof battery.onchargingchange, 'object');
+ assert_equals(typeof battery.onchargingtimechange, 'object');
+ assert_equals(typeof battery.ondischargingtimechange, 'object');
+ assert_equals(typeof battery.onlevelchange, 'object');
+}, 'verify basic getBattery API support');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html b/testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html
new file mode 100644
index 0000000000..f65f3629df
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<body>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/permissions-policy/resources/permissions-policy.js></script>
+<script>
+'use strict';
+
+const relative_path = '/permissions-policy/resources/permissions-policy-battery.html';
+const base_src = '/permissions-policy/resources/redirect-on-load.html#';
+const same_origin_src = base_src + relative_path;
+const cross_origin_src = base_src + 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ relative_path;
+const header = 'permissions policy allow="battery"';
+
+async_test(t => {
+ test_feature_availability(
+ 'navigator.getBattery()', t, same_origin_src,
+ expect_feature_available_default, 'battery');
+}, `${header} allows same-origin relocation.`);
+
+async_test(t => {
+ test_feature_availability(
+ 'navigator.getBattery()', t, cross_origin_src,
+ expect_feature_unavailable_default, 'battery');
+}, `${header} disallows cross-origin relocation.`);
+</script>
+</body>
diff --git a/testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy-attribute.https.sub.html b/testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy-attribute.https.sub.html
new file mode 100644
index 0000000000..fc4a7bad81
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy-attribute.https.sub.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<body>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/permissions-policy/resources/permissions-policy.js></script>
+<script>
+'use strict';
+
+const same_origin_src = '/permissions-policy/resources/permissions-policy-battery.html';
+const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+const feature_name = 'permissions policy "battery"';
+const header = 'allow="battery" attribute';
+
+async_test(t => {
+ test_feature_availability(
+ 'navigator.getBattery()', t, same_origin_src,
+ expect_feature_available_default, 'battery');
+}, `${feature_name} can be enabled in same-origin iframe using ${header}`);
+
+async_test(t => {
+ test_feature_availability(
+ 'navigator.getBattery()', t, cross_origin_src,
+ expect_feature_available_default, 'battery');
+}, `${feature_name} can be enabled in cross-origin iframe using ${header}`);
+</script>
+</body>
diff --git a/testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy.https.sub.html b/testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy.https.sub.html
new file mode 100644
index 0000000000..8cbf39997b
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy.https.sub.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<body>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/permissions-policy/resources/permissions-policy.js></script>
+<script>
+'use strict';
+
+const same_origin_src = '/permissions-policy/resources/permissions-policy-battery.html';
+const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+const header = 'Permissions-Policy header "battery=*"';
+
+promise_test(
+ async () => await navigator.getBattery(),
+ `${header} allows the top-level document.`);
+
+async_test(t => {
+ test_feature_availability('navigator.getBattery()', t, same_origin_src,
+ expect_feature_available_default);
+}, `${header} allows same-origin iframes.`);
+
+async_test(t => {
+ test_feature_availability('navigator.getBattery()', t, cross_origin_src,
+ expect_feature_available_default);
+}, `${header} allows cross-origin iframes.`);
+</script>
+</body>
diff --git a/testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy.https.sub.html.headers b/testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy.https.sub.html.headers
new file mode 100644
index 0000000000..989fdc3df8
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-allowed-by-permissions-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Permissions-Policy: battery=*
diff --git a/testing/web-platform/tests/battery-status/battery-allowed-in-same-origin-iframe.https.html b/testing/web-platform/tests/battery-status/battery-allowed-in-same-origin-iframe.https.html
new file mode 100644
index 0000000000..03475162df
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-allowed-in-same-origin-iframe.https.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: navigator.getBattery() is allowed in same origin iframe</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://www.w3.org/TR/battery-status/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe id="blank" src="about:blank" style="display: none"></iframe>
+<script>
+
+function load_iframe(iframe, src) {
+ return new Promise((resolve, reject) => {
+ iframe.onload = () => resolve(iframe);
+ iframe.src = src;
+ });
+}
+
+promise_test(async t => {
+ let iframe = document.getElementById('blank');
+ const src = 'resources/support-iframe.html';
+ iframe = await load_iframe(iframe, src);
+ await iframe.contentWindow.navigator.getBattery();
+}, "navigator.getBattery() is allowed in same origin iframe");
+
+</script>
diff --git a/testing/web-platform/tests/battery-status/battery-charging-manual.https.html b/testing/web-platform/tests/battery-status/battery-charging-manual.https.html
new file mode 100644
index 0000000000..9ff7421638
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-charging-manual.https.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: battery neither empty or full, charger plugged in</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://www.w3.org/TR/battery-status/">
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<h2>Description</h2>
+<p>
+ This test validates that all of the BatteryManager attributes exist and are set to their correct values when battery is charging.
+</p>
+
+<h2>Preconditions</h2>
+<ol>
+ <li>
+ The device is plugged in to the charger before this test is run.
+ </li>
+ <li>
+ The battery must neither be empty or full, nor reach empty or full capacity during the test.
+ </li>
+ <li>
+ Waiting for battery level change to fire levelchange event, maybe need a long time
+ </li>
+</ol>
+
+<script>
+
+setup({ explicit_timeout: true });
+
+async_test(function (t) {
+ navigator.getBattery().then(function (battery) {
+ t.step(function () {
+ assert_true(battery.charging, 'charging must be set to true');
+ assert_equals(battery.dischargingTime, Infinity, 'dischargingTime must be set to Infinity');
+ assert_greater_than(battery.level, 0, 'level must be greater than 0');
+ assert_less_than_equal(battery.level, 1.0, 'level must be less than or equal to 1.0');
+
+ var battery_level = battery.level;
+ battery.onlevelchange = t.step_func(function () {
+ assert_greater_than(battery.level, battery_level, 'The value of the level attribute must increase');
+ t.done();
+ });
+ });
+ }, function (error) {
+ t.step(function () {
+ assert_unreached(error.message);
+ });
+ t.done();
+ });
+}, document.title);
+
+</script>
diff --git a/testing/web-platform/tests/battery-status/battery-default-permissions-policy.https.sub.html b/testing/web-platform/tests/battery-status/battery-default-permissions-policy.https.sub.html
new file mode 100644
index 0000000000..7485250dae
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-default-permissions-policy.https.sub.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<body>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/permissions-policy/resources/permissions-policy.js></script>
+<script>
+'use strict';
+
+const same_origin_src = '/permissions-policy/resources/permissions-policy-battery.html';
+const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+const header = 'Default "battery" permissions policy';
+
+promise_test(
+ async () => await navigator.getBattery(),
+ `${header} allows the top-level document.`);
+
+async_test(t => {
+ test_feature_availability('navigator.getBattery()', t, same_origin_src,
+ expect_feature_available_default);
+}, `${header} allows same-origin iframes.`);
+
+async_test(t => {
+ test_feature_availability('navigator.getBattery()', t, cross_origin_src,
+ expect_feature_unavailable_default);
+}, `${header} disallows cross-origin iframes.`);
+</script>
+</body>
diff --git a/testing/web-platform/tests/battery-status/battery-disabled-by-permissions-policy.https.sub.html b/testing/web-platform/tests/battery-status/battery-disabled-by-permissions-policy.https.sub.html
new file mode 100644
index 0000000000..4afdee8a0c
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-disabled-by-permissions-policy.https.sub.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<body>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/permissions-policy/resources/permissions-policy.js></script>
+<script>
+'use strict';
+
+const same_origin_src = '/permissions-policy/resources/permissions-policy-battery.html';
+const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+const header = 'Permissions-Policy header "battery=()"';
+
+promise_test(async t => {
+ await promise_rejects_dom(t, 'NotAllowedError', navigator.getBattery());
+}, `${header} disallows the top-level document.`);
+
+async_test(t => {
+ test_feature_availability('navigator.getBattery()', t, same_origin_src,
+ expect_feature_unavailable_default);
+}, `${header} disallows same-origin iframes.`);
+
+async_test(t => {
+ test_feature_availability('navigator.getBattery()', t, cross_origin_src,
+ expect_feature_unavailable_default);
+}, `${header} disallows cross-origin iframes.`);
+</script>
+</body>
diff --git a/testing/web-platform/tests/battery-status/battery-disabled-by-permissions-policy.https.sub.html.headers b/testing/web-platform/tests/battery-status/battery-disabled-by-permissions-policy.https.sub.html.headers
new file mode 100644
index 0000000000..9ff0bc6190
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-disabled-by-permissions-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Permissions-Policy: battery=()
diff --git a/testing/web-platform/tests/battery-status/battery-disallowed-in-cross-origin-iframe.https.sub.html b/testing/web-platform/tests/battery-status/battery-disallowed-in-cross-origin-iframe.https.sub.html
new file mode 100644
index 0000000000..c86e01f6ab
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-disallowed-in-cross-origin-iframe.https.sub.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: navigator.getBattery() is not allowed in cross origin iframe</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://www.w3.org/TR/battery-status/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe id="blank" src="about:blank" style="display: none"></iframe>
+<script>
+
+function load_iframe(iframe, src) {
+ return new Promise((resolve, reject) => {
+ iframe.onload = () => resolve(iframe);
+ iframe.src = src;
+ });
+}
+
+promise_test(async t => {
+ let iframe = document.getElementById('blank');
+ const path = location.pathname.substring(0, location.pathname.lastIndexOf('/') + 1);
+ const src = 'https://{{domains[www1]}}:{{ports[https][0]}}' + path + 'resources/support-iframe.html';
+ iframe = await load_iframe(iframe, src);
+ await promise_rejects_dom(t, 'NotAllowedError', iframe.contentWindow.navigator.getBattery());
+}, "throw a 'NotAllowedError' when invoking navigator.getBattery() within cross-origin iframe");
+
+</script>
diff --git a/testing/web-platform/tests/battery-status/battery-discharging-manual.https.html b/testing/web-platform/tests/battery-status/battery-discharging-manual.https.html
new file mode 100644
index 0000000000..f321cf7548
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-discharging-manual.https.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: battery neither empty or full, charger unplugged in</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://www.w3.org/TR/battery-status/">
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<h2>Description</h2>
+<p>
+ This test validates that all of the BatteryManager attributes exist and are set to their correct values when battery is discharging.
+</p>
+
+<h2>Preconditions</h2>
+<ol>
+ <li>
+ The device is unplugged from the charger before this test is run.
+ </li>
+ <li>
+ The battery must neither be empty or full, nor reach empty or full capacity during the test.
+ </li>
+ <li>
+ Waiting for battery level change to fire levelchange event, maybe need a long time
+ </li>
+</ol>
+
+<script>
+
+setup({ explicit_timeout: true });
+
+async_test(function (t) {
+ navigator.getBattery().then(function (battery) {
+ t.step(function () {
+ assert_false(battery.charging, 'charging must be set to false');
+ assert_equals(battery.chargingTime, Infinity, 'chargingTime must be set to Infinity');
+ assert_greater_than(battery.level, 0, 'level must be greater than 0');
+ assert_less_than_equal(battery.level, 1.0, 'level must be less than or equal to 1.0');
+
+ var battery_level = battery.level;
+ battery.onlevelchange = t.step_func(function () {
+ assert_less_than(battery.level, battery_level, 'The value of the level attribute must decrease');
+ t.done();
+ });
+ });
+ }, function (error) {
+ t.step(function () {
+ assert_unreached(error.message);
+ });
+ t.done();
+ });
+}, document.title);
+
+</script>
diff --git a/testing/web-platform/tests/battery-status/battery-full-manual.https.html b/testing/web-platform/tests/battery-status/battery-full-manual.https.html
new file mode 100644
index 0000000000..0680b7d933
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-full-manual.https.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: battery full, charger plugged in</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://www.w3.org/TR/battery-status/">
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<h2>Description</h2>
+<p>
+ This test validates that all of the BatteryManager attributes exist and are set to their correct values when battery is full.
+</p>
+
+<h2>Preconditions</h2>
+<ol>
+ <li>
+ The device is plugged in to the charger before this test is run.
+ </li>
+ <li>
+ The battery is full.
+ </li>
+</ol>
+
+<script>
+
+async_test(function (t) {
+ navigator.getBattery().then(function (battery) {
+ t.step(function () {
+ assert_true(battery.charging, 'charging must be set to true');
+ assert_equals(battery.chargingTime, 0, 'chargingTime must be set to 0');
+ assert_equals(battery.dischargingTime, Infinity, 'dischargingTime must be set to Infinity');
+ assert_equals(battery.level, 1.0, 'level must be set to 1.0');
+ });
+ t.done();
+ }, function (error) {
+ t.step(function () {
+ assert_unreached(error.message);
+ });
+ t.done();
+ });
+}, document.title);
+
+</script>
diff --git a/testing/web-platform/tests/battery-status/battery-plugging-in-manual.https.html b/testing/web-platform/tests/battery-status/battery-plugging-in-manual.https.html
new file mode 100644
index 0000000000..1445bd7e26
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-plugging-in-manual.https.html
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: battery not full, charger plugging in</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://www.w3.org/TR/battery-status/">
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #note {
+ background-color: #fef1b5;
+ border: solid 1px #cdab2d;
+ padding: 5px;
+ margin: 15px;
+ display: block;
+ }
+</style>
+
+<h2>Description</h2>
+<p>
+ This test validates that all of the BatteryManager attributes exist and
+ are set to correct values, with corresponding events fired,
+ when the charger is plugged in.
+</p>
+
+<h2>Preconditions</h2>
+<ol>
+ <li>
+ The device is unplugged from the charger before this test is run.
+ </li>
+ <li>
+ The battery must not be full or reach full capacity before the time the test is run.
+ </li>
+</ol>
+
+<div id="note">
+ <ol>
+ <li>
+ Plug in the charger and wait for all the tests to complete.
+ </li>
+ <li>
+ The tests may take long time since the definition of how
+ often the chargingtimechange, dischargingtimechange, and levelchange
+ events are fired is left to the implementation.
+ </li>
+ </ol>
+</div>
+
+<div id="log"></div>
+
+<script>
+
+(function() {
+
+ setup({ explicit_timeout: true });
+
+ var onchargingchange_test = async_test(
+ 'When the device is plugged in and its charging state is updated, ' +
+ 'must set the charging attribute\'s value to true and ' +
+ 'fire a chargingchange event.');
+ var onchargingtimechange_test = async_test(
+ 'When the device is plugged in and its charging time is updated, ' +
+ 'must set the chargingTime attribute\'s value and fire ' +
+ 'a chargingtimechange event.');
+ var ondischargingtimechange_test = async_test(
+ 'When the device is plugged in and its discharging time is updated, ' +
+ 'must set the dischargingTime attribute\'s value to Infinity and ' +
+ 'fire a dischargingtimechange event.');
+ var onlevelchange_test = async_test(
+ 'When the device is plugged in and the battery level is updated, ' +
+ 'must set the level attribute\'s value and fire a levelchange event.');
+
+ var batterySuccess = function (battery) {
+ battery.onchargingchange = onchargingchange_test.step_func(function () {
+ assert_true(battery.charging, 'The charging attribute must be set to true.');
+ onchargingchange_test.done();
+ });
+
+ var battery_chargingtime = battery.chargingTime;
+ battery.onchargingtimechange = onchargingtimechange_test.step_func(function () {
+ assert_less_than(battery.chargingTime, battery_chargingtime,
+ 'The value of the chargingTime attribute must decrease.');
+ onchargingtimechange_test.done();
+ });
+
+ battery.ondischargingtimechange = ondischargingtimechange_test.step_func(function () {
+ if (battery.charging) {
+ assert_equals(battery.dischargingTime, Infinity,
+ 'The value of the dischargingTime attribute must be set to Infinity.');
+ ondischargingtimechange_test.done();
+ }
+ });
+
+ battery.onlevelchange = onlevelchange_test.step_func(function () {
+ assert_greater_than(battery.level, 0);
+ assert_less_than_equal(battery.level, 1.0);
+ onlevelchange_test.done();
+ });
+ };
+
+ var batteryFailure = function (error) {
+ onchargingchange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ onchargingchange_test.done();
+
+ onchargingtimechange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ onchargingtimechange_test.done();
+
+ ondischargingtimechange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ ondischargingtimechange_test.done();
+
+ onlevelchange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ onlevelchange_test.done();
+ };
+
+ navigator.getBattery().then(batterySuccess, batteryFailure);
+
+})();
+
+</script>
diff --git a/testing/web-platform/tests/battery-status/battery-promise-window.https.html b/testing/web-platform/tests/battery-status/battery-promise-window.https.html
new file mode 100644
index 0000000000..362ef93667
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-promise-window.https.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: window.open() makes a different Navigator object</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://www.w3.org/TR/battery-status/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #note {
+ background-color: #fef1b5;
+ border: solid 1px #cdab2d;
+ padding: 5px;
+ margin: 15px;
+ display: block;
+ }
+</style>
+<div id="note">
+ Allow pop-up windows before running the tests.
+</div>
+<div id="log"></div>
+<script>
+async_test(function (t) {
+ var win = window.open('resources/support-window-open.html');
+ window.onmessage = t.step_func(function(e) {
+ assert_array_equals(e.data, [false, false, true]);
+ win.close();
+ t.done();
+ });
+}, 'window.open() makes a different Navigator object thus getting another battery promise');
+</script>
diff --git a/testing/web-platform/tests/battery-status/battery-promise.https.html b/testing/web-platform/tests/battery-status/battery-promise.https.html
new file mode 100644
index 0000000000..ecf7318e1c
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-promise.https.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: navigator.getBattery() always return same battery promise</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://www.w3.org/TR/battery-status/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+promise_test(function () {
+ return navigator.getBattery().then(function (result) {
+ assert_class_string(result, 'BatteryManager',
+ 'getBattery should return BatteryManager Object.');
+ });
+}, 'navigator.getBattery() shall return BatteryManager as a promise');
+
+test(function () {
+ assert_equals(navigator.getBattery(), navigator.getBattery());
+}, 'navigator.getBattery() shall always return the same promise');
+</script>
diff --git a/testing/web-platform/tests/battery-status/battery-unplugging-manual.https.html b/testing/web-platform/tests/battery-status/battery-unplugging-manual.https.html
new file mode 100644
index 0000000000..3b515786dc
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/battery-unplugging-manual.https.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: charger unplugging</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://www.w3.org/TR/battery-status/">
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #note {
+ background-color: #fef1b5;
+ border: solid 1px #cdab2d;
+ padding: 5px;
+ margin: 15px;
+ display: block;
+ }
+</style>
+
+<h2>Description</h2>
+<p>
+ This test validates that all of the BatteryManager attributes exist and
+ are set to correct values, with corresponding events fired,
+ when the charger is unplugged.
+</p>
+
+<h2>Preconditions</h2>
+<ol>
+ <li>
+ The device is plugged in to the charger before this test is run.
+ </li>
+</ol>
+
+<div id="note">
+ Unplug the charger and wait for all the tests to complete.
+</div>
+
+<div id="log"></div>
+
+<script>
+
+(function() {
+
+ setup({ explicit_timeout: true });
+
+ var onchargingchange_test = async_test(
+ 'When the device is unplugged in and its charging state is updated, ' +
+ 'must set the charging attribute\'s value to false and ' +
+ 'fire a chargingchange event.');
+ var onchargingtimechange_test = async_test(
+ 'When the device is unplugged in and its charging time is updated, ' +
+ 'must set the chargingTime attribute\'s value to Infinity and ' +
+ 'fire a chargingtimechange event.');
+ var ondischargingtimechange_test = async_test(
+ 'When the device is unplugged in and its discharging time is updated, ' +
+ 'must set the dischargingTime attribute\'s value and ' +
+ 'fire a dischargingtimechange event.');
+ var onlevelchange_test = async_test(
+ 'When the device is unplugged in and the battery level is updated, ' +
+ 'must set the level attribute\'s value and fire a levelchange event.');
+
+ var batterySuccess = function (battery) {
+ battery.onchargingchange = onchargingchange_test.step_func(function () {
+ assert_false(battery.charging, 'The charging attribute must be set to false.');
+ onchargingchange_test.done();
+ });
+
+ battery.onchargingtimechange = onchargingtimechange_test.step_func(function () {
+ assert_equals(battery.chargingTime, Infinity,
+ 'The value of the chargingTime attribute must be set to Infinity.');
+ onchargingtimechange_test.done();
+ });
+
+ battery.ondischargingtimechange = ondischargingtimechange_test.step_func(function () {
+ assert_less_than(battery.dischargingTime, Infinity,
+ 'The value of the dischargingTime attribute must be set to the remaining discharging time.');
+ ondischargingtimechange_test.done();
+ });
+
+ battery.onlevelchange = onlevelchange_test.step_func(function () {
+ assert_greater_than(battery.level, 0);
+ assert_less_than_equal(battery.level, 1.0);
+ onlevelchange_test.done();
+ });
+ };
+
+ var batteryFailure = function (error) {
+ onchargingchange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ onchargingchange_test.done();
+
+ onchargingtimechange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ onchargingtimechange_test.done();
+
+ ondischargingtimechange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ ondischargingtimechange_test.done();
+
+ onlevelchange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ onlevelchange_test.done();
+ };
+
+ navigator.getBattery().then(batterySuccess, batteryFailure);
+
+})();
+
+</script>
diff --git a/testing/web-platform/tests/battery-status/idlharness.https.window.js b/testing/web-platform/tests/battery-status/idlharness.https.window.js
new file mode 100644
index 0000000000..8113d9e779
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/idlharness.https.window.js
@@ -0,0 +1,20 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+// META: timeout=long
+
+// https://w3c.github.io/battery/
+
+'use strict';
+
+idl_test(
+ ['battery-status'],
+ ['dom', 'html'],
+ async idl_array => {
+ idl_array.add_objects({
+ Navigator: ['navigator'],
+ BatteryManager: ['manager'],
+ })
+
+ self.manager = await navigator.getBattery();
+ }
+);
diff --git a/testing/web-platform/tests/battery-status/multiple-promises-after-resolve.https.html b/testing/web-platform/tests/battery-status/multiple-promises-after-resolve.https.html
new file mode 100644
index 0000000000..2b43f124c0
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/multiple-promises-after-resolve.https.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/test-only-api.js"></script>
+<script src="resources/battery-status-helpers.js"></script>
+</head>
+<body>
+<script>
+battery_status_test(async (t, mockBatteryMonitor) => {
+ const promise1 = navigator.getBattery();
+ mockBatteryMonitor.setBatteryStatus(false, 10, 20, 0.5);
+ const result1 = await promise1;
+ mockBatteryMonitor.verifyBatteryStatus(result1);
+ const promise2 = navigator.getBattery();
+ assert_equals(promise1, promise2);
+ const result2 = await promise2;
+ mockBatteryMonitor.verifyBatteryStatus(result2);
+}, 'multiple consecutive invocations of navigator.getBattery()');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/battery-status/multiple-promises.https.html b/testing/web-platform/tests/battery-status/multiple-promises.https.html
new file mode 100644
index 0000000000..35015c80ba
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/multiple-promises.https.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/test-only-api.js"></script>
+<script src="resources/battery-status-helpers.js"></script>
+</head>
+<body>
+<script>
+battery_status_test(async (t, mockBatteryMonitor) => {
+ const promise1 = navigator.getBattery();
+ const promise2 = navigator.getBattery();
+ assert_equals(promise1, promise2);
+
+ mockBatteryMonitor.setBatteryStatus(false, 10, 20, 0.5);
+ mockBatteryMonitor.verifyBatteryStatus(await promise1);
+ mockBatteryMonitor.verifyBatteryStatus(await promise2);
+}, 'multiple parallel invocations of navigator.getBattery()');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/battery-status/no-leak-on-detached-use.https.html b/testing/web-platform/tests/battery-status/no-leak-on-detached-use.https.html
new file mode 100644
index 0000000000..8ea7ea303c
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/no-leak-on-detached-use.https.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+function waitForMessage(data) {
+ return new Promise(
+ resolve => {
+ window.addEventListener('message', e => {
+ if (e.data == data) {
+ resolve();
+ }
+ }, {once: true});
+ });
+}
+
+promise_test(async t => {
+ const w = window.open('resources/window-postmessage-open-close.html');
+ await waitForMessage('opened');
+
+ const nav = w.navigator;
+ let result = nav.getBattery();
+ assert_equals(typeof result, 'object');
+ assert_equals(result.constructor, w.Promise);
+
+ w.close();
+ await waitForMessage('closed');
+ result = nav.getBattery();
+ assert_equals(result, undefined);
+}, 'navigator.getBattery() does not operate on a closed window');
+
+promise_test(async t => {
+ const iframe = document.createElement('iframe');
+ iframe.srcdoc = '<html></html>';
+ document.body.appendChild(iframe);
+
+ const frameNav = iframe.contentWindow.navigator;
+ document.body.removeChild(iframe);
+
+ const battery = await frameNav.getBattery();
+ assert_equals(battery, undefined);
+}, 'navigator.getBattery() on a detached frame does not leak or crash');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/battery-status/page-visibility.https.html b/testing/web-platform/tests/battery-status/page-visibility.https.html
new file mode 100644
index 0000000000..27cc0208a8
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/page-visibility.https.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/test-only-api.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/page-visibility/resources/window_state_context.js"></script>
+<script src="resources/battery-status-helpers.js"></script>
+</head>
+<body>
+<script>
+battery_status_test(async (t, mockBatteryMonitor) => {
+ mockBatteryMonitor.setBatteryStatus(false, 10, 20, 0.5);
+ const battery = await navigator.getBattery();
+
+ mockBatteryMonitor.verifyBatteryStatus(battery);
+
+ const fail = () => { throw new Error('unexpected levelchange event'); };
+ battery.addEventListener('levelchange', fail);
+
+ const {minimize, restore} = window_state_context(t);
+ await minimize();
+ mockBatteryMonitor.setBatteryStatus(false, 10, 20, 0.55);
+ battery.removeEventListener('levelchange', fail);
+
+ const change =
+ new Promise(resolve => battery.addEventListener('levelchange', resolve));
+ await restore();
+ mockBatteryMonitor.setBatteryStatus(false, 10, 20, 0.6);
+ await change;
+
+ mockBatteryMonitor.verifyBatteryStatus(battery);
+}, 'battery status events only fire on visible pages');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/battery-status/promise-with-eventlisteners.https.html b/testing/web-platform/tests/battery-status/promise-with-eventlisteners.https.html
new file mode 100644
index 0000000000..6d7544b856
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/promise-with-eventlisteners.https.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/test-only-api.js"></script>
+<script src="resources/battery-status-helpers.js"></script>
+</head>
+<body>
+<script>
+function nextEvent(target, name) {
+ return new Promise(
+ resolve => target.addEventListener(name, resolve, {once: true}));
+}
+
+battery_status_test(async (t, mockBatteryMonitor) => {
+ mockBatteryMonitor.setBatteryStatus(false, 10, 20, 0.5);
+ const battery = await navigator.getBattery();
+
+ mockBatteryMonitor.verifyBatteryStatus(battery);
+
+ const events = Promise.all([
+ nextEvent(battery, 'chargingchange'),
+ nextEvent(battery, 'chargingtimechange'),
+ nextEvent(battery, 'dischargingtimechange'),
+ nextEvent(battery, 'levelchange'),
+ ]);
+
+ t.step_timeout(() => mockBatteryMonitor.setBatteryStatus(true, 11, 22, 0.6));
+
+ await events;
+ mockBatteryMonitor.verifyBatteryStatus(battery);
+}, 'event listeners fire as specified');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/battery-status/resources/battery-status-helpers.js b/testing/web-platform/tests/battery-status/resources/battery-status-helpers.js
new file mode 100644
index 0000000000..02acfe6c29
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/resources/battery-status-helpers.js
@@ -0,0 +1,34 @@
+'use strict';
+
+// These tests rely on the User Agent providing an implementation of
+// platform battery status backends.
+//
+// In Chromium-based browsers this implementation is provided by a polyfill
+// in order to reduce the amount of test-only code shipped to users. To enable
+// these tests the browser must be run with these options:
+//
+// --enable-blink-features=MojoJS,MojoJSTest
+
+let mockBatteryMonitor = undefined;
+
+function battery_status_test(func, name, properties) {
+ promise_test(async t => {
+ if (mockBatteryMonitor === undefined) {
+ if (isChromiumBased) {
+ const mocks =
+ await import('/resources/chromium/mock-battery-monitor.js');
+ mockBatteryMonitor = mocks.mockBatteryMonitor;
+ }
+ }
+ assert_implements(
+ mockBatteryMonitor, 'missing mockBatteryMonitor after initialization');
+
+ mockBatteryMonitor.start();
+
+ t.add_cleanup(() => {
+ mockBatteryMonitor.reset();
+ return mockBatteryMonitor.stop();
+ });
+ return func(t, mockBatteryMonitor);
+ }, name, properties);
+}
diff --git a/testing/web-platform/tests/battery-status/resources/support-iframe.html b/testing/web-platform/tests/battery-status/resources/support-iframe.html
new file mode 100644
index 0000000000..d4e5b31f13
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/resources/support-iframe.html
@@ -0,0 +1,5 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<div>
+Hello!
+</div>
diff --git a/testing/web-platform/tests/battery-status/resources/support-window-open.html b/testing/web-platform/tests/battery-status/resources/support-window-open.html
new file mode 100644
index 0000000000..afffc3af28
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/resources/support-window-open.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<script>
+var data = [
+ navigator === window.opener.navigator,
+ navigator.getBattery() === window.opener.navigator.getBattery(),
+ navigator.getBattery() === navigator.getBattery()
+];
+window.opener.postMessage(data, '*');
+</script>
diff --git a/testing/web-platform/tests/battery-status/resources/window-postmessage-open-close.html b/testing/web-platform/tests/battery-status/resources/window-postmessage-open-close.html
new file mode 100644
index 0000000000..3adb8ceecd
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/resources/window-postmessage-open-close.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<!-- Used when testing access of a closed/detached window's properties -->
+<html>
+<body onunload="opener.postMessage('closed', '*');">
+<script>
+opener.postMessage("opened", "*");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/battery-status/restricted-level-precision.https.html b/testing/web-platform/tests/battery-status/restricted-level-precision.https.html
new file mode 100644
index 0000000000..a66a22cecf
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/restricted-level-precision.https.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/test-only-api.js"></script>
+<script src="resources/battery-status-helpers.js"></script>
+</head>
+<body>
+<script>
+battery_status_test(async (t, mockBatteryMonitor) => {
+ const levelFullPrecision = 0.556789;
+ const levelRounded = 0.56;
+
+ mockBatteryMonitor.setBatteryStatus(false, 10, 20, levelFullPrecision);
+
+ const battery = await navigator.getBattery();
+ assert_equals(battery.level, levelRounded);
+}, 'battery level is reported with restricted precision');
+</script>
+</body>
+</html>