mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Sync WPT with upstream (25-05-2025) (#37123)
Automated downstream sync of changes from upstream as of 25-05-2025 [no-wpt-sync] Signed-off-by: WPT Sync Bot <ghbot+wpt-sync@servo.org>
This commit is contained in:
parent
2b840a4d9a
commit
0d44ca8ddc
1119 changed files with 16957 additions and 4009 deletions
3162
tests/wpt/meta/MANIFEST.json
vendored
3162
tests/wpt/meta/MANIFEST.json
vendored
File diff suppressed because it is too large
Load diff
|
@ -1,24 +0,0 @@
|
|||
[gap-decorations-rule-shorthand-computed-from-longhands.html]
|
||||
[column-rule computed from width: 5px, style: solid, color: rgb(0, 128, 0)]
|
||||
expected: FAIL
|
||||
|
||||
[column-rule computed from width: repeat(auto, 5px), style: repeat(auto, solid), color: repeat(auto, rgb(255, 0, 0))]
|
||||
expected: FAIL
|
||||
|
||||
[column-rule computed from width: repeat(auto, thin medium), style: solid, color: repeat(8, red blue)]
|
||||
expected: FAIL
|
||||
|
||||
[column-rule computed from width: repeat(6, 15px thick), style: repeat(auto, solid), color: repeat(auto, red)]
|
||||
expected: FAIL
|
||||
|
||||
[column-rule computed from width: 15px 25px 35px, style: solid dotted, color: green]
|
||||
expected: FAIL
|
||||
|
||||
[column-rule computed from width: repeat(auto, 5px), style: solid double, color: repeat(7, red)]
|
||||
expected: FAIL
|
||||
|
||||
[column-rule computed from width: repeat(auto, 5px 8px 10px), style: repeat(auto, solid double), color: repeat(auto, red green blue)]
|
||||
expected: FAIL
|
||||
|
||||
[column-rule computed from width: repeat(2, 1px 3px 5px), style: repeat(2, solid double), color: repeat(2, red)]
|
||||
expected: FAIL
|
|
@ -1,42 +0,0 @@
|
|||
[idlharness.tentative.window.html]
|
||||
[idl_test setup]
|
||||
expected: FAIL
|
||||
|
||||
[idl_test validation]
|
||||
expected: FAIL
|
||||
|
||||
[Partial interface CustomElementRegistry: member names are unique]
|
||||
expected: FAIL
|
||||
|
||||
[Partial interface HTMLTemplateElement: member names are unique]
|
||||
expected: FAIL
|
||||
|
||||
[Partial interface Element: member names are unique]
|
||||
expected: FAIL
|
||||
|
||||
[Partial dictionary ShadowRootInit: member names are unique]
|
||||
expected: FAIL
|
||||
|
||||
[Partial dictionary ElementCreationOptions: member names are unique]
|
||||
expected: FAIL
|
||||
|
||||
[Document includes DocumentOrShadowRoot: member names are unique]
|
||||
expected: FAIL
|
||||
|
||||
[ShadowRoot includes DocumentOrShadowRoot: member names are unique]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLTemplateElement interface: attribute shadowRootCustomElementRegistry]
|
||||
expected: FAIL
|
||||
|
||||
[CustomElementRegistry interface: operation initialize(Node)]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: attribute customElementRegistry]
|
||||
expected: FAIL
|
||||
|
||||
[ShadowRoot interface: attribute customElementRegistry]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: attribute customElementRegistry]
|
||||
expected: FAIL
|
|
@ -1,90 +0,0 @@
|
|||
[on-dialog-behavior-request-close.tentative.html]
|
||||
[invoking to request-close (with command property as request-close) open dialog closes]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close with value (with command property as request-close) open dialog closes and sets returnValue]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command property as request-close) open dialog with preventDefault is no-op]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command property as request-close) open modal dialog with preventDefault is no-op]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command property as request-close) open dialog while changing command still closes]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command property as request-close) open modal dialog while changing command still closes]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command attribute as request-close) open dialog closes]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close with value (with command attribute as request-close) open dialog closes and sets returnValue]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command attribute as request-close) open dialog with preventDefault is no-op]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command attribute as request-close) open modal dialog with preventDefault is no-op]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command attribute as request-close) open dialog while changing command still closes]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command attribute as request-close) open modal dialog while changing command still closes]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command property as reQuEst-Close) open dialog closes]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close with value (with command property as reQuEst-Close) open dialog closes and sets returnValue]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command property as reQuEst-Close) open dialog with preventDefault is no-op]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command property as reQuEst-Close) open modal dialog with preventDefault is no-op]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command property as reQuEst-Close) open dialog while changing command still closes]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command property as reQuEst-Close) open modal dialog while changing command still closes]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command attribute as reQuEst-Close) open dialog closes]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close with value (with command attribute as reQuEst-Close) open dialog closes and sets returnValue]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command attribute as reQuEst-Close) open dialog with preventDefault is no-op]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command attribute as reQuEst-Close) open modal dialog with preventDefault is no-op]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command attribute as reQuEst-Close) open dialog while changing command still closes]
|
||||
expected: FAIL
|
||||
|
||||
[invoking to request-close (with command attribute as reQuEst-Close) open modal dialog while changing command still closes]
|
||||
expected: FAIL
|
||||
|
||||
[invoking (as request-close) already closed dialog is noop]
|
||||
expected: FAIL
|
||||
|
||||
[invoking (as request-close) dialog as open popover=manual is noop]
|
||||
expected: FAIL
|
||||
|
||||
[invoking (as request-close) dialog as open popover=auto is noop]
|
||||
expected: FAIL
|
||||
|
||||
[invoking (as request-close) dialog that is removed is noop]
|
||||
expected: FAIL
|
||||
|
||||
[invoking (as request-close) dialog from a detached invoker]
|
||||
expected: FAIL
|
||||
|
||||
[invoking (as request-close) detached dialog from a detached invoker]
|
||||
expected: FAIL
|
|
@ -1,6 +0,0 @@
|
|||
[serializing-lt-gt.tentative.html]
|
||||
[innerHTML]
|
||||
expected: FAIL
|
||||
|
||||
[outerHTML]
|
||||
expected: FAIL
|
|
@ -1,8 +0,0 @@
|
|||
[parsing.html?type=report]
|
||||
|
||||
[parsing.html?type=enforce]
|
||||
[Ensure that test is working with a valid destination]
|
||||
expected: FAIL
|
||||
|
||||
[Ensure that test is working with a valid destination and source]
|
||||
expected: FAIL
|
|
@ -1,15 +0,0 @@
|
|||
[script.https.html]
|
||||
[Ensure that a script without integrity did not run]
|
||||
expected: FAIL
|
||||
|
||||
[Ensure that a script with unknown integrity algorithm did not run]
|
||||
expected: FAIL
|
||||
|
||||
[Ensure that a script without integrity algorithm runs and gets reported in report-only mode]
|
||||
expected: FAIL
|
||||
|
||||
[Ensure that a no-cors script gets blocked]
|
||||
expected: FAIL
|
||||
|
||||
[Ensure that ReportingObserver gets called without endpoints]
|
||||
expected: FAIL
|
2
tests/wpt/tests/.github/workflows/docker.yml
vendored
2
tests/wpt/tests/.github/workflows/docker.yml
vendored
|
@ -40,7 +40,7 @@ jobs:
|
|||
latest
|
||||
type=raw,value=${{ inputs.tag }}
|
||||
- name: Build and push the Docker image
|
||||
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
|
||||
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0
|
||||
with:
|
||||
context: ./tools/docker
|
||||
push: true
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
|
||||
*/
|
||||
|
||||
.alt-counter::before {
|
||||
counter-set: cnt 5051;
|
||||
content: "" / counter(cnt);
|
||||
}
|
||||
.simple-before::before {
|
||||
content: " before "; /* [sic] leading and trailing space */
|
||||
margin:0 0.1em;
|
||||
|
@ -103,6 +107,12 @@
|
|||
<a href="#" data-expectedlabel="label" data-testname="link name from content" class="ex">label</a><br>
|
||||
<br>
|
||||
|
||||
<h1>alt counter with ::before</h1>
|
||||
<button data-expectedlabel="5051 label" data-testname="button with alt counter on ::before" class="ex alt-counter">label</button><br>
|
||||
<h3 data-expectedlabel="5051 label" data-testname="heading with alt counter on ::before" class="ex alt-counter">label</h3>
|
||||
<a href="#" data-expectedlabel="5051 label" data-testname="link with alt counter on ::before" class="ex alt-counter">label</a><br>
|
||||
<br>
|
||||
|
||||
<h1>simple with ::before</h1>
|
||||
<button data-expectedlabel="before label" data-testname="button name from content with ::before" class="ex simple-before">label</button><br>
|
||||
<h3 data-expectedlabel="before label" data-testname="heading name from content with ::before" class="ex simple-before">label</h3>
|
||||
|
|
38
tests/wpt/tests/accname/name/comp_name_from_content_alt_counter_invalidation.html
vendored
Normal file
38
tests/wpt/tests/accname/name/comp_name_from_content_alt_counter_invalidation.html
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
<!doctype html>
|
||||
<title>Name Comp: Name From Alt Counter in Content Invalidation</title>
|
||||
<meta charset="utf-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/resources/testdriver-actions.js"></script>
|
||||
<script src="/wai-aria/scripts/aria-utils.js"></script>
|
||||
<style type="text/css">
|
||||
.alt-counter::before {
|
||||
counter-set: cnt 5051;
|
||||
content: "" / counter(cnt);
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Tests the <a href="https://w3c.github.io/accname/#comp_name_from_content">#comp_name_from_content</a> portions of the AccName <em>Name Computation</em> algorithm.</p>
|
||||
|
||||
<p>This series of tests exercises the button, heading, and link elements, because each have different characteristics worthy of testing in each of the name computation algorithm scenarios:</p>
|
||||
<ul>
|
||||
<li>button is a leaf node with sub-level elements presentational.</li>
|
||||
<li>heading is block level, and can contain sub-level interactives like links.</li>
|
||||
<li>link (a[href]) is an interactive inline element that can include non-presentational descendants.</li>
|
||||
</ul>
|
||||
|
||||
<h1>alt counter with ::before</h1>
|
||||
<button data-expectedlabel="228 label" data-testname="button with alt counter on ::before" class="ex alt-counter">label</button><br>
|
||||
<h3 data-expectedlabel="228 label" data-testname="heading with alt counter on ::before" class="ex alt-counter">label</h3>
|
||||
<a href="#" data-expectedlabel="228 label" data-testname="link with alt counter on ::before" class="ex alt-counter">label</a><br>
|
||||
<br>
|
||||
|
||||
<script>
|
||||
document.documentElement.offsetTop;
|
||||
let sheet = document.styleSheets[0];
|
||||
sheet.cssRules[0].style.counterSet = "cnt 228";
|
||||
document.documentElement.offsetTop;
|
||||
AriaUtils.verifyLabelsBySelector(".ex");
|
||||
</script>
|
|
@ -52,3 +52,15 @@ promise_test(async () => {
|
|||
assert_array_equals(detector.expectedInputLanguages, expectedInputLanguages);
|
||||
assert_true(Object.isFrozen(detector.expectedInputLanguages));
|
||||
}, 'Creating LanguageDetector with expectedInputLanguages');
|
||||
|
||||
|
||||
promise_test(async () => {
|
||||
const detector = await createLanguageDetector();
|
||||
|
||||
const results = await detector.detect('');
|
||||
assert_equals(results.length, 1);
|
||||
|
||||
const [result] = results;
|
||||
assert_equals(result.detectedLanguage, 'und');
|
||||
assert_equals(result.confidence, 1);
|
||||
}, 'LanguageDetector.detect() detects empty string');
|
||||
|
|
|
@ -9,21 +9,21 @@ promise_test(async t => {
|
|||
await testAbortPromise(t, signal => {
|
||||
return createRewriter({signal: signal});
|
||||
});
|
||||
}, 'Aborting Rewriter.create().');
|
||||
}, 'Aborting Rewriter.create()');
|
||||
|
||||
promise_test(async t => {
|
||||
const rewriter = await createRewriter();
|
||||
await testAbortPromise(t, signal => {
|
||||
return rewriter.rewrite(kTestPrompt, { signal: signal });
|
||||
});
|
||||
}, 'Aborting Rewriter.rewrite().');
|
||||
}, 'Aborting Rewriter.rewrite()');
|
||||
|
||||
promise_test(async t => {
|
||||
const rewriter = await createRewriter();
|
||||
await testAbortReadableStream(t, signal => {
|
||||
return rewriter.rewriteStreaming(kTestPrompt, { signal: signal });
|
||||
});
|
||||
}, 'Aborting Rewriter.rewriteStreaming().');
|
||||
}, 'Aborting Rewriter.rewriteStreaming()');
|
||||
|
||||
promise_test(async t => {
|
||||
const rewriter = await createRewriter();
|
||||
|
@ -32,4 +32,4 @@ promise_test(async t => {
|
|||
kTestPrompt, { signal: controller.signal });
|
||||
for await (const chunk of streamingResponse); // Do nothing
|
||||
controller.abort();
|
||||
}, 'Aborting Rewriter.rewriteStreaming() after finished reading.');
|
||||
}, 'Aborting Rewriter.rewriteStreaming() after finished reading');
|
||||
|
|
102
tests/wpt/tests/ai/rewriter/rewriter-create-available.tentative.https.window.js
vendored
Normal file
102
tests/wpt/tests/ai/rewriter/rewriter-create-available.tentative.https.window.js
vendored
Normal file
|
@ -0,0 +1,102 @@
|
|||
// META: title=Rewriter Create Available
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
assert_equals(typeof rewriter, 'object');
|
||||
|
||||
assert_equals(typeof rewriter.rewrite, 'function');
|
||||
assert_equals(typeof rewriter.rewriteStreaming, 'function');
|
||||
assert_equals(typeof rewriter.measureInputUsage, 'function');
|
||||
assert_equals(typeof rewriter.destroy, 'function');
|
||||
|
||||
assert_equals(typeof rewriter.expectedContextLanguages, 'object');
|
||||
assert_equals(typeof rewriter.expectedInputLanguages, 'object');
|
||||
assert_equals(typeof rewriter.inputQuota, 'number');
|
||||
assert_equals(typeof rewriter.outputLanguage, 'object');
|
||||
assert_equals(typeof rewriter.sharedContext, 'string');
|
||||
|
||||
assert_equals(typeof rewriter.tone, 'string');
|
||||
assert_equals(typeof rewriter.format, 'string');
|
||||
assert_equals(typeof rewriter.length, 'string');
|
||||
|
||||
assert_equals(rewriter.tone, 'as-is');
|
||||
assert_equals(rewriter.format, 'as-is');
|
||||
assert_equals(rewriter.length, 'as-is');
|
||||
}, 'Rewriter.create() returns a valid object with default options');
|
||||
|
||||
promise_test(async () => {
|
||||
await testMonitor(createRewriter);
|
||||
}, 'Rewriter.create() notifies its monitor on downloadprogress');
|
||||
|
||||
promise_test(async t => {
|
||||
await testCreateMonitorWithAbort(t, Rewriter.create);
|
||||
}, 'Progress events are not emitted after aborted');
|
||||
|
||||
promise_test(async () => {
|
||||
const sharedContext = 'This is a shared context string';
|
||||
const rewriter = await createRewriter({sharedContext: sharedContext});
|
||||
assert_equals(rewriter.sharedContext, sharedContext);
|
||||
}, 'Rewriter.sharedContext');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({ tone: 'more-formal' });
|
||||
assert_equals(rewriter.tone, 'more-formal');
|
||||
}, 'Creating a Rewriter with "more-formal" tone');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({ tone: 'more-casual' });
|
||||
assert_equals(rewriter.tone, 'more-casual');
|
||||
}, 'Creating a Rewriter with "more-casual" tone');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({ format: 'plain-text' });
|
||||
assert_equals(rewriter.format, 'plain-text');
|
||||
}, 'Creating a Rewriter with "plain-text" format');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({ format: 'markdown' });
|
||||
assert_equals(rewriter.format, 'markdown');
|
||||
}, 'Creating a Rewriter with "markdown" format');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({ length: 'shorter' });
|
||||
assert_equals(rewriter.length, 'shorter');
|
||||
}, 'Creating a Rewriter with "shorter" length');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({ length: 'longer' });
|
||||
assert_equals(rewriter.length, 'longer');
|
||||
}, 'Creating a Rewriter with "longer" length');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({expectedInputLanguages: ['en']});
|
||||
assert_array_equals(rewriter.expectedInputLanguages, ['en']);
|
||||
}, 'Rewriter.expectedInputLanguages');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({expectedContextLanguages: ['en']});
|
||||
assert_array_equals(rewriter.expectedContextLanguages, ['en']);
|
||||
}, 'Rewriter.expectedContextLanguages');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({outputLanguage: 'en'});
|
||||
assert_equals(rewriter.outputLanguage, 'en');
|
||||
}, 'Rewriter.outputLanguage');
|
||||
|
||||
promise_test(async (t) => {
|
||||
promise_rejects_js(
|
||||
t, RangeError,
|
||||
createRewriter({ expectedInputLanguages: ['en-abc-invalid'] }));
|
||||
}, 'Creating Rewriter with malformed language string');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({});
|
||||
assert_equals(rewriter.expectedInputLanguages, null);
|
||||
assert_equals(rewriter.expectedContextLanguages, null);
|
||||
assert_equals(rewriter.outputLanguage, null);
|
||||
}, 'Rewriter optional attributes return null');
|
24
tests/wpt/tests/ai/rewriter/rewriter-create.tentative.https.window.js
vendored
Normal file
24
tests/wpt/tests/ai/rewriter/rewriter-create.tentative.https.window.js
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
// META: title=Rewriter Create
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
assert_true(!!Rewriter);
|
||||
}, 'Rewriter must be defined.');
|
||||
|
||||
promise_test(async t => {
|
||||
// Creating Rewriter without user activation rejects with NotAllowedError.
|
||||
await promise_rejects_dom(t, 'NotAllowedError', Rewriter.create());
|
||||
|
||||
// Creating Rewriter with user activation succeeds.
|
||||
await createRewriter();
|
||||
|
||||
// Expect available after create.
|
||||
assert_equals(await Rewriter.availability(), 'available');
|
||||
|
||||
// Now that it is available, we should no longer need user activation.
|
||||
await Rewriter.create();
|
||||
}, 'Rewriter.create() requires user activation when availability is "downloadable"');
|
|
@ -44,7 +44,8 @@ promise_test(async (t) => {
|
|||
iframe.remove();
|
||||
|
||||
assert_throws_dom(
|
||||
'InvalidStateError', iframeDOMException, () => rewriter.rewriteStreaming('hello'));
|
||||
'InvalidStateError',
|
||||
iframeDOMException, () => rewriter.rewriteStreaming('hello'));
|
||||
}, 'Rewriter.rewriteStreaming() fails on a detached iframe.');
|
||||
|
||||
promise_test(async (t) => {
|
||||
|
|
12
tests/wpt/tests/ai/rewriter/rewriter-measureInputUsage.tentative.https.window.js
vendored
Normal file
12
tests/wpt/tests/ai/rewriter/rewriter-measureInputUsage.tentative.https.window.js
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
// META: title=Rewriter measureInputUsage
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
const result = await rewriter.measureInputUsage(kTestPrompt);
|
||||
assert_greater_than(result, 0);
|
||||
}, 'Rewriter.measureInputUsage() returns non-empty result');
|
46
tests/wpt/tests/ai/rewriter/rewriter-rewrite-streaming.tentative.https.window.js
vendored
Normal file
46
tests/wpt/tests/ai/rewriter/rewriter-rewrite-streaming.tentative.https.window.js
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
// META: title=Rewriter Rewrite Streaming
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
const streamingResponse =
|
||||
rewriter.rewriteStreaming(kTestPrompt, { context: kTestContext });
|
||||
assert_equals(
|
||||
Object.prototype.toString.call(streamingResponse),
|
||||
'[object ReadableStream]');
|
||||
let result = '';
|
||||
for await (const chunk of streamingResponse) {
|
||||
result += chunk;
|
||||
}
|
||||
assert_greater_than(result.length, 0);
|
||||
}, 'Simple Rewriter.rewriteStreaming() call');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const rewriter = await createRewriter();
|
||||
rewriter.destroy();
|
||||
assert_throws_dom(
|
||||
'InvalidStateError', () => rewriter.rewriteStreaming(kTestPrompt));
|
||||
}, 'Rewriter.rewriteStreaming() fails after destroyed');
|
||||
|
||||
promise_test(async t => {
|
||||
const rewriter = await createRewriter();
|
||||
const streamingResponse = rewriter.rewriteStreaming('');
|
||||
assert_equals(
|
||||
Object.prototype.toString.call(streamingResponse),
|
||||
"[object ReadableStream]"
|
||||
);
|
||||
const { result, done } = await streamingResponse.getReader().read();
|
||||
assert_true(done);
|
||||
}, 'Rewriter.rewriteStreaming() returns a ReadableStream without any chunk on an empty input');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
await Promise.all([
|
||||
rewriter.rewriteStreaming(kTestPrompt),
|
||||
rewriter.rewriteStreaming(kTestPrompt)
|
||||
]);
|
||||
}, 'Multiple Rewriter.rewriteStreaming() calls are resolved successfully');
|
43
tests/wpt/tests/ai/rewriter/rewriter-rewrite.tentative.https.window.js
vendored
Normal file
43
tests/wpt/tests/ai/rewriter/rewriter-rewrite.tentative.https.window.js
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
// META: title=Rewriter Rewrite
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async (t) => {
|
||||
const rewriter = await createRewriter();
|
||||
let result = await rewriter.rewrite('');
|
||||
assert_equals(result, '');
|
||||
}, 'Rewriter.rewrite() with an empty input returns an empty text');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const rewriter = await createRewriter();
|
||||
let result = await rewriter.rewrite(' ');
|
||||
assert_equals(result, ' ');
|
||||
}, 'Rewriter.rewrite() with a whitespace input returns a whitespace text');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const rewriter = await createRewriter();
|
||||
const result = await rewriter.rewrite(kTestPrompt, { context: ' ' });
|
||||
assert_not_equals(result, '');
|
||||
}, 'Rewriter.rewrite() with a whitespace context returns a non-empty result');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const rewriter = await createRewriter();
|
||||
rewriter.destroy();
|
||||
await promise_rejects_dom(
|
||||
t, 'InvalidStateError', rewriter.rewrite(kTestPrompt));
|
||||
}, 'Rewriter.rewrite() fails after destroyed');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
const result = await rewriter.rewrite(kTestPrompt, { context: kTestContext });
|
||||
assert_equals(typeof result, 'string');
|
||||
}, 'Simple Rewriter.rewrite() call');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
await Promise.all(
|
||||
[rewriter.rewrite(kTestPrompt), rewriter.rewrite(kTestPrompt)]);
|
||||
}, 'Multiple Rewriter.rewrite() calls are resolved successfully');
|
|
@ -1,173 +0,0 @@
|
|||
// META: title=Rewriter
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
assert_true(!!Rewriter);
|
||||
}, 'Rewriter must be defined.');
|
||||
|
||||
promise_test(async t => {
|
||||
// Creating Rewriter without user activation rejects with NotAllowedError.
|
||||
await promise_rejects_dom(t, 'NotAllowedError', Rewriter.create());
|
||||
|
||||
// Creating Rewriter with user activation succeeds.
|
||||
await createRewriter();
|
||||
|
||||
// Expect available after create.
|
||||
assert_equals(await Rewriter.availability(), 'available');
|
||||
|
||||
// Now that it is available, we should no longer need user activation.
|
||||
await Rewriter.create();
|
||||
}, 'Rewriter.create() requires user activation when availability is "downloadable."');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
assert_equals(Object.prototype.toString.call(rewriter), '[object Rewriter]');
|
||||
}, 'Rewriter.create() must be return a Rewriter.');
|
||||
|
||||
promise_test(async () => {
|
||||
await testMonitor(createRewriter);
|
||||
}, 'Rewriter.create() notifies its monitor on downloadprogress');
|
||||
|
||||
promise_test(async t => {
|
||||
await testCreateMonitorWithAbort(t, Rewriter.create);
|
||||
}, 'Progress events are not emitted after aborted.');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
assert_equals(rewriter.sharedContext, '');
|
||||
assert_equals(rewriter.tone, 'as-is');
|
||||
assert_equals(rewriter.format, 'as-is');
|
||||
assert_equals(rewriter.length, 'as-is');
|
||||
}, 'Rewriter.create() default values.');
|
||||
|
||||
promise_test(async () => {
|
||||
const sharedContext = 'This is a shared context string';
|
||||
const rewriter = await createRewriter({sharedContext: sharedContext});
|
||||
assert_equals(rewriter.sharedContext, sharedContext);
|
||||
}, 'Rewriter.sharedContext');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({tone: 'more-formal'});
|
||||
assert_equals(rewriter.tone, 'more-formal');
|
||||
}, 'Creating a Rewriter with "more-formal" tone');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({tone: 'more-casual'});
|
||||
assert_equals(rewriter.tone, 'more-casual');
|
||||
}, 'Creating a Rewriter with "more-casual" tone');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({format: 'plain-text'});
|
||||
assert_equals(rewriter.format, 'plain-text');
|
||||
}, 'Creating a Rewriter with "plain-text" format');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({format: 'markdown'});
|
||||
assert_equals(rewriter.format, 'markdown');
|
||||
}, 'Creating a Rewriter with "markdown" format');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({length: 'shorter'});
|
||||
assert_equals(rewriter.length, 'shorter');
|
||||
}, 'Creating a Rewriter with "shorter" length');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({length: 'longer'});
|
||||
assert_equals(rewriter.length, 'longer');
|
||||
}, 'Creating a Rewriter with "longer" length');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({expectedInputLanguages: ['en']});
|
||||
assert_array_equals(rewriter.expectedInputLanguages, ['en']);
|
||||
}, 'Creating a Rewriter with expectedInputLanguages');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({expectedContextLanguages: ['en']});
|
||||
assert_array_equals(rewriter.expectedContextLanguages, ['en']);
|
||||
}, 'Creating a Rewriter with expectedContextLanguages');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({outputLanguage: 'en'});
|
||||
assert_equals(rewriter.outputLanguage, 'en');
|
||||
}, 'Creating a Rewriter with outputLanguage');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter({});
|
||||
assert_equals(rewriter.expectedInputLanguages, null);
|
||||
assert_equals(rewriter.expectedContextLanguages, null);
|
||||
assert_equals(rewriter.outputLanguage, null);
|
||||
}, 'Creating a Rewriter without optional attributes');
|
||||
|
||||
promise_test(
|
||||
async (t) => {
|
||||
const rewriter = await createRewriter();
|
||||
let result = await rewriter.rewrite('');
|
||||
assert_equals(result, '');
|
||||
result = await rewriter.rewrite(' ');
|
||||
assert_equals(result, ' ');
|
||||
},
|
||||
'Rewriter.rewrite() with an empty input or whitespace returns the ' +
|
||||
'original input');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const rewriter = await createRewriter();
|
||||
const result = await rewriter.rewrite('hello', {context: ' '});
|
||||
assert_not_equals(result, '');
|
||||
}, 'Rewriter.rewrite() with a whitespace context returns a non-empty result');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const rewriter = await createRewriter();
|
||||
rewriter.destroy();
|
||||
await promise_rejects_dom(t, 'InvalidStateError', rewriter.rewrite('hello'));
|
||||
}, 'Rewriter.rewrite() fails after destroyed');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const rewriter = await createRewriter();
|
||||
rewriter.destroy();
|
||||
assert_throws_dom(
|
||||
'InvalidStateError', () => rewriter.rewriteStreaming('hello'));
|
||||
}, 'Rewriter.rewriteStreaming() fails after destroyed');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
const result = await rewriter.measureInputUsage(kTestPrompt);
|
||||
assert_greater_than(result, 0);
|
||||
}, 'Rewriter.measureInputUsage() returns non-empty result');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
const result = await rewriter.rewrite(kTestPrompt, {context: kTestContext});
|
||||
assert_equals(typeof result, 'string');
|
||||
}, 'Simple Rewriter.rewrite() call');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
const streamingResponse =
|
||||
rewriter.rewriteStreaming(kTestPrompt, {context: kTestContext});
|
||||
assert_equals(
|
||||
Object.prototype.toString.call(streamingResponse),
|
||||
'[object ReadableStream]');
|
||||
let result = '';
|
||||
for await (const chunk of streamingResponse) {
|
||||
result += chunk;
|
||||
}
|
||||
assert_greater_than(result.length, 0);
|
||||
}, 'Simple Rewriter.rewriteStreaming() call');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
await Promise.all(
|
||||
[rewriter.rewrite(kTestPrompt), rewriter.rewrite(kTestPrompt)]);
|
||||
}, 'Multiple Rewriter.rewrite() calls are resolved successfully.');
|
||||
|
||||
promise_test(async () => {
|
||||
const rewriter = await createRewriter();
|
||||
await Promise.all([
|
||||
rewriter.rewriteStreaming(kTestPrompt),
|
||||
rewriter.rewriteStreaming(kTestPrompt)
|
||||
]);
|
||||
}, 'Multiple Rewriter.rewriteStreaming() calls are resolved successfully.');
|
|
@ -1,6 +1,7 @@
|
|||
// META: title=Summarizer Abort
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
|
@ -11,15 +12,24 @@ promise_test(async t => {
|
|||
}, 'Aborting Summarizer.create().');
|
||||
|
||||
promise_test(async t => {
|
||||
const session = await createSummarizer();
|
||||
const summarizer = await createSummarizer();
|
||||
await testAbortPromise(t, signal => {
|
||||
return session.summarize(kTestPrompt, { signal: signal });
|
||||
return summarizer.summarize(kTestPrompt, { signal: signal });
|
||||
});
|
||||
}, 'Aborting Summarizer.summarize().');
|
||||
}, 'Aborting Summarizer.summarize()');
|
||||
|
||||
promise_test(async t => {
|
||||
const session = await createSummarizer();
|
||||
const summarizer = await createSummarizer();
|
||||
await testAbortReadableStream(t, signal => {
|
||||
return session.summarizeStreaming(kTestPrompt, { signal: signal });
|
||||
return summarizer.summarizeStreaming(kTestPrompt, { signal: signal });
|
||||
});
|
||||
}, 'Aborting Summarizer.summarizeStreaming().');
|
||||
}, 'Aborting Summarizer.summarizeStreaming()');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const summarizer = await createSummarizer();
|
||||
const controller = new AbortController();
|
||||
const streamingResponse = summarizer.summarizeStreaming(
|
||||
kTestPrompt, { signal: controller.signal });
|
||||
for await (const chunk of streamingResponse); // Do nothing
|
||||
controller.abort();
|
||||
}, 'Aborting Summarizer.summarizeStreaming() after finished reading');
|
||||
|
|
|
@ -12,7 +12,7 @@ promise_test(async () => {
|
|||
|
||||
promise_test(async () => {
|
||||
const availability = await Summarizer.availability({
|
||||
type: 'tl;dr',
|
||||
type: 'tldr',
|
||||
format: 'plain-text',
|
||||
length: 'medium',
|
||||
expectedInputLanguages: ['en-GB'],
|
||||
|
@ -24,7 +24,7 @@ promise_test(async () => {
|
|||
|
||||
promise_test(async () => {
|
||||
const availability = await Summarizer.availability({
|
||||
type: 'tl;dr',
|
||||
type: 'tldr',
|
||||
format: 'plain-text',
|
||||
length: 'medium',
|
||||
expectedInputLanguages: ['es'], // not supported
|
||||
|
|
|
@ -18,7 +18,7 @@ promise_test(async () => {
|
|||
promise_test(async () => {
|
||||
// An array of plausible test option values.
|
||||
const kCreateOptionsSpec = [
|
||||
{type: [undefined, 'tl;dr', 'teaser', 'key-points', 'headline']},
|
||||
{type: [undefined, 'tldr', 'teaser', 'key-points', 'headline']},
|
||||
{format: [undefined, 'plain-text', 'markdown']},
|
||||
{length: [undefined, 'short', 'medium', 'long']},
|
||||
{expectedInputLanguages: [[], ['en'], ['es'], ['jp', 'fr']]},
|
||||
|
|
|
@ -36,7 +36,7 @@ promise_test(async () => {
|
|||
|
||||
promise_test(async t => {
|
||||
await testCreateMonitorWithAbort(t, Summarizer.create);
|
||||
}, 'Progress events are not emitted after aborted.');
|
||||
}, 'Progress events are not emitted after aborted');
|
||||
|
||||
promise_test(async () => {
|
||||
const sharedContext = 'This is a shared context string';
|
||||
|
@ -74,6 +74,12 @@ promise_test(async () => {
|
|||
assert_equals(summarizer.outputLanguage, 'en');
|
||||
}, 'Summarizer.outputLanguage');
|
||||
|
||||
promise_test(async (t) => {
|
||||
promise_rejects_js(
|
||||
t, RangeError,
|
||||
createSummarizer({ expectedInputLanguages: ['en-abc-invalid'] }));
|
||||
}, 'Creating Summarizer with malformed language string');
|
||||
|
||||
promise_test(async () => {
|
||||
const summarizer = await createSummarizer();
|
||||
assert_equals(summarizer.expectedInputLanguages, null);
|
||||
|
|
|
@ -22,4 +22,4 @@ promise_test(async t => {
|
|||
|
||||
// Now that it is available, we should no longer need user activation.
|
||||
await Summarizer.create();
|
||||
}, 'Summarizer.create() requires user activation when availability is "downloadable."');
|
||||
}, 'Summarizer.create() requires user activation when availability is "downloadable"');
|
||||
|
|
57
tests/wpt/tests/ai/summarizer/summarizer-from-detached-iframe.tentative.https.window.js
vendored
Normal file
57
tests/wpt/tests/ai/summarizer/summarizer-from-detached-iframe.tentative.https.window.js
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
// META: title=Summarizer Detached Iframe
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async (t) => {
|
||||
const iframe = document.body.appendChild(document.createElement('iframe'));
|
||||
await test_driver.bless('Summarizer create()', null, iframe.contentWindow);
|
||||
iframe.contentWindow.Summarizer.create();
|
||||
iframe.remove();
|
||||
}, 'Detaching iframe during Summarizer.create() should not leak memory');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const iframe = document.body.appendChild(document.createElement('iframe'));
|
||||
await test_driver.bless('Summarizer create()', null, iframe.contentWindow);
|
||||
const iframeWindow = iframe.contentWindow;
|
||||
const iframeDOMException = iframeWindow.DOMException;
|
||||
const iframeSummarizer = iframeWindow.Summarizer;
|
||||
iframe.remove();
|
||||
|
||||
await promise_rejects_dom(
|
||||
t, 'InvalidStateError', iframeDOMException, iframeSummarizer.create());
|
||||
}, 'Summarizer.create() fails on a detached iframe');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const iframe = document.body.appendChild(document.createElement('iframe'));
|
||||
await test_driver.bless('Summarizer create()', null, iframe.contentWindow);
|
||||
const iframeDOMException = iframe.contentWindow.DOMException;
|
||||
const summarizer = await iframe.contentWindow.Summarizer.create();
|
||||
iframe.remove();
|
||||
|
||||
await promise_rejects_dom(
|
||||
t, 'InvalidStateError', iframeDOMException, summarizer.summarize(kTestPrompt));
|
||||
}, 'Summarizer.summarize() fails on a detached iframe');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const iframe = document.body.appendChild(document.createElement('iframe'));
|
||||
await test_driver.bless('Summarizer create()', null, iframe.contentWindow);
|
||||
const iframeWindow = iframe.contentWindow;
|
||||
const iframeDOMException = iframeWindow.DOMException;
|
||||
const summarizer = await iframeWindow.Summarizer.create();
|
||||
iframe.remove();
|
||||
|
||||
assert_throws_dom(
|
||||
'InvalidStateError',
|
||||
iframeDOMException, () => summarizer.summarizeStreaming(kTestPrompt));
|
||||
}, 'Summarizer.summarizeStreaming() fails on a detached iframe');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const iframe = document.body.appendChild(document.createElement('iframe'));
|
||||
await test_driver.bless('Summarizer create()', null, iframe.contentWindow);
|
||||
const summarizer = await iframe.contentWindow.Summarizer.create();
|
||||
summarizer.summarize(kTestPrompt);
|
||||
iframe.remove();
|
||||
}, 'Detaching iframe during Summarizer.summarize() should not leak memory');
|
|
@ -7,34 +7,34 @@
|
|||
|
||||
promise_test(async t => {
|
||||
const summarizer = await createSummarizer();
|
||||
const streamingResponse = summarizer.summarizeStreaming(
|
||||
"The web-platform-tests Project is a cross-browser test suite for the Web-platform stack. Writing tests in a way that allows them to be run in all browsers gives browser projects confidence that they are shipping software that is compatible with other implementations, and that later implementations will be compatible with their implementations. This in turn gives Web authors/developers confidence that they can actually rely on the Web platform to deliver on the promise of working across browsers and devices without needing extra layers of abstraction to paper over the gaps left by specification editors and implementors.");
|
||||
const streamingResponse = summarizer.summarizeStreaming(kTestPrompt);
|
||||
assert_equals(
|
||||
Object.prototype.toString.call(streamingResponse),
|
||||
"[object ReadableStream]"
|
||||
);
|
||||
const reader = streamingResponse.getReader();
|
||||
let result = "";
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
result += value;
|
||||
let result = '';
|
||||
for await (const chunk of streamingResponse) {
|
||||
result += chunk;
|
||||
}
|
||||
assert_greater_than(result.length, 0);
|
||||
}, 'Summarizer.summarizeStreaming() returns ReadableStream with a non-empty text.');
|
||||
}, 'Simple Summarizer.summarizeStreaming() call');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const summarizer = await createSummarizer();
|
||||
summarizer.destroy();
|
||||
assert_throws_dom('InvalidStateError', () => summarizer.summarizeStreaming(kTestPrompt));
|
||||
}, 'Summarizer.summarizeStreaming() fails after destroyed');
|
||||
|
||||
promise_test(async t => {
|
||||
const summarizer = await createSummarizer();
|
||||
const streamingResponse = summarizer.summarizeStreaming("");
|
||||
const streamingResponse = summarizer.summarizeStreaming('');
|
||||
assert_equals(
|
||||
Object.prototype.toString.call(streamingResponse),
|
||||
"[object ReadableStream]"
|
||||
);
|
||||
const { result, done } = await streamingResponse.getReader().read();
|
||||
assert_true(done);
|
||||
}, 'Summarizer.summarizeStreaming() returns a ReadableStream without any chunk on an empty input.');
|
||||
}, 'Summarizer.summarizeStreaming() returns a ReadableStream without any chunk on an empty input');
|
||||
|
||||
promise_test(async () => {
|
||||
const summarizer = await createSummarizer();
|
||||
|
@ -42,4 +42,4 @@ promise_test(async () => {
|
|||
summarizer.summarizeStreaming(kTestPrompt),
|
||||
summarizer.summarizeStreaming(kTestPrompt)
|
||||
]);
|
||||
}, 'Multiple Summarizer.summarizeStreaming() calls are resolved successfully.');
|
||||
}, 'Multiple Summarizer.summarizeStreaming() calls are resolved successfully');
|
||||
|
|
|
@ -1,16 +1,36 @@
|
|||
// META: title=Summarizer Create Available
|
||||
// META: title=Summarizer Summarize
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async (t) => {
|
||||
const summarizer = await createSummarizer();
|
||||
let result = await summarizer.summarize('');
|
||||
assert_equals(result, '');
|
||||
result = await summarizer.summarize(' ');
|
||||
assert_equals(result, '');
|
||||
}, 'Summarizer.summarize() with an empty input returns an empty text');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const summarizer = await createSummarizer();
|
||||
const result = await summarizer.summarize(kTestPrompt, { context: ' ' });
|
||||
assert_not_equals(result, '');
|
||||
}, 'Summarizer.summarize() with a whitespace context returns an empty result');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const summarizer = await createSummarizer();
|
||||
summarizer.destroy();
|
||||
await promise_rejects_dom(t, 'InvalidStateError', summarizer.summarize(kTestPrompt));
|
||||
}, 'Summarizer.summarize() fails after destroyed');
|
||||
|
||||
promise_test(async () => {
|
||||
const summarizer = await createSummarizer();
|
||||
const result = await summarizer.summarize(kTestPrompt);
|
||||
assert_equals(typeof result, 'string');
|
||||
assert_greater_than(result.length, 0);
|
||||
}, 'Summarizer.summarize() returns non-empty result.');
|
||||
}, 'Simple Summarizer.summarize() call');
|
||||
|
||||
promise_test(async () => {
|
||||
const summarizer = await createSummarizer();
|
||||
|
@ -18,4 +38,4 @@ promise_test(async () => {
|
|||
summarizer.summarize(kTestPrompt),
|
||||
summarizer.summarize(kTestPrompt)
|
||||
]);
|
||||
}, 'Multiple Summarizer.summarize() calls are resolved successfully.');
|
||||
}, 'Multiple Summarizer.summarize() calls are resolved successfully');
|
||||
|
|
50
tests/wpt/tests/ai/translator/translator-locale.https.window.js
vendored
Normal file
50
tests/wpt/tests/ai/translator/translator-locale.https.window.js
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
// META: title=Detect english
|
||||
// META: global=window
|
||||
// META: timeout=long
|
||||
// META: script=resources/util.js
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: script=../resources/locale-util.js
|
||||
|
||||
'use strict';
|
||||
|
||||
function assert_rejects_invalid_expected_input_languages(
|
||||
t, method, sourceLanguage, targetLanguage) {
|
||||
return promise_rejects_js(
|
||||
t, RangeError, method({sourceLanguage, targetLanguage}));
|
||||
}
|
||||
|
||||
function testInvalidLanguagePairs(t, method) {
|
||||
const allValidLanguageTags = Object.values(valid_language_tags).flat();
|
||||
// Invalid source language.
|
||||
for (const sourceLanguage of invalid_language_tags) {
|
||||
for (const targetLanguage of allValidLanguageTags) {
|
||||
assert_rejects_invalid_expected_input_languages(
|
||||
t, method, sourceLanguage, targetLanguage);
|
||||
}
|
||||
}
|
||||
// Invalid target language.
|
||||
for (const sourceLanguage of allValidLanguageTags) {
|
||||
for (const targetLanguage of invalid_language_tags) {
|
||||
assert_rejects_invalid_expected_input_languages(
|
||||
t, method, sourceLanguage, targetLanguage);
|
||||
}
|
||||
}
|
||||
// Invalid source and target language
|
||||
for (const sourceLanguage of invalid_language_tags) {
|
||||
for (const targetLanguage of invalid_language_tags) {
|
||||
assert_rejects_invalid_expected_input_languages(
|
||||
t, method, sourceLanguage, targetLanguage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
promise_test(async t => {
|
||||
// We don't need to consume user activation since it should throw a RangeError
|
||||
// before it even can check if it needs to consume user activation.
|
||||
testInvalidLanguagePairs(t, Translator.create);
|
||||
}, 'LanguageDetector.create() throws RangeError for invalid language tags');
|
||||
|
||||
promise_test(async t => {
|
||||
testInvalidLanguagePairs(t, Translator.availability);
|
||||
}, 'LanguageDetector.availability() throws RangeError for invalid language tags');
|
|
@ -9,29 +9,27 @@ promise_test(async t => {
|
|||
await testAbortPromise(t, signal => {
|
||||
return createWriter({signal: signal});
|
||||
});
|
||||
}, 'Aborting Writer.create().');
|
||||
}, 'Aborting Writer.create()');
|
||||
|
||||
promise_test(async t => {
|
||||
const writer = await createWriter();
|
||||
await testAbortPromise(t, signal => {
|
||||
return writer.write(kTestPrompt, { signal: signal });
|
||||
});
|
||||
}, 'Aborting Writer.write().');
|
||||
}, 'Aborting Writer.write()');
|
||||
|
||||
promise_test(async t => {
|
||||
const writer = await createWriter();
|
||||
await testAbortReadableStream(t, signal => {
|
||||
return writer.writeStreaming(kTestPrompt, { signal: signal });
|
||||
});
|
||||
}, 'Aborting Writer.writeStreaming().');
|
||||
}, 'Aborting Writer.writeStreaming()');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const writer = await createWriter();
|
||||
const controller = new AbortController();
|
||||
const streamingResponse = writer.writeStreaming(kTestPrompt, {
|
||||
signal: controller.signal,
|
||||
context: kTestContext,
|
||||
});
|
||||
const streamingResponse = writer.writeStreaming(
|
||||
kTestPrompt, { signal: controller.signal });
|
||||
for await (const chunk of streamingResponse); // Do nothing
|
||||
controller.abort();
|
||||
}, 'Aborting Writer.writeStreaming() after finished reading.');
|
||||
}, 'Aborting Writer.writeStreaming() after finished reading');
|
||||
|
|
97
tests/wpt/tests/ai/writer/writer-create-available.tentative.https.window.js
vendored
Normal file
97
tests/wpt/tests/ai/writer/writer-create-available.tentative.https.window.js
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
// META: title=Writer Create Available
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
assert_equals(typeof writer, 'object');
|
||||
|
||||
assert_equals(typeof writer.write, 'function');
|
||||
assert_equals(typeof writer.writeStreaming, 'function');
|
||||
assert_equals(typeof writer.measureInputUsage, 'function');
|
||||
assert_equals(typeof writer.destroy, 'function');
|
||||
|
||||
assert_equals(typeof writer.expectedContextLanguages, 'object');
|
||||
assert_equals(typeof writer.expectedInputLanguages, 'object');
|
||||
assert_equals(typeof writer.inputQuota, 'number');
|
||||
assert_equals(typeof writer.outputLanguage, 'object');
|
||||
assert_equals(typeof writer.sharedContext, 'string');
|
||||
|
||||
assert_equals(typeof writer.tone, 'string');
|
||||
assert_equals(typeof writer.format, 'string');
|
||||
assert_equals(typeof writer.length, 'string');
|
||||
|
||||
assert_equals(writer.tone, 'neutral');
|
||||
assert_equals(writer.format, 'plain-text');
|
||||
assert_equals(writer.length, 'medium');
|
||||
}, 'Writer.create() returns a valid object with default options');
|
||||
|
||||
promise_test(async () => {
|
||||
await testMonitor(createWriter);
|
||||
}, 'Writer.create() notifies its monitor on downloadprogress');
|
||||
|
||||
promise_test(async t => {
|
||||
await testCreateMonitorWithAbort(t, Writer.create);
|
||||
}, 'Progress events are not emitted after aborted');
|
||||
|
||||
promise_test(async () => {
|
||||
const sharedContext = 'This is a shared context string';
|
||||
const writer = await createWriter({sharedContext: sharedContext});
|
||||
assert_equals(writer.sharedContext, sharedContext);
|
||||
}, 'Writer.sharedContext');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({tone: 'formal'});
|
||||
assert_equals(writer.tone, 'formal');
|
||||
}, 'Creating a Writer with "formal" tone');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({tone: 'casual'});
|
||||
assert_equals(writer.tone, 'casual');
|
||||
}, 'Creating a Writer with "casual" tone');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({format: 'markdown'});
|
||||
assert_equals(writer.format, 'markdown');
|
||||
}, 'Creating a Writer with "markdown" format');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({length: 'short'});
|
||||
assert_equals(writer.length, 'short');
|
||||
}, 'Creating a Writer with "short" length');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({length: 'long'});
|
||||
assert_equals(writer.length, 'long');
|
||||
}, 'Creating a Writer with "long" length');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({expectedInputLanguages: ['en']});
|
||||
assert_array_equals(writer.expectedInputLanguages, ['en']);
|
||||
}, 'Writer.expectedInputLanguages');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({expectedContextLanguages: ['en']});
|
||||
assert_array_equals(writer.expectedContextLanguages, ['en']);
|
||||
}, 'Writer.expectedContextLanguages');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({outputLanguage: 'en'});
|
||||
assert_equals(writer.outputLanguage, 'en');
|
||||
}, 'Writer.outputLanguage');
|
||||
|
||||
promise_test(async (t) => {
|
||||
promise_rejects_js(
|
||||
t, RangeError,
|
||||
createWriter({ expectedInputLanguages: ['en-abc-invalid'] }));
|
||||
}, 'Creating Writer with malformed language string');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({});
|
||||
assert_equals(writer.expectedInputLanguages, null);
|
||||
assert_equals(writer.expectedContextLanguages, null);
|
||||
assert_equals(writer.outputLanguage, null);
|
||||
}, 'Writer optional attributes return null');
|
24
tests/wpt/tests/ai/writer/writer-create.tentative.https.window.js
vendored
Normal file
24
tests/wpt/tests/ai/writer/writer-create.tentative.https.window.js
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
// META: title=Writer Create
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
assert_true(!!Writer);
|
||||
}, 'Writer must be defined.');
|
||||
|
||||
promise_test(async t => {
|
||||
// Creating Writer without user activation rejects with NotAllowedError.
|
||||
await promise_rejects_dom(t, 'NotAllowedError', Writer.create());
|
||||
|
||||
// Creating Writer with user activation succeeds.
|
||||
await createWriter();
|
||||
|
||||
// Expect available after create.
|
||||
assert_equals(await Writer.availability(), 'available');
|
||||
|
||||
// Now that it is available, we should no longer need user activation.
|
||||
await Writer.create();
|
||||
}, 'Writer.create() requires user activation when availability is "downloadable"');
|
|
@ -22,7 +22,7 @@ promise_test(async (t) => {
|
|||
|
||||
await promise_rejects_dom(
|
||||
t, 'InvalidStateError', iframeDOMException, iframeWriter.create());
|
||||
}, 'Writer.create() fails on a detached iframe.');
|
||||
}, 'Writer.create() fails on a detached iframe');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const iframe = document.body.appendChild(document.createElement('iframe'));
|
||||
|
@ -32,8 +32,8 @@ promise_test(async (t) => {
|
|||
iframe.remove();
|
||||
|
||||
await promise_rejects_dom(
|
||||
t, 'InvalidStateError', iframeDOMException, writer.write('hello'));
|
||||
}, 'Writer.write() fails on a detached iframe.');
|
||||
t, 'InvalidStateError', iframeDOMException, writer.write(kTestPrompt));
|
||||
}, 'Writer.write() fails on a detached iframe');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const iframe = document.body.appendChild(document.createElement('iframe'));
|
||||
|
@ -44,13 +44,14 @@ promise_test(async (t) => {
|
|||
iframe.remove();
|
||||
|
||||
assert_throws_dom(
|
||||
'InvalidStateError', iframeDOMException, () => writer.writeStreaming('hello'));
|
||||
}, 'Writer.writeStreaming() fails on a detached iframe.');
|
||||
'InvalidStateError',
|
||||
iframeDOMException, () => writer.writeStreaming(kTestPrompt));
|
||||
}, 'Writer.writeStreaming() fails on a detached iframe');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const iframe = document.body.appendChild(document.createElement('iframe'));
|
||||
await test_driver.bless('Writer create()', null, iframe.contentWindow);
|
||||
const writer = await iframe.contentWindow.Writer.create();
|
||||
writer.write('hello');
|
||||
writer.write(kTestPrompt);
|
||||
iframe.remove();
|
||||
}, 'Detaching iframe during Writer.write() should not leak memory');
|
||||
|
|
12
tests/wpt/tests/ai/writer/writer-measureInputUsage.tentative.https.window.js
vendored
Normal file
12
tests/wpt/tests/ai/writer/writer-measureInputUsage.tentative.https.window.js
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
// META: title=Writer measureInputUsage
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
const result = await writer.measureInputUsage(kTestPrompt);
|
||||
assert_greater_than(result, 0);
|
||||
}, 'Writer.measureInputUsage() returns non-empty result');
|
45
tests/wpt/tests/ai/writer/writer-write-streaming.tentative.https.window.js
vendored
Normal file
45
tests/wpt/tests/ai/writer/writer-write-streaming.tentative.https.window.js
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
// META: title=Writer Write Streaming
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
const streamingResponse =
|
||||
writer.writeStreaming(kTestPrompt, { context: kTestContext });
|
||||
assert_equals(
|
||||
Object.prototype.toString.call(streamingResponse),
|
||||
'[object ReadableStream]');
|
||||
let result = '';
|
||||
for await (const chunk of streamingResponse) {
|
||||
result += chunk;
|
||||
}
|
||||
assert_greater_than(result.length, 0);
|
||||
}, 'Simple Writer.writeStreaming() call');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const writer = await createWriter();
|
||||
writer.destroy();
|
||||
assert_throws_dom('InvalidStateError', () => writer.writeStreaming(kTestPrompt));
|
||||
}, 'Writer.writeStreaming() fails after destroyed');
|
||||
|
||||
promise_test(async t => {
|
||||
const writer = await createWriter();
|
||||
const streamingResponse = writer.writeStreaming('');
|
||||
assert_equals(
|
||||
Object.prototype.toString.call(streamingResponse),
|
||||
"[object ReadableStream]"
|
||||
);
|
||||
const { result, done } = await streamingResponse.getReader().read();
|
||||
assert_true(done);
|
||||
}, 'Writer.writeStreaming() returns a ReadableStream without any chunk on an empty input');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
await Promise.all([
|
||||
writer.writeStreaming(kTestPrompt),
|
||||
writer.writeStreaming(kTestPrompt)
|
||||
]);
|
||||
}, 'Multiple Writer.writeStreaming() calls are resolved successfully');
|
41
tests/wpt/tests/ai/writer/writer-write.tentative.https.window.js
vendored
Normal file
41
tests/wpt/tests/ai/writer/writer-write.tentative.https.window.js
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
// META: title=Writer Write
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async (t) => {
|
||||
const writer = await createWriter();
|
||||
let result = await writer.write('');
|
||||
assert_equals(result, '');
|
||||
}, 'Writer.write() with an empty input returns an empty text');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const writer = await createWriter();
|
||||
let result = await writer.write(' ');
|
||||
assert_equals(result, '');
|
||||
}, 'Writer.write() with a whitespace input returns an empty text');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const writer = await createWriter();
|
||||
const result = await writer.write(kTestPrompt, { context: ' ' });
|
||||
assert_not_equals(result, '');
|
||||
}, 'Writer.write() with a whitespace context returns a non-empty result');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const writer = await createWriter();
|
||||
writer.destroy();
|
||||
await promise_rejects_dom(t, 'InvalidStateError', writer.write(kTestPrompt));
|
||||
}, 'Writer.write() fails after destroyed');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
const result = await writer.write(kTestPrompt, {context: kTestContext});
|
||||
assert_equals(typeof result, 'string');
|
||||
}, 'Simple Writer.write() call');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
await Promise.all([writer.write(kTestPrompt), writer.write(kTestPrompt)]);
|
||||
}, 'Multiple Writer.write() calls are resolved successfully');
|
|
@ -1,175 +0,0 @@
|
|||
// META: title=Writer
|
||||
// META: script=/resources/testdriver.js
|
||||
// META: script=../resources/util.js
|
||||
// META: timeout=long
|
||||
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
assert_true(!!Writer);
|
||||
}, 'Writer must be defined.');
|
||||
|
||||
promise_test(async t => {
|
||||
// Creating Writer without user activation rejects with NotAllowedError.
|
||||
await promise_rejects_dom(t, 'NotAllowedError', Writer.create());
|
||||
|
||||
// Creating Writer with user activation succeeds.
|
||||
await createWriter();
|
||||
|
||||
// Expect available after create.
|
||||
assert_equals(await Writer.availability(), 'available');
|
||||
|
||||
// Now that it is available, we should no longer need user activation.
|
||||
await Writer.create();
|
||||
}, 'Writer.create() requires user activation when availability is "downloadable."');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
assert_equals(Object.prototype.toString.call(writer), '[object Writer]');
|
||||
}, 'Writer.create() must be return a Writer.');
|
||||
|
||||
promise_test(async () => {
|
||||
await testMonitor(createWriter);
|
||||
}, 'Writer.create() notifies its monitor on downloadprogress');
|
||||
|
||||
promise_test(async t => {
|
||||
await testCreateMonitorWithAbort(t, Writer.create);
|
||||
}, 'Progress events are not emitted after aborted.');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
assert_equals(writer.sharedContext, '');
|
||||
assert_equals(writer.tone, 'neutral');
|
||||
assert_equals(writer.format, 'plain-text');
|
||||
assert_equals(writer.length, 'medium');
|
||||
}, 'Writer.create() default values.');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const controller = new AbortController();
|
||||
controller.abort();
|
||||
const createPromise = createWriter({signal: controller.signal});
|
||||
await promise_rejects_dom(t, 'AbortError', createPromise);
|
||||
}, 'Writer.create() call with an aborted signal.');
|
||||
|
||||
promise_test(async () => {
|
||||
const sharedContext = 'This is a shared context string';
|
||||
const writer = await createWriter({sharedContext: sharedContext});
|
||||
assert_equals(writer.sharedContext, sharedContext);
|
||||
}, 'Writer.sharedContext');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({tone: 'formal'});
|
||||
assert_equals(writer.tone, 'formal');
|
||||
}, 'Creating a Writer with "formal" tone');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({tone: 'casual'});
|
||||
assert_equals(writer.tone, 'casual');
|
||||
}, 'Creating a Writer with "casual" tone');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({format: 'markdown'});
|
||||
assert_equals(writer.format, 'markdown');
|
||||
}, 'Creating a Writer with "markdown" format');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({length: 'short'});
|
||||
assert_equals(writer.length, 'short');
|
||||
}, 'Creating a Writer with "short" length');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({length: 'long'});
|
||||
assert_equals(writer.length, 'long');
|
||||
}, 'Creating a Writer with "long" length');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({expectedInputLanguages: ['en']});
|
||||
assert_array_equals(writer.expectedInputLanguages, ['en']);
|
||||
}, 'Creating a Writer with expectedInputLanguages');
|
||||
|
||||
|
||||
promise_test(async (t) => {
|
||||
promise_rejects_js(
|
||||
t, RangeError,
|
||||
createWriter({expectedInputLanguages: ['en-abc-invalid']}));
|
||||
}, 'Creating a Writer with malformed language string');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({expectedContextLanguages: ['en']});
|
||||
assert_array_equals(writer.expectedContextLanguages, ['en']);
|
||||
}, 'Creating a Writer with expectedContextLanguages');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({outputLanguage: 'en'});
|
||||
assert_equals(writer.outputLanguage, 'en');
|
||||
}, 'Creating a Writer with outputLanguage');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter({});
|
||||
assert_equals(writer.expectedInputLanguages, null);
|
||||
assert_equals(writer.expectedContextLanguages, null);
|
||||
assert_equals(writer.outputLanguage, null);
|
||||
}, 'Creating a Writer without optional attributes');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const writer = await createWriter();
|
||||
let result = await writer.write('');
|
||||
assert_equals(result, '');
|
||||
result = await writer.write(' ');
|
||||
assert_equals(result, '');
|
||||
}, 'Writer.write() with an empty input or whitespace returns an empty text');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const writer = await createWriter();
|
||||
const result = await writer.write('hello', {context: ' '});
|
||||
assert_not_equals(result, '');
|
||||
}, 'Writer.write() with a whitespace context returns a non-empty result');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const writer = await createWriter();
|
||||
writer.destroy();
|
||||
await promise_rejects_dom(t, 'InvalidStateError', writer.write('hello'));
|
||||
}, 'Writer.write() fails after destroyed');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const writer = await createWriter();
|
||||
writer.destroy();
|
||||
assert_throws_dom('InvalidStateError', () => writer.writeStreaming('hello'));
|
||||
}, 'Writer.writeStreaming() fails after destroyed');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
const result = await writer.measureInputUsage(kTestPrompt);
|
||||
assert_greater_than(result, 0);
|
||||
}, 'Writer.measureInputUsage() returns non-empty result');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
const result = await writer.write(kTestPrompt, {context: kTestContext});
|
||||
assert_equals(typeof result, 'string');
|
||||
}, 'Simple Writer.write() call');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
const streamingResponse =
|
||||
writer.writeStreaming(kTestPrompt, {context: kTestContext});
|
||||
assert_equals(
|
||||
Object.prototype.toString.call(streamingResponse),
|
||||
'[object ReadableStream]');
|
||||
let result = '';
|
||||
for await (const chunk of streamingResponse) {
|
||||
result += chunk;
|
||||
}
|
||||
assert_greater_than(result.length, 0);
|
||||
}, 'Simple Writer.writeStreaming() call');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
await Promise.all([writer.write(kTestPrompt), writer.write(kTestPrompt)]);
|
||||
}, 'Multiple Writer.write() calls are resolved successfully.');
|
||||
|
||||
promise_test(async () => {
|
||||
const writer = await createWriter();
|
||||
await Promise.all(
|
||||
[writer.writeStreaming(kTestPrompt), writer.writeStreaming(kTestPrompt)]);
|
||||
}, 'Multiple Writer.writeStreaming() calls are resolved successfully.');
|
|
@ -25,48 +25,79 @@
|
|||
});
|
||||
}
|
||||
|
||||
let typesToSet_ = ["text/html", "web txt/csv"];
|
||||
button.onclick = () => document.execCommand("copy");
|
||||
document.oncopy = (ev) => {
|
||||
ev.preventDefault();
|
||||
ev.clipboardData.setData("text/html", `<div>Test html</div>`);
|
||||
for (let i = 0; i < typesToSet_.length; i++) {
|
||||
const type = typesToSet_[i];
|
||||
const data = new Blob([`Test data for ${type}`], {type: type});
|
||||
ev.clipboardData.setData(type, data);
|
||||
}
|
||||
};
|
||||
|
||||
function triggerCopyToClipboard() {
|
||||
function triggerCopyToClipboard(typesToSet) {
|
||||
if (typesToSet) {
|
||||
typesToSet_ = typesToSet;
|
||||
}
|
||||
return test_driver.click(button);
|
||||
}
|
||||
|
||||
promise_test(async (test) => {
|
||||
let clipboardChangeEventCount = 0;
|
||||
let eventType = "";
|
||||
let capturedEventTypes = null;
|
||||
navigator.clipboard.addEventListener("clipboardchange", (ev) => {
|
||||
clipboardChangeEventCount++;
|
||||
eventType = ev.type;
|
||||
capturedEventTypes = ev.types;
|
||||
});
|
||||
await triggerCopyToClipboard();
|
||||
assert_equals(clipboardChangeEventCount, 1, "clipboardchange event should be called exactly once");
|
||||
assert_equals(eventType, "clipboardchange", "Event type should be 'clipboardchange'");
|
||||
assert_true(capturedEventTypes.includes("text/html"), "types should contain 'text/html'");
|
||||
assert_false(capturedEventTypes.includes("web txt/csv"), "types should not contain custom MIME type");
|
||||
}, "clipboardchange event is invoked");
|
||||
|
||||
promise_test(async (test) => {
|
||||
await tryGrantWritePermission();
|
||||
let clipboardChangeEventCount = 0;
|
||||
let capturedEventTypes = null;
|
||||
navigator.clipboard.addEventListener("clipboardchange", (ev) => {
|
||||
clipboardChangeEventCount++;
|
||||
capturedEventTypes = ev.types;
|
||||
});
|
||||
await navigator.clipboard.writeText("Test text");
|
||||
await waitForRender();
|
||||
assert_equals(clipboardChangeEventCount, 1, "clipboardchange event should be called exactly once");
|
||||
assert_true(capturedEventTypes.includes("text/plain"), "types should contain 'text/plain'");
|
||||
}, "clipboardchange event is invoked with async clipboard API");
|
||||
|
||||
promise_test(async (test) => {
|
||||
let onClipboardChangeAttributeCount = 0;
|
||||
navigator.clipboard.onclipboardchange = () => {
|
||||
let capturedEventTypes = null;
|
||||
navigator.clipboard.onclipboardchange = (ev) => {
|
||||
onClipboardChangeAttributeCount++;
|
||||
capturedEventTypes = ev.types;
|
||||
};
|
||||
await triggerCopyToClipboard();
|
||||
assert_equals(onClipboardChangeAttributeCount, 1, "onclipboardchange attribute should be called exactly once");
|
||||
assert_true(capturedEventTypes.includes("text/html"), "types should contain 'text/html'");
|
||||
assert_false(capturedEventTypes.includes("web txt/csv"), "types should not contain custom MIME type");
|
||||
}, "clipboardchange event is invoked using onclipboardchange attribute");
|
||||
|
||||
promise_test(async (test) => {
|
||||
let onClipboardChangeAttributeCount = 0;
|
||||
let capturedEventTypes = null;
|
||||
navigator.clipboard.onclipboardchange = (ev) => {
|
||||
onClipboardChangeAttributeCount++;
|
||||
capturedEventTypes = ev.types;
|
||||
};
|
||||
await triggerCopyToClipboard(["web txt/csv"]);
|
||||
assert_equals(onClipboardChangeAttributeCount, 1, "onclipboardchange attribute should be called exactly once");
|
||||
assert_equals(capturedEventTypes.length, 0, "clipboardchange event should have no types");
|
||||
}, "clipboardchange event is invoked even when only custom MIME types are set");
|
||||
|
||||
promise_test(async (test) => {
|
||||
let listenerCallCount = 0;
|
||||
function clipboardChangeListener() {
|
||||
|
@ -89,6 +120,55 @@
|
|||
assert_equals(listenerCallCount, 2, "Event listener should be called exactly once after re-adding");
|
||||
}, "clipboardchange event listener behavior when adding, removing, and re-adding");
|
||||
|
||||
promise_test(async (test) => {
|
||||
// https://w3c.github.io/clipboard-apis/#mandatory-data-types-x
|
||||
const standardTypes = [
|
||||
"text/plain",
|
||||
"text/html",
|
||||
"image/png",
|
||||
];
|
||||
const unsupportedTypes = [
|
||||
"web application/custom",
|
||||
"web web/proprietary",
|
||||
"web x-custom/type",
|
||||
"txt/json",
|
||||
"text/rtf",
|
||||
"image/svg+xml",
|
||||
"text/uri-list",
|
||||
];
|
||||
const allTypesToSet = [...standardTypes, ...unsupportedTypes];
|
||||
|
||||
let clipboardChangeEventCount = 0;
|
||||
let capturedEventTypes = null;
|
||||
|
||||
navigator.clipboard.addEventListener("clipboardchange", (ev) => {
|
||||
clipboardChangeEventCount++;
|
||||
capturedEventTypes = ev.types;
|
||||
});
|
||||
|
||||
await triggerCopyToClipboard(allTypesToSet);
|
||||
|
||||
assert_true(clipboardChangeEventCount == 1, "clipboardchange event should be invoked once");
|
||||
|
||||
// Check that types is a frozen array
|
||||
assert_true(Array.isArray(capturedEventTypes), "types should be an array");
|
||||
assert_true(Object.isFrozen(capturedEventTypes), "types should be frozen");
|
||||
|
||||
// Verify all standard types are included
|
||||
for (const type of standardTypes) {
|
||||
assert_true(capturedEventTypes.includes(type), `types should contain standard MIME type '${type}'`);
|
||||
}
|
||||
|
||||
// Verify custom types are filtered out
|
||||
for (const type of unsupportedTypes) {
|
||||
assert_false(capturedEventTypes.includes(type), `types should not contain custom MIME type '${type}'`);
|
||||
}
|
||||
|
||||
// Verify we have exactly the standard types and nothing else
|
||||
assert_equals(capturedEventTypes.length, standardTypes.length,
|
||||
"clipboardchange event types should contain exactly the standard MIME types");
|
||||
}, "clipboardchange event exposes all standard MIME types and filters non-standard ones");
|
||||
|
||||
promise_test(async (test) => {
|
||||
// Focus the document and acquire permission to write to the clipboard
|
||||
await test_driver.click(document.body);
|
||||
|
@ -97,6 +177,7 @@
|
|||
const iframe = document.getElementById('iframe');
|
||||
|
||||
let frameEventCount = 0;
|
||||
let capturedEventTypes = null;
|
||||
let focusEventFired = false;
|
||||
iframe.contentWindow.addEventListener("focus", () => {
|
||||
focusEventFired = true;
|
||||
|
@ -106,6 +187,7 @@
|
|||
iframe.contentWindow.navigator.clipboard.addEventListener("clipboardchange", () => {
|
||||
assert_true(focusEventFired, "focus event should fire before clipboardchange event");
|
||||
frameEventCount++;
|
||||
capturedEventTypes = event.types;
|
||||
});
|
||||
|
||||
// Ensure iFrame doesn't have the focus
|
||||
|
@ -114,7 +196,13 @@
|
|||
|
||||
// Trigger multiple clipboard changes
|
||||
await navigator.clipboard.writeText("Test text");
|
||||
await navigator.clipboard.writeText("Test text 2");
|
||||
|
||||
// Write HTML to clipboard to ensure the event captured only html and not txt
|
||||
await navigator.clipboard.write([
|
||||
new ClipboardItem({
|
||||
"text/html": new Blob(["<p>Test HTML</p>"], {type: "text/html"})
|
||||
})
|
||||
]);
|
||||
await waitForRender();
|
||||
|
||||
assert_equals(frameEventCount, 0, "iframe should not recieve any clipboardchange event yet");
|
||||
|
@ -122,6 +210,9 @@
|
|||
iframe.focus();
|
||||
assert_true(iframe.contentWindow.document.hasFocus(), "iFrame should have focus");
|
||||
assert_equals(frameEventCount, 1, "iframe should receive event only 1 event after focus");
|
||||
assert_equals(capturedEventTypes.length, 1, "clipboardchange event should only have one type");
|
||||
assert_true(capturedEventTypes.includes("text/html"), "clipboardchange event should only have text/html type");
|
||||
}, "clipboardchange event should only fire in the focused context");
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,4 +1,5 @@
|
|||
<!doctype html>
|
||||
<meta name="timeout" content="long">
|
||||
<link rel="author" href="mailto:wpt@keithcirkel.co.uk" />
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!doctype html>
|
||||
<meta name="timeout" content="long">
|
||||
<link rel="author" href="mailto:wpt@keithcirkel.co.uk" />
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!doctype html>
|
||||
<meta name="timeout" content="long">
|
||||
<link rel="author" href="mailto:wpt@keithcirkel.co.uk" />
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
|
|
@ -210,9 +210,10 @@ async function cookie_test(func, description) {
|
|||
|
||||
// Wipe cookies used by tests before and after the test.
|
||||
async function deleteAllCookies() {
|
||||
(await cookieStore.getAll()).forEach(({name, value}) => {
|
||||
cookieStore.delete(name);
|
||||
});
|
||||
await Promise.all((await cookieStore.getAll()).map(async ({name, value}) => {
|
||||
await cookieStore.delete(name);
|
||||
await cookieStore.delete({name: name, partitioned: true});
|
||||
}));
|
||||
}
|
||||
|
||||
return promise_test(async t => {
|
||||
|
|
74
tests/wpt/tests/css/css-anchor-position/anchor-ident-function.html
vendored
Normal file
74
tests/wpt/tests/css/css-anchor-position/anchor-ident-function.html
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Anchor Positioning: The ident() function </title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-5/#ident">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/computed-testcommon.js"></script>
|
||||
<style>
|
||||
#cb {
|
||||
border: 1px solid black;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
position: relative;
|
||||
}
|
||||
.anchor {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
background-color: skyblue;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
}
|
||||
/* sibling-index() could make this nicer, but it's not universally
|
||||
supported at the time of writing: */
|
||||
.anchor:nth-child(1) { anchor-name: --a1; left: calc(20px * 1); }
|
||||
.anchor:nth-child(2) { anchor-name: --a2; left: calc(20px * 2); }
|
||||
.anchor:nth-child(3) { anchor-name: --a3; left: calc(20px * 3); }
|
||||
#target {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
background-color: tomato;
|
||||
position: absolute;
|
||||
position-anchor: --a1;
|
||||
}
|
||||
</style>
|
||||
<div id=cb>
|
||||
<div>
|
||||
<div class=anchor></div>
|
||||
<div class=anchor></div>
|
||||
<div class=anchor></div>
|
||||
</div>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Test the computed values of various anchor related properties:
|
||||
|
||||
let actual_ident = 'ident("--myident" calc(42 * sign(1em - 1px)))';
|
||||
let expected_ident = '--myident42';
|
||||
|
||||
// https://drafts.csswg.org/css-anchor-position-1/#name
|
||||
test_computed_value('anchor-name', actual_ident, expected_ident);
|
||||
test_computed_value('anchor-name', `--tl, ${actual_ident}`,
|
||||
`--tl, ${expected_ident}`);
|
||||
test_computed_value('anchor-name', `${actual_ident}, ${actual_ident}`,
|
||||
`${expected_ident}, ${expected_ident}`);
|
||||
|
||||
// https://drafts.csswg.org/css-anchor-position-1/#anchor-scope
|
||||
test_computed_value('anchor-scope', actual_ident, expected_ident);
|
||||
test_computed_value('anchor-scope', `--tl, ${actual_ident}`,
|
||||
`--tl, ${expected_ident}`);
|
||||
test_computed_value('anchor-scope', `${actual_ident}, ${actual_ident}`,
|
||||
`${expected_ident}, ${expected_ident}`);
|
||||
|
||||
// https://drafts.csswg.org/css-anchor-position-1/#position-anchor
|
||||
test_computed_value('position-anchor', actual_ident, expected_ident);
|
||||
|
||||
// Test ident() usage within anchor functions:
|
||||
test_computed_value('left', 'anchor(--a1 left)', '20px');
|
||||
test_computed_value('left', 'anchor(--a2 left)', '40px');
|
||||
test_computed_value('left', 'anchor(--a3 left)', '60px');
|
||||
test_computed_value('left', 'calc(anchor(--a1 left)*4)', '80px');
|
||||
test_computed_value('width', 'calc(anchor-size(--a1)*2)', '30px');
|
||||
test_computed_value('width', 'anchor-size(--a1)', '15px');
|
||||
</script>
|
46
tests/wpt/tests/css/css-anchor-position/anchor-in-multicol-crash.html
vendored
Normal file
46
tests/wpt/tests/css/css-anchor-position/anchor-in-multicol-crash.html
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Anchor Positioning: Crash with anchor in multicol</title>
|
||||
<link rel="help" href="https://issues.chromium.org/issues/324930388">
|
||||
<style>
|
||||
.cb {
|
||||
position: relative;
|
||||
border: 1px solid black;
|
||||
}
|
||||
.columns {
|
||||
column-count: 4;
|
||||
column-width: 100px;
|
||||
width: 320px;
|
||||
height: 100px;
|
||||
}
|
||||
.anchor {
|
||||
anchor-name: --a1;
|
||||
width: 100px;
|
||||
height: 90px;
|
||||
background: blue;
|
||||
}
|
||||
.target {
|
||||
position: absolute;
|
||||
position-anchor: --a1;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: purple;
|
||||
position-try-fallbacks: --pf1, --pf2;
|
||||
}
|
||||
@position-try --pf1 {
|
||||
right: 400px;
|
||||
bottom: 10px;
|
||||
}
|
||||
@position-try --pf2 {
|
||||
right: 40px;
|
||||
bottom: 30px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
PASS if no crash
|
||||
<div class="columns">
|
||||
<div class="cb">
|
||||
<div class="anchor"></div>
|
||||
<div class="target"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
53
tests/wpt/tests/css/css-anchor-position/anchor-in-multicol-inherit-crash.html
vendored
Normal file
53
tests/wpt/tests/css/css-anchor-position/anchor-in-multicol-inherit-crash.html
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Anchor Positioning: Crash with anchor in multicol (inheritance)</title>
|
||||
<link rel="help" href="https://issues.chromium.org/issues/324930388">
|
||||
<style>
|
||||
.cb {
|
||||
position: relative;
|
||||
border: 1px solid black;
|
||||
}
|
||||
.columns {
|
||||
column-count: 4;
|
||||
column-width: 100px;
|
||||
width: 320px;
|
||||
height: 100px;
|
||||
}
|
||||
.anchor {
|
||||
anchor-name: --a1;
|
||||
width: 100px;
|
||||
height: 90px;
|
||||
background: blue;
|
||||
}
|
||||
.target {
|
||||
position: absolute;
|
||||
position-anchor: --a1;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: purple;
|
||||
position-try-fallbacks: --pf1, --pf2;
|
||||
}
|
||||
.child {
|
||||
position: fixed;
|
||||
right: inherit;
|
||||
bottom: inherit;
|
||||
}
|
||||
@position-try --pf1 {
|
||||
right: 400px;
|
||||
bottom: 10px;
|
||||
}
|
||||
@position-try --pf2 {
|
||||
right: 40px;
|
||||
bottom: 30px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
PASS if no crash
|
||||
<div class="columns">
|
||||
<div class="cb">
|
||||
<div class="anchor"></div>
|
||||
<div class="target">
|
||||
<div class="child"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
12
tests/wpt/tests/css/css-anchor-position/chrome-419501749-crash.html
vendored
Normal file
12
tests/wpt/tests/css/css-anchor-position/chrome-419501749-crash.html
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://crbug.com/419501749">
|
||||
<style>
|
||||
#crash {
|
||||
position: absolute;
|
||||
left: anchor(right);
|
||||
--grad: linear-gradient(black, blue);
|
||||
content: var(--grad);
|
||||
}
|
||||
</style>
|
||||
<p>Pass if no crash</p>
|
||||
<div id="crash"></div>
|
23
tests/wpt/tests/css/css-anchor-position/position-try-ident-function.html
vendored
Normal file
23
tests/wpt/tests/css/css-anchor-position/position-try-ident-function.html
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Anchor Positioning: The ident() function in @position-try/position-try</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-5/#ident">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#fallback-rule">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#position-try-fallbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/computed-testcommon.js"></script>
|
||||
<div id=target></div>
|
||||
<script>
|
||||
let actual_ident = 'ident("--myident" calc(42 * sign(1em - 1px)))';
|
||||
let expected_ident = '--myident42';
|
||||
|
||||
// https://drafts.csswg.org/css-anchor-position-1/#position-try-fallbacks
|
||||
test_computed_value('position-try-fallbacks', actual_ident, expected_ident);
|
||||
test_computed_value('position-try-fallbacks', `flip-block, ${actual_ident}`,
|
||||
`flip-block, ${expected_ident}`);
|
||||
|
||||
// https://drafts.csswg.org/css-anchor-position-1/#position-try-prop
|
||||
test_computed_value('position-try', actual_ident, expected_ident);
|
||||
test_computed_value('position-try', `most-width ${actual_ident}`,
|
||||
`most-width ${expected_ident}`);
|
||||
</script>
|
|
@ -4,9 +4,7 @@
|
|||
<link rel="help" href="https://drafts.csswg.org/css-borders-4/#corner-shaping">
|
||||
<link rel="match" href="corner-shape-any-ref.html">
|
||||
<meta name="fuzzy" content="maxDifference=0-200;totalPixels=0-550">
|
||||
<meta name="variant" content="?corner-shape=scoop&border-radius=20%&border-width=20px&border-top-color=rebeccapurple&border-bottom-color=blue">
|
||||
<meta name="variant" content="?corner-shape=scoop&border-radius=20%&border-width=20px">
|
||||
<meta name="variant" content="?corner-top-left-shape=notch&border-radius=40px&border-width=10px&border-color=blue&border-left-color=yellow">
|
||||
<meta name="variant" content="?corner-shape=superellipse(-2)&border-radius=20%&border-width=20px">
|
||||
<meta name="variant" content="?corner-top-left-shape=bevel&border-radius=40px&border-width=10px">
|
||||
<meta name="variant" content="?corner-top-left-shape=scoop&corner-top-right-shape=scoop&border-radius=50%">
|
||||
|
|
|
@ -18,7 +18,34 @@
|
|||
test_cq_condition_known('style(--my-prop: )');
|
||||
test_cq_condition_known('style(--foo: bar !important)');
|
||||
test_cq_condition_known('style(--foo)');
|
||||
test_cq_condition_known('style(--my-prop: attr(data-foo))');
|
||||
test_cq_condition_known('style(--foo >= --bar)');
|
||||
test_cq_condition_known('style(--foo = --bar)');
|
||||
test_cq_condition_known('style(--foo <= --bar)');
|
||||
test_cq_condition_known('style(10px > 10em)');
|
||||
test_cq_condition_known('style(--foo >= 10em)');
|
||||
test_cq_condition_known('style(10px > --bar)');
|
||||
test_cq_condition_known('style(10px = --bar)');
|
||||
test_cq_condition_known('style(--foo < --bar)');
|
||||
test_cq_condition_known('style(10px <= 10em)');
|
||||
test_cq_condition_known('style(10px = 10em)');
|
||||
test_cq_condition_known('style(10px <= calc(10em + 20em))');
|
||||
test_cq_condition_known('style(calc(10em + 20em) < 10px)');
|
||||
test_cq_condition_known('style(--foo < 10em)');
|
||||
test_cq_condition_known('style(10px <= --bar)');
|
||||
test_cq_condition_known('style(--foo < --bar <= --baz)');
|
||||
test_cq_condition_known('style(--foo >= --bar > --baz)');
|
||||
test_cq_condition_known('style(--foo > 10px > 10em)');
|
||||
test_cq_condition_known('style(10px < --foo < 10em)');
|
||||
test_cq_condition_known('style(10px < --foo <= 10em)');
|
||||
test_cq_condition_known('style(10px <= --foo < 10em)');
|
||||
test_cq_condition_known('style(10px > 10em > --foo)');
|
||||
test_cq_condition_known('style(10px < 10em < 10)');
|
||||
test_cq_condition_known('style(var(--p) < calc(100 + 200))');
|
||||
test_cq_condition_known('style(attr(data-foo type(<number>)) < var(--p) < var(--q))');
|
||||
|
||||
test_cq_condition_unknown('style(--foo: bar;)');
|
||||
test_cq_condition_unknown('style(style(--foo: bar))');
|
||||
test_cq_condition_unknown('style(10px < 10em > 10)');
|
||||
test_cq_condition_unknown('style( < 10em)');
|
||||
</script>
|
||||
|
|
24
tests/wpt/tests/css/css-conditional/container-queries/container-ident-function.html
vendored
Normal file
24
tests/wpt/tests/css/css-conditional/container-queries/container-ident-function.html
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Conditional: The ident() function in @container/container-name</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-5/#ident">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-rule">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-name">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/computed-testcommon.js"></script>
|
||||
<div id=target></div>
|
||||
<script>
|
||||
let actual_ident = 'ident("--myident" calc(42 * sign(1em - 1px)))';
|
||||
let expected_ident = '--myident42';
|
||||
|
||||
// https://drafts.csswg.org/css-conditional-5/#container-name
|
||||
test_computed_value('container-name', actual_ident, expected_ident);
|
||||
test_computed_value('container-name', `--c ${actual_ident}`,
|
||||
`--c ${expected_ident}`);
|
||||
|
||||
// https://drafts.csswg.org/css-conditional-5/#container-shorthand
|
||||
test_computed_value('container', actual_ident, expected_ident);
|
||||
test_computed_value('container', `--c ${actual_ident} / size`,
|
||||
`--c ${expected_ident} / size`);
|
||||
|
||||
</script>
|
|
@ -7,6 +7,7 @@
|
|||
<style>
|
||||
@import url("/fonts/ahem.css");
|
||||
:root { font-family: 'Ahem'; font-size: 10px; line-height: 10px; }
|
||||
#log { font-family: sans-serif; }
|
||||
#em_container {
|
||||
container-type: inline-size;
|
||||
width: 100px;
|
||||
|
@ -100,19 +101,23 @@
|
|||
<div id="rlh_test"></div>
|
||||
</div>
|
||||
<script>
|
||||
setup(() => assert_implements_size_container_queries());
|
||||
setup(() => assert_implements_size_container_queries(), { explicit_done: true });
|
||||
|
||||
const green = "rgb(0, 128, 0)";
|
||||
test(() => assert_equals(getComputedStyle(em_test).color, green), "em relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(rem_test).color, green), "rem relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(ex_test).color, green), "ex relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(rex_test).color, green), "rex relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(ch_test).color, green), "ch relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(rch_test).color, green), "rch relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(ic_test).color, green), "ic relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(ric_test).color, green), "ric relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(lh_test).color, green), "lh relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(rlh_test).color, green), "rlh relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(cap_test).color, green), "cap relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(rcap_test).color, green), "rcap relative inline-size");
|
||||
|
||||
document.fonts.ready.then(() => {
|
||||
test(() => assert_equals(getComputedStyle(em_test).color, green), "em relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(rem_test).color, green), "rem relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(ex_test).color, green), "ex relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(rex_test).color, green), "rex relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(ch_test).color, green), "ch relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(rch_test).color, green), "rch relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(ic_test).color, green), "ic relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(ric_test).color, green), "ric relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(lh_test).color, green), "lh relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(rlh_test).color, green), "rlh relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(cap_test).color, green), "cap relative inline-size");
|
||||
test(() => assert_equals(getComputedStyle(rcap_test).color, green), "rcap relative inline-size");
|
||||
done();
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
.pointerMove(0, 0, {origin: "viewport"})
|
||||
.pause(50)
|
||||
.send();
|
||||
await waitForAnimationFrames(2);
|
||||
assert_equals(changeTarget, snapped1, "snapchange has not been called for #snapped2");
|
||||
assert_equals(changingTarget, snapped2, "snapchanging has been called for #snapped2");
|
||||
assert_equals(getComputedStyle(target1).getPropertyValue("--snapped"), "",
|
||||
|
|
|
@ -1,66 +1,32 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Test: 'contain: layout' with stacking contents. Z-index is defined only for siblings and children.</title>
|
||||
<link rel="author" title="Yusuf Sermet" href="mailto:ysermet@mozilla.com">
|
||||
<link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
|
||||
<link rel="help" href="https://drafts.csswg.org/css2/visuren.html#x43">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-contain/#containment-layout">
|
||||
<link rel="match" href="contain-paint-stacking-context-001-ref.html">
|
||||
<style>
|
||||
div {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
}
|
||||
#div1,
|
||||
#div3 {
|
||||
background-color: #cfc;
|
||||
}
|
||||
#div1 {
|
||||
z-index: 5;
|
||||
}
|
||||
#div2 {
|
||||
contain: layout;
|
||||
background-color: #fdd;
|
||||
height: 100px;
|
||||
top: -20px;
|
||||
}
|
||||
#div2_1 {
|
||||
background-color: #ffc;
|
||||
z-index: 6;
|
||||
top: -10px;
|
||||
}
|
||||
#div2_2 {
|
||||
z-index: 3;
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
width: 40px;
|
||||
height: 100px;
|
||||
background-color: #ddf;
|
||||
}
|
||||
#div3 {
|
||||
z-index: 2;
|
||||
top: -50px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="div1">
|
||||
<br/><br/>
|
||||
</div>
|
||||
|
||||
<div id="div2">
|
||||
<div id="div2_1">
|
||||
<br/><br/>
|
||||
</div>
|
||||
|
||||
<div id="div2_2">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="div3">
|
||||
<br/><br/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<title>'contain: layout' establishes stacking context.</title>
|
||||
<link rel="author" title="Psychpsyo" href="mailto:psychpsyo@gmail.com">
|
||||
<link rel="help" href="https://drafts.csswg.org/css2/visuren.html#x43">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-contain/#containment-layout">
|
||||
<link rel="match" href="contain-paint-stacking-context-001-ref.html">
|
||||
<style>
|
||||
div {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
#front {
|
||||
background-color: green;
|
||||
/* makes a stacking context and puts this on top */
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
}
|
||||
#back {
|
||||
contain: layout;
|
||||
}
|
||||
#notOnTop {
|
||||
background-color: red;
|
||||
/* z-index is higher than on #front, but this should still be covered up because it is inside #back, which has 'contain: layout' */
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
}
|
||||
</style>
|
||||
<div id="front"></div>
|
||||
<div id="back">
|
||||
<div id="notOnTop"></div>
|
||||
</div>
|
||||
Test succeeds if there is no red.
|
||||
|
|
|
@ -41,8 +41,9 @@
|
|||
<div id="log"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
setup({ explicit_done: true });
|
||||
|
||||
setup(() => {
|
||||
assert_implements(CSS.supports('wrap-flow', 'clear'), "'wrap-flow: clear'");
|
||||
}, {explicit_done: true});
|
||||
document.fonts.ready.then(() => {
|
||||
test(function() {assert_equals(checkLinePos("linesBelow",150,"top"), true)}, "Verify top of the 'linesBelow' span is positioned correctly");
|
||||
done();
|
||||
|
|
|
@ -44,8 +44,9 @@
|
|||
<div id="log"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
setup({ explicit_done: true });
|
||||
|
||||
setup(() => {
|
||||
assert_implements(CSS.supports('wrap-flow', 'start'), "'wrap-flow: start'");
|
||||
}, {explicit_done: true});
|
||||
document.fonts.ready.then(() => {
|
||||
test(function() {assert_equals(checkLinePos("lineLeft1",36,"top"), true)}, "Verify top of the 'lineLeft1' span is positioned correctly");
|
||||
test(function() {assert_equals(checkLinePos("lineLeft2",48,"top"), true)}, "Verify top of the 'lineLeft2' span is positioned correctly");
|
||||
|
|
|
@ -44,8 +44,9 @@
|
|||
<div id="log"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
setup({ explicit_done: true });
|
||||
|
||||
setup(() => {
|
||||
assert_implements(CSS.supports('wrap-flow', 'auto'), "'wrap-flow: auto'");
|
||||
}, {explicit_done: true});
|
||||
document.fonts.ready.then(() => {
|
||||
test(function() {assert_equals(checkLinePos("line1",216,"right"), true)}, "Verify right of the 'line1' span is positioned correctly");
|
||||
test(function() {assert_equals(checkLinePos("line2",192,"right"), true)}, "Verify right of the 'line2' span is positioned correctly");
|
||||
|
|
|
@ -45,8 +45,9 @@
|
|||
<div id="log"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
setup({ explicit_done: true });
|
||||
|
||||
setup(() => {
|
||||
assert_implements(CSS.supports('wrap-flow', 'both'), "'wrap-flow: both'");
|
||||
}, {explicit_done: true});
|
||||
document.fonts.ready.then(() => {
|
||||
/* Line 1 */
|
||||
test(function() {assert_equals(checkLinePos("line1",0,"top"), true)}, "Verify top of the 'line1' span is positioned correctly");
|
||||
|
|
|
@ -45,8 +45,9 @@
|
|||
<div id="log"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
setup({ explicit_done: true });
|
||||
|
||||
setup(() => {
|
||||
assert_implements(CSS.supports('wrap-flow', 'end'), "'wrap-flow: end'");
|
||||
}, {explicit_done: true});
|
||||
document.fonts.ready.then(() => {
|
||||
/* Line 1 */
|
||||
test(function() {assert_equals(checkLinePos("line1",0,"top"), true)}, "Verify top of the 'line1' span is positioned correctly");
|
||||
|
|
|
@ -44,8 +44,9 @@
|
|||
<div id="log"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
setup({ explicit_done: true });
|
||||
|
||||
setup(() => {
|
||||
assert_implements(CSS.supports('wrap-flow', 'maximum'), "'wrap-flow: maximum'");
|
||||
}, {explicit_done: true});
|
||||
document.fonts.ready.then(() => {
|
||||
/*Line 1*/
|
||||
test(function() {assert_equals(checkLinePos("line1",0,"top"), true)}, "Verify top of the 'line1' span is positioned correctly");
|
||||
|
|
|
@ -51,8 +51,10 @@
|
|||
<div id="log"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
setup({ explicit_done: true });
|
||||
|
||||
setup(() => {
|
||||
assert_implements(CSS.supports('wrap-through', 'none'), "'wrap-through: none'");
|
||||
assert_implements(CSS.supports('wrap-flow', 'both'), "'wrap-flow: both'");
|
||||
}, {explicit_done: true});
|
||||
document.fonts.ready.then(() => {
|
||||
/* Line 1 */
|
||||
test(function() {assert_equals(checkLinePos("line1",0,"top"), true)}, "Verify top of the first line above the exclusion");
|
||||
|
|
34
tests/wpt/tests/css/css-flexbox/flex-aspect-ratio-img-vert-lr.html
vendored
Normal file
34
tests/wpt/tests/css/css-flexbox/flex-aspect-ratio-img-vert-lr.html
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#algo-main-item">
|
||||
<meta name="assert" content="Flex item should compute its main size from its definite cros size and aspect ratio.">
|
||||
<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
|
||||
<style>
|
||||
.flexbox {
|
||||
position: relative;
|
||||
display: flex;
|
||||
writing-mode: vertical-lr;
|
||||
width: 100px;
|
||||
align-items: start;
|
||||
}
|
||||
.flex-item{
|
||||
width: 40px
|
||||
}
|
||||
.abspos {
|
||||
width: 60px;
|
||||
height: 100px; background-color: green;
|
||||
position: absolute;
|
||||
left: 40px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test passes if there is a filled green square.</p>
|
||||
<div class="flexbox">
|
||||
<img class="flex-item" src="support/20x50-green.png">
|
||||
<div class="abspos"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -165,5 +165,5 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/check-layout-th.js"></script>
|
||||
<script>
|
||||
checkLayout(".flex");
|
||||
document.fonts.ready.then(() => { checkLayout(".flex") })
|
||||
</script>
|
||||
|
|
|
@ -165,5 +165,5 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/check-layout-th.js"></script>
|
||||
<script>
|
||||
checkLayout(".flex");
|
||||
document.fonts.ready.then(() => { checkLayout(".flex") });
|
||||
</script>
|
||||
|
|
|
@ -16,7 +16,7 @@ font-family: reversed-range-test;
|
|||
font-stretch: 200% 50%;
|
||||
font-style: oblique 90deg -90deg;
|
||||
font-weight: 900 100;
|
||||
src: local(Ahem);
|
||||
src: url(/fonts/Ahem.ttf);
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
|
|
|
@ -14,22 +14,22 @@
|
|||
@font-face {
|
||||
font-family: test1;
|
||||
font-style: normal;
|
||||
src: local(Ahem);
|
||||
src: url(/fonts/Ahem.ttf);
|
||||
}
|
||||
@font-face {
|
||||
font-family: test2;
|
||||
font-style: oblique 0deg;
|
||||
src: local(Ahem);
|
||||
src: url(/fonts/Ahem.ttf);
|
||||
}
|
||||
@font-face {
|
||||
font-family: test3;
|
||||
font-style: oblique 0deg 10deg;
|
||||
src: local(Ahem);
|
||||
src: url(/fonts/Ahem.ttf);
|
||||
}
|
||||
@font-face {
|
||||
font-family: test4;
|
||||
font-style: normal 10deg;
|
||||
src: local(Ahem);
|
||||
src: url(/fonts/Ahem.ttf);
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
|
|
|
@ -24,12 +24,14 @@ div {
|
|||
let ahem = document.getElementById('ahem');
|
||||
let ahem_expected_width = ahem.offsetWidth;
|
||||
kGenericFontFamilyKeywords.forEach(keyword => {
|
||||
test(() => {
|
||||
promise_test(async function() {
|
||||
let element = document.getElementById('test');
|
||||
element.setAttribute("style", `font-family: ${keyword};`);
|
||||
let expected_width = element.offsetWidth;
|
||||
|
||||
// Insert the @font-face rules for quoted and unquoted keywords.
|
||||
// NOTE that we have to wait for font loads again at each step,
|
||||
// as new asynchronous loads may be initiated when the style changes.
|
||||
document.documentElement.insertAdjacentHTML('beforeend', `
|
||||
<style>
|
||||
@font-face {
|
||||
|
@ -43,10 +45,11 @@ div {
|
|||
src: local(Ahem), url('/fonts/Ahem.ttf');
|
||||
}
|
||||
</style>`);
|
||||
|
||||
await document.fonts.ready;
|
||||
assert_equals(element.offsetWidth, expected_width, `unquoted ${keyword} does not match @font-face rule`);
|
||||
|
||||
element.setAttribute("style", `font-family: "${keyword}";`);
|
||||
await document.fonts.ready;
|
||||
assert_equals(element.offsetWidth, ahem_expected_width, `quoted ${keyword} matches @font-face rule`);
|
||||
}, `@font-face matching for quoted and unquoted ${keyword}`);
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<canvas id="canvas" width="400" height="150"></canvas>
|
||||
<script>
|
||||
setup({ explicit_done: true });
|
||||
window.addEventListener("load", () => { document.fonts.ready.then(runTests); });
|
||||
window.addEventListener("load", () => { document.fonts.load("25px Ahem").then(runTests); });
|
||||
function runTests() {
|
||||
const measured_text = "|||||";
|
||||
const canvas = document.getElementById("canvas");
|
||||
|
@ -19,7 +19,7 @@
|
|||
let ahem_expected_width = ctx.measureText(measured_text).width;
|
||||
|
||||
kGenericFontFamilyKeywords.forEach(keyword => {
|
||||
test(() => {
|
||||
promise_test(async function() {
|
||||
ctx.font = `25px ${keyword}`;
|
||||
let expected_width = ctx.measureText(measured_text).width;
|
||||
|
||||
|
@ -38,10 +38,12 @@
|
|||
}
|
||||
</style>`);
|
||||
|
||||
await document.fonts.load(`25px ${keyword}`);
|
||||
ctx.font = `25px ${keyword}`;
|
||||
let unquoted_width = ctx.measureText(measured_text).width;
|
||||
assert_equals(unquoted_width, expected_width, `unquoted ${keyword} does not match @font-face rule`);
|
||||
|
||||
await document.fonts.load(`25px "${keyword}"`);
|
||||
ctx.font = `25px "${keyword}"`;
|
||||
let quoted_width = ctx.measureText(measured_text).width;
|
||||
assert_equals(quoted_width, ahem_expected_width, `quoted ${keyword} matches @font-face rule`);
|
||||
|
|
24
tests/wpt/tests/css/css-fonts/test-synthetic-bold-2-notref.html
vendored
Normal file
24
tests/wpt/tests/css/css-fonts/test-synthetic-bold-2-notref.html
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Fonts: font-weight: bold; with bold font face without explicit font weight</title>
|
||||
<meta charset="utf-8" />
|
||||
<style type="text/css">
|
||||
@font-face {
|
||||
font-family: "csstest-bold";
|
||||
src: local("CSSTest Basic Bold");
|
||||
}
|
||||
div { font-size: 36px; }
|
||||
span#verify { font-family: "CSSTest Verify"; }
|
||||
div.test {
|
||||
font-family: "csstest-bold";
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div><a href="http://www.w3.org/Style/CSS/Test/Fonts/">Test fonts</a> must be installed for this test: <span id="verify">FAIL</span></div>
|
||||
<p>Test passes if the second line is bolder than the first:</p>
|
||||
<div class="test">Filler text</div>
|
||||
<div class="test">Filler text</div>
|
||||
</body>
|
||||
</html>
|
32
tests/wpt/tests/css/css-fonts/test-synthetic-bold-2.html
vendored
Normal file
32
tests/wpt/tests/css/css-fonts/test-synthetic-bold-2.html
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Fonts: font-weight: bold; with bold font face without explicit font weight</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="author" title="Max Ihlenfeldt" href="mailto:max@igalia.com" />
|
||||
<link rel="help" href="https://drafts.csswg.org/css-fonts/#font-style-matching">
|
||||
<link rel="mismatch" href="test-synthetic-bold-2-notref.html">
|
||||
<meta name="assert" content="Bold text in a bold font face that was declared without an explicit font weight is synthetically bolded.">
|
||||
<style type="text/css">
|
||||
@font-face {
|
||||
font-family: "csstest-bold";
|
||||
src: local("CSSTest Basic Bold");
|
||||
}
|
||||
div { font-size: 36px; }
|
||||
span#verify { font-family: "CSSTest Verify"; }
|
||||
div#test1 {
|
||||
font-family: "csstest-bold";
|
||||
}
|
||||
div#test2 {
|
||||
font-family: "csstest-bold";
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div><a href="http://www.w3.org/Style/CSS/Test/Fonts/">Test fonts</a> must be installed for this test: <span id="verify">FAIL</span></div>
|
||||
<p>Test passes if the second line is bolder than the first:</p>
|
||||
<div id="test1">Filler text</div>
|
||||
<div id="test2">Filler text</div>
|
||||
</body>
|
||||
</html>
|
24
tests/wpt/tests/css/css-fonts/test-synthetic-italic-4-notref.html
vendored
Normal file
24
tests/wpt/tests/css/css-fonts/test-synthetic-italic-4-notref.html
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Fonts: font-style: italic; with italic font face without explicit font style</title>
|
||||
<meta charset="utf-8" />
|
||||
<style type="text/css">
|
||||
@font-face {
|
||||
font-family: "csstest-italic";
|
||||
src: local("CSSTest Basic Italic");
|
||||
}
|
||||
div { font-size: 36px; }
|
||||
span#verify { font-family: "CSSTest Verify"; }
|
||||
div.test {
|
||||
font-family: "csstest-italic";
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div><a href="http://www.w3.org/Style/CSS/Test/Fonts/">Test fonts</a> must be installed for this test: <span id="verify">FAIL</span></div>
|
||||
<p>Test passes if the second line is more italic than the first:</p>
|
||||
<div class="test">Filler text</div>
|
||||
<div class="test">Filler text</div>
|
||||
</body>
|
||||
</html>
|
32
tests/wpt/tests/css/css-fonts/test-synthetic-italic-4.html
vendored
Normal file
32
tests/wpt/tests/css/css-fonts/test-synthetic-italic-4.html
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Fonts: font-style: italic; with italic font face without explicit font style</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="author" title="Max Ihlenfeldt" href="mailto:max@igalia.com" />
|
||||
<link rel="help" href="https://drafts.csswg.org/css-fonts/#font-style-matching">
|
||||
<link rel="mismatch" href="test-synthetic-italic-4-notref.html">
|
||||
<meta name="assert" content="Italic text in an italic font face that was declared without an explicit font style is synthetically italicized.">
|
||||
<style type="text/css">
|
||||
@font-face {
|
||||
font-family: "csstest-italic";
|
||||
src: local("CSSTest Basic Italic");
|
||||
}
|
||||
div { font-size: 36px; }
|
||||
span#verify { font-family: "CSSTest Verify"; }
|
||||
div#test1 {
|
||||
font-family: "csstest-italic";
|
||||
}
|
||||
div#test2 {
|
||||
font-family: "csstest-italic";
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div><a href="http://www.w3.org/Style/CSS/Test/Fonts/">Test fonts</a> must be installed for this test: <span id="verify">FAIL</span></div>
|
||||
<p>Test passes if the second line is more italic than the first:</p>
|
||||
<div id="test1">Filler text</div>
|
||||
<div id="test2">Filler text</div>
|
||||
</body>
|
||||
</html>
|
32
tests/wpt/tests/css/css-gaps/agnostic/gap-decorations-004-ref.html
vendored
Normal file
32
tests/wpt/tests/css/css-gaps/agnostic/gap-decorations-004-ref.html
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
#current {
|
||||
columns: 6;
|
||||
column-gap: 2px;
|
||||
column-rule-style: solid;
|
||||
column-rule-width: 2px;
|
||||
column-fill: auto;
|
||||
height: 20px;
|
||||
column-rule-color: hotpink;
|
||||
width: 72px;
|
||||
height: 20px;
|
||||
}
|
||||
.items {
|
||||
background-color: lightgreen;
|
||||
height: 20px
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="current">
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
51
tests/wpt/tests/css/css-gaps/agnostic/gap-decorations-004.html
vendored
Normal file
51
tests/wpt/tests/css/css-gaps/agnostic/gap-decorations-004.html
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<head>
|
||||
<title>column-rule-color declared with repeaters doesn't crash when recomputing</title>
|
||||
<link rel="match" href="gap-decorations-003-ref.html">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-color-4/#resolving-other-colors">
|
||||
<link rel="author" href="mailto:javiercon@microsoft.com">
|
||||
</head>
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
#current {
|
||||
color: firebrick;
|
||||
columns: 6;
|
||||
column-gap: 2px;
|
||||
column-rule-style: solid;
|
||||
column-rule-width: 2px;
|
||||
column-fill: auto;
|
||||
height: 20px;
|
||||
column-rule-color: gold;
|
||||
width: 72px;
|
||||
height: 20px;
|
||||
}
|
||||
.items {
|
||||
background-color: lightgreen;
|
||||
height: 20px
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="current">
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
// Use double requestAnimationFrame to remove need of setTimeout.
|
||||
// Wait for the first frame to ensure that the style is computed.
|
||||
requestAnimationFrame(() => {
|
||||
// Wait for the second frame to ensure that the style is painted.
|
||||
requestAnimationFrame(() => {
|
||||
document.getElementById("current").style.columnRuleColor = "hotpink";
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
52
tests/wpt/tests/css/css-gaps/agnostic/gap-decorations-006-ref.html
vendored
Normal file
52
tests/wpt/tests/css/css-gaps/agnostic/gap-decorations-006-ref.html
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-gaps-1/">
|
||||
<link rel="author" title="Javier Contreras" href="mailto:javiercon@microsoft.com">
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
column-gap: 10px;
|
||||
row-gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.item {
|
||||
background: skyblue;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.row-gap {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
background: green;
|
||||
width: 110px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.column-gap {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 50px;
|
||||
background: pink;
|
||||
height: 110px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div class="container">
|
||||
<div class="item"></div>
|
||||
<div class="item"></div>
|
||||
<div class="item"></div>
|
||||
<div class="item"></div>
|
||||
</div>
|
||||
<button id="btn">Set decorations</button>
|
||||
|
||||
<div class="column-gap"></div>
|
||||
<div class="row-gap"></div>
|
57
tests/wpt/tests/css/css-gaps/flex/flex-gap-decorations-023.html
vendored
Normal file
57
tests/wpt/tests/css/css-gaps/flex/flex-gap-decorations-023.html
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
<!DOCTYPE html>
|
||||
<title>
|
||||
CSS Gap Decorations: flex gaps are painted when going from no gap rule to a gap rule that would be visible.
|
||||
</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-gaps-1/">
|
||||
<link rel="match" href="../agnostic/gap-decorations-006-ref.html">
|
||||
<link rel="author" title="Javier Contreras" href="mailto:javiercon@microsoft.com">
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.flex-container {
|
||||
height: 110px;
|
||||
width: 110px;
|
||||
|
||||
display: flex;
|
||||
|
||||
column-gap: 10px;
|
||||
row-gap: 10px;
|
||||
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.flex-item {
|
||||
background: skyblue;
|
||||
width: 50px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function setup() {
|
||||
const button = document.getElementById('btn');
|
||||
button.click();
|
||||
}
|
||||
|
||||
function setDecorations() {
|
||||
const container = document.querySelector('.flex-container');
|
||||
if (container) {
|
||||
container.style.columnRuleStyle = 'solid';
|
||||
container.style.columnRuleWidth = '10px';
|
||||
container.style.columnRuleColor = 'pink';
|
||||
container.style.rowRuleStyle = 'solid';
|
||||
container.style.rowRuleWidth = '10px';
|
||||
container.style.rowRuleColor = 'green';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<body onload="setup()">
|
||||
<div class="flex-container">
|
||||
<div class="flex-item"></div>
|
||||
<div class="flex-item"></div>
|
||||
<div class="flex-item"></div>
|
||||
<div class="flex-item"></div>
|
||||
</div>
|
||||
<button onclick="setDecorations()" id="btn">Set decorations</button>
|
||||
</body>
|
38
tests/wpt/tests/css/css-gaps/flex/flex-gap-decorations-024.html
vendored
Normal file
38
tests/wpt/tests/css/css-gaps/flex/flex-gap-decorations-024.html
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
<title>
|
||||
CSS Gap Decorations: shorthands column rules with !important are painted and overriden correctly.
|
||||
</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-gaps-1/">
|
||||
<link rel="match" href="../agnostic/gap-decorations-001-ref.html">
|
||||
<link rel="author" title="Javier Contreras" href="mailto:javiercon@microsoft.com">
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
.flex-container {
|
||||
height: 110px;
|
||||
width: 110px;
|
||||
display: flex;
|
||||
column-gap: 10px;
|
||||
row-gap: 10px;
|
||||
column-rule: 10px solid pink !important;
|
||||
row-rule-color: green;
|
||||
row-rule-style: solid;
|
||||
row-rule-width: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
#container {
|
||||
column-rule: 9px dotted blue;
|
||||
}
|
||||
.flex-item {
|
||||
background: skyblue;
|
||||
width: 50px;
|
||||
}
|
||||
</style>
|
||||
<div class="flex-container" id="container">
|
||||
<div class="flex-item"></div>
|
||||
<div class="flex-item"></div>
|
||||
<div class="flex-item"></div>
|
||||
<div class="flex-item"></div>
|
||||
</div>
|
63
tests/wpt/tests/css/css-gaps/grid/grid-gap-decorations-039.html
vendored
Normal file
63
tests/wpt/tests/css/css-gaps/grid/grid-gap-decorations-039.html
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
<!DOCTYPE html>
|
||||
<title>
|
||||
CSS Gap Decorations: grid column gaps are painted with solid styling.
|
||||
</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-gaps-1/">
|
||||
<link rel="match" href="../agnostic/gap-decorations-006-ref.html">
|
||||
<link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com">
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.grid-container {
|
||||
height: 110px;
|
||||
width: 110px;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
|
||||
column-gap: 10px;
|
||||
row-gap: 10px;
|
||||
|
||||
column-rule-color: pink;
|
||||
column-rule-style: solid;
|
||||
column-rule-width: 10px;
|
||||
|
||||
row-rule-color: green;
|
||||
row-rule-style: solid;
|
||||
row-rule-width: 10px;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
background: skyblue;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function setup() {
|
||||
const button = document.getElementById('btn');
|
||||
button.click();
|
||||
}
|
||||
|
||||
function setDecorations() {
|
||||
const container = document.querySelector('.grid-container');
|
||||
if (container) {
|
||||
container.style.columnRuleStyle = 'solid';
|
||||
container.style.columnRuleWidth = '10px';
|
||||
container.style.columnRuleColor = 'pink';
|
||||
container.style.rowRuleStyle = 'solid';
|
||||
container.style.rowRuleWidth = '10px';
|
||||
container.style.rowRuleColor = 'green';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<body onload="setup()">
|
||||
<div class="grid-container">
|
||||
<div class="grid-item"></div>
|
||||
<div class="grid-item"></div>
|
||||
<div class="grid-item"></div>
|
||||
<div class="grid-item"></div>
|
||||
</div>
|
||||
<button onclick="setDecorations()" id="btn">Set decorations</button>
|
||||
</body>
|
50
tests/wpt/tests/css/css-gaps/multicol/multicol-gap-decorations-018-ref.html
vendored
Normal file
50
tests/wpt/tests/css/css-gaps/multicol/multicol-gap-decorations-018-ref.html
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-gaps-1/">
|
||||
<link rel="author" title="Javier Contreras" href="mailto:javiercon@microsoft.com">
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.container {
|
||||
border: 2px solid rgb(96 139 168);
|
||||
width: 200px;
|
||||
height: 130px;
|
||||
column-gap: 10px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.items {
|
||||
background: rgb(96 139 168 / 0.2);
|
||||
height: 130px;
|
||||
margin: 0px;
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.row-gap {
|
||||
position: absolute;
|
||||
height: 10px;
|
||||
width: 200px;
|
||||
background: gold;
|
||||
left: 2px;
|
||||
top: 62px;
|
||||
}
|
||||
|
||||
.column-gap {
|
||||
position: absolute;
|
||||
height: 130px;
|
||||
width: 10px;
|
||||
background: blue;
|
||||
top: 2px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
</div>
|
||||
<button onclick="setDecorations()" id="btn">Set decorations</button>
|
||||
<div class="column-gap" style="left:62px;"></div>
|
||||
<div class="column-gap" style="left:132px;"></div>
|
||||
<div class="row-gap"></div>
|
55
tests/wpt/tests/css/css-gaps/multicol/multicol-gap-decorations-019.html
vendored
Normal file
55
tests/wpt/tests/css/css-gaps/multicol/multicol-gap-decorations-019.html
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<head>
|
||||
<title>column-rule-color declared with repeaters that depend on currentcolor should be recomputed when currentcolor changes</title>
|
||||
<link rel="match" href="../agnostic/gap-decorations-003-ref.html">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-color-4/#resolving-other-colors">
|
||||
<link rel="author" href="mailto:javiercon@microsoft.com">
|
||||
</head>
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#current {
|
||||
color: firebrick;
|
||||
columns: 6;
|
||||
column-gap: 2px;
|
||||
column-rule-style: solid;
|
||||
column-rule-width: 2px;
|
||||
column-fill: auto;
|
||||
height: 20px;
|
||||
column-rule-color: repeat(auto, currentColor);
|
||||
|
||||
width: 72px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.items {
|
||||
background-color: lightgreen;
|
||||
height: 20px
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="current">
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
<div class="items"></div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
// Use double requestAnimationFrame to remove need of setTimeout.
|
||||
// Wait for the first frame to ensure that the style is computed.
|
||||
requestAnimationFrame(() => {
|
||||
// Wait for the second frame to ensure that the style is painted.
|
||||
requestAnimationFrame(() => {
|
||||
document.getElementById("current").style.color = "hotpink";
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
60
tests/wpt/tests/css/css-gaps/multicol/multicol-gap-intersections-018.html
vendored
Normal file
60
tests/wpt/tests/css/css-gaps/multicol/multicol-gap-intersections-018.html
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
<!DOCTYPE html>
|
||||
<title>
|
||||
CSS Gap Decorations: Multicolumn gap decorations that are added later are painted.
|
||||
</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-gaps-1/">
|
||||
<link rel="match" href="multicol-gap-decorations-018-ref.html">
|
||||
<link rel="author" title="Javier Contreras" href="mailto:javiercon@microsoft.com">
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.container {
|
||||
border: 2px solid rgb(96 139 168);
|
||||
width: 200px;
|
||||
height: 130px;
|
||||
column-count: 3;
|
||||
column-width: 60px;
|
||||
column-height: 60px;
|
||||
column-gap: 10px;
|
||||
row-gap: 10px;
|
||||
column-wrap: wrap;
|
||||
}
|
||||
|
||||
p {
|
||||
background: rgb(96 139 168 / 0.2);
|
||||
height: 60px;
|
||||
margin: 0px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function setup() {
|
||||
const button = document.getElementById('btn');
|
||||
button.click();
|
||||
}
|
||||
|
||||
function setDecorations() {
|
||||
const container = document.querySelector('.container');
|
||||
if (container) {
|
||||
container.style.columnRuleStyle = 'solid';
|
||||
container.style.columnRuleWidth = '10px';
|
||||
container.style.columnRuleColor = 'blue';
|
||||
container.style.rowRuleStyle = 'solid';
|
||||
container.style.rowRuleWidth = '10px';
|
||||
container.style.rowRuleColor = 'gold';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<body onload="setup()">
|
||||
<div class="container">
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
</div>
|
||||
<button onclick="setDecorations()" id="btn">Set decorations</button>
|
||||
</body>
|
|
@ -44,6 +44,11 @@
|
|||
test(function() {
|
||||
assert_equals(window.getComputedStyle(document.getElementById('target1')).getPropertyValue('rule-style'), 'solid');
|
||||
}, "rule-style shorthand computed from longhand values");
|
||||
test(function() {
|
||||
assert_equals(window.getComputedStyle(document.getElementById('target1')).getPropertyValue('rule'), '10px solid rgb(0, 255, 0)');
|
||||
}, "rule shorthand computed from longhand values");
|
||||
|
||||
|
||||
|
||||
test(function() {
|
||||
assert_equals(window.getComputedStyle(document.getElementById('target2')).getPropertyValue('rule-color'), '');
|
||||
|
@ -54,6 +59,9 @@
|
|||
test(function() {
|
||||
assert_equals(window.getComputedStyle(document.getElementById('target2')).getPropertyValue('rule-style'), '');
|
||||
}, "rule-style shorthand cannot be computed from longhand values so expect an empty string");
|
||||
test(function() {
|
||||
assert_equals(window.getComputedStyle(document.getElementById('target2')).getPropertyValue('rule'), '');
|
||||
}, "rule shorthand cannot be computed from longhand values so expect an empty string");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
20
tests/wpt/tests/css/css-gaps/parsing/gap-decorations-important.html
vendored
Normal file
20
tests/wpt/tests/css/css-gaps/parsing/gap-decorations-important.html
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS GapDecorations: !important flag parsing</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-gaps-1/">
|
||||
<link rel="author" title="Javier Contreras" href="mailto:javiercon@microsoft.com">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="target" style="display: flex; column-rule: 5px solid red !important"></div>
|
||||
</body>
|
||||
<script>
|
||||
test(() => {
|
||||
assert_equals(target.style.columnRuleStyle, 'solid');
|
||||
assert_equals(target.style.columnRuleWidth, '5px');
|
||||
assert_equals(target.style.columnRuleColor, 'red');
|
||||
});
|
||||
</script>
|
||||
</html>
|
|
@ -23,8 +23,7 @@
|
|||
}
|
||||
</style>
|
||||
<script>
|
||||
// TODO(samomekarajr): Add `row-rule` to this test when implemented.
|
||||
const properties = ["column-rule",];
|
||||
const properties = ["column-rule", "row-rule", "rule"];
|
||||
for (let property of properties) {
|
||||
const currentcolor = "rgb(0, 255, 0)";
|
||||
const mediumWidth = getComputedStyle(document.getElementById('reference')).columnRuleWidth; // e.g. 3px.
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
<meta charset="utf-8">
|
||||
<title>CSS Gap Decorations: individual separate longhands form shorthand</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-multicol/#propdef-column-rule">
|
||||
<meta name="assert" content="Setting *-rule-width, *-rule-style, and *-rule-color results in the misaligned column-rule shorthand.">
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/12201">
|
||||
<meta name="assert" content="Setting *-rule-width, *-rule-style, and *-rule-color results in the misaligned *-rule shorthand.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
|
@ -63,14 +64,26 @@ const testCases = [
|
|||
},
|
||||
];
|
||||
|
||||
for (const {width, style, color, expected} of testCases) {
|
||||
let div = document.querySelector('#target');
|
||||
const rule_properties = {
|
||||
'column-rule': ['columnRuleWidth',
|
||||
'columnRuleStyle',
|
||||
'columnRuleColor'],
|
||||
'row-rule': ['rowRuleWidth',
|
||||
'rowRuleStyle',
|
||||
'rowRuleColor'],
|
||||
};
|
||||
|
||||
div.style.columnRuleWidth = width;
|
||||
div.style.columnRuleStyle = style;
|
||||
div.style.columnRuleColor = color;
|
||||
for(rule_property in rule_properties) {
|
||||
const [widthProperty, styleProperty, colorProperty] = rule_properties[rule_property];
|
||||
for (const {width, style, color, expected} of testCases) {
|
||||
let div = document.querySelector('#target');
|
||||
div.style[widthProperty] = width;
|
||||
div.style[styleProperty] = style;
|
||||
div.style[colorProperty]= color;
|
||||
test(() => {
|
||||
assert_equals(window.getComputedStyle(div).columnRule, expected);
|
||||
}, `column-rule computed from width: ${width}, style: ${style}, color: ${color}`);
|
||||
assert_equals(window.getComputedStyle(div)[rule_property], expected);
|
||||
assert_equals(div.style[rule_property], expected);
|
||||
}, `${rule_property} computed from width: ${width}, style: ${style}, color: ${color}`);
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -12,8 +12,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<script>
|
||||
// TODO(samomekarajr): Add `row-rule` and `rule` to this test.
|
||||
const properties = ["column-rule",];
|
||||
const properties = ["column-rule", "row-rule", "rule"];
|
||||
for (let property of properties) {
|
||||
test_invalid_value(property, "auto");
|
||||
|
||||
|
|
21
tests/wpt/tests/css/css-gaps/parsing/gap-decorations-rule-shorthand-roundtrip.tentative.html
vendored
Normal file
21
tests/wpt/tests/css/css-gaps/parsing/gap-decorations-rule-shorthand-roundtrip.tentative.html
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Gap Decorations: *rule properties round trips properly</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-multicol/#propdef-column-rule">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
const rule_properties = ['column-rule', 'row-rule', 'rule']
|
||||
for(let rule_property of rule_properties) {
|
||||
let div = document.querySelector('#target');
|
||||
const computed_rule_serialization = window.getComputedStyle(div)[rule_property];
|
||||
div.style[rule_property] = computed_rule_serialization;
|
||||
|
||||
test(() => {
|
||||
assert_equals(computed_rule_serialization, div.style[rule_property]);
|
||||
}, `${rule_property} round trips properly.`);
|
||||
}
|
||||
</script>
|
59
tests/wpt/tests/css/css-gaps/parsing/gap-decorations-rule-shorthand-valid.html
vendored
Normal file
59
tests/wpt/tests/css/css-gaps/parsing/gap-decorations-rule-shorthand-valid.html
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Gap Decorations: parsing column-rule with valid values</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-gaps-1/#propdef-column-rule">
|
||||
<link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com">
|
||||
<meta name="assert" content="column-rule supports the full grammar ' <gap-rule-or-repeat>#'.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
const properties = ["column-rule", "row-rule", "rule"];
|
||||
for (let property of properties) {
|
||||
// <gap-rule> = [<line-width> || <line-style> || <line-color>]
|
||||
test_valid_value(property, "5px solid red");
|
||||
test_valid_value(property, "solid 10px rgb(0, 0, 255)", "10px solid rgb(0, 0, 255)");
|
||||
test_valid_value(property, "double");
|
||||
test_valid_value(property, "blue 6px", "6px blue");
|
||||
test_valid_value(property, "currentcolor hidden medium", "hidden");
|
||||
test_valid_value(property, "currentcolor none medium", "medium");
|
||||
|
||||
|
||||
// <gap-auto-repeat-rule> = repeat( auto , <gap-rule># )
|
||||
test_valid_value(property, "repeat(auto, 5px solid green)");
|
||||
test_valid_value(property, "repeat(auto, 5px solid yellow, 10px dotted blue)");
|
||||
test_valid_value(property, "repeat(auto, 5px solid purple, dotted blue, 15px double green)");
|
||||
test_valid_value(property, "repeat(auto, 6px blue, 5px solid red)");
|
||||
|
||||
// <gap-repeat-rule> = repeat( <integer [1,∞]> , <gap-rule># )
|
||||
test_valid_value(property, "repeat(4, 15px dotted pink)");
|
||||
test_valid_value(property, "repeat(3, 8px ridge red, 20px dotted green)");
|
||||
test_valid_value(property, "repeat(1, 15px ridge yellow, 10px dotted blue, 15px double green)");
|
||||
test_valid_value(property, "repeat(4, blue, 5px red)");
|
||||
test_valid_value(property, "repeat(3, 16px, thin dashed purple, 10px dotted)");
|
||||
test_valid_value(property, "repeat(4, 10px solid red)", "repeat(4, 10px solid red)");
|
||||
|
||||
// <gap-rule-list> = <gap-rule-or-repeat>#
|
||||
// <gap-rule-or-repeat> = <gap-rule> | <gap-repeat-rule>
|
||||
test_valid_value(property, "thick, dashed, hotpink");
|
||||
test_valid_value(property, "5px double salmon, repeat(4, 5px ridge red)");
|
||||
test_valid_value(property, "15px dashed skyblue, repeat(3, 3px solid red, 10px dotted blue)");
|
||||
test_valid_value(property, "repeat(1, 5px solid gray, 10px dotted blue, 15px double green), 5px solid red, repeat(4, 6px, 5px solid red)");
|
||||
test_valid_value(property, "repeat(3, 16px lime, 5px solid red, 10px dotted), repeat(4, 5px solid red)");
|
||||
test_valid_value(property, "repeat(4, 5px solid red), repeat(3, 5px solid red, 10px dotted blue)");
|
||||
|
||||
// <gap-auto-rule-list> = <gap-rule-or-repeat>#? ,
|
||||
// <gap-auto-repeat-rule> ,
|
||||
// <gap-rule-or-repeat>#?
|
||||
test_valid_value(property, "repeat(auto, 5px solid red), thin dotted green, 10px dotted blue, 15px double green");
|
||||
test_valid_value(property, "5px solid red, repeat(auto, 5px solid red), 10px dotted blue");
|
||||
test_valid_value(property, "10px dotted blue, repeat(4, blue, 5px yellow), repeat(auto, 5px solid red)");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -11,116 +11,184 @@
|
|||
</head>
|
||||
<body>
|
||||
<script>
|
||||
// TODO(samomekarajr): Add `row-rule` to this test.
|
||||
const rule_properties = {
|
||||
'column-rule': ['column-rule-width',
|
||||
'column-rule-style',
|
||||
'column-rule-color'],
|
||||
'row-rule': ['row-rule-width',
|
||||
'row-rule-style',
|
||||
'row-rule-color'],
|
||||
'rule': [
|
||||
['column-rule-width', 'row-rule-width'],
|
||||
['column-rule-style', 'row-rule-style'],
|
||||
['column-rule-color', 'row-rule-color'],
|
||||
]
|
||||
|
||||
};
|
||||
|
||||
for(rule_property in rule_properties) {
|
||||
const [width, style, color] = rule_properties[rule_property];
|
||||
const testCases = [
|
||||
// <gap-rule> = [<line-width> || <line-style> || <line-color>].
|
||||
test_shorthand_value(rule_property, '5px solid red', {
|
||||
[width]: '5px',
|
||||
[style]: 'solid',
|
||||
[color]: 'red'
|
||||
});
|
||||
{
|
||||
input: '5px solid red',
|
||||
expected: {
|
||||
width: '5px',
|
||||
style: 'solid',
|
||||
color: 'red'
|
||||
}
|
||||
},
|
||||
{
|
||||
input: 'double',
|
||||
expected: {
|
||||
width: 'medium',
|
||||
style: 'double',
|
||||
color: 'currentcolor'
|
||||
}
|
||||
},
|
||||
{
|
||||
input: 'blue 10px',
|
||||
expected: {
|
||||
width: '10px',
|
||||
style: 'none',
|
||||
color: 'blue'
|
||||
}
|
||||
},
|
||||
|
||||
test_shorthand_value(rule_property, 'double', {
|
||||
[width]: 'medium',
|
||||
[style]: 'double',
|
||||
[color]: 'currentcolor'
|
||||
});
|
||||
// <gap-auto-repeat-rule> = repeat(auto, <gap-rule># ).
|
||||
{
|
||||
input: 'repeat(auto, 5px solid green)',
|
||||
expected: {
|
||||
width: 'repeat(auto, 5px)',
|
||||
style: 'repeat(auto, solid)',
|
||||
color: 'repeat(auto, green)'
|
||||
}
|
||||
},
|
||||
{
|
||||
input: 'repeat(auto, 5px solid yellow, 10px dotted blue)',
|
||||
expected: {
|
||||
width: 'repeat(auto, 5px 10px)',
|
||||
style: 'repeat(auto, solid dotted)',
|
||||
color: 'repeat(auto, yellow blue)'
|
||||
}
|
||||
},
|
||||
{
|
||||
input: 'repeat(auto, blue 6px, 5px solid red)',
|
||||
expected: {
|
||||
width: 'repeat(auto, 6px 5px)',
|
||||
style: 'repeat(auto, none solid)',
|
||||
color: 'repeat(auto, blue red)'
|
||||
}
|
||||
},
|
||||
|
||||
test_shorthand_value(rule_property, 'blue 10px', {
|
||||
[width]: '10px',
|
||||
[style]: 'none',
|
||||
[color]: 'blue'
|
||||
});
|
||||
|
||||
// <gap-auto-repeat-rule> = repeat( auto , <gap-rule># ).
|
||||
test_shorthand_value(rule_property, 'repeat(auto, 5px solid green)', {
|
||||
[width]: 'repeat(auto, 5px)',
|
||||
[style]: 'repeat(auto, solid)',
|
||||
[color]: 'repeat(auto, green)'
|
||||
});
|
||||
|
||||
test_shorthand_value(rule_property, 'repeat(auto, 5px solid yellow, 10px dotted blue)', {
|
||||
[width]: 'repeat(auto, 5px 10px)',
|
||||
[style]: 'repeat(auto, solid dotted)',
|
||||
[color]: 'repeat(auto, yellow blue)'
|
||||
});
|
||||
|
||||
test_shorthand_value(rule_property, 'repeat(auto, blue 6px, 5px solid red)', {
|
||||
[width]: 'repeat(auto, 6px 5px)',
|
||||
[style]: 'repeat(auto, none solid)',
|
||||
[color]: 'repeat(auto, blue red)'
|
||||
});
|
||||
|
||||
// <gap-repeat-rule> = repeat( <integer [1,∞]> , <gap-rule># ).
|
||||
test_shorthand_value(rule_property, 'repeat(4, 15px dotted pink)', {
|
||||
[width]: 'repeat(4, 15px)',
|
||||
[style]: 'repeat(4, dotted)',
|
||||
[color]: 'repeat(4, pink)'
|
||||
});
|
||||
test_shorthand_value(rule_property, 'repeat(1, 15px ridge yellow, 10px dotted blue, 15px double green)', {
|
||||
[width]: 'repeat(1, 15px 10px 15px)',
|
||||
[style]: 'repeat(1, ridge dotted double)',
|
||||
[color]: 'repeat(1, yellow blue green)'
|
||||
});
|
||||
test_shorthand_value(rule_property, 'repeat(3, lime 16px, dashed purple, 10px dotted)', {
|
||||
[width]: 'repeat(3, 16px medium 10px)',
|
||||
[style]: 'repeat(3, none dashed dotted)',
|
||||
[color]: 'repeat(3, lime purple currentcolor)'
|
||||
});
|
||||
// <gap-repeat-rule> = repeat(<integer [1,∞]>, <gap-rule># ).
|
||||
{
|
||||
input: 'repeat(4, 15px dotted pink)',
|
||||
expected: {
|
||||
width: 'repeat(4, 15px)',
|
||||
style: 'repeat(4, dotted)',
|
||||
color: 'repeat(4, pink)'
|
||||
}
|
||||
},
|
||||
{
|
||||
input: 'repeat(1, 15px ridge yellow, 10px dotted blue, 15px double green)',
|
||||
expected: {
|
||||
width: 'repeat(1, 15px 10px 15px)',
|
||||
style: 'repeat(1, ridge dotted double)',
|
||||
color: 'repeat(1, yellow blue green)'
|
||||
}
|
||||
},
|
||||
{
|
||||
input: 'repeat(3, lime 16px, dashed purple, 10px dotted)',
|
||||
expected: {
|
||||
width: 'repeat(3, 16px medium 10px)',
|
||||
style: 'repeat(3, none dashed dotted)',
|
||||
color: 'repeat(3, lime purple currentcolor)'
|
||||
}
|
||||
},
|
||||
|
||||
// <gap-rule-list> = <gap-rule-or-repeat>#.
|
||||
// <gap-rule-or-repeat> = <gap-rule> | <gap-repeat-rule>.
|
||||
test_shorthand_value(rule_property, 'thin, dashed, hotpink', {
|
||||
[width]: 'thin medium medium',
|
||||
[style]: 'none dashed none',
|
||||
[color]: 'currentcolor currentcolor hotpink'
|
||||
});
|
||||
test_shorthand_value(rule_property, '5px double salmon, repeat(4, 5px ridge red)', {
|
||||
[width]: '5px repeat(4, 5px)',
|
||||
[style]: 'double repeat(4, ridge)',
|
||||
[color]: 'salmon repeat(4, red)'
|
||||
});
|
||||
test_shorthand_value(rule_property,
|
||||
'repeat(2, dashed gray, 10px blue dotted, 20px double), 5px solid red, repeat(4, blue 6px, 5px solid white)', {
|
||||
[width]: 'repeat(2, medium 10px 20px) 5px repeat(4, 6px 5px)',
|
||||
[style]: 'repeat(2, dashed dotted double) solid repeat(4, none solid)',
|
||||
[color]: 'repeat(2, gray blue currentcolor) red repeat(4, blue white)'
|
||||
});
|
||||
test_shorthand_value(rule_property, 'repeat(4, thick hidden skyblue), repeat(3, 5px solid red, 10px dotted)', {
|
||||
[width]: 'repeat(4, thick) repeat(3, 5px 10px)',
|
||||
[style]: 'repeat(4, hidden) repeat(3, solid dotted)',
|
||||
[color]: 'repeat(4, skyblue) repeat(3, red currentcolor)'
|
||||
});
|
||||
{
|
||||
input: 'thin, dashed, hotpink',
|
||||
expected: {
|
||||
width: 'thin medium medium',
|
||||
style: 'none dashed none',
|
||||
color: 'currentcolor currentcolor hotpink'
|
||||
}
|
||||
},
|
||||
{
|
||||
input: '5px double salmon, repeat(4, 5px ridge red)',
|
||||
expected: {
|
||||
width: '5px repeat(4, 5px)',
|
||||
style: 'double repeat(4, ridge)',
|
||||
color: 'salmon repeat(4, red)'
|
||||
}
|
||||
},
|
||||
{
|
||||
input: 'repeat(2, dashed gray, 10px blue dotted, 20px double), 5px solid red, repeat(4, blue 6px, 5px solid white)',
|
||||
expected: {
|
||||
width: 'repeat(2, medium 10px 20px) 5px repeat(4, 6px 5px)',
|
||||
style: 'repeat(2, dashed dotted double) solid repeat(4, none solid)',
|
||||
color: 'repeat(2, gray blue currentcolor) red repeat(4, blue white)'
|
||||
}
|
||||
},
|
||||
{
|
||||
input: 'repeat(4, thick hidden skyblue), repeat(3, 5px solid red, 10px dotted)',
|
||||
expected: {
|
||||
width: 'repeat(4, thick) repeat(3, 5px 10px)',
|
||||
style: 'repeat(4, hidden) repeat(3, solid dotted)',
|
||||
color: 'repeat(4, skyblue) repeat(3, red currentcolor)'
|
||||
}
|
||||
},
|
||||
|
||||
// <gap-auto-rule-list> = <gap-rule-or-repeat>#? ,
|
||||
// <gap-auto-repeat-rule> ,
|
||||
// <gap-rule-or-repeat>#?.
|
||||
test_shorthand_value(rule_property,
|
||||
'repeat(auto, 10px solid red), medium dotted green, repeat(3, thick dashed blue, 15px double green)', {
|
||||
[width]: 'repeat(auto, 10px) medium repeat(3, thick 15px)',
|
||||
[style]: 'repeat(auto, solid) dotted repeat(3, dashed double)',
|
||||
[color]: 'repeat(auto, red) green repeat(3, blue green)'
|
||||
});
|
||||
{
|
||||
input: 'repeat(auto, 10px solid red), medium dotted green, repeat(3, thick dashed blue, 15px double green)',
|
||||
expected: {
|
||||
width: 'repeat(auto, 10px) medium repeat(3, thick 15px)',
|
||||
style: 'repeat(auto, solid) dotted repeat(3, dashed double)',
|
||||
color: 'repeat(auto, red) green repeat(3, blue green)'
|
||||
}
|
||||
},
|
||||
{
|
||||
input: 'ridge red, repeat(auto, 5px solid green), 10px dotted blue',
|
||||
expected: {
|
||||
width: 'medium repeat(auto, 5px) 10px',
|
||||
style: 'ridge repeat(auto, solid) dotted',
|
||||
color: 'red repeat(auto, green) blue'
|
||||
}
|
||||
},
|
||||
{
|
||||
input: '10px dotted salmon, repeat(4, thin blue, hidden 5px purple), repeat(auto, 5px solid red, teal)',
|
||||
expected: {
|
||||
width: '10px repeat(4, thin 5px) repeat(auto, 5px medium)',
|
||||
style: 'dotted repeat(4, none hidden) repeat(auto, solid none)',
|
||||
color: 'salmon repeat(4, blue purple) repeat(auto, red teal)'
|
||||
}
|
||||
} ];
|
||||
|
||||
test_shorthand_value(rule_property, 'ridge red, repeat(auto, 5px solid green), 10px dotted blue', {
|
||||
[width]: 'medium repeat(auto, 5px) 10px',
|
||||
[style]: 'ridge repeat(auto, solid) dotted',
|
||||
[color]: 'red repeat(auto, green) blue'
|
||||
});
|
||||
for(rule_property in rule_properties) {
|
||||
const [width, style, color] = rule_properties[rule_property];
|
||||
|
||||
test_shorthand_value(rule_property,
|
||||
'10px dotted salmon, repeat(4, thin blue, hidden 5px purple), repeat(auto, 5px solid red, teal)', {
|
||||
[width]: '10px repeat(4, thin 5px) repeat(auto, 5px medium)',
|
||||
[style]: 'dotted repeat(4, none hidden) repeat(auto, solid none)',
|
||||
[color]: 'salmon repeat(4, blue purple) repeat(auto, red teal)'
|
||||
});
|
||||
for (const { input, expected } of testCases) {
|
||||
if (rule_property === 'rule') {
|
||||
test_shorthand_value(rule_property, input, {
|
||||
[width[0]]: expected.width,
|
||||
[width[1]]: expected.width,
|
||||
[style[0]]: expected.style,
|
||||
[style[1]]: expected.style,
|
||||
[color[0]]: expected.color,
|
||||
[color[1]]: expected.color
|
||||
});
|
||||
} else {
|
||||
test_shorthand_value(rule_property, input, {
|
||||
[width]: expected.width,
|
||||
[style]: expected.style,
|
||||
[color]: expected.color
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -105,17 +105,21 @@ function mutateContent() {
|
|||
</div>
|
||||
</body>
|
||||
<script>
|
||||
document.body.offsetHeight;
|
||||
mutateContent();
|
||||
document.body.offsetHeight;
|
||||
setup({ explicit_done: true });
|
||||
document.fonts.ready.then(() => {
|
||||
document.body.offsetHeight;
|
||||
mutateContent();
|
||||
document.body.offsetHeight;
|
||||
|
||||
let tests = document.querySelectorAll(".test");
|
||||
tests.forEach((element) => {
|
||||
test(function() {
|
||||
let expectedHeight = element.getAttribute("data-expected-height");
|
||||
assert_equals(element.offsetHeight, Number(expectedHeight), "height");
|
||||
let tests = document.querySelectorAll(".test");
|
||||
tests.forEach((element) => {
|
||||
test(function() {
|
||||
let expectedHeight = element.getAttribute("data-expected-height");
|
||||
assert_equals(element.offsetHeight, Number(expectedHeight), "height");
|
||||
});
|
||||
});
|
||||
});
|
||||
done();
|
||||
})
|
||||
</script>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>Eight Red Triangles on White Ground (with gradients)</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#propdef-background-size">
|
||||
<meta name="assert" content="Gradients are correctly repeated.">
|
||||
<meta name="fuzzy" content="maxDifference=0-1;totalPixels=0-40000">
|
||||
<link rel="match" href="tiled-gradients-ref.html">
|
||||
<style>
|
||||
#gradient {
|
||||
width: 400px;
|
||||
height: 200px;
|
||||
background-size: 25% 50%;
|
||||
background-image: linear-gradient(to bottom left, red 50%, transparent 50%);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="gradient"></div>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Eight Red Triangles on White Ground (with gradients)</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#propdef-background-size">
|
||||
<meta name="assert" content="Gradients are correctly repeated.">
|
||||
<meta name="fuzzy" content="0-255; 0-564">
|
||||
<link rel="match" href="tiled-gradients-ref.html">
|
||||
<style>
|
||||
#gradient {
|
||||
width: 400px;
|
||||
height: 200px;
|
||||
background-size: 25% 50%;
|
||||
background-image: linear-gradient(to bottom left, red 50%, transparent 50%);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="gradient"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -65,7 +65,10 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
test(()=> {
|
||||
setup({ explicit_done: true });
|
||||
|
||||
document.fonts.ready.then(() => {
|
||||
test(()=> {
|
||||
var span = document.querySelector("#horizontalTbLtr span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -77,9 +80,9 @@
|
|||
assert_equals(rects[2].top, 70);
|
||||
assert_equals(rects[3].left, 300);
|
||||
assert_equals(rects[3].top, 50);
|
||||
}, "horizontal-tb ltr");
|
||||
}, "horizontal-tb ltr");
|
||||
|
||||
test(()=> {
|
||||
test(()=> {
|
||||
var span = document.querySelector("#verticalLrLtr span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -91,9 +94,9 @@
|
|||
assert_equals(rects[2].top, 150);
|
||||
assert_equals(rects[3].left, 100);
|
||||
assert_equals(rects[3].top, 250);
|
||||
}, "vertical-lr ltr");
|
||||
}, "vertical-lr ltr");
|
||||
|
||||
test(()=> {
|
||||
test(()=> {
|
||||
var span = document.querySelector("#verticalRlLtr span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -105,8 +108,9 @@
|
|||
assert_equals(rects[2].top, 150);
|
||||
assert_equals(rects[3].left, 120);
|
||||
assert_equals(rects[3].top, 250);
|
||||
}, "vertical-rl ltr");
|
||||
test(()=> {
|
||||
}, "vertical-rl ltr");
|
||||
|
||||
test(()=> {
|
||||
var span = document.querySelector("#horizontalTbRtl span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -118,8 +122,9 @@
|
|||
assert_equals(rects[2].top, 70);
|
||||
assert_equals(rects[3].left, 110);
|
||||
assert_equals(rects[3].top, 50);
|
||||
}, "horizontal-tb rtl");
|
||||
test(()=> {
|
||||
}, "horizontal-tb rtl");
|
||||
|
||||
test(()=> {
|
||||
var span = document.querySelector("#verticalLrRtl span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -131,8 +136,9 @@
|
|||
assert_equals(rects[2].top, 160);
|
||||
assert_equals(rects[3].left, 100);
|
||||
assert_equals(rects[3].top, 60);
|
||||
}, "vertical-lr rtl");
|
||||
test(()=> {
|
||||
}, "vertical-lr rtl");
|
||||
|
||||
test(()=> {
|
||||
var span = document.querySelector("#verticalRlRtl span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -144,5 +150,8 @@
|
|||
assert_equals(rects[2].top, 160);
|
||||
assert_equals(rects[3].left, 120);
|
||||
assert_equals(rects[3].top, 60);
|
||||
}, "vertical-rl rtl");
|
||||
}, "vertical-rl rtl");
|
||||
|
||||
done();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -102,7 +102,10 @@
|
|||
const GAP = 10;
|
||||
const TEXT_SIZE = 80;
|
||||
|
||||
test(()=> {
|
||||
setup({ explicit_done: true });
|
||||
|
||||
document.fonts.ready.then(() => {
|
||||
test(()=> {
|
||||
var span = document.querySelector("#horizontalTbLtr span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -114,9 +117,9 @@
|
|||
assert_equals(rects[2].top, 70);
|
||||
assert_equals(rects[3].left, 300);
|
||||
assert_equals(rects[3].top, 50);
|
||||
}, "horizontal-tb ltr");
|
||||
}, "horizontal-tb ltr");
|
||||
|
||||
test(()=> {
|
||||
test(()=> {
|
||||
var span = document.querySelector("#verticalLrLtr span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -128,9 +131,9 @@
|
|||
assert_equals(rects[2].top, 150);
|
||||
assert_equals(rects[3].left, 100);
|
||||
assert_equals(rects[3].top, 250);
|
||||
}, "vertical-lr ltr");
|
||||
}, "vertical-lr ltr");
|
||||
|
||||
test(()=> {
|
||||
test(()=> {
|
||||
var span = document.querySelector("#verticalRlLtr span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -142,9 +145,9 @@
|
|||
assert_equals(rects[2].top, 150);
|
||||
assert_equals(rects[3].left, 120);
|
||||
assert_equals(rects[3].top, 250);
|
||||
}, "vertical-rl ltr");
|
||||
}, "vertical-rl ltr");
|
||||
|
||||
test(()=> {
|
||||
test(()=> {
|
||||
var span = document.querySelector("#sidewaysLrLtr span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -156,9 +159,9 @@
|
|||
assert_equals(rects[2].top, TOP + COLUMN * 2 + GAP - TEXT_SIZE);
|
||||
assert_equals(rects[3].left, LEFT);
|
||||
assert_equals(rects[3].top, TOP + COLUMN - TEXT_SIZE);
|
||||
}, "sideways-lr ltr");
|
||||
}, "sideways-lr ltr");
|
||||
|
||||
test(()=> {
|
||||
test(()=> {
|
||||
var span = document.querySelector("#sidewaysRlLtr span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -170,9 +173,9 @@
|
|||
assert_equals(rects[2].top, TOP + COLUMN + GAP);
|
||||
assert_equals(rects[3].left, LEFT + LINE);
|
||||
assert_equals(rects[3].top, TOP + COLUMN * 2 + GAP * 2);
|
||||
}, "sideways-rl ltr");
|
||||
}, "sideways-rl ltr");
|
||||
|
||||
test(()=> {
|
||||
test(()=> {
|
||||
var span = document.querySelector("#horizontalTbRtl span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -184,8 +187,9 @@
|
|||
assert_equals(rects[2].top, 70);
|
||||
assert_equals(rects[3].left, 110);
|
||||
assert_equals(rects[3].top, 50);
|
||||
}, "horizontal-tb rtl");
|
||||
test(()=> {
|
||||
}, "horizontal-tb rtl");
|
||||
|
||||
test(()=> {
|
||||
var span = document.querySelector("#verticalLrRtl span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -197,8 +201,9 @@
|
|||
assert_equals(rects[2].top, 160);
|
||||
assert_equals(rects[3].left, 100);
|
||||
assert_equals(rects[3].top, 60);
|
||||
}, "vertical-lr rtl");
|
||||
test(()=> {
|
||||
}, "vertical-lr rtl");
|
||||
|
||||
test(()=> {
|
||||
var span = document.querySelector("#verticalRlRtl span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -210,9 +215,9 @@
|
|||
assert_equals(rects[2].top, 160);
|
||||
assert_equals(rects[3].left, 120);
|
||||
assert_equals(rects[3].top, 60);
|
||||
}, "vertical-rl rtl");
|
||||
}, "vertical-rl rtl");
|
||||
|
||||
test(()=> {
|
||||
test(()=> {
|
||||
var span = document.querySelector("#sidewaysLrRtl span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -224,9 +229,9 @@
|
|||
assert_equals(rects[2].top, TOP + COLUMN + GAP);
|
||||
assert_equals(rects[3].left, LEFT);
|
||||
assert_equals(rects[3].top, TOP + COLUMN + GAP + COLUMN + GAP);
|
||||
}, "sideways-lr rtl");
|
||||
}, "sideways-lr rtl");
|
||||
|
||||
test(()=> {
|
||||
test(()=> {
|
||||
var span = document.querySelector("#sidewaysRlRtl span");
|
||||
var rects = span.getClientRects();
|
||||
assert_equals(rects.length, 4);
|
||||
|
@ -238,5 +243,8 @@
|
|||
assert_equals(rects[2].top, TOP + COLUMN * 2 + GAP - TEXT_SIZE);
|
||||
assert_equals(rects[3].left, LEFT + LINE);
|
||||
assert_equals(rects[3].top, TOP + COLUMN - TEXT_SIZE);
|
||||
}, "sideways-rl rtl");
|
||||
}, "sideways-rl rtl");
|
||||
|
||||
done();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -22,20 +22,28 @@
|
|||
</span>
|
||||
</div>
|
||||
<script>
|
||||
test(()=> {
|
||||
setup({ explicit_done: true });
|
||||
document.fonts.ready.then(() => {
|
||||
test(() => {
|
||||
assert_equals(outer.offsetWidth, 292);
|
||||
assert_equals(outer.offsetHeight, 40);
|
||||
}, "outer");
|
||||
test(()=> {
|
||||
|
||||
test(() => {
|
||||
assert_equals(middle.offsetWidth, 150);
|
||||
assert_equals(middle.offsetHeight, 40);
|
||||
}, "middle");
|
||||
test(()=> {
|
||||
|
||||
test(() => {
|
||||
assert_equals(inner1.offsetWidth, 64);
|
||||
assert_equals(inner1.offsetHeight, 24);
|
||||
}, "inner1");
|
||||
test(()=> {
|
||||
|
||||
test(() => {
|
||||
assert_equals(inner2.offsetWidth, 110);
|
||||
assert_equals(inner2.offsetHeight, 40);
|
||||
}, "inner2");
|
||||
|
||||
done();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
const currentColor = 'rgb(0, 255, 0)';
|
||||
const mediumWidth = getComputedStyle(document.getElementById('reference')).columnRuleWidth; // e.g. 3px
|
||||
|
||||
test_computed_value("column-rule", "10px", "0px none " + currentColor);
|
||||
test_computed_value("column-rule", "10px", "0px " + currentColor);
|
||||
test_computed_value("column-rule", "dotted", mediumWidth + " dotted " + currentColor);
|
||||
test_computed_value("column-rule", "0px none rgb(255, 0, 255)");
|
||||
test_computed_value("column-rule", "0px none rgb(255, 0, 255)", "0px rgb(255, 0, 255)");
|
||||
test_computed_value("column-rule", "10px dotted rgb(255, 0, 255)");
|
||||
|
||||
test_computed_value("column-rule", "medium hidden currentcolor", "0px hidden " + currentColor);
|
||||
|
|
25
tests/wpt/tests/css/css-properties-values-api/registered-property-ident-function.html
vendored
Normal file
25
tests/wpt/tests/css/css-properties-values-api/registered-property-ident-function.html
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Properties Values API: Registered custom properties with ident()</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-5/#ident">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-properties-values-api-1">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
@property --ident {
|
||||
syntax: "<custom-ident>";
|
||||
inherits: true;
|
||||
initial-value: none;
|
||||
}
|
||||
</style>
|
||||
<div id=target></div>
|
||||
<script>
|
||||
let actual_ident = 'ident("--myident" calc(42 * sign(1em - 1px)))';
|
||||
let expected_ident = '--myident42';
|
||||
|
||||
test((t) => {
|
||||
t.add_cleanup(() => { target.style = ''; })
|
||||
target.style.setProperty('--ident', actual_ident);
|
||||
assert_equals(getComputedStyle(target).getPropertyValue('--ident'),
|
||||
expected_ident);
|
||||
}, 'The ident() function is resolved in a registered custom property');
|
||||
</script>
|
220
tests/wpt/tests/css/css-ruby/line-spacing.html
vendored
220
tests/wpt/tests/css/css-ruby/line-spacing.html
vendored
|
@ -23,11 +23,17 @@ body > div {
|
|||
text-emphasis: 'x';
|
||||
text-emphasis-position: under left;
|
||||
}
|
||||
|
||||
#log {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
setup({ explicit_done: true });
|
||||
|
||||
function renderRuby(source) {
|
||||
document.body.insertAdjacentHTML('afterbegin', source);
|
||||
const firstChild = document.body.firstChild;
|
||||
|
@ -45,120 +51,124 @@ function renderRubyAndGetBoxes(source) {
|
|||
};
|
||||
}
|
||||
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRubyAndGetBoxes(
|
||||
'<div><ruby>base<rt>annotation</rt></ruby></div>');
|
||||
assert_true(container.top <= rt.top);
|
||||
assert_true(rt.top < ruby.top);
|
||||
}, 'Over ruby doesn\'t overflow the block');
|
||||
document.fonts.load("16px Ahem").then(() => {
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRubyAndGetBoxes(
|
||||
'<div><ruby>base<rt>annotation</rt></ruby></div>');
|
||||
assert_true(container.top <= rt.top);
|
||||
assert_true(rt.top < ruby.top);
|
||||
}, 'Over ruby doesn\'t overflow the block');
|
||||
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRubyAndGetBoxes(
|
||||
'<div>before <span style="vertical-align:32px;">' +
|
||||
'<ruby>base<rt>annotation</rt></ruby>' +
|
||||
'</span> after</div>');
|
||||
assert_true(container.top <= rt.top);
|
||||
assert_true(rt.top < ruby.top);
|
||||
}, 'Over ruby + vertical-align doesn\'t overflow the block');
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRubyAndGetBoxes(
|
||||
'<div>before <span style="vertical-align:32px;">' +
|
||||
'<ruby>base<rt>annotation</rt></ruby>' +
|
||||
'</span> after</div>');
|
||||
assert_true(container.top <= rt.top);
|
||||
assert_true(rt.top < ruby.top);
|
||||
}, 'Over ruby + vertical-align doesn\'t overflow the block');
|
||||
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRubyAndGetBoxes(
|
||||
'<div><ruby style="ruby-position:under">base<rt>annotation</rt></ruby></div>');
|
||||
assert_true(container.bottom >= rt.bottom);
|
||||
assert_true(rt.bottom > ruby.bottom);
|
||||
}, 'Under ruby doesn\'t overflow the block');
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRubyAndGetBoxes(
|
||||
'<div><ruby style="ruby-position:under">base<rt>annotation</rt></ruby></div>');
|
||||
assert_true(container.bottom >= rt.bottom);
|
||||
assert_true(rt.bottom > ruby.bottom);
|
||||
}, 'Under ruby doesn\'t overflow the block');
|
||||
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRubyAndGetBoxes(
|
||||
'<div>before <ruby style="vertical-align:-32px; ruby-position:under">' +
|
||||
'base<rt>annotation</rt></ruby> after</div>');
|
||||
assert_true(container.bottom >= rt.bottom);
|
||||
assert_true(rt.bottom > ruby.bottom);
|
||||
}, 'Under ruby + vertical-align doesn\'t overflow the block');
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRubyAndGetBoxes(
|
||||
'<div>before <ruby style="vertical-align:-32px; ruby-position:under">' +
|
||||
'base<rt>annotation</rt></ruby> after</div>');
|
||||
assert_true(container.bottom >= rt.bottom);
|
||||
assert_true(rt.bottom > ruby.bottom);
|
||||
}, 'Under ruby + vertical-align doesn\'t overflow the block');
|
||||
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div><ruby style="ruby-position:under">base<rt>annotation</rt></ruby>' +
|
||||
'<div>n</div></div>');
|
||||
const nextBlockBox = container.querySelector('div').getBoundingClientRect();
|
||||
const rtBox = rt.getBoundingClientRect();
|
||||
assert_greater_than_equal(nextBlockBox.top, rtBox.bottom);
|
||||
}, 'Under ruby doesn\'t overwrap with the next block');
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div><ruby style="ruby-position:under">base<rt>annotation</rt></ruby>' +
|
||||
'<div>n</div></div>');
|
||||
const nextBlockBox = container.querySelector('div').getBoundingClientRect();
|
||||
const rtBox = rt.getBoundingClientRect();
|
||||
assert_greater_than_equal(nextBlockBox.top, rtBox.bottom);
|
||||
}, 'Under ruby doesn\'t overwrap with the next block');
|
||||
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div><span>before</span><br><ruby>base<rt style="font-size:16px"' +
|
||||
'>annotation</rt></ruby></div>');
|
||||
const firstLine = container.querySelector('span').getBoundingClientRect();
|
||||
assert_true(ruby.getBoundingClientRect().top - firstLine.bottom > 1);
|
||||
}, 'Expand inter-lines spacing');
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div><span>before</span><br><ruby>base<rt style="font-size:16px"' +
|
||||
'>annotation</rt></ruby></div>');
|
||||
const firstLine = container.querySelector('span').getBoundingClientRect();
|
||||
assert_true(ruby.getBoundingClientRect().top - firstLine.bottom > 1);
|
||||
}, 'Expand inter-lines spacing');
|
||||
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div style="line-height:1.5;">' +
|
||||
'<span>First line</span><br>' +
|
||||
'<span>Second line</span><br>' +
|
||||
'<ruby>base<rt style="font-size:50%">' +
|
||||
'annotation</rt></ruby></div>');
|
||||
const firstLine = container.querySelector('span').getBoundingClientRect();
|
||||
const secondLine = container.querySelectorAll('span')[1].getBoundingClientRect();
|
||||
const rubyLine = ruby.getBoundingClientRect();
|
||||
assert_approx_equals(secondLine.top - firstLine.top, rubyLine.top - secondLine.top, 1);
|
||||
}, 'Consume half-leading of the previous line');
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div style="line-height:1.5;">' +
|
||||
'<span>First line</span><br>' +
|
||||
'<span>Second line</span><br>' +
|
||||
'<ruby>base<rt style="font-size:50%">' +
|
||||
'annotation</rt></ruby></div>');
|
||||
const firstLine = container.querySelector('span').getBoundingClientRect();
|
||||
const secondLine = container.querySelectorAll('span')[1].getBoundingClientRect();
|
||||
const rubyLine = ruby.getBoundingClientRect();
|
||||
assert_approx_equals(secondLine.top - firstLine.top, rubyLine.top - secondLine.top, 1);
|
||||
}, 'Consume half-leading of the previous line');
|
||||
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div style="line-height:1.5;">' +
|
||||
'<span>First line</span><br>' +
|
||||
'<span class="under_emp">Second line</span><br>' +
|
||||
'<ruby>base<rt style="font-size:50%">' +
|
||||
'annotation</rt></ruby></div>');
|
||||
const firstLine = container.querySelector('span').getBoundingClientRect();
|
||||
const secondLine = container.querySelectorAll('span')[1].getBoundingClientRect();
|
||||
const rubyLine = ruby.getBoundingClientRect();
|
||||
const RUBY_EMPHASIS_SIZE = 8;
|
||||
assert_greater_than_equal(rubyLine.top - secondLine.top,
|
||||
secondLine.top - firstLine.top + RUBY_EMPHASIS_SIZE);
|
||||
}, 'Don\'t Consume half-leading of the previous line with text-emphasis');
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div style="line-height:1.5;">' +
|
||||
'<span>First line</span><br>' +
|
||||
'<span class="under_emp">Second line</span><br>' +
|
||||
'<ruby>base<rt style="font-size:50%">' +
|
||||
'annotation</rt></ruby></div>');
|
||||
const firstLine = container.querySelector('span').getBoundingClientRect();
|
||||
const secondLine = container.querySelectorAll('span')[1].getBoundingClientRect();
|
||||
const rubyLine = ruby.getBoundingClientRect();
|
||||
const RUBY_EMPHASIS_SIZE = 8;
|
||||
assert_greater_than_equal(rubyLine.top - secondLine.top,
|
||||
secondLine.top - firstLine.top + RUBY_EMPHASIS_SIZE);
|
||||
}, 'Don\'t Consume half-leading of the previous line with text-emphasis');
|
||||
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div style="line-height:1.5;">' +
|
||||
'<span>First line</span><br>' +
|
||||
'<ruby style="ruby-position:under">base<rt style="font-size:50%">' +
|
||||
'annotation</rt></ruby><br>' +
|
||||
'<span>Third line</span></div>');
|
||||
const firstLine = container.querySelector('span').getBoundingClientRect();
|
||||
const rubyLine = ruby.getBoundingClientRect();
|
||||
const thirdLine = container.querySelectorAll('span')[1].getBoundingClientRect();
|
||||
assert_approx_equals(rubyLine.top - firstLine.top, thirdLine.top - rubyLine.top, 1);
|
||||
}, 'Consume half-leading of the next line');
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div style="line-height:1.5;">' +
|
||||
'<span>First line</span><br>' +
|
||||
'<ruby style="ruby-position:under">base<rt style="font-size:50%">' +
|
||||
'annotation</rt></ruby><br>' +
|
||||
'<span>Third line</span></div>');
|
||||
const firstLine = container.querySelector('span').getBoundingClientRect();
|
||||
const rubyLine = ruby.getBoundingClientRect();
|
||||
const thirdLine = container.querySelectorAll('span')[1].getBoundingClientRect();
|
||||
assert_approx_equals(rubyLine.top - firstLine.top, thirdLine.top - rubyLine.top, 1);
|
||||
}, 'Consume half-leading of the next line');
|
||||
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div style="line-height:1.5;">' +
|
||||
'<span>First line</span><br>' +
|
||||
'<ruby style="ruby-position:under">base<rt style="font-size:50%">' +
|
||||
'annotation</rt></ruby><br>' +
|
||||
'<span class="over_emp">Third line</span>' +
|
||||
'</div>');
|
||||
const firstLine = container.querySelector('span').getBoundingClientRect();
|
||||
const rubyLine = ruby.getBoundingClientRect();
|
||||
const thirdLine = container.querySelectorAll('span')[1].getBoundingClientRect();
|
||||
const RUBY_EMPHASIS_SIZE = 8;
|
||||
assert_greater_than_equal(thirdLine.top - rubyLine.top,
|
||||
rubyLine.top - firstLine.top + RUBY_EMPHASIS_SIZE);
|
||||
}, 'Don\'t Consume half-leading of the next line with text-emphasis');
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div style="line-height:1.5;">' +
|
||||
'<span>First line</span><br>' +
|
||||
'<ruby style="ruby-position:under">base<rt style="font-size:50%">' +
|
||||
'annotation</rt></ruby><br>' +
|
||||
'<span class="over_emp">Third line</span>' +
|
||||
'</div>');
|
||||
const firstLine = container.querySelector('span').getBoundingClientRect();
|
||||
const rubyLine = ruby.getBoundingClientRect();
|
||||
const thirdLine = container.querySelectorAll('span')[1].getBoundingClientRect();
|
||||
const RUBY_EMPHASIS_SIZE = 8;
|
||||
assert_greater_than_equal(thirdLine.top - rubyLine.top,
|
||||
rubyLine.top - firstLine.top + RUBY_EMPHASIS_SIZE);
|
||||
}, 'Don\'t Consume half-leading of the next line with text-emphasis');
|
||||
|
||||
// crbug.com/336592423
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div style="line-height:1;">' +
|
||||
'<span style="display:inline-block; width:1em; height:4em; vertical-align:top"></span><br>' +
|
||||
'<ruby>base<rt>annotation</rt></ruby></div>');
|
||||
const firstLine = container.querySelector('span').getBoundingClientRect();
|
||||
const rtBox = rt.getBoundingClientRect();
|
||||
assert_greater_than_equal(rtBox.top, firstLine.bottom);
|
||||
}, 'An atomic-inline should not overlap with an annotation in the next line');
|
||||
// crbug.com/336592423
|
||||
test(() => {
|
||||
const {container, ruby, rt} = renderRuby(
|
||||
'<div style="line-height:1;">' +
|
||||
'<span style="display:inline-block; width:1em; height:4em; vertical-align:top"></span><br>' +
|
||||
'<ruby>base<rt>annotation</rt></ruby></div>');
|
||||
const firstLine = container.querySelector('span').getBoundingClientRect();
|
||||
const rtBox = rt.getBoundingClientRect();
|
||||
assert_greater_than_equal(rtBox.top, firstLine.bottom);
|
||||
}, 'An atomic-inline should not overlap with an annotation in the next line');
|
||||
|
||||
done();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
179
tests/wpt/tests/css/css-scroll-snap/input/paged.html
vendored
Normal file
179
tests/wpt/tests/css/css-scroll-snap/input/paged.html
vendored
Normal file
|
@ -0,0 +1,179 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-scroll-snap-1/#scroll-snap-type" />
|
||||
<title>Page scroll snapping</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1">
|
||||
<meta name="flags" content="should">
|
||||
<meta name="assert"
|
||||
content="Test passes if page operation doesn't skip content">
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/resources/testdriver-actions.js"></script>
|
||||
<script src="/dom/events/scrolling/scroll_support.js"></script>
|
||||
<script src="../support/common.js"></script>
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
}
|
||||
.scroller {
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
scroll-snap-type: y mandatory;
|
||||
counter-reset: --page;
|
||||
}
|
||||
|
||||
.gap {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.page {
|
||||
counter-increment: --page;
|
||||
height: 90vh;
|
||||
scroll-snap-align: center;
|
||||
padding: 8px;
|
||||
position: relative;
|
||||
--page: counter(--page);
|
||||
}
|
||||
.short {
|
||||
height: 25vh;
|
||||
}
|
||||
.page > div::before {
|
||||
content: "Page " counter(--page);
|
||||
font-size: 1.5em;
|
||||
}
|
||||
.page > div {
|
||||
box-sizing: border-box;
|
||||
border: 3px solid black;
|
||||
border-radius: 5px;
|
||||
overflow: clip; /* Make sure font size doesn't cause pages to be larger than expected. */
|
||||
padding: 8px;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
<div class="scroller" tabindex="0">
|
||||
<div class="page">
|
||||
<div>
|
||||
<p>This tests what happens when you perform a paging scroll (e.g. space bar or page down key) with mandatory scroll snap.</p>
|
||||
<p>When snapped to this page, pressing page down should not skip page 2.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="short page">
|
||||
<div>
|
||||
<p>This page should not be skipped by paging scroll operations.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page">
|
||||
<div>
|
||||
<p>We must stop at this page before going to page 4.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="short page">
|
||||
<div>
|
||||
<p>Pages 4, 5, and 6 should be a single snap stop on page 5.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="short page">
|
||||
<div>
|
||||
<p>
|
||||
This should be the snapped page when paging.
|
||||
The next page operation should jump to page 7.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="short page">
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="page">
|
||||
<div>
|
||||
<p>
|
||||
The next page is further than a page away,
|
||||
but there are no closer snap points
|
||||
so it should be scrolled to next.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gap"></div>
|
||||
<div class="page">
|
||||
<div>
|
||||
<p>
|
||||
The last page
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const scroller = document.querySelector(".scroller");
|
||||
|
||||
scrollTop = () => scroller.scrollTop;
|
||||
|
||||
async function snapTo(page) {
|
||||
if (page == 1 && scroller.scrollTop == 0)
|
||||
return;
|
||||
let scrollEndPromise = waitForScrollEndFallbackToDelayWithoutScrollEvent(scroller);
|
||||
scroller.scrollTop = 0;
|
||||
await scrollEndPromise;
|
||||
if (page > 1) {
|
||||
scrollEndPromise = waitForScrollEndFallbackToDelayWithoutScrollEvent(scroller);
|
||||
scroller.querySelector(`.page[data-page="${page}"]`).scrollIntoView({block: "center"});
|
||||
await scrollEndPromise;
|
||||
}
|
||||
}
|
||||
|
||||
scroller.querySelectorAll('.page').forEach((div, index) => {
|
||||
div.setAttribute("data-page", index + 1);
|
||||
});
|
||||
function visiblePages() {
|
||||
return Array.prototype.slice.apply(
|
||||
scroller.querySelectorAll('.page')).filter(
|
||||
div => div.offsetTop >= scroller.scrollTop &&
|
||||
div.offsetTop + div.offsetHeight <= scroller.scrollTop + scroller.clientHeight).map(
|
||||
div => parseInt(div.getAttribute("data-page")));
|
||||
}
|
||||
|
||||
async function pageDown() {
|
||||
const scrollEndPromise = waitForScrollEndFallbackToDelayWithoutScrollEvent(scroller);
|
||||
await keyPress(scroller, "Space");
|
||||
await scrollEndPromise;
|
||||
}
|
||||
|
||||
promise_test(async t => {
|
||||
await snapTo(1);
|
||||
assert_array_equals(visiblePages(), [1]);
|
||||
await pageDown();
|
||||
assert_array_equals(visiblePages(), [2]);
|
||||
}, `Doesn't skip past small snappable content`);
|
||||
|
||||
promise_test(async t => {
|
||||
await snapTo(2);
|
||||
assert_array_equals(visiblePages(), [2]);
|
||||
await pageDown();
|
||||
assert_array_equals(visiblePages(), [3]);
|
||||
}, `Doesn't skip past large snappable content`);
|
||||
|
||||
promise_test(async t => {
|
||||
await snapTo(3);
|
||||
assert_array_equals(visiblePages(), [3]);
|
||||
await pageDown();
|
||||
assert_array_equals(visiblePages(), [4, 5, 6]);
|
||||
}, `Scrolls multiple smaller items into view`);
|
||||
|
||||
promise_test(async t => {
|
||||
await snapTo(5);
|
||||
assert_array_equals(visiblePages(), [4, 5, 6]);
|
||||
await pageDown();
|
||||
assert_array_equals(visiblePages(), [7]);
|
||||
}, `Scrolls past items currently in view`);
|
||||
|
||||
promise_test(async t => {
|
||||
await snapTo(7);
|
||||
assert_array_equals(visiblePages(), [7]);
|
||||
await pageDown();
|
||||
assert_array_equals(visiblePages(), [8]);
|
||||
}, `Scrolls more than a page if necessary`);
|
||||
|
||||
</script>
|
|
@ -32,7 +32,7 @@
|
|||
generate_tests( ParsingUtils.testShapeMarginInlineStyle,
|
||||
ParsingUtils.buildTestCases(shape_margin_valid_unit_tests, "inline"));
|
||||
ParsingUtils.setupFonts();
|
||||
document.fonts.ready.then(()=> {
|
||||
document.fonts.load("10px Ahem").then(()=> {
|
||||
generate_tests( ParsingUtils.testShapeMarginComputedStyle,
|
||||
ParsingUtils.buildTestCases(shape_margin_valid_unit_tests, "computed"));
|
||||
ParsingUtils.restoreFonts();
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
generate_tests( ParsingUtils.testInlineStyle,
|
||||
ParsingUtils.buildPositionTests("circle", true, 'lengthUnit + inline', ParsingUtils.validUnits) );
|
||||
ParsingUtils.setupFonts();
|
||||
document.fonts.ready.then(()=> {
|
||||
document.fonts.load("10px Ahem").then(()=> {
|
||||
generate_tests( ParsingUtils.testComputedStyle,
|
||||
ParsingUtils.buildPositionTests("circle", true, 'lengthUnit + computed', ParsingUtils.validUnits) );
|
||||
ParsingUtils.restoreFonts();
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
setup({explicit_done: true});
|
||||
generate_tests(ParsingUtils.testInlineStyle, ParsingUtils.buildRadiiTests('circle', 'lengthUnit + inline', ParsingUtils.validUnits));
|
||||
ParsingUtils.setupFonts();
|
||||
document.fonts.ready.then(()=> {
|
||||
document.fonts.load("10px Ahem").then(()=> {
|
||||
generate_tests(ParsingUtils.testComputedStyle, ParsingUtils.buildRadiiTests('circle', 'lengthUnit + computed', ParsingUtils.validUnits));
|
||||
ParsingUtils.restoreFonts();
|
||||
done();
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
generate_tests( ParsingUtils.testInlineStyle,
|
||||
ParsingUtils.buildPositionTests("ellipse", true, 'lengthUnit + inline', ParsingUtils.validUnits) );
|
||||
ParsingUtils.setupFonts();
|
||||
document.fonts.ready.then(()=> {
|
||||
document.fonts.load("10px Ahem").then(()=> {
|
||||
generate_tests( ParsingUtils.testComputedStyle,
|
||||
ParsingUtils.buildPositionTests("ellipse", true, 'lengthUnit + computed', ParsingUtils.validUnits) );
|
||||
ParsingUtils.restoreFonts();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue