Bug 1429043 - Update web-platform-tests to revision 4de5305adf3d33badc23952672bcf28168fea37e, a=testonly

MozReview-Commit-ID: 8hFZiSUb5Qr


--HG--
rename : testing/web-platform/tests/bluetooth/idl-Bluetooth.html => testing/web-platform/tests/bluetooth/idl/idl-Bluetooth.html
rename : testing/web-platform/tests/cookies/secure/set-from-ws.https.sub.html => testing/web-platform/tests/cookies/secure/set-from-ws.sub.html
rename : testing/web-platform/tests/css/css-values/iframe/vh-support-transform-origin-iframe.html => testing/web-platform/tests/css/css-values/support/vh-support-transform-origin-iframe.html
rename : testing/web-platform/tests/css/css-values/iframe/vh-support-transform-translate-iframe.html => testing/web-platform/tests/css/css-values/support/vh-support-transform-translate-iframe.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/a-ref.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/a-ref.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/a.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/a.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/match/a-ref.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/match/a-ref.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/match/a.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/match/a.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/match/support/a.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/match/support/a.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/match/support/tools/a.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/match/support/tools/a.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/match/tools/a.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/match/tools/a.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/not-match/a-ref.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/not-match/a-ref.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/not-match/a.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/not-match/a.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/not-match/support/a.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/not-match/support/a.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/not-match/tools/a.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/not-match/tools/a.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/selectors/a.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/selectors/a.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/support/a.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/support/a.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/support/tools/a.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/support/tools/a.html
rename : testing/web-platform/tests/tools/lint/tests/dummy/css-unique/tools/a.html => testing/web-platform/tests/tools/lint/tests/dummy/css/css-unique/tools/a.html
rename : testing/web-platform/tests/tools/py/.hgignore => testing/web-platform/tests/tools/third_party/py/.hgignore
rename : testing/web-platform/tests/tools/py/AUTHORS => testing/web-platform/tests/tools/third_party/py/AUTHORS
rename : testing/web-platform/tests/tools/py/LICENSE => testing/web-platform/tests/tools/third_party/py/LICENSE
rename : testing/web-platform/tests/tools/py/bench/localpath.py => testing/web-platform/tests/tools/third_party/py/bench/localpath.py
rename : testing/web-platform/tests/tools/py/doc/Makefile => testing/web-platform/tests/tools/third_party/py/doc/Makefile
rename : testing/web-platform/tests/tools/py/doc/_templates/layout.html => testing/web-platform/tests/tools/third_party/py/doc/_templates/layout.html
rename : testing/web-platform/tests/tools/py/doc/announce/release-0.9.0.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-0.9.0.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-0.9.2.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-0.9.2.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.0.0.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.0.0.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.0.1.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.0.1.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.0.2.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.0.2.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.1.0.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.1.0.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.1.1.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.1.1.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.2.0.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.2.0.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.2.1.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.2.1.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.3.0.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.3.0.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.3.1.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.3.1.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.3.2.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.3.2.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.3.3.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.3.3.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.3.4.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.3.4.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.4.0.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.4.0.txt
rename : testing/web-platform/tests/tools/py/doc/announce/release-1.4.1.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/release-1.4.1.txt
rename : testing/web-platform/tests/tools/py/doc/announce/releases.txt => testing/web-platform/tests/tools/third_party/py/doc/announce/releases.txt
rename : testing/web-platform/tests/tools/py/doc/changelog.txt => testing/web-platform/tests/tools/third_party/py/doc/changelog.txt
rename : testing/web-platform/tests/tools/py/doc/code.txt => testing/web-platform/tests/tools/third_party/py/doc/code.txt
rename : testing/web-platform/tests/tools/py/doc/conf.py => testing/web-platform/tests/tools/third_party/py/doc/conf.py
rename : testing/web-platform/tests/tools/py/doc/download.html => testing/web-platform/tests/tools/third_party/py/doc/download.html
rename : testing/web-platform/tests/tools/py/doc/example/genhtml.py => testing/web-platform/tests/tools/third_party/py/doc/example/genhtml.py
rename : testing/web-platform/tests/tools/py/doc/example/genhtmlcss.py => testing/web-platform/tests/tools/third_party/py/doc/example/genhtmlcss.py
rename : testing/web-platform/tests/tools/py/doc/example/genxml.py => testing/web-platform/tests/tools/third_party/py/doc/example/genxml.py
rename : testing/web-platform/tests/tools/py/doc/faq.txt => testing/web-platform/tests/tools/third_party/py/doc/faq.txt
rename : testing/web-platform/tests/tools/py/doc/img/pylib.png => testing/web-platform/tests/tools/third_party/py/doc/img/pylib.png
rename : testing/web-platform/tests/tools/py/doc/io.txt => testing/web-platform/tests/tools/third_party/py/doc/io.txt
rename : testing/web-platform/tests/tools/py/doc/links.inc => testing/web-platform/tests/tools/third_party/py/doc/links.inc
rename : testing/web-platform/tests/tools/py/doc/log.txt => testing/web-platform/tests/tools/third_party/py/doc/log.txt
rename : testing/web-platform/tests/tools/py/doc/style.css => testing/web-platform/tests/tools/third_party/py/doc/style.css
rename : testing/web-platform/tests/tools/py/doc/xml.txt => testing/web-platform/tests/tools/third_party/py/doc/xml.txt
rename : testing/web-platform/tests/tools/py/py/__metainfo.py => testing/web-platform/tests/tools/third_party/py/py/__metainfo.py
rename : testing/web-platform/tests/tools/py/py/_builtin.py => testing/web-platform/tests/tools/third_party/py/py/_builtin.py
rename : testing/web-platform/tests/tools/py/py/_code/__init__.py => testing/web-platform/tests/tools/third_party/py/py/_code/__init__.py
rename : testing/web-platform/tests/tools/py/py/_code/_py2traceback.py => testing/web-platform/tests/tools/third_party/py/py/_code/_py2traceback.py
rename : testing/web-platform/tests/tools/py/py/_io/__init__.py => testing/web-platform/tests/tools/third_party/py/py/_io/__init__.py
rename : testing/web-platform/tests/tools/py/py/_io/capture.py => testing/web-platform/tests/tools/third_party/py/py/_io/capture.py
rename : testing/web-platform/tests/tools/py/py/_io/saferepr.py => testing/web-platform/tests/tools/third_party/py/py/_io/saferepr.py
rename : testing/web-platform/tests/tools/py/py/_log/__init__.py => testing/web-platform/tests/tools/third_party/py/py/_log/__init__.py
rename : testing/web-platform/tests/tools/py/py/_path/__init__.py => testing/web-platform/tests/tools/third_party/py/py/_path/__init__.py
rename : testing/web-platform/tests/tools/py/py/_path/cacheutil.py => testing/web-platform/tests/tools/third_party/py/py/_path/cacheutil.py
rename : testing/web-platform/tests/tools/py/py/_process/__init__.py => testing/web-platform/tests/tools/third_party/py/py/_process/__init__.py
rename : testing/web-platform/tests/tools/py/py/_process/cmdexec.py => testing/web-platform/tests/tools/third_party/py/py/_process/cmdexec.py
rename : testing/web-platform/tests/tools/py/py/_process/forkedfunc.py => testing/web-platform/tests/tools/third_party/py/py/_process/forkedfunc.py
rename : testing/web-platform/tests/tools/py/py/_process/killproc.py => testing/web-platform/tests/tools/third_party/py/py/_process/killproc.py
rename : testing/web-platform/tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/WHEEL => testing/web-platform/tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/WHEEL
rename : testing/web-platform/tests/tools/py/py/test.py => testing/web-platform/tests/tools/third_party/py/py/test.py
rename : testing/web-platform/tests/tools/py/testing/code/test_code.py => testing/web-platform/tests/tools/third_party/py/testing/code/test_code.py
rename : testing/web-platform/tests/tools/py/testing/conftest.py => testing/web-platform/tests/tools/third_party/py/testing/conftest.py
rename : testing/web-platform/tests/tools/py/testing/io_/__init__.py => testing/web-platform/tests/tools/third_party/py/testing/io_/__init__.py
rename : testing/web-platform/tests/tools/py/testing/path/repotest.dump => testing/web-platform/tests/tools/third_party/py/testing/path/repotest.dump
rename : testing/web-platform/tests/tools/py/testing/path/svntestbase.py => testing/web-platform/tests/tools/third_party/py/testing/path/svntestbase.py
rename : testing/web-platform/tests/tools/py/testing/path/test_svnurl.py => testing/web-platform/tests/tools/third_party/py/testing/path/test_svnurl.py
rename : testing/web-platform/tests/tools/py/testing/process/__init__.py => testing/web-platform/tests/tools/third_party/py/testing/process/__init__.py
rename : testing/web-platform/tests/tools/py/testing/root/__init__.py => testing/web-platform/tests/tools/third_party/py/testing/root/__init__.py
rename : testing/web-platform/tests/tools/py/testing/root/test_builtin.py => testing/web-platform/tests/tools/third_party/py/testing/root/test_builtin.py
rename : testing/web-platform/tests/tools/py/testing/root/test_std.py => testing/web-platform/tests/tools/third_party/py/testing/root/test_std.py
rename : testing/web-platform/tests/tools/pytest/.gitattributes => testing/web-platform/tests/tools/third_party/pytest/.gitattributes
rename : testing/web-platform/tests/tools/pytest/bench/bench.py => testing/web-platform/tests/tools/third_party/pytest/bench/bench.py
rename : testing/web-platform/tests/tools/pytest/bench/bench_argcomplete.py => testing/web-platform/tests/tools/third_party/pytest/bench/bench_argcomplete.py
rename : testing/web-platform/tests/tools/pytest/bench/empty.py => testing/web-platform/tests/tools/third_party/pytest/bench/empty.py
rename : testing/web-platform/tests/tools/pytest/bench/manyparam.py => testing/web-platform/tests/tools/third_party/pytest/bench/manyparam.py
rename : testing/web-platform/tests/tools/pytest/bench/skip.py => testing/web-platform/tests/tools/third_party/pytest/bench/skip.py
rename : testing/web-platform/tests/tools/pytest/doc/en/_templates/sidebarintro.html => testing/web-platform/tests/tools/third_party/pytest/doc/en/_templates/sidebarintro.html
rename : testing/web-platform/tests/tools/pytest/doc/en/_themes/.gitignore => testing/web-platform/tests/tools/third_party/pytest/doc/en/_themes/.gitignore
rename : testing/web-platform/tests/tools/pytest/doc/en/_themes/LICENSE => testing/web-platform/tests/tools/third_party/pytest/doc/en/_themes/LICENSE
rename : testing/web-platform/tests/tools/pytest/doc/en/_themes/README => testing/web-platform/tests/tools/third_party/pytest/doc/en/_themes/README
rename : testing/web-platform/tests/tools/pytest/doc/en/_themes/flask/layout.html => testing/web-platform/tests/tools/third_party/pytest/doc/en/_themes/flask/layout.html
rename : testing/web-platform/tests/tools/pytest/doc/en/_themes/flask/relations.html => testing/web-platform/tests/tools/third_party/pytest/doc/en/_themes/flask/relations.html
rename : testing/web-platform/tests/tools/pytest/doc/en/_themes/flask/static/flasky.css_t => testing/web-platform/tests/tools/third_party/pytest/doc/en/_themes/flask/static/flasky.css_t
rename : testing/web-platform/tests/tools/pytest/doc/en/_themes/flask/theme.conf => testing/web-platform/tests/tools/third_party/pytest/doc/en/_themes/flask/theme.conf
rename : testing/web-platform/tests/tools/pytest/doc/en/_themes/flask_theme_support.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/_themes/flask_theme_support.py
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.0.0.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.0.0.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.0.1.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.0.1.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.1.0.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.1.0.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.1.1.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.1.1.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.1.2.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.1.2.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.1.3.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.1.3.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.2.0.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.2.0.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.2.2.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.2.2.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.3.1.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.3.1.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.3.4.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.3.4.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.4.1.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.4.1.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.4.2.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.4.2.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.5.1.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.5.1.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.6.0.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.6.0.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.6.1.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.6.1.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.6.2.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.6.2.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.7.2.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.7.2.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.8.2.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.8.2.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.8.3.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.8.3.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.8.4.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.8.4.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.8.5.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.8.5.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.8.6.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.8.6.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/announce/release-2.8.7.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/announce/release-2.8.7.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/changelog.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/changelog.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/check_sphinx.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/check_sphinx.py
rename : testing/web-platform/tests/tools/pytest/doc/en/conftest.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/conftest.py
rename : testing/web-platform/tests/tools/pytest/doc/en/contributing.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/contributing.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/example/assertion/global_testmodule_config/conftest.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/assertion/global_testmodule_config/conftest.py
rename : testing/web-platform/tests/tools/pytest/doc/en/example/assertion/global_testmodule_config/test_hello.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/assertion/global_testmodule_config/test_hello.py
rename : testing/web-platform/tests/tools/pytest/doc/en/example/assertion/test_failures.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/assertion/test_failures.py
rename : testing/web-platform/tests/tools/pytest/doc/en/example/conftest.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/conftest.py
rename : testing/web-platform/tests/tools/pytest/doc/en/example/costlysetup/sub1/__init__.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/costlysetup/sub1/__init__.py
rename : testing/web-platform/tests/tools/pytest/doc/en/example/costlysetup/sub1/test_quick.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/costlysetup/sub1/test_quick.py
rename : testing/web-platform/tests/tools/pytest/doc/en/example/costlysetup/sub2/__init__.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/costlysetup/sub2/__init__.py
rename : testing/web-platform/tests/tools/pytest/doc/en/example/costlysetup/sub2/test_two.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/costlysetup/sub2/test_two.py
rename : testing/web-platform/tests/tools/pytest/doc/en/example/nonpython/test_simple.yml => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/nonpython/test_simple.yml
rename : testing/web-platform/tests/tools/pytest/doc/en/example/py2py3/conftest.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/py2py3/conftest.py
rename : testing/web-platform/tests/tools/pytest/doc/en/example/py2py3/test_py2.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/py2py3/test_py2.py
rename : testing/web-platform/tests/tools/pytest/doc/en/example/py2py3/test_py3.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/py2py3/test_py3.py
rename : testing/web-platform/tests/tools/pytest/doc/en/example/xfail_demo.py => testing/web-platform/tests/tools/third_party/pytest/doc/en/example/xfail_demo.py
rename : testing/web-platform/tests/tools/pytest/doc/en/funcargs.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/funcargs.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/img/cramer2.png => testing/web-platform/tests/tools/third_party/pytest/doc/en/img/cramer2.png
rename : testing/web-platform/tests/tools/pytest/doc/en/img/freiburg2.jpg => testing/web-platform/tests/tools/third_party/pytest/doc/en/img/freiburg2.jpg
rename : testing/web-platform/tests/tools/pytest/doc/en/img/gaynor3.png => testing/web-platform/tests/tools/third_party/pytest/doc/en/img/gaynor3.png
rename : testing/web-platform/tests/tools/pytest/doc/en/img/keleshev.png => testing/web-platform/tests/tools/third_party/pytest/doc/en/img/keleshev.png
rename : testing/web-platform/tests/tools/pytest/doc/en/img/pullrequest.png => testing/web-platform/tests/tools/third_party/pytest/doc/en/img/pullrequest.png
rename : testing/web-platform/tests/tools/pytest/doc/en/img/pylib.png => testing/web-platform/tests/tools/third_party/pytest/doc/en/img/pylib.png
rename : testing/web-platform/tests/tools/pytest/doc/en/img/pytest1.png => testing/web-platform/tests/tools/third_party/pytest/doc/en/img/pytest1.png
rename : testing/web-platform/tests/tools/pytest/doc/en/img/pytest1favi.ico => testing/web-platform/tests/tools/third_party/pytest/doc/en/img/pytest1favi.ico
rename : testing/web-platform/tests/tools/pytest/doc/en/img/theuni.png => testing/web-platform/tests/tools/third_party/pytest/doc/en/img/theuni.png
rename : testing/web-platform/tests/tools/pytest/doc/en/naming20.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/naming20.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/pytest.ini => testing/web-platform/tests/tools/third_party/pytest/doc/en/pytest.ini
rename : testing/web-platform/tests/tools/pytest/doc/en/test/config.html => testing/web-platform/tests/tools/third_party/pytest/doc/en/test/config.html
rename : testing/web-platform/tests/tools/pytest/doc/en/test/dist.html => testing/web-platform/tests/tools/third_party/pytest/doc/en/test/dist.html
rename : testing/web-platform/tests/tools/pytest/doc/en/test/extend.html => testing/web-platform/tests/tools/third_party/pytest/doc/en/test/extend.html
rename : testing/web-platform/tests/tools/pytest/doc/en/test/index.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/test/index.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/test/plugin/django.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/test/plugin/django.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/test/plugin/index.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/test/plugin/index.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/test/plugin/oejskit.rst => testing/web-platform/tests/tools/third_party/pytest/doc/en/test/plugin/oejskit.rst
rename : testing/web-platform/tests/tools/pytest/doc/en/test/test.html => testing/web-platform/tests/tools/third_party/pytest/doc/en/test/test.html
rename : testing/web-platform/tests/tools/pytest/extra/setup-py.test/setup.py => testing/web-platform/tests/tools/third_party/pytest/extra/setup-py.test/setup.py
rename : testing/web-platform/tests/tools/pytest/testing/cx_freeze/tests/test_doctest.txt => testing/web-platform/tests/tools/third_party/pytest/testing/freeze/tests/test_doctest.txt
This commit is contained in:
James Graham 2018-01-03 16:24:44 +00:00
Родитель 3a7a79b6b8
Коммит 0375220b76
2064 изменённых файлов: 82530 добавлений и 25532 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -1,2 +1,2 @@
local: 5b33b070378ae0806bed0b5e5e34de429a29e7db
upstream: df8508402c2b47f43c2f5bf8da8ba9e95a2a56b9
local: ac93fdadf1022211eec62258ad22b42cb37a6d14
upstream: 45668a155fde7eb87c4c82721fc18fcf8c757c60

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

@ -63,7 +63,7 @@ matrix:
- fonts-liberation
env:
- secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM="
- JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=chrome:unstable
- JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=chrome:dev
- os: linux
python: "2.7"
env:
@ -94,7 +94,7 @@ matrix:
- env: JOB=build_css SCRIPT=css/build-css-testsuites.sh
- env:
- secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM="
- JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=chrome:unstable
- JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=chrome:dev
- env:
- secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM="
- JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=sauce:MicrosoftEdge:14.14393 PLATFORM='Windows 10'

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

@ -21,6 +21,15 @@ _addTest(function(canvas, ctx) {
var g = ctx.createLinearGradient(0, 0, 100, 0);
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, ""); });
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)'); });
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'null'); });
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'undefined'); });
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, null); });
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, undefined); });
var g = ctx.createRadialGradient(0, 0, 0, 100, 0, 0);
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, ""); });
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)'); });
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'null'); });
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'undefined'); });
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, null); });

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

@ -1,10 +1,6 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
function makeCanvas() {
@ -86,6 +82,22 @@ function makeInvalidBlob() {
});
}
function makeBrokenImage() {
return new Promise(resolve => {
const image = new Image();
image.src = "data,x";
image.onerror = () => resolve(image);
});
}
function makeAvailableButBrokenImage() {
return new Promise(resolve => {
const image = new Image();
image.src = "/images/broken.png";
image.onload = () => resolve(image);
});
}
imageSourceTypes = [
{ name: 'HTMLImageElement', factory: makeImage },
{ name: 'HTMLVideoElement', factory: makeVideo },
@ -152,36 +164,48 @@ promise_test( t => {
}, "createImageBitmap with null image source rejects with a TypeError.");
promise_test( t => {
return promise_rejects(t, new DOMException('', 'InvalidStateError'),
return promise_rejects(t, "InvalidStateError",
createImageBitmap(new Image()));
}, "createImageBitmap with empty image source rejects with a InvalidStateError.");
promise_test( t => {
return promise_rejects(t, new DOMException('', 'InvalidStateError'),
return promise_rejects(t, "InvalidStateError",
createImageBitmap(document.createElement('video')));
}, "createImageBitmap with empty video source rejects with a InvalidStateError.");
promise_test( t => {
return makeOversizedCanvas().then(canvas => {
return promise_rejects(t, new DOMException('', 'InvalidStateError'),
return promise_rejects(t, "InvalidStateError",
createImageBitmap(canvas));
});
}, "createImageBitmap with an oversized canvas source rejects with a RangeError.");
promise_test( t => {
return makeOversizedOffscreenCanvas().then(offscreenCanvas => {
return promise_rejects(t, new DOMException('', 'InvalidStateError'),
return promise_rejects(t, "InvalidStateError",
createImageBitmap(offscreenCanvas));
});
}, "createImageBitmap with an invalid OffscreenCanvas source rejects with a RangeError.");
promise_test( t => {
return makeInvalidBlob().then(blob => {
return promise_rejects(t, new DOMException('', 'InvalidStateError'),
return promise_rejects(t, "InvalidStateError",
createImageBitmap(blob));
});
}, "createImageBitmap with an undecodable blob source rejects with an InvalidStateError.");
promise_test( t => {
return makeBrokenImage().then(image => {
return promise_rejects(t, "InvalidStateError",
createImageBitmap(image));
});
}, "createImageBitmap with a broken image source rejects with an InvalidStateError.");
promise_test( t => {
return makeAvailableButBrokenImage().then(image => {
return promise_rejects(t, "InvalidStateError",
createImageBitmap(image));
});
}, "createImageBitmap with an available but undecodable image source rejects with an InvalidStateError.");
</script>
</body>
</html>

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

@ -2092,6 +2092,15 @@
code: |
var g = ctx.createLinearGradient(0, 0, 100, 0);
@assert throws SYNTAX_ERR g.addColorStop(0, "");
@assert throws SYNTAX_ERR g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)');
@assert throws SYNTAX_ERR g.addColorStop(0, 'null');
@assert throws SYNTAX_ERR g.addColorStop(0, 'undefined');
@assert throws SYNTAX_ERR g.addColorStop(0, null);
@assert throws SYNTAX_ERR g.addColorStop(0, undefined);
var g = ctx.createRadialGradient(0, 0, 0, 100, 0, 0);
@assert throws SYNTAX_ERR g.addColorStop(0, "");
@assert throws SYNTAX_ERR g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)');
@assert throws SYNTAX_ERR g.addColorStop(0, 'null');
@assert throws SYNTAX_ERR g.addColorStop(0, 'undefined');
@assert throws SYNTAX_ERR g.addColorStop(0, null);

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

@ -0,0 +1,41 @@
<!doctype html>
<title>Revoking blob URL used with Request/fetch</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
promise_test(function(t) {
const blob = new Blob(["test"]);
const url = URL.createObjectURL(blob);
const request = new Request(url);
// Revoke the object URL. Request should take a reference to the blob as
// soon as it receives it in open(), so the request succeeds even though we
// revoke the URL before calling fetch().
URL.revokeObjectURL(url);
return fetch(request).then(response => response.text()).then(text => {
assert_equals(text, 'test');
});
}, "Revoke blob URL after creating Request, will fetch");
promise_test(function(t) {
const blob = new Blob(["test"]);
const url = URL.createObjectURL(blob);
return fetch(url).then(response => response.text()).then(text => {
assert_equals(text, 'test');
});
// Revoke the object URL. fetch should have already resolved the blob URL.
URL.revokeObjectURL(url);
}, "Revoke blob URL after fetch, will fetch");
promise_test(t => {
const blob = new Blob(["test"]);
const url = URL.createObjectURL(blob);
URL.revokeObjectURL(url);
const request = new Request(url);
return promise_rejects(t, new TypeError, fetch(request));
}, "Revoke blob URL before creating Request, network error (after fetch)")
</script>

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

@ -0,0 +1,104 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Blob constructor: endings option</title>
<link rel=help href="https://w3c.github.io/FileAPI/#constructorBlob">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
// Windows platforms use CRLF as the native line ending. All others use LF.
const crlf = navigator.platform.startsWith('Win');
const native_ending = crlf ? '\r\n' : '\n';
function readBlobAsPromise(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsText(blob);
reader.onload = e => resolve(reader.result);
reader.onerror = e => reject(reader.error);
});
}
[
'transparent',
'native'
].forEach(value => test(t => {
assert_class_string(new Blob([], {endings: value}), 'Blob',
`Constructor should allow "${value}" endings`);
}, `Valid "endings" value: ${JSON.stringify(value)}`));
[
null,
'',
'invalidEnumValue',
'Transparent',
'NATIVE',
0,
{}
].forEach(value => test(t => {
assert_throws(new TypeError(), () => new Blob([], {endings: value}),
'Blob constructor should throw');
}, `Invalid "endings" value: ${JSON.stringify(value)}`));
test(t => {
const test_error = {name: 'test'};
assert_throws(
test_error,
() => new Blob([], { get endings() { throw test_error; }}),
'Blob constructor should propagate exceptions from "endings" property');
}, 'Exception propagation from options');
test(t => {
let got = false;
new Blob([], { get endings() { got = true; } });
assert_true(got, 'The "endings" property was accessed during construction.');
}, 'The "endings" options property is used');
[
{name: 'LF', input: '\n', native: native_ending},
{name: 'CR', input: '\r', native: native_ending},
{name: 'CRLF', input: '\r\n', native: native_ending},
{name: 'CRCR', input: '\r\r', native: native_ending.repeat(2)},
{name: 'LFCR', input: '\n\r', native: native_ending.repeat(2)},
{name: 'LFLF', input: '\n\n', native: native_ending.repeat(2)},
{name: 'CRCRLF', input: '\r\r\n', native: native_ending.repeat(2)},
{name: 'CRLFLF', input: '\r\n\n', native: native_ending.repeat(2)},
{name: 'CRLFCR', input: '\r\n\r\n', native: native_ending.repeat(2)},
{name: 'CRLFCRLF', input: '\r\n\r\n', native: native_ending.repeat(2)},
{name: 'LFCRLFCR', input: '\n\r\n\r', native: native_ending.repeat(3)},
].forEach(testCase => {
promise_test(async t => {
const blob = new Blob([testCase.input]);
assert_equals(
await readBlobAsPromise(blob), testCase.input,
'Newlines should not change with endings unspecified');
}, `Input ${testCase.name} with endings unspecified`);
promise_test(async t => {
const blob = new Blob([testCase.input], {endings: 'transparent'});
assert_equals(
await readBlobAsPromise(blob), testCase.input,
'Newlines should not change with endings "transparent"');
}, `Input ${testCase.name} with endings 'transparent'`);
promise_test(async t => {
const blob = new Blob([testCase.input], {endings: 'native'});
assert_equals(
await readBlobAsPromise(blob), testCase.native,
'Newlines should match the platform with endings "native"');
}, `Input ${testCase.name} with endings 'native'`);
});
promise_test(async t => {
const blob = new Blob(['\r', '\n'], {endings: 'native'});
const expected = native_ending.repeat(2);
assert_equals(
await readBlobAsPromise(blob), expected,
'CR/LF in adjacent strings should be converted to two platform newlines');
}, `CR/LF in adjacent input strings`);
</script>

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

@ -74,6 +74,20 @@ test_blob(function() {
type: "",
desc: "A plain object with @@iterator should be treated as a sequence for the blobParts argument."
});
test(t => {
const blob = new Blob({
[Symbol.iterator]() {
var i = 0;
return {next: () => [
{done:false, value:'ab'},
{done:false, value:'cde'},
{done:true}
][i++]
};
}
});
assert_equals(blob.size, 5, 'Custom @@iterator should be treated as a sequence');
}, "A plain object with custom @@iterator should be treated as a sequence for the blobParts argument.");
test_blob(function() {
return new Blob({
[Symbol.iterator]: Array.prototype[Symbol.iterator],
@ -392,26 +406,20 @@ test_blob(function() {
desc: "Array with mixed types"
});
// options argument
test(function() {
new Blob([], { endings: "invalidEnumValue" });
new Blob([], { endings: null });
new Blob([], { endings: undefined });
new Blob([], { endings: 0 });
new Blob([], { get endings() { assert_unreached("Should not call getter"); } });
}, "The 'endings' property should be ignored.");
const accessed = [];
const stringified = [];
test(function() {
assert_throws(test_error, function() {
new Blob([], {
get type() { throw test_error; }
});
new Blob([], {
get type() { accessed.push('type'); },
get endings() { accessed.push('endings'); }
});
assert_throws(test_error, function() {
new Blob([], {
type: { toString: function() { throw test_error; } }
});
new Blob([], {
type: { toString: () => { stringified.push('type'); return ''; } },
endings: { toString: () => { stringified.push('endings'); return 'transparent'; } }
});
assert_array_equals(accessed, ['endings', 'type']);
assert_array_equals(stringified, ['endings', 'type']);
}, "options properties should be accessed in lexicographic order.");
test(function() {
@ -449,19 +457,16 @@ test(function() {
});
});
test_blob(function() {
return new Blob(["\na\r\nb\n\rc\r"], { endings: "transparent" });
}, {
expected: "\na\r\nb\n\rc\r",
type: "",
desc: "Newlines should not change when endings is 'transparent'."
});
test_blob(function() {
return new Blob(["\na\r\nb\n\rc\r"], { endings: "native" });
}, {
expected: "\na\r\nb\n\rc\r",
type: "",
desc: "Newlines should not change when endings is 'native'."
[
123,
123.4,
true,
'abc'
].forEach(arg => {
test(t => {
assert_throws(new TypeError(), () => new Blob([], arg),
'Blob constructor should throw with invalid property bag');
}, `Passing ${JSON.stringify(arg)} for options should throw`);
});
var type_tests = [
@ -471,6 +476,7 @@ var type_tests = [
[[], 'A', 'a'],
[[], 'text/html', 'text/html'],
[[], 'TEXT/HTML', 'text/html'],
[[], 'text/plain;charset=utf-8', 'text/plain;charset=utf-8'],
[[], '\u00E5', ''],
[[], '\uD801\uDC7E', ''], // U+1047E
[[], ' image/gif ', ' image/gif '],

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

@ -0,0 +1,104 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>File constructor: endings option</title>
<link rel=help href="https://w3c.github.io/FileAPI/#file-constructor">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
// Windows platforms use CRLF as the native line ending. All others use LF.
const crlf = navigator.platform.startsWith('Win');
const native_ending = crlf ? '\r\n' : '\n';
function readBlobAsPromise(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsText(blob);
reader.onload = e => resolve(reader.result);
reader.onerror = e => reject(reader.error);
});
}
[
'transparent',
'native'
].forEach(value => test(t => {
assert_class_string(new File([], "name", {endings: value}), 'File',
`Constructor should allow "${value}" endings`);
}, `Valid "endings" value: ${JSON.stringify(value)}`));
[
null,
'',
'invalidEnumValue',
'Transparent',
'NATIVE',
0,
{}
].forEach(value => test(t => {
assert_throws(new TypeError(), () => new File([], "name", {endings: value}),
'File constructor should throw');
}, `Invalid "endings" value: ${JSON.stringify(value)}`));
test(t => {
const test_error = {name: 'test'};
assert_throws(
test_error,
() => new File([], "name", { get endings() { throw test_error; }}),
'File constructor should propagate exceptions from "endings" property');
}, 'Exception propagation from options');
test(t => {
let got = false;
new File([], "name", { get endings() { got = true; } });
assert_true(got, 'The "endings" property was accessed during construction.');
}, 'The "endings" options property is used');
[
{name: 'LF', input: '\n', native: native_ending},
{name: 'CR', input: '\r', native: native_ending},
{name: 'CRLF', input: '\r\n', native: native_ending},
{name: 'CRCR', input: '\r\r', native: native_ending.repeat(2)},
{name: 'LFCR', input: '\n\r', native: native_ending.repeat(2)},
{name: 'LFLF', input: '\n\n', native: native_ending.repeat(2)},
{name: 'CRCRLF', input: '\r\r\n', native: native_ending.repeat(2)},
{name: 'CRLFLF', input: '\r\n\n', native: native_ending.repeat(2)},
{name: 'CRLFCR', input: '\r\n\r\n', native: native_ending.repeat(2)},
{name: 'CRLFCRLF', input: '\r\n\r\n', native: native_ending.repeat(2)},
{name: 'LFCRLFCR', input: '\n\r\n\r', native: native_ending.repeat(3)},
].forEach(testCase => {
promise_test(async t => {
const file = new File([testCase.input], "name");
assert_equals(
await readBlobAsPromise(file), testCase.input,
'Newlines should not change with endings unspecified');
}, `Input ${testCase.name} with endings unspecified`);
promise_test(async t => {
const file = new File([testCase.input], "name", {endings: 'transparent'});
assert_equals(
await readBlobAsPromise(file), testCase.input,
'Newlines should not change with endings "transparent"');
}, `Input ${testCase.name} with endings 'transparent'`);
promise_test(async t => {
const file = new File([testCase.input], "name", {endings: 'native'});
assert_equals(
await readBlobAsPromise(file), testCase.native,
'Newlines should match the platform with endings "native"');
}, `Input ${testCase.name} with endings 'native'`);
});
promise_test(async t => {
const file = new File(['\r', '\n'], "name", {endings: 'native'});
const expected = native_ending.repeat(2);
assert_equals(
await readBlobAsPromise(file), expected,
'CR/LF in adjacent strings should be converted to two platform newlines');
}, `CR/LF in adjacent input strings`);
</script>

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

@ -6,10 +6,20 @@
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
const to_string_obj = { toString: () => 'a string' };
const to_string_throws = { toString: () => { throw new Error('expected'); } };
test(function() {
assert_true("File" in window, "window should have a File property.");
}, "File interface object exists");
test(t => {
assert_throws(new TypeError(), () => new File(),
'Bits argument is required');
assert_throws(new TypeError(), () => new File([]),
'Name argument is required');
}, 'Required arguments');
function test_first_argument(arg1, expectedSize, testName) {
test(function() {
var file = new File(arg1, "dummy");
@ -22,14 +32,48 @@ function test_first_argument(arg1, expectedSize, testName) {
}, testName);
}
test_first_argument([], 0, "empty fileBits");
test_first_argument(["bits"], 4, "DOMString fileBits");
test_first_argument(["𝓽𝓮𝔁𝓽"], 16, "Unicode DOMString fileBits");
test_first_argument([new String('string object')], 13, "String object fileBits");
test_first_argument([new Blob()], 0, "Empty Blob fileBits");
test_first_argument([new Blob(["bits"])], 4, "Blob fileBits");
test_first_argument([new File([], 'world.txt')], 0, "Empty File fileBits");
test_first_argument([new File(["bits"], 'world.txt')], 4, "File fileBits");
test_first_argument([new ArrayBuffer(8)], 8, "ArrayBuffer fileBits");
test_first_argument([new Uint8Array([0x50, 0x41, 0x53, 0x53])], 4, "Typed array fileBits");
test_first_argument(["bits", new Blob(["bits"]), new Blob(), new Uint8Array([0x50, 0x41]),
new Uint16Array([0x5353]), new Uint32Array([0x53534150])], 16, "Various fileBits");
test_first_argument([12], 2, "Number in fileBits");
test_first_argument([[1,2,3]], 5, "Array in fileBits");
test_first_argument([{}], 15, "Object in fileBits"); // "[object Object]"
test_first_argument([document], 21, "HTMLDocument in fileBits"); // "[object HTMLDocument]"
test_first_argument([to_string_obj], 8, "Object with toString in fileBits");
test_first_argument({[Symbol.iterator]() {
let i = 0;
return {next: () => [
{done:false, value:'ab'},
{done:false, value:'cde'},
{done:true}
][i++]};
}}, 5, 'Custom @@iterator');
[
'hello',
0,
null
].forEach(arg => {
test(t => {
assert_throws(new TypeError(), () => new File(arg, 'world.html'),
'Constructor should throw for invalid bits argument');
}, `Invalid bits argument: ${JSON.stringify(arg)}`);
});
test(t => {
assert_throws(new Error(), () => new File([to_string_throws], 'name.txt'),
'Constructor should propagate exceptions');
}, 'Bits argument: object that throws');
function test_second_argument(arg2, expectedFileName, testName) {
test(function() {
@ -41,23 +85,29 @@ function test_second_argument(arg2, expectedFileName, testName) {
test_second_argument("dummy", "dummy", "Using fileName");
test_second_argument("dummy/foo", "dummy:foo", "Using special character in fileName");
test_second_argument(null, "null", "Using null fileName");
test_second_argument(1, "1", "Using number fileName");
test_second_argument('', '', "Using empty string fileName");
test_second_argument(document, '[object HTMLDocument]', "Using object fileName");
// testing the third argument
test(function() {
var file = new File(["bits"], "dummy", { type: "text/plain"});
assert_true(file instanceof File);
assert_equals(file.type, "text/plain");
}, "Using type on the File constructor");
test(function() {
var file = new File(["bits"], "dummy", { type: "TEXT/PLAIN"});
assert_true(file instanceof File);
assert_equals(file.type, "text/plain");
}, "Using uppercase characters in type");
test(function() {
var file = new File(["bits"], "dummy", { type: "𝓽𝓮𝔁𝓽/𝔭𝔩𝔞𝔦𝔫"});
assert_true(file instanceof File);
assert_equals(file.type, "");
}, "Using illegal character for type");
[
{type: 'text/plain', expected: 'text/plain'},
{type: 'text/plain;charset=UTF-8', expected: 'text/plain;charset=utf-8'},
{type: 'TEXT/PLAIN', expected: 'text/plain'},
{type: '𝓽𝓮𝔁𝓽/𝔭𝔩𝔞𝔦𝔫', expected: ''},
{type: 'ascii/nonprintable\u001F', expected: ''},
{type: 'ascii/nonprintable\u007F', expected: ''},
{type: 'nonascii\u00EE', expected: ''},
{type: 'nonascii\u1234', expected: ''},
{type: 'nonparsable', expected: 'nonparsable'}
].forEach(testCase => {
test(t => {
var file = new File(["bits"], "dummy", { type: testCase.type});
assert_true(file instanceof File);
assert_equals(file.type, testCase.expected);
}, `Using type in File constructor: ${testCase.type}`);
});
test(function() {
var file = new File(["bits"], "dummy", { lastModified: 42 });
assert_true(file instanceof File);
@ -68,5 +118,41 @@ test(function() {
assert_true(file instanceof File);
assert_equals(file.name, "dummy");
}, "Misusing name");
test(function() {
var file = new File(["bits"], "dummy", { unknownKey: "value" });
assert_true(file instanceof File);
assert_equals(file.name, "dummy");
}, "Unknown properties are ignored");
[
123,
123.4,
true,
'abc'
].forEach(arg => {
test(t => {
assert_throws(new TypeError(), () => new File(['bits'], 'name.txt', arg),
'Constructor should throw for invalid property bag type');
}, `Invalid property bag: ${JSON.stringify(arg)}`);
});
[
null,
undefined,
[1,2,3],
/regex/,
function() {}
].forEach(arg => {
test(t => {
assert_equals(new File(['bits'], 'name.txt', arg).size, 4,
'Constructor should accept object-ish property bag type');
}, `Unusual but valid property bag: ${arg}`);
});
test(t => {
assert_throws(new Error(),
() => new File(['bits'], 'name.txt', {type: to_string_throws}),
'Constructor should propagate exceptions');
}, 'Property bag propagates exceptions');
</script>

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

@ -0,0 +1,71 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Upload files in ISO-2022-JP form (tentative)</title>
<!--
NOTE: This test is tentative because encoding for filename
characters unrepresentable in the form charset is not yet
standardized.
-->
<link rel="help"
href="https://github.com/whatwg/html/issues/3223">
<link rel="help"
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
<link rel="help"
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
<link rel="help"
href="https://w3c.github.io/FileAPI/#file-constructor">
<link rel="author" title="Benjamin C. Wiley Sittler"
href="mailto:bsittler@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../support/send-file-form-helper.js"></script>
<script>
'use strict';
formPostFileUploadTest({
fileNameSource: 'ASCII',
fileBaseName: 'file-for-upload-in-form.txt',
formEncoding: 'ISO-2022-JP',
expectedEncodedBaseName: 'file-for-upload-in-form.txt',
});
formPostFileUploadTest({
fileNameSource: 'x-user-defined',
fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
formEncoding: 'ISO-2022-JP',
expectedEncodedBaseName: (
'file-for-upload-in-form-&#63472;&#63379;&#63363;&#63392;.txt'),
});
formPostFileUploadTest({
fileNameSource: 'windows-1252',
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
formEncoding: 'ISO-2022-JP',
expectedEncodedBaseName: (
'file-for-upload-in-form-&#226;&#732;&#186;&#240;&#376;&#732;&#8218;.txt'),
});
formPostFileUploadTest({
fileNameSource: 'JIS X 0201 and JIS X 0208',
fileBaseName: 'file-for-upload-in-form-★星★.txt',
formEncoding: 'ISO-2022-JP',
expectedEncodedBaseName: 'file-for-upload-in-form-\x1B$B!z@1!z\x1B(B.txt',
});
formPostFileUploadTest({
fileNameSource: 'Unicode',
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
formEncoding: 'ISO-2022-JP',
expectedEncodedBaseName: 'file-for-upload-in-form-&#9786;&#128514;.txt',
});
formPostFileUploadTest({
fileNameSource: 'Unicode',
fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
formEncoding: 'ISO-2022-JP',
expectedEncodedBaseName: `file-for-upload-in-form-${
kTestFallbackIso2022jp
}.txt`,
});
</script>

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

@ -0,0 +1,61 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Upload files in UTF-8 form</title>
<link rel="help"
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
<link rel="help"
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
<link rel="help"
href="https://w3c.github.io/FileAPI/#file-constructor">
<link rel="author" title="Benjamin C. Wiley Sittler"
href="mailto:bsittler@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../support/send-file-form-helper.js"></script>
<script>
'use strict';
formPostFileUploadTest({
fileNameSource: 'ASCII',
fileBaseName: 'file-for-upload-in-form.txt',
formEncoding: 'UTF-8',
expectedEncodedBaseName: 'file-for-upload-in-form.txt',
});
formPostFileUploadTest({
fileNameSource: 'x-user-defined',
fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
formEncoding: 'UTF-8',
expectedEncodedBaseName: (
'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt'),
});
formPostFileUploadTest({
fileNameSource: 'windows-1252',
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
formEncoding: 'UTF-8',
expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
});
formPostFileUploadTest({
fileNameSource: 'JIS X 0201 and JIS X 0208',
fileBaseName: 'file-for-upload-in-form-★星★.txt',
formEncoding: 'UTF-8',
expectedEncodedBaseName: 'file-for-upload-in-form-★星★.txt',
});
formPostFileUploadTest({
fileNameSource: 'Unicode',
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
formEncoding: 'UTF-8',
expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
});
formPostFileUploadTest({
fileNameSource: 'Unicode',
fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
formEncoding: 'UTF-8',
expectedEncodedBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
});
</script>

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

@ -0,0 +1,70 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Upload files in Windows-1252 form (tentative)</title>
<!--
NOTE: This test is tentative because encoding for filename
characters unrepresentable in the form charset is not yet
standardized.
-->
<link rel="help"
href="https://github.com/whatwg/html/issues/3223">
<link rel="help"
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
<link rel="help"
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
<link rel="help"
href="https://w3c.github.io/FileAPI/#file-constructor">
<link rel="author" title="Benjamin C. Wiley Sittler"
href="mailto:bsittler@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../support/send-file-form-helper.js"></script>
<script>
'use strict';
formPostFileUploadTest({
fileNameSource: 'ASCII',
fileBaseName: 'file-for-upload-in-form.txt',
formEncoding: 'windows-1252',
expectedEncodedBaseName: 'file-for-upload-in-form.txt',
});
formPostFileUploadTest({
fileNameSource: 'x-user-defined',
fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
formEncoding: 'windows-1252',
expectedEncodedBaseName: (
'file-for-upload-in-form-&#63472;&#63379;&#63363;&#63392;.txt'),
});
formPostFileUploadTest({
fileNameSource: 'windows-1252',
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
formEncoding: 'windows-1252',
expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
});
formPostFileUploadTest({
fileNameSource: 'JIS X 0201 and JIS X 0208',
fileBaseName: 'file-for-upload-in-form-★星★.txt',
formEncoding: 'windows-1252',
expectedEncodedBaseName: 'file-for-upload-in-form-&#9733;&#26143;&#9733;.txt',
});
formPostFileUploadTest({
fileNameSource: 'Unicode',
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
formEncoding: 'windows-1252',
expectedEncodedBaseName: 'file-for-upload-in-form-&#9786;&#128514;.txt',
});
formPostFileUploadTest({
fileNameSource: 'Unicode',
fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
formEncoding: 'windows-1252',
expectedEncodedBaseName: `file-for-upload-in-form-${
kTestFallbackWindows1252
}.txt`,
});
</script>

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

@ -0,0 +1,70 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Upload files in x-user-defined form (tentative)</title>
<!--
NOTE: This test is tentative because encoding for filename
characters unrepresentable in the form charset is not yet
standardized.
-->
<link rel="help"
href="https://github.com/whatwg/html/issues/3223">
<link rel="help"
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
<link rel="help"
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
<link rel="help"
href="https://w3c.github.io/FileAPI/#file-constructor">
<link rel="author" title="Benjamin C. Wiley Sittler"
href="mailto:bsittler@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../support/send-file-form-helper.js"></script>
<script>
'use strict';
formPostFileUploadTest({
fileNameSource: 'ASCII',
fileBaseName: 'file-for-upload-in-form.txt',
formEncoding: 'x-user-defined',
expectedEncodedBaseName: 'file-for-upload-in-form.txt',
});
formPostFileUploadTest({
fileNameSource: 'x-user-defined',
fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
formEncoding: 'x-user-defined',
expectedEncodedBaseName: 'file-for-upload-in-form-𓃠.txt',
});
formPostFileUploadTest({
fileNameSource: 'windows-1252',
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
formEncoding: 'x-user-defined',
expectedEncodedBaseName: ('file-for-upload-in-form-' +
'&#226;&#732;&#186;&#240;&#376;&#732;&#8218;.txt'),
});
formPostFileUploadTest({
fileNameSource: 'JIS X 0201 and JIS X 0208',
fileBaseName: 'file-for-upload-in-form-★星★.txt',
formEncoding: 'x-user-defined',
expectedEncodedBaseName: 'file-for-upload-in-form-&#9733;&#26143;&#9733;.txt',
});
formPostFileUploadTest({
fileNameSource: 'Unicode',
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
formEncoding: 'x-user-defined',
expectedEncodedBaseName: 'file-for-upload-in-form-&#9786;&#128514;.txt',
});
formPostFileUploadTest({
fileNameSource: 'Unicode',
fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
formEncoding: 'x-user-defined',
expectedEncodedBaseName: `file-for-upload-in-form-${
kTestFallbackXUserDefined
}.txt`,
});
</script>

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

@ -0,0 +1,25 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Upload ASCII-named file in UTF-8 form</title>
<link rel="help"
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
<link rel="help"
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
<link rel="help"
href="https://w3c.github.io/FileAPI/#file-constructor">
<link rel="author" title="Benjamin C. Wiley Sittler"
href="mailto:bsittler@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../support/send-file-form-helper.js"></script>
<script>
'use strict';
formPostFileUploadTest({
fileNameSource: 'ASCII',
fileBaseName: 'file-for-upload-in-form.txt',
formEncoding: 'UTF-8',
expectedEncodedBaseName: 'file-for-upload-in-form.txt',
});
</script>

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

@ -30,8 +30,6 @@ setup(function() {
request.onload = function() {
var idls = request.responseText;
idl_array.add_untested_idls("[PrimaryGlobal] interface Window { };");
idl_array.add_untested_idls("[Exposed=(Window,Worker)] interface ArrayBuffer {};");
idl_array.add_untested_idls("interface URL {};");
idl_array.add_untested_idls("[Exposed=(Window,Worker)] interface EventTarget {};");

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

@ -0,0 +1,249 @@
'use strict';
// Rationale for this particular test character sequence, which is
// used in filenames and also in file contents:
//
// - ABC~ ensures the string starts with something we can read to
// ensure it is from the correct source; ~ is used because even
// some 1-byte otherwise-ASCII-like parts of ISO-2022-JP
// interpret it differently.
// - ‾¥ are inside a single-byte range of ISO-2022-JP and help
// diagnose problems due to filesystem encoding or locale
// - ≈ is inside IBM437 and helps diagnose problems due to filesystem
// encoding or locale
// - ¤ is inside Latin-1 and helps diagnose problems due to
// filesystem encoding or locale; it is also the "simplest" case
// needing substitution in ISO-2022-JP
// - ・ is inside a single-byte range of ISO-2022-JP in some variants
// and helps diagnose problems due to filesystem encoding or locale;
// on the web it is distinct when decoding but unified when encoding
// - ・ is inside a double-byte range of ISO-2022-JP and helps
// diagnose problems due to filesystem encoding or locale
// - • is inside Windows-1252 and helps diagnose problems due to
// filesystem encoding or locale and also ensures these aren't
// accidentally turned into e.g. control codes
// - ∙ is inside IBM437 and helps diagnose problems due to filesystem
// encoding or locale
// - · is inside Latin-1 and helps diagnose problems due to
// filesystem encoding or locale and also ensures HTML named
// character references (e.g. &middot;) are not used
// - ☼ is inside IBM437 shadowing C0 and helps diagnose problems due to
// filesystem encoding or locale and also ensures these aren't
// accidentally turned into e.g. control codes
// - ★ is inside ISO-2022-JP on a non-Kanji page and makes correct
// output easier to spot
// - 星 is inside ISO-2022-JP on a Kanji page and makes correct
// output easier to spot
// - 🌟 is outside the BMP and makes incorrect surrogate pair
// substitution detectable and ensures substitutions work
// correctly immediately after Kanji 2-byte ISO-2022-JP
// - 星 repeated here ensures the correct codec state is used
// after a non-BMP substitution
// - ★ repeated here also makes correct output easier to spot
// - ☼ is inside IBM437 shadowing C0 and helps diagnose problems due to
// filesystem encoding or locale and also ensures these aren't
// accidentally turned into e.g. control codes and also ensures
// substitutions work correctly immediately after non-Kanji
// 2-byte ISO-2022-JP
// - · is inside Latin-1 and helps diagnose problems due to
// filesystem encoding or locale and also ensures HTML named
// character references (e.g. &middot;) are not used
// - ∙ is inside IBM437 and helps diagnose problems due to filesystem
// encoding or locale
// - • is inside Windows-1252 and again helps diagnose problems
// due to filesystem encoding or locale
// - ・ is inside a double-byte range of ISO-2022-JP and helps
// diagnose problems due to filesystem encoding or locale
// - ・ is inside a single-byte range of ISO-2022-JP in some variants
// and helps diagnose problems due to filesystem encoding or locale;
// on the web it is distinct when decoding but unified when encoding
// - ¤ is inside Latin-1 and helps diagnose problems due to
// filesystem encoding or locale; again it is a "simple"
// substitution case
// - ≈ is inside IBM437 and helps diagnose problems due to filesystem
// encoding or locale
// - ¥‾ are inside a single-byte range of ISO-2022-JP and help
// diagnose problems due to filesystem encoding or locale
// - ~XYZ ensures earlier errors don't lead to misencoding of
// simple ASCII
//
// Overall the near-symmetry makes common I18N mistakes like
// off-by-1-after-non-BMP easier to spot. All the characters
// are also allowed in Windows Unicode filenames.
const kTestChars = 'ABC~‾¥≈¤・・•∙·☼★星🌟星★☼·∙•・・¤≈¥‾~XYZ';
// NOTE: The expected interpretation of ISO-2022-JP according to
// https://encoding.spec.whatwg.org/#iso-2022-jp-encoder unifies
// single-byte and double-byte katakana.
const kTestFallbackIso2022jp =
('ABC~\x1B(J~\\≈¤\x1B$B!&!&\x1B(B•∙·☼\x1B$B!z@1\x1B(B🌟' +
'\x1B$B@1!z\x1B(B☼·∙•\x1B$B!&!&\x1B(B¤≈\x1B(J\\~\x1B(B~XYZ').replace(
/[^\0-\x7F]/gu,
x => `&#${x.codePointAt(0)};`);
// NOTE: \uFFFD is used here to replace Windows-1252 bytes to match
// how we will see them in the reflected POST bytes in a frame using
// UTF-8 byte interpretation. The bytes will actually be intact, but
// this code cannot tell and does not really care.
const kTestFallbackWindows1252 =
'ABC~‾\xA5≈\xA4・・\x95∙\xB7☼★星🌟星★☼\xB7∙\x95・・\xA4≈\xA5‾~XYZ'.replace(
/[^\0-\xFF]/gu,
x => `&#${x.codePointAt(0)};`).replace(/[\x80-\xFF]/g, '\uFFFD');
const kTestFallbackXUserDefined =
kTestChars.replace(/[^\0-\x7F]/gu, x => `&#${x.codePointAt(0)};`);
// formPostFileUploadTest - verifies multipart upload structure and
// numeric character reference replacement for filenames, field names,
// and field values.
//
// Uses /fetch/api/resources/echo-content.py to echo the upload
// POST with UTF-8 byte interpretation, leading to the "UTF-8 goggles"
// behavior documented below for expectedEncodedBaseName when non-
// UTF-8-compatible byte sequences appear in the formEncoding-encoded
// uploaded data.
//
// Fields in the parameter object:
//
// - fileNameSource: purely explanatory and gives a clue about which
// character encoding is the source for the non-7-bit-ASCII parts of
// the fileBaseName, or Unicode if no smaller-than-Unicode source
// contains all the characters. Used in the test name.
// - fileBaseName: the not-necessarily-just-7-bit-ASCII file basename
// used for the constructed test file. Used in the test name.
// - formEncoding: the acceptCharset of the form used to submit the
// test file. Used in the test name.
// - expectedEncodedBaseName: the expected formEncoding-encoded
// version of fileBaseName with unencodable characters replaced by
// numeric character references and non-7-bit-ASCII bytes seen
// through UTF-8 goggles; subsequences not interpretable as UTF-8
// have each byte represented here by \uFFFD REPLACEMENT CHARACTER.
const formPostFileUploadTest = ({
fileNameSource,
fileBaseName,
formEncoding,
expectedEncodedBaseName,
}) => {
promise_test(async testCase => {
if (document.readyState !== 'complete') {
await new Promise(resolve => addEventListener('load', resolve));
}
const formTargetFrame = Object.assign(document.createElement('iframe'), {
name: 'formtargetframe',
});
document.body.append(formTargetFrame);
testCase.add_cleanup(() => {
document.body.removeChild(formTargetFrame);
});
const form = Object.assign(document.createElement('form'), {
acceptCharset: formEncoding,
action: '/fetch/api/resources/echo-content.py',
method: 'POST',
enctype: 'multipart/form-data',
target: formTargetFrame.name,
});
document.body.append(form);
testCase.add_cleanup(() => {
document.body.removeChild(form);
});
// Used to verify that the browser agrees with the test about
// which form charset is used.
form.append(Object.assign(document.createElement('input'), {
type: 'hidden',
name: '_charset_',
}));
// Used to verify that the browser agrees with the test about
// field value replacement and encoding independently of file system
// idiosyncracies.
form.append(Object.assign(document.createElement('input'), {
type: 'hidden',
name: 'filename',
value: fileBaseName,
}));
// Same, but with name and value reversed to ensure field names
// get the same treatment.
form.append(Object.assign(document.createElement('input'), {
type: 'hidden',
name: fileBaseName,
value: 'filename',
}));
const fileInput = Object.assign(document.createElement('input'), {
type: 'file',
name: 'file',
});
form.append(fileInput);
// Removes c:\fakepath\ or other pseudofolder and returns just the
// final component of filePath; allows both / and \ as segment
// delimiters.
const baseNameOfFilePath = filePath => filePath.split(/[\/\\]/).pop();
await new Promise(resolve => {
const dataTransfer = new DataTransfer;
dataTransfer.items.add(
new File([kTestChars], fileBaseName, {type: 'text/plain'}));
fileInput.files = dataTransfer.files;
// For historical reasons .value will be prefixed with
// c:\fakepath\, but the basename should match the file name
// exposed through the newer .files[0].name API. This check
// verifies that assumption.
assert_equals(
fileInput.files[0].name,
baseNameOfFilePath(fileInput.value),
`The basename of the field's value should match its files[0].name`);
form.submit();
formTargetFrame.onload = resolve;
});
const formDataText = formTargetFrame.contentDocument.body.textContent;
const formDataLines = formDataText.split('\n');
if (formDataLines.length && !formDataLines[formDataLines.length - 1]) {
--formDataLines.length;
}
assert_greater_than(
formDataLines.length,
2,
`${fileBaseName}: multipart form data must have at least 3 lines: ${
JSON.stringify(formDataText)
}`);
const boundary = formDataLines[0];
assert_equals(
formDataLines[formDataLines.length - 1],
boundary + '--',
`${fileBaseName}: multipart form data must end with ${boundary}--: ${
JSON.stringify(formDataText)
}`);
const expectedText = [
boundary,
'Content-Disposition: form-data; name="_charset_"',
'',
formEncoding,
boundary,
'Content-Disposition: form-data; name="filename"',
'',
expectedEncodedBaseName,
boundary,
`Content-Disposition: form-data; name="${expectedEncodedBaseName}"`,
'',
'filename',
boundary,
`Content-Disposition: form-data; name="file"; ` +
`filename="${expectedEncodedBaseName}"`,
'Content-Type: text/plain',
'',
kTestChars,
boundary + '--',
].join('\n');
assert_true(
formDataText.startsWith(expectedText),
`Unexpected multipart-shaped form data received:\n${
formDataText
}\nExpected:\n${expectedText}`);
}, `Upload ${fileBaseName} (${fileNameSource}) in ${formEncoding} form`);
};

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

@ -0,0 +1,46 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Blob/Unicode interaction: normalization and encoding</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
'use strict';
const OMICRON_WITH_OXIA = '\u1F79'; // NFC normalized to U+3CC
const CONTAINS_UNPAIRED_SURROGATES = 'abc\uDC00def\uD800ghi';
const REPLACED = 'abc\uFFFDdef\uFFFDghi';
function readBlobAsPromise(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsText(blob);
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
});
}
promise_test(async t => {
const blob = new Blob([OMICRON_WITH_OXIA]);
const result = await readBlobAsPromise(blob);
assert_equals(result, OMICRON_WITH_OXIA, 'String should not be normalized');
}, 'Test that strings are not NFC normalized by Blob constructor');
promise_test(async t => {
const file = new File([OMICRON_WITH_OXIA], 'name');
const result = await readBlobAsPromise(file);
assert_equals(result, OMICRON_WITH_OXIA, 'String should not be normalized');
}, 'Test that strings are not NFC normalized by File constructor');
promise_test(async t => {
const blob = new Blob([CONTAINS_UNPAIRED_SURROGATES]);
const result = await readBlobAsPromise(blob);
assert_equals(result, REPLACED, 'Unpaired surrogates should be replaced.');
}, 'Test that unpaired surrogates are replaced by Blob constructor');
promise_test(async t => {
const file = new File([CONTAINS_UNPAIRED_SURROGATES], 'name');
const result = await readBlobAsPromise(file);
assert_equals(result, REPLACED, 'Unpaired surrogates should be replaced.');
}, 'Test that unpaired surrogates are replaced by File constructor');
</script>

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

@ -20,9 +20,8 @@
http.onloadend = function() {
var fileDisplay = document.querySelector("#fileDisplay");
fileDisplay.src = window.URL.createObjectURL(http.response);
takeScreenshot();
fileDisplay.onload = takeScreenshot;
};
http.send();
</script>
</html>

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

@ -20,7 +20,7 @@ async_test(function(t) {
var idls = request.responseText;
// https://html.spec.whatwg.org/multipage/browsers.html#window
idlArray.add_untested_idls("[PrimaryGlobal] interface Window { };");
idlArray.add_untested_idls("[Global=Window, Exposed=Window] interface Window { };");
// https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope-mixin
idlArray.add_untested_idls(`[NoInterfaceObject, Exposed=(Window,Worker)]

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

@ -53,8 +53,15 @@ Running Tests Manually
======================
The test server can be started using
```
./wpt serve
```
./wpt serve
**On Windows**: You will need to preceed the prior command with
`python` or the path to the python binary.
```bash
python wpt serve
```
This will start HTTP servers on two ports and a websockets server on
one port. By default one web server starts on port 8000 and the other
@ -82,12 +89,15 @@ file setup documented above, but you must *not* have the
test server already running when calling `wpt run`. The basic command
line syntax is:
```
```bash
./wpt run product [tests]
```
**On Windows**: You will need to preceed the prior command with
`python` or the path to the python binary.
```bash
python wpt product [tests]
```
where `product` is currently `firefox` or `chrome` and `[tests]` is a
list of paths to tests. This will attempt to automatically locate a
@ -114,7 +124,7 @@ brew install nss
On other platforms, download the firefox archive and common.tests.zip
archive for your platform from
[https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central/](Mozilla CI)
[Mozilla CI](https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central/).
Then extract `certutil[.exe]` from the tests.zip package and
`libnss3[.so|.dll|.dynlib]` and put the former on your path and the latter on
@ -187,9 +197,13 @@ then remove the `tools` and `resources` directories, as above.
<span id="windows-notes">Windows Notes</span>
=============================================
On Windows `wpt` commands mut bre prefixed with `python` or the path
On Windows `wpt` commands must be prefixed with `python` or the path
to the python binary (if `python` is not in your `%PATH%`).
```bash
python wpt [command]
```
Alternatively, you may also use
[Bash on Ubuntu on Windows](https://msdn.microsoft.com/en-us/commandline/wsl/about)
in the Windows 10 Anniversary Update build, then access your windows

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

@ -29,11 +29,6 @@ setup(function() {
request.onload = function() {
var idls = request.responseText;
idl_array.add_untested_idls("[PrimaryGlobal] interface Window { };");
idl_array.add_untested_idls("interface ArrayBuffer {};");
idl_array.add_untested_idls("interface ArrayBufferView {};");
idl_array.add_idls(idls);
idl_array.add_objects({"Crypto":["crypto"], "SubtleCrypto":["crypto.subtle"]});

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

@ -29,11 +29,6 @@ setup(function() {
request.onload = function() {
var idls = request.responseText;
idl_array.add_untested_idls("[PrimaryGlobal] interface Window { };");
idl_array.add_untested_idls("interface ArrayBuffer {};");
idl_array.add_untested_idls("interface ArrayBufferView {};");
idl_array.add_idls(idls);
idl_array.add_objects({"Crypto":["crypto"], "SubtleCrypto":["crypto.subtle"]});

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

@ -17,7 +17,7 @@
{
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://nonexistent-origin.{{host}}}:{{ports[http][0]}}", false);
xhr.open("POST", "http://nonexistent-origin.{{host}}:{{ports[http][0]}}", false);
assert_throws("NetworkError", function()
{
@ -25,6 +25,12 @@
});
assert_equals(xhr.readyState, 4)
}, "http URL");
test(function()
{
var xhr = new XMLHttpRequest();
xhr.open("GET", "data:text/html;charset=utf-8;base64,PT0NUWVBFIGh0bWw%2BDQo8", false);
assert_throws("NetworkError", function()
@ -33,7 +39,7 @@
});
assert_equals(xhr.readyState, 4)
});
}, "data URL");
</script>
</body>
</html>

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

@ -15,8 +15,8 @@
<div id="log"></div>
<script type="text/javascript">
function testRedirectPost(code, shouldResendPost) {
var test = async_test(document.title + " (" + code + ")");
function testRedirectPost(params) {
var test = async_test(document.title + " (" + params.name + ")");
var actual = [];
// We check upload.onprogress with a boolean because it *might* fire more than once
var progressFiredReadyState1 = false;
@ -24,13 +24,13 @@
var expectedHeaders, expectedEvents;
// 307 redirects should resend the POST data, and events and headers will be a little different..
if(shouldResendPost) {
if(params.expectResendPost) {
expectedHeaders = {
"X-Request-Content-Length": "11988",
"X-Request-Content-Length": "12000",
"X-Request-Content-Type": "text/plain;charset=UTF-8",
"X-Request-Method": "POST",
"X-Request-Query": "NO",
"Content-Length": "11988"
"Content-Length": "12000"
}
expectedEvents = [
"xhr onreadystatechange 1",
@ -63,6 +63,10 @@
"xhr loadend 4"
];
}
// Override expectations if provided.
if(params.expectedContentType)
expectedHeaders["X-Request-Content-Type"] = params.expectedContentType;
test.step(function()
{
var xhr = new XMLHttpRequest();
@ -105,20 +109,24 @@
}
assert_array_equals(actual, expectedEvents, "events firing in expected order and states");
if (params.expectedBody)
assert_equals(xhr.response, params.expectedBody, 'request body was resent');
test.done();
});
xhr.open("POST", "./resources/redirect.py?location=content.py&code=" + code, true);
xhr.send((new Array(1000)).join("Test Message"));
xhr.open("POST", "./resources/redirect.py?location=content.py&code=" + params.code, true);
xhr.send(params.body);
});
}
const stringBody = "Test Message".repeat(1000);
const blobBody = new Blob(new Array(1000).fill("Test Message"));
testRedirectPost(301, false);
testRedirectPost(302, false);
testRedirectPost(303, false);
testRedirectPost(307, true);
testRedirectPost({name: "301", code: 301, expectResendPost: false, body: stringBody});
testRedirectPost({name: "302", code: 302, expectResendPost: false, body: stringBody});
testRedirectPost({name: "303", code: 303, expectResendPost: false, body: stringBody});
testRedirectPost({name: "307 (string)", code: 307, expectResendPost: true, body: stringBody, expectedBody: stringBody });
testRedirectPost({name: "307 (blob)", code: 307, expectResendPost: true, body: blobBody, expectedBody: stringBody, expectedContentType: "NO" });
</script>
</body>
</html>

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

@ -0,0 +1,14 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/feature-policy/resources/featurepolicy.js"></script>
<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
<script>
"use strict";
run_fp_tests_disabled(Accelerometer);
run_fp_tests_disabled(LinearAccelerationSensor);
run_fp_tests_disabled(GravitySensor);
</script>
</body>

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

@ -0,0 +1 @@
Feature-Policy: accelerometer 'none'

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

@ -0,0 +1,14 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/feature-policy/resources/featurepolicy.js"></script>
<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
<script>
"use strict";
run_fp_tests_enabled_by_attribute_redirect_on_load(Accelerometer);
run_fp_tests_enabled_by_attribute_redirect_on_load(LinearAccelerationSensor);
run_fp_tests_enabled_by_attribute_redirect_on_load(GravitySensor);
</script>
</body>

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

@ -0,0 +1,14 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/feature-policy/resources/featurepolicy.js"></script>
<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
<script>
"use strict";
run_fp_tests_enabled_by_attribute(Accelerometer);
run_fp_tests_enabled_by_attribute(LinearAccelerationSensor);
run_fp_tests_enabled_by_attribute(GravitySensor);
</script>
</body>

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

@ -0,0 +1,14 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/feature-policy/resources/featurepolicy.js"></script>
<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
<script>
"use strict";
run_fp_tests_enabled(Accelerometer);
run_fp_tests_enabled(LinearAccelerationSensor);
run_fp_tests_enabled(GravitySensor);
</script>
</body>

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

@ -0,0 +1 @@
Feature-Policy: accelerometer *

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

@ -0,0 +1,14 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/feature-policy/resources/featurepolicy.js"></script>
<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
<script>
"use strict";
run_fp_tests_enabled_on_self_origin(Accelerometer);
run_fp_tests_enabled_on_self_origin(LinearAccelerationSensor);
run_fp_tests_enabled_on_self_origin(GravitySensor);
</script>
</body>

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

@ -0,0 +1 @@
Feature-Policy: accelerometer 'self'

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

@ -10,5 +10,6 @@
<script>
runGenericSensorTests(Accelerometer);
runGenericSensorTests(GravitySensor);
</script>

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

@ -16,5 +16,6 @@
<script>
runGenericSensorInsecureContext("Accelerometer");
runGenericSensorInsecureContext("GravitySensor");
</script>

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

@ -16,5 +16,6 @@
<script>
runGenericSensorOnerror(Accelerometer);
runGenericSensorOnerror(GravitySensor);
</script>

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

@ -0,0 +1,12 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/feature-policy/resources/featurepolicy.js"></script>
<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
<script>
"use strict";
run_fp_tests_disabled(AmbientLightSensor);
</script>
</body>

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

@ -0,0 +1 @@
Feature-Policy: ambient-light-sensor 'none'

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

@ -0,0 +1,12 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/feature-policy/resources/featurepolicy.js"></script>
<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
<script>
"use strict";
run_fp_tests_enabled_by_attribute_redirect_on_load(AmbientLightSensor);
</script>
</body>

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

@ -0,0 +1,12 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/feature-policy/resources/featurepolicy.js"></script>
<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
<script>
"use strict";
run_fp_tests_enabled_by_attribute(AmbientLightSensor);
</script>
</body>

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

@ -0,0 +1,12 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/feature-policy/resources/featurepolicy.js"></script>
<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
<script>
"use strict";
run_fp_tests_enabled(AmbientLightSensor);
</script>
</body>

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

@ -0,0 +1 @@
Feature-Policy: ambient-light-sensor *

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

@ -0,0 +1,12 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/feature-policy/resources/featurepolicy.js"></script>
<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
<script>
"use strict";
run_fp_tests_enabled_on_self_origin(AmbientLightSensor);
</script>
</body>

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

@ -0,0 +1 @@
Feature-Policy: ambient-light-sensor 'self'

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

@ -0,0 +1,2 @@
@toddreifsteck
@igrigorik

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

@ -0,0 +1,12 @@
# Web Bluetooth Testing
Web Bluetooth testing relies on the [Web Bluetooth Testing API] which must be
provided by browsers under test.
In this test suite `resources/bluetooth-helpers.js` detects and triggers
the API to be loaded as needed.
The Chromium implementation is provided by
`../resources/chromium/web-bluetooth-test.js`.
[Web Bluetooth Testing API]: https://docs.google.com/document/d/1Nhv_oVDCodd1pEH_jj9k8gF4rPGb_84VYaZ9IG8M_WY/

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

@ -0,0 +1,166 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
'use strict'
var base_uuid = '00000000-0000-1000-8000-00805f9b34fb'
test(() => {
let base_alias = 0x0
assert_equals(BluetoothUUID.getService(base_alias), base_uuid);
assert_equals(BluetoothUUID.getCharacteristic(base_alias), base_uuid);
assert_equals(BluetoothUUID.getDescriptor(base_alias), base_uuid);
}, '0x0 should produce valid UUID.');
test(() => {
assert_equals(BluetoothUUID.getService(NaN), base_uuid);
assert_equals(BluetoothUUID.getCharacteristic(NaN), base_uuid);
assert_equals(BluetoothUUID.getDescriptor(NaN), base_uuid);
}, 'NaN returns basic uuid');
test(() => {
let max_uuid = 'ffffffff-0000-1000-8000-00805f9b34fb';
let nine_digits = 0xfffffffff;
let thirteen_digits = 0xfffffffffffff;
let fourteen_digits = 0xffffffffffffff;
assert_equals(BluetoothUUID.getService(nine_digits), max_uuid);
assert_equals(BluetoothUUID.getCharacteristic(nine_digits), max_uuid);
assert_equals(BluetoothUUID.getDescriptor(nine_digits), max_uuid);
assert_equals(BluetoothUUID.getService(thirteen_digits), max_uuid);
assert_equals(BluetoothUUID.getCharacteristic(thirteen_digits), max_uuid);
assert_equals(BluetoothUUID.getDescriptor(thirteen_digits), max_uuid);
assert_equals(BluetoothUUID.getService(fourteen_digits), base_uuid);
assert_equals(BluetoothUUID.getCharacteristic(fourteen_digits), base_uuid);
assert_equals(BluetoothUUID.getDescriptor(fourteen_digits), base_uuid);
}, 'Values between 0xfffffffff (8 digits) and 0xffffffffffffff (14 digits)' +
'should return max UUID');
test(() => {
assert_equals(BluetoothUUID.getService(Infinity), base_uuid);
assert_equals(BluetoothUUID.getCharacteristic(Infinity), base_uuid);
assert_equals(BluetoothUUID.getDescriptor(Infinity), base_uuid);
}, 'Infinity returns base UUID');
test(() => {
let deadbeef_alias = 0xDEADBEEF;
let deadbeef_uuid = 'deadbeef-0000-1000-8000-00805f9b34fb';
assert_equals(BluetoothUUID.getService(deadbeef_alias), deadbeef_uuid);
assert_equals(BluetoothUUID.getCharacteristic(deadbeef_alias), deadbeef_uuid);
assert_equals(BluetoothUUID.getDescriptor(deadbeef_alias), deadbeef_uuid);
}, '0xdeadbeef should produce valid UUID.');
test(() => {
let adeadbeef_alias = 0xADEADBEEF;
let adeadbeef_uuid = 'deadbeef-0000-1000-8000-00805f9b34fb';
assert_equals(BluetoothUUID.getService(adeadbeef_alias), adeadbeef_uuid);
assert_equals(BluetoothUUID.getCharacteristic(adeadbeef_alias), adeadbeef_uuid);
assert_equals(BluetoothUUID.getDescriptor(adeadbeef_alias), adeadbeef_uuid);
}, 'Only first 32bits should be used.');
test(() => {
let basic_uuid = '1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d';
assert_equals(BluetoothUUID.getService(basic_uuid), basic_uuid);
assert_equals(BluetoothUUID.getCharacteristic(basic_uuid), basic_uuid);
assert_equals(BluetoothUUID.getDescriptor(basic_uuid), basic_uuid);
}, 'A valid UUID String should return the same UUID.');
test(() => {
let all_caps_uuid = '1A2B3C4D-5E6F-7A8B-9C0D-1E2F3A4B5C6D';
assert_throws(TypeError(), () => BluetoothUUID.getService(all_caps_uuid));
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(all_caps_uuid));
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(all_caps_uuid));
}, 'A UUID String with uppercase letters is an invalid UUID.');
test(() => {
let string_alias = 'deadbeef';
assert_throws(TypeError(), () => BluetoothUUID.getService(string_alias));
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(string_alias));
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(string_alias));
}, 'A 32bit *String* alias is invalid.');
test(() => {
let invalid_character_uuid = '0000000g-0000-1000-8000-00805f9b34fb';
assert_throws(TypeError(), () => BluetoothUUID.getService(invalid_character_uuid));
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(invalid_character_uuid));
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(invalid_character_uuid));
}, 'A UUID with invalid characters is an invalid UUID.');
test(() => {
assert_equals(BluetoothUUID.getService('alert_notification'),
'00001811-0000-1000-8000-00805f9b34fb');
assert_equals(BluetoothUUID.getCharacteristic('aerobic_heart_rate_lower_limit'),
'00002a7e-0000-1000-8000-00805f9b34fb');
assert_equals(BluetoothUUID.getDescriptor('gatt.characteristic_extended_properties'),
'00002900-0000-1000-8000-00805f9b34fb');
}, 'A valid UUID from a name.');
test(() => {
assert_throws(TypeError(), () => {
BluetoothUUID.getService('aerobic_heart_rate_lower_limit');
});
assert_throws(TypeError(), () => {
BluetoothUUID.getService('gatt.characteristic_extended_properties');
});
assert_throws(TypeError(), () => {
BluetoothUUID.getCharacteristic('alert_notification');
});
assert_throws(TypeError(), () => {
BluetoothUUID.getCharacteristic('gatt.characteristic_extended_properties');
});
assert_throws(TypeError(), () => {
BluetoothUUID.getDescriptor('alert_notification');
});
assert_throws(TypeError(), () => {
BluetoothUUID.getDescriptor('aerobic_heart_rate_lower_limit');
});
}, 'Make sure attributes don\'t share a map');
test(() => {
let wrong_name = 'wrong_name';
assert_throws(TypeError(), () => BluetoothUUID.getService(wrong_name));
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(wrong_name));
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(wrong_name));
}, 'Invalid Descriptor name');
test(() => {
let object = {};
let array = [];
let func = () => {};
// cannonicalUUID
assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(object));
// [] converts to '', which converts to 0 before the range check.
assert_equals(BluetoothUUID.canonicalUUID(array), base_uuid);
assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(func));
assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(undefined));
assert_equals(BluetoothUUID.canonicalUUID(null), base_uuid);
assert_equals(BluetoothUUID.canonicalUUID(false), base_uuid);
assert_equals(BluetoothUUID.canonicalUUID(true), BluetoothUUID.canonicalUUID(1));
assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(NaN));
// getService
assert_throws(TypeError(), () => BluetoothUUID.getService(object));
assert_throws(TypeError(), () => BluetoothUUID.getService(array));
assert_throws(TypeError(), () => BluetoothUUID.getService(func));
assert_throws(TypeError(), () => BluetoothUUID.getService(undefined));
assert_throws(TypeError(), () => BluetoothUUID.getService(null));
assert_throws(TypeError(), () => BluetoothUUID.getService(false));
// getCharacteristic
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(object));
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(array));
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(func));
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(undefined));
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(null));
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(false));
// getDescriptor
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(object));
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(array));
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(func));
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(undefined));
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(null));
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(false));
}, 'Non-number and non-strings');
</script>

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

@ -0,0 +1,15 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
'use strict';
test(() => {
assert_true('bluetooth' in navigator,
'navigator.bluetooth exists.');
}, 'navigator.bluetooth IDL test');
test(() => {
assert_equals(navigator.bluetooth, navigator.bluetooth);
}, '[SameObject] test for navigator.bluetooth');
</script>

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

@ -0,0 +1,800 @@
'use strict';
function loadScript(path) {
let script = document.createElement('script');
let promise = new Promise(resolve => script.onload = resolve);
script.src = path;
script.async = false;
document.head.appendChild(script);
return promise;
}
function loadScripts(paths) {
let chain = Promise.resolve();
for (let path of paths) {
chain = chain.then(() => loadScript(path));
}
return chain;
}
function performChromiumSetup() {
// Make sure we are actually on Chromium.
if (!Mojo) {
return;
}
// Load the Chromium-specific resources.
let prefix = '/resources/chromium';
let extra = [];
if (window.location.pathname.includes('/LayoutTests/')) {
let root = window.location.pathname.match(/.*LayoutTests/);
prefix = `${root}/external/wpt/resources/chromium`;
extra = [
`${root}/resources/bluetooth/bluetooth-fake-adapter.js`,
];
} else if (window.location.pathname.startsWith('/bluetooth/https/')) {
extra = [
'/js-test-resources/bluetooth/bluetooth-fake-adapter.js',
];
}
return loadScripts([
`${prefix}/mojo_bindings.js`,
`${prefix}/mojo_layouttest_test.mojom.js`,
`${prefix}/uuid.mojom.js`,
`${prefix}/fake_bluetooth.mojom.js`,
`${prefix}/web-bluetooth-test.js`,
].concat(extra))
// Call setBluetoothFakeAdapter() to clean up any fake adapters left over
// by legacy tests.
// Legacy tests that use setBluetoothFakeAdapter() sometimes fail to clean
// their fake adapter. This is not a problem for these tests because the
// next setBluetoothFakeAdapter() will clean it up anyway but it is a
// problem for the new tests that do not use setBluetoothFakeAdapter().
// TODO(crbug.com/569709): Remove once setBluetoothFakeAdapter is no
// longer used.
.then(() => setBluetoothFakeAdapter ? setBluetoothFakeAdapter('')
: undefined);
}
// These tests rely on the User Agent providing an implementation of the
// Web Bluetooth Testing API.
// https://docs.google.com/document/d/1Nhv_oVDCodd1pEH_jj9k8gF4rPGb_84VYaZ9IG8M_WY/edit?ts=59b6d823#heading=h.7nki9mck5t64
function bluetooth_test(func, name, properties) {
Promise.resolve()
.then(() => promise_test(t => Promise.resolve()
// Trigger Chromium-specific setup.
.then(performChromiumSetup)
.then(() => func(t)), name, properties));
}
// HCI Error Codes. Used for simulateGATT[Dis]ConnectionResponse.
// For a complete list of possible error codes see
// BT 4.2 Vol 2 Part D 1.3 List Of Error Codes.
const HCI_SUCCESS = 0x0000;
const HCI_CONNECTION_TIMEOUT = 0x0008;
// GATT Error codes. Used for GATT operations responses.
// BT 4.2 Vol 3 Part F 3.4.1.1 Error Response
const GATT_SUCCESS = 0x0000;
const GATT_INVALID_HANDLE = 0x0001;
// Bluetooth UUID constants:
// Services:
var blocklist_test_service_uuid = "611c954a-263b-4f4a-aab6-01ddb953f985";
var request_disconnection_service_uuid = "01d7d889-7451-419f-aeb8-d65e7b9277af";
// Characteristics:
var blocklist_exclude_reads_characteristic_uuid =
"bad1c9a2-9a5b-4015-8b60-1579bbbf2135";
var request_disconnection_characteristic_uuid =
"01d7d88a-7451-419f-aeb8-d65e7b9277af";
// Descriptors:
var blocklist_test_descriptor_uuid = "bad2ddcf-60db-45cd-bef9-fd72b153cf7c";
// Sometimes we need to test that using either the name, alias, or UUID
// produces the same result. The following objects help us do that.
var generic_access = {
alias: 0x1800,
name: 'generic_access',
uuid: '00001800-0000-1000-8000-00805f9b34fb'
};
var device_name = {
alias: 0x2a00,
name: 'gap.device_name',
uuid: '00002a00-0000-1000-8000-00805f9b34fb'
};
var reconnection_address = {
alias: 0x2a03,
name: 'gap.reconnection_address',
uuid: '00002a03-0000-1000-8000-00805f9b34fb'
};
var heart_rate = {
alias: 0x180d,
name: 'heart_rate',
uuid: '0000180d-0000-1000-8000-00805f9b34fb'
};
var health_thermometer = {
alias: 0x1809,
name: 'health_thermometer',
uuid: '00001809-0000-1000-8000-00805f9b34fb'
};
var body_sensor_location = {
alias: 0x2a38,
name: 'body_sensor_location',
uuid: '00002a38-0000-1000-8000-00805f9b34fb'
};
var glucose = {
alias: 0x1808,
name: 'glucose',
uuid: '00001808-0000-1000-8000-00805f9b34fb'
};
var battery_service = {
alias: 0x180f,
name: 'battery_service',
uuid: '0000180f-0000-1000-8000-00805f9b34fb'
};
var battery_level = {
alias: 0x2A19,
name: 'battery_level',
uuid: '00002a19-0000-1000-8000-00805f9b34fb'
};
var user_description = {
alias: 0x2901,
name: 'gatt.characteristic_user_description',
uuid: '00002901-0000-1000-8000-00805f9b34fb'
};
var client_characteristic_configuration = {
alias: 0x2902,
name: 'gatt.client_characteristic_configuration',
uuid: '00002902-0000-1000-8000-00805f9b34fb'
};
var measurement_interval = {
alias: 0x2a21,
name: 'measurement_interval',
uuid: '00002a21-0000-1000-8000-00805f9b34fb'
};
// The following tests make sure the Web Bluetooth implementation
// responds correctly to the different types of errors the
// underlying platform might return for GATT operations.
// Each browser should map these characteristics to specific code paths
// that result in different errors thus increasing code coverage
// when testing. Therefore some of these characteristics might not be useful
// for all browsers.
//
// TODO(ortuno): According to the testing spec errorUUID(0x101) to
// errorUUID(0x1ff) should be use for the uuids of the characteristics.
var gatt_errors_tests = [{
testName: 'GATT Error: Unknown.',
uuid: errorUUID(0xA1),
error: new DOMException(
'GATT Error Unknown.',
'NotSupportedError')
}, {
testName: 'GATT Error: Failed.',
uuid: errorUUID(0xA2),
error: new DOMException(
'GATT operation failed for unknown reason.',
'NotSupportedError')
}, {
testName: 'GATT Error: In Progress.',
uuid: errorUUID(0xA3),
error: new DOMException(
'GATT operation already in progress.',
'NetworkError')
}, {
testName: 'GATT Error: Invalid Length.',
uuid: errorUUID(0xA4),
error: new DOMException(
'GATT Error: invalid attribute length.',
'InvalidModificationError')
}, {
testName: 'GATT Error: Not Permitted.',
uuid: errorUUID(0xA5),
error: new DOMException(
'GATT operation not permitted.',
'NotSupportedError')
}, {
testName: 'GATT Error: Not Authorized.',
uuid: errorUUID(0xA6),
error: new DOMException(
'GATT operation not authorized.',
'SecurityError')
}, {
testName: 'GATT Error: Not Paired.',
uuid: errorUUID(0xA7),
// TODO(ortuno): Change to InsufficientAuthenticationError or similiar
// once https://github.com/WebBluetoothCG/web-bluetooth/issues/137 is
// resolved.
error: new DOMException(
'GATT Error: Not paired.',
'NetworkError')
}, {
testName: 'GATT Error: Not Supported.',
uuid: errorUUID(0xA8),
error: new DOMException(
'GATT Error: Not supported.',
'NotSupportedError')
}];
function callWithTrustedClick(callback) {
return new Promise(resolve => {
let button = document.createElement('button');
button.textContent = 'click to continue test';
button.style.display = 'block';
button.style.fontSize = '20px';
button.style.padding = '10px';
button.onclick = () => {
document.body.removeChild(button);
resolve(callback());
};
document.body.appendChild(button);
test_driver.click(button);
});
}
// Calls requestDevice() in a context that's 'allowed to show a popup'.
function requestDeviceWithTrustedClick() {
let args = arguments;
return callWithTrustedClick(
() => navigator.bluetooth.requestDevice.apply(navigator.bluetooth, args));
}
// errorUUID(alias) returns a UUID with the top 32 bits of
// '00000000-97e5-4cd7-b9f1-f5a427670c59' replaced with the bits of |alias|.
// For example, errorUUID(0xDEADBEEF) returns
// 'deadbeef-97e5-4cd7-b9f1-f5a427670c59'. The bottom 96 bits of error UUIDs
// were generated as a type 4 (random) UUID.
function errorUUID(uuidAlias) {
// Make the number positive.
uuidAlias >>>= 0;
// Append the alias as a hex number.
var strAlias = '0000000' + uuidAlias.toString(16);
// Get last 8 digits of strAlias.
strAlias = strAlias.substr(-8);
// Append Base Error UUID
return strAlias + '-97e5-4cd7-b9f1-f5a427670c59';
}
// Function to test that a promise rejects with the expected error type and
// message.
function assert_promise_rejects_with_message(promise, expected, description) {
return promise.then(() => {
assert_unreached('Promise should have rejected: ' + description);
}, error => {
assert_equals(error.name, expected.name, 'Unexpected Error Name:');
if (expected.message) {
assert_equals(error.message, expected.message, 'Unexpected Error Message:');
}
});
}
function runGarbageCollection()
{
// Run gc() as a promise.
return new Promise(
function(resolve, reject) {
GCController.collect();
step_timeout(resolve, 0);
});
}
function eventPromise(target, type, options) {
return new Promise(resolve => {
let wrapper = function(event) {
target.removeEventListener(type, wrapper);
resolve(event);
};
target.addEventListener(type, wrapper, options);
});
}
// Helper function to assert that events are fired and a promise resolved
// in the correct order.
// 'event' should be passed as |should_be_first| to indicate that the events
// should be fired first, otherwise 'promiseresolved' should be passed.
// Attaches |num_listeners| |event| listeners to |object|. If all events have
// been fired and the promise resolved in the correct order, returns a promise
// that fulfills with the result of |object|.|func()| and |event.target.value|
// of each of event listeners. Otherwise throws an error.
function assert_promise_event_order_(should_be_first, object, func, event, num_listeners) {
let order = [];
let event_promises = [];
for (let i = 0; i < num_listeners; i++) {
event_promises.push(new Promise(resolve => {
let event_listener = (e) => {
object.removeEventListener(event, event_listener);
order.push('event');
resolve(e.target.value);
};
object.addEventListener(event, event_listener);
}));
}
let func_promise = object[func]().then(result => {
order.push('promiseresolved');
return result;
});
return Promise.all([func_promise, ...event_promises])
.then((result) => {
if (should_be_first !== order[0]) {
throw should_be_first === 'promiseresolved' ?
`'${event}' was fired before promise resolved.` :
`Promise resolved before '${event}' was fired.`;
}
if (order[0] !== 'promiseresolved' &&
order[order.length - 1] !== 'promiseresolved') {
throw 'Promise resolved in between event listeners.';
}
return result;
});
}
// See assert_promise_event_order_ above.
function assert_promise_resolves_before_event(
object, func, event, num_listeners=1) {
return assert_promise_event_order_(
'promiseresolved', object, func, event, num_listeners);
}
// See assert_promise_event_order_ above.
function assert_promise_resolves_after_event(
object, func, event, num_listeners=1) {
return assert_promise_event_order_(
'event', object, func, event, num_listeners);
}
// Returns a promise that resolves after 100ms unless
// the the event is fired on the object in which case
// the promise rejects.
function assert_no_events(object, event_name) {
return new Promise((resolve, reject) => {
let event_listener = (e) => {
object.removeEventListener(event_name, event_listener);
assert_unreached('Object should not fire an event.');
};
object.addEventListener(event_name, event_listener);
// TODO: Remove timeout.
// http://crbug.com/543884
step_timeout(() => {
object.removeEventListener(event_name, event_listener);
resolve();
}, 100);
});
}
class TestCharacteristicProperties {
// |properties| is an array of strings for property bits to be set
// as true.
constructor(properties) {
this.broadcast = false;
this.read = false;
this.writeWithoutResponse = false;
this.write = false;
this.notify = false;
this.indicate = false;
this.authenticatedSignedWrites = false;
this.reliableWrite = false;
this.writableAuxiliaries = false;
properties.forEach(val => {
if (this.hasOwnProperty(val))
this[val] = true;
else
throw `Invalid member '${val}'`;
});
}
}
function assert_properties_equal(properties, expected_properties) {
for (let key in expected_properties) {
assert_equals(properties[key], expected_properties[key]);
}
}
class EventCatcher {
constructor(object, event) {
this.eventFired = false;
let event_listener = () => {
object.removeEventListener(event, event_listener);
this.eventFired = true;
};
object.addEventListener(event, event_listener);
}
}
// Returns a function that when called returns a promise that resolves when
// the device has disconnected. Example:
// device.gatt.connect()
// .then(gatt => get_request_disconnection(gatt))
// .then(requestDisconnection => requestDisconnection())
// .then(() => // device is now disconnected)
function get_request_disconnection(gattServer) {
return gattServer.getPrimaryService(request_disconnection_service_uuid)
.then(service => service.getCharacteristic(request_disconnection_characteristic_uuid))
.then(characteristic => {
return () => assert_promise_rejects_with_message(
characteristic.writeValue(new Uint8Array([0])),
new DOMException(
'GATT Server is disconnected. Cannot perform GATT operations. ' +
'(Re)connect first with `device.gatt.connect`.',
'NetworkError'));
});
}
function generateRequestDeviceArgsWithServices(services = ['heart_rate']) {
return [{
filters: [{ services: services }]
}, {
filters: [{ services: services, name: 'Name' }]
}, {
filters: [{ services: services, namePrefix: 'Pre' }]
}, {
filters: [{ services: services, name: 'Name', namePrefix: 'Pre' }]
}, {
filters: [{ services: services }],
optionalServices: ['heart_rate']
}, {
filters: [{ services: services, name: 'Name' }],
optionalServices: ['heart_rate']
}, {
filters: [{ services: services, namePrefix: 'Pre' }],
optionalServices: ['heart_rate']
}, {
filters: [{ services: services, name: 'Name', namePrefix: 'Pre' }],
optionalServices: ['heart_rate']
}];
}
// Simulates a pre-connected device with |address|, |name| and
// |knownServiceUUIDs|.
function setUpPreconnectedDevice({
address = '00:00:00:00:00:00', name = 'LE Device', knownServiceUUIDs = []}) {
return navigator.bluetooth.test.simulateCentral({state: 'powered-on'})
.then(fake_central => fake_central.simulatePreconnectedPeripheral({
address: address,
name: name,
knownServiceUUIDs: knownServiceUUIDs,
}));
}
// Returns a FakePeripheral that corresponds to a simulated pre-connected device
// called 'Health Thermometer'. The device has two known serviceUUIDs:
// 'generic_access' and 'health_thermometer'.
function setUpHealthThermometerDevice() {
return setUpPreconnectedDevice({
address: '09:09:09:09:09:09',
name: 'Health Thermometer',
knownServiceUUIDs: ['generic_access', 'health_thermometer'],
});
}
// Returns an array containing two FakePeripherals corresponding
// to the simulated devices.
function setUpHealthThermometerAndHeartRateDevices() {
return navigator.bluetooth.test.simulateCentral({state: 'powered-on'})
.then(fake_central => Promise.all([
fake_central.simulatePreconnectedPeripheral({
address: '09:09:09:09:09:09',
name: 'Health Thermometer',
knownServiceUUIDs: ['generic_access', 'health_thermometer'],
}),
fake_central.simulatePreconnectedPeripheral({
address: '08:08:08:08:08:08',
name: 'Heart Rate',
knownServiceUUIDs: ['generic_access', 'heart_rate'],
})]));
}
// Returns the same fake peripheral as setUpHealthThermometerDevice() except
// that connecting to the peripheral will succeed.
function setUpConnectableHealthThermometerDevice() {
let fake_peripheral;
return setUpHealthThermometerDevice()
.then(_ => fake_peripheral = _)
.then(() => fake_peripheral.setNextGATTConnectionResponse({
code: HCI_SUCCESS,
}))
.then(() => fake_peripheral);
}
// Returns an object containing a BluetoothDevice discovered using |options|,
// its corresponding FakePeripheral and FakeRemoteGATTServices.
// The simulated device is called 'Health Thermometer' it has two known service
// UUIDs: 'generic_access' and 'health_thermometer' which correspond to two
// services with the same UUIDs. The 'health thermometer' service contains three
// characteristics:
// - 'temperature_measurement' (indicate),
// - 'temperature_type' (read),
// - 'measurement_interval' (read, write, indicate)
// The 'measurement_interval' characteristic contains a
// 'gatt.client_characteristic_configuration' descriptor and a
// 'characteristic_user_description' descriptor.
// The device has been connected to and its attributes are ready to be
// discovered.
function getHealthThermometerDevice(options) {
let result;
return getConnectedHealthThermometerDevice(options)
.then(_ => result = _)
.then(() => result.fake_peripheral.setNextGATTDiscoveryResponse({
code: HCI_SUCCESS,
}))
.then(() => result);
}
// Similar to getHealthThermometerDevice except that the peripheral has
// two 'health_thermometer' services.
function getTwoHealthThermometerServicesDevice(options) {
let device;
let fake_peripheral;
let fake_generic_access;
let fake_health_thermometer1;
let fake_health_thermometer2;
return getConnectedHealthThermometerDevice(options)
.then(result => {
({
device,
fake_peripheral,
fake_generic_access,
fake_health_thermometer: fake_health_thermometer1,
} = result);
})
.then(() => fake_peripheral.addFakeService({uuid: 'health_thermometer'}))
.then(s => fake_health_thermometer2 = s)
.then(() => fake_peripheral.setNextGATTDiscoveryResponse({
code: HCI_SUCCESS}))
.then(() => ({
device: device,
fake_peripheral: fake_peripheral,
fake_generic_access: fake_generic_access,
fake_health_thermometer1: fake_health_thermometer1,
fake_health_thermometer2: fake_health_thermometer2
}));
}
// Returns an object containing a Health Thermometer BluetoothRemoteGattService
// and its corresponding FakeRemoteGATTService.
function getHealthThermometerService() {
let result;
return getHealthThermometerDevice()
.then(r => result = r)
.then(() => result.device.gatt.getPrimaryService('health_thermometer'))
.then(service => Object.assign(result, {
service,
fake_service: result.fake_health_thermometer,
}));
}
// Returns an object containing a Measurement Interval
// BluetoothRemoteGATTCharacteristic and its corresponding
// FakeRemoteGATTCharacteristic.
function getMeasurementIntervalCharacteristic() {
let result;
return getHealthThermometerService()
.then(r => result = r)
.then(() => result.service.getCharacteristic('measurement_interval'))
.then(characteristic => Object.assign(result, {
characteristic,
fake_characteristic: result.fake_measurement_interval,
}));
}
function getUserDescriptionDescriptor() {
let result;
return getMeasurementIntervalCharacteristic()
.then(r => result = r)
.then(() => result.characteristic.getDescriptor(
'gatt.characteristic_user_description'))
.then(descriptor => Object.assign(result, {
descriptor,
fake_descriptor: result.fake_user_description,
}));
}
// Populates a fake_peripheral with various fakes appropriate for a health
// thermometer. This resolves to an associative array composed of the fakes,
// including the |fake_peripheral|.
function populateHealthThermometerFakes(fake_peripheral) {
let fake_generic_access, fake_health_thermometer, fake_measurement_interval,
fake_user_description, fake_cccd, fake_temperature_measurement,
fake_temperature_type;
return fake_peripheral.addFakeService({uuid: 'generic_access'})
.then(_ => fake_generic_access = _)
.then(() => fake_peripheral.addFakeService({
uuid: 'health_thermometer',
}))
.then(_ => fake_health_thermometer = _)
.then(() => fake_health_thermometer.addFakeCharacteristic({
uuid: 'measurement_interval',
properties: ['read', 'write', 'indicate'],
}))
.then(_ => fake_measurement_interval = _)
.then(() => fake_measurement_interval.addFakeDescriptor({
uuid: 'gatt.characteristic_user_description',
}))
.then(_ => fake_user_description = _)
.then(() => fake_measurement_interval.addFakeDescriptor({
uuid: 'gatt.client_characteristic_configuration',
}))
.then(_ => fake_cccd = _)
.then(() => fake_health_thermometer.addFakeCharacteristic({
uuid: 'temperature_measurement',
properties: ['indicate'],
}))
.then(_ => fake_temperature_measurement = _)
.then(() => fake_health_thermometer.addFakeCharacteristic({
uuid: 'temperature_type',
properties: ['read'],
}))
.then(_ => fake_temperature_type = _)
.then(() => ({
fake_peripheral,
fake_generic_access,
fake_health_thermometer,
fake_measurement_interval,
fake_cccd,
fake_user_description,
fake_temperature_measurement,
fake_temperature_type,
}));
}
// Similar to getHealthThermometerDevice except the GATT discovery
// response has not been set yet so more attributes can still be added.
function getConnectedHealthThermometerDevice(options) {
let device, fake_peripheral, fakes;
return getDiscoveredHealthThermometerDevice(options)
.then(_ => ({device, fake_peripheral} = _))
.then(() => fake_peripheral.setNextGATTConnectionResponse({
code: HCI_SUCCESS,
}))
.then(() => populateHealthThermometerFakes(fake_peripheral))
.then(_ => fakes = _)
.then(() => device.gatt.connect())
.then(() => Object.assign({device}, fakes));
}
// Returns the same device and fake peripheral as getHealthThermometerDevice()
// after another frame (an iframe we insert) discovered the device,
// connected to it and discovered its services.
function getHealthThermometerDeviceWithServicesDiscovered(options) {
let device, fake_peripheral, fakes;
let iframe = document.createElement('iframe');
return setUpConnectableHealthThermometerDevice()
.then(_ => fake_peripheral = _)
.then(() => populateHealthThermometerFakes(fake_peripheral))
.then(_ => fakes = _)
.then(() => fake_peripheral.setNextGATTDiscoveryResponse({
code: HCI_SUCCESS,
}))
.then(() => new Promise(resolve => {
iframe.src = '../../../resources/bluetooth/health-thermometer-iframe.html';
document.body.appendChild(iframe);
iframe.addEventListener('load', resolve);
}))
.then(() => new Promise((resolve, reject) => {
callWithTrustedClick(() => {
iframe.contentWindow.postMessage({
type: 'DiscoverServices',
options: options
}, '*');
});
function messageHandler(messageEvent) {
if (messageEvent.data == 'DiscoveryComplete') {
window.removeEventListener('message', messageHandler);
resolve();
} else {
reject(new Error(`Unexpected message: ${messageEvent.data}`));
}
}
window.addEventListener('message', messageHandler);
}))
.then(() => requestDeviceWithTrustedClick(options))
.then(_ => device = _)
.then(device => device.gatt.connect())
.then(_ => Object.assign({device}, fakes));
}
// Similar to getHealthThermometerDevice() except the device has no services,
// characteristics, or descriptors.
function getEmptyHealthThermometerDevice(options) {
return getDiscoveredHealthThermometerDevice(options)
.then(({device, fake_peripheral}) => {
return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS})
.then(() => device.gatt.connect())
.then(() => fake_peripheral.setNextGATTDiscoveryResponse({
code: HCI_SUCCESS}))
.then(() => ({
device: device,
fake_peripheral: fake_peripheral
}));
});
}
// Similar to getHealthThermometerService() except the service has no
// characteristics or included services.
function getEmptyHealthThermometerService(options) {
let device;
let fake_peripheral;
let fake_health_thermometer;
return getDiscoveredHealthThermometerDevice(options)
.then(result => ({device, fake_peripheral} = result))
.then(() => fake_peripheral.setNextGATTConnectionResponse({
code: HCI_SUCCESS}))
.then(() => device.gatt.connect())
.then(() => fake_peripheral.addFakeService({uuid: 'health_thermometer'}))
.then(s => fake_health_thermometer = s)
.then(() => fake_peripheral.setNextGATTDiscoveryResponse({
code: HCI_SUCCESS}))
.then(() => device.gatt.getPrimaryService('health_thermometer'))
.then(service => ({
service: service,
fake_health_thermometer: fake_health_thermometer,
}));
}
// Returns a BluetoothDevice discovered using |options| and its
// corresponding FakePeripheral.
// The simulated device is called 'HID Device' it has three known service
// UUIDs: 'generic_access', 'device_information', 'human_interface_device'.
// The primary service with 'device_information' UUID has a characteristics
// with UUID 'serial_number_string'. The device has been connected to and its
// attributes are ready to be discovered.
// TODO(crbug.com/719816): Add descriptors.
function getHIDDevice(options) {
return setUpPreconnectedDevice({
address: '10:10:10:10:10:10',
name: 'HID Device',
knownServiceUUIDs: [
'generic_access',
'device_information',
'human_interface_device'
],
})
.then(fake_peripheral => {
return requestDeviceWithTrustedClick(options)
.then(device => {
return fake_peripheral
.setNextGATTConnectionResponse({
code: HCI_SUCCESS})
.then(() => device.gatt.connect())
.then(() => fake_peripheral.addFakeService({
uuid: 'generic_access'}))
.then(() => fake_peripheral.addFakeService({
uuid: 'device_information'}))
// Blocklisted Characteristic:
// https://github.com/WebBluetoothCG/registries/blob/master/gatt_blocklist.txt
.then(dev_info => dev_info.addFakeCharacteristic({
uuid: 'serial_number_string', properties: ['read']}))
.then(() => fake_peripheral.addFakeService({
uuid: 'human_interface_device'}))
.then(() => fake_peripheral.setNextGATTDiscoveryResponse({
code: HCI_SUCCESS}))
.then(() => ({
device: device,
fake_peripheral: fake_peripheral
}));
});
});
}
// Similar to getHealthThermometerDevice() except the device
// is not connected and thus its services have not been
// discovered.
function getDiscoveredHealthThermometerDevice(
options = {filters: [{services: ['health_thermometer']}]}) {
return setUpHealthThermometerDevice()
.then(fake_peripheral => {
return requestDeviceWithTrustedClick(options)
.then(device => ({
device: device,
fake_peripheral: fake_peripheral
}));
});
}

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

@ -33,3 +33,14 @@ function getAudioURI(base)
return base + extension;
}
function getMediaContentType(url) {
var extension = new URL(url, location).pathname.split(".").pop();
var map = {
"mp4": "video/mp4",
"ogv": "video/ogg",
"mp3": "audio/mp3",
"oga": "audio/ogg",
};
return map[extension];
}

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

@ -4,9 +4,9 @@
<title>ARIA Tree Example</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="./css/treesimple.css" type="text/css">
<script type="text/javascript" src="./js/prototype.js"></script>
<script type="text/javascript" src="./js/aria.js"></script>
<script type="text/javascript" src="./js/init.js"></script>
<script src="./js/prototype.js"></script>
<script src="./js/aria.js"></script>
<script src="./js/init.js"></script>
</head>
<body>

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

@ -4,9 +4,9 @@
<title>ARIA Tree Example</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="./css/treebox.css" type="text/css">
<script type="text/javascript" src="./js/prototype.js"></script>
<script type="text/javascript" src="./js/aria.js"></script>
<script type="text/javascript" src="./js/init.js"></script>
<script src="./js/prototype.js"></script>
<script src="./js/aria.js"></script>
<script src="./js/init.js"></script>
</head>
<body>

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

@ -15,7 +15,7 @@
After the onload event completes a child DOM text node is added to the element with
the aria-live attribute.</p>
<script type="text/javascript">
<script>
function addTextNode() {
var node = document.getElementById('TEST_ID');

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

@ -15,7 +15,7 @@
After the onload event completes a child DOM text node is added to the element
with the aria-live attribute.</p>
<script type="text/javascript">
<script>
function addTextNode() {
var node = document.getElementById('TEST_ID');

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

@ -16,7 +16,7 @@
value 'assertive' is added to the element and a child DOM text
node is added to the element.</p>
<script type="text/javascript">
<script>
function addLiveRegion() {
var node = document.getElementById('TEST_ID');

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

@ -16,7 +16,7 @@
value 'assertive' is added to the document and a child element and text
node is added to the element with the aria-live attribute.</p>
<script type="text/javascript">
<script>
function addElement() {
var node = document.getElementById('TEST_ID');

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

@ -17,7 +17,7 @@
After the onload event completes a child DOM element node with text content has the
CSS dsiplay property changed to display="block".</p>
<script type="text/javascript">
<script>
function showElement() {
var node = document.getElementById('TEST_ID');

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

@ -18,7 +18,7 @@
a child DOM element node with text content has the CSS dsiplay property
changed to display="block".</p>
<script type="text/javascript">
<script>
function showElement() {
var node = document.getElementById('TEST_ID');

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

@ -20,7 +20,7 @@
After the onload event completes a child DOM element node with text content has the
CSS dsiplay property changed to visibility="visible".</p>
<script type="text/javascript">
<script>
function showElement() {
var node = document.getElementById('TEST_ID');

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

@ -19,7 +19,7 @@
After the onload event completes a child DOM element node with text content has the CSS dsiplay
property changed to visibility="visible".</p>
<script type="text/javascript">
<script>
function showElement() {
var node = document.getElementById('TEST_ID');

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

@ -15,7 +15,7 @@
event with the value="polite". After the onload event completes a child DOM text node is added
to the element with the aria-live attribute.</p>
<script type="text/javascript">
<script>
function addChildTextNode() {
var node = document.getElementById('TEST_ID');

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

@ -15,7 +15,7 @@
event with the value="assertive". After the onload event completes a child DOM text node is
added to the element with the aria-live attribute.</p>
<script type="text/javascript">
<script>
function addChildTextNode() {
var node = document.getElementById('TEST_ID_2');

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

@ -15,7 +15,7 @@
event with the value="polite". After the onload event completes a child DOM element node is
added to the element with the aria-live attribute.</p>
<script type="text/javascript">
<script>
function addChildElementNode() {
var node = document.getElementById('TEST_ID_2');

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

@ -15,7 +15,7 @@
the onload event with the value="assertive". After the onload event completes a
child DOM element node is added to the element with the aria-live attribute.</p>
<script type="text/javascript">
<script>
function addChildElementNode() {
var node = document.getElementById('TEST_ID_2');

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

@ -16,7 +16,7 @@
that is hidden using CSS display="none". After the onload event completes a child DOM element
node with text content has the CSS display property changed to display="block".</p>
<script type="text/javascript">
<script>
function showElement() {
var node = document.getElementById('TEST_ID_3');

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

@ -16,7 +16,7 @@
that is hidden using CSS display="none". After the onload event completes a child DOM element
node with text content has the CSS display property changed to display="block".</p>
<script type="text/javascript">
<script>
function showElement() {
var node = document.getElementById('TEST_ID_3');

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

@ -17,7 +17,7 @@
event completes a child DOM element node with text content has the CSS display property
changed to visibility="visible".</p>
<script type="text/javascript">
<script>
function showElement() {
var node = document.getElementById('TEST_ID_3');

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

@ -17,7 +17,7 @@
After the onload event completes a child DOM element node with text content
has the CSS display property changed to visibility="visible".</p>
<script type="text/javascript">
<script>
function showElement() {
var node = document.getElementById('TEST_ID_3');

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

@ -15,7 +15,7 @@
onload event completes with the value="polite". After the aria-live attribute is added,
a child DOM text node is added to the element with the aria-live attribute.</p>
<script type="text/javascript">
<script>
function addChildTextNode() {
var node = document.getElementById('TEST_ID_2');

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

@ -15,7 +15,7 @@
the onload event completes with the value="assertive". After the aria-live attribute
is added, a child DOM text node is added to the element with the aria-live attribute.</p>
<script type="text/javascript">
<script>
function addChildTextNode() {
var node = document.getElementById('TEST_ID_2');

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

@ -16,7 +16,7 @@
attribute is added, a child DOM element node is added to the element with
the aria-live attribute.</p>
<script type="text/javascript">
<script>
function addChildElementNode() {
var node = document.getElementById('TEST_ID_2');

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

@ -15,7 +15,7 @@
the onload event completes with the value="assertive". After the aria-live attribute
is added, a child DOM element node is added to the element with the aria-live attribute.</p>
<script type="text/javascript">
<script>
function addChildElementNode() {
var node = document.getElementById('TEST_ID_2');

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

@ -17,7 +17,7 @@
aria-live attribute is added, the child DOM element node with text content has the
CSS display property changed to display="block".</p>
<script type="text/javascript">
<script>
function showElement() {
var node = document.getElementById('TEST_ID_2');

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

@ -17,7 +17,7 @@
the aria-live attribute is added, the child DOM element node with text content has
the CSS display property changed to display="block".</p>
<script type="text/javascript">
<script>
function showElement() {
var node = document.getElementById('TEST_ID_3');

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

@ -17,7 +17,7 @@
visibility="hidden". After the aria-live attribute is added, the child DOM
element node with text content has the CSS display property changed to visibility="visible".</p>
<script type="text/javascript">
<script>
function showElement() {
var node = document.getElementById('TEST_ID_3');

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

@ -18,7 +18,7 @@
the aria-live attribute is added, the child DOM element node with text content has
the CSS display property changed to visibility="visible".</p>
<script type="text/javascript">
<script>
function showElement() {
var node = document.getElementById('TEST_ID_2');

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

@ -16,7 +16,7 @@
has a child DOM text node with content. After the onload event completes the child
DOM text node is deleted.</p>
<script type="text/javascript">
<script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_1');

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

@ -16,7 +16,7 @@
has a child DOM text node with content. After the onload event completes the child DOM
text node is deleted.</p>
<script type="text/javascript">
<script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_1');

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

@ -16,7 +16,7 @@
has a child DOM element node that contains text content. After the onload event completes
the child DOM element node is deleted.</p>
<script type="text/javascript">
<script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_1');

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

@ -16,7 +16,7 @@
value="assertive" has a child DOM element node that contains text content.
After the onload event completes the child DOM element node is deleted.</p>
<script type="text/javascript">
<script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_1');

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

@ -17,7 +17,7 @@
content. After the onload event completes the CSS 'display' property
of the child DOM element node is changed to display="none".</p>
<script type="text/javascript">
<script>
function hideElement() {
var node = document.getElementById('TEST_ID_1');

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

@ -16,7 +16,7 @@
has a child DOM element node that contains text content. After the onload event completes
the CSS 'display' property of the child DOM element node is changed to display="none".</p>
<script type="text/javascript">
<script>
function hideElement() {
var node = document.getElementById('TEST_ID_1');

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

@ -17,7 +17,7 @@
completes the CSS 'visibility' property of the child DOM element node is changed
to visibility="hidden".</p>
<script type="text/javascript">
<script>
function hideElement() {
var node = document.getElementById('TEST_ID_1');

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

@ -16,7 +16,7 @@
has a child DOM element node that contains text content. After the onload event completes
the CSS 'visibility' property of the child DOM element node is changed to visibility="hidden".</p>
<script type="text/javascript">
<script>
function hideElement() {
var node = document.getElementById('TEST_ID_1');

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

@ -16,7 +16,7 @@
text node with content. After the onload event completes the child DOM text
node is deleted.</p>
<script type="text/javascript">
<script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_2');

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

@ -15,7 +15,7 @@
event with the value="assertive" and the element has a child DOM text node with content. After
the onload event completes the child DOM text node is deleted.</p>
<script type="text/javascript">
<script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_2');

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

@ -16,7 +16,7 @@
DOM element node that contains text content. After the onload event completes
the child DOM element node is deleted.</p>
<script type="text/javascript">
<script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_2');

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

@ -16,7 +16,7 @@
node that contains text content. After the onload event completes the child DOM
element node is deleted.</p>
<script type="text/javascript">
<script>
function deleteChildNodes() {

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

@ -16,7 +16,7 @@
that contains text content. After the onload event completes the CSS 'display'
property of the child DOM element node is changed to display="none".</p>
<script type="text/javascript">
<script>
function hideElement() {

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

@ -16,7 +16,7 @@
node that contains text content. After the onload event completes the CSS 'display'
property of the child DOM element node is changed to display="none".</p>
<script type="text/javascript">
<script>
function hideElement() {

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

@ -17,7 +17,7 @@
the CSS 'visibility' property of the child DOM element node is changed
to visibility="hidden".</p>
<script type="text/javascript">
<script>
function hideElement() {

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

@ -17,7 +17,7 @@
event completes the CSS 'visibility' property of the child DOM element
node is changed to visibility="hidden".</p>
<script type="text/javascript">
<script>
function hideElement() {

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

@ -16,7 +16,7 @@
the element has a child DOM text node with content. After the
aria-live attribute is added, the child DOM text node is deleted.</p>
<script type="text/javascript">
<script>
function deleteChildNodes() {

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

@ -16,7 +16,7 @@
and the element has a child DOM text node with content. After the
aria-live attribute is added, the child DOM text node is deleted.</p>
<script type="text/javascript">
<script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_2');

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

@ -16,7 +16,7 @@
a child DOM element node that contains text content. After the aria-live
attribute is added, the child DOM element node is deleted.</p>
<script type="text/javascript">
<script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_1');

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

@ -17,7 +17,7 @@
a child DOM element node that contains text content. After the aria-live
attribute is added, the child DOM element node is deleted.</p>
<script type="text/javascript">
<script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_1');

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

@ -17,7 +17,7 @@
attribute is added, the CSS 'display' property of the child DOM element
node is changed to display="none".</p>
<script type="text/javascript">
<script>
function hideElement() {
var node = document.getElementById('TEST_ID_2');

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

@ -17,7 +17,7 @@
attribute is added, the CSS 'display' property of the child DOM element
node is changed to display="none".</p>
<script type="text/javascript">
<script>
function hideElement() {
var node = document.getElementById('TEST_ID_2');

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше