blob: cd46e166045c2cbc4351c364657708a36a6389dc [file] [log] [blame]
<!doctype html>
<html>
<head>
<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
<script>
function test()
{
let suite = InspectorTest.createSyncSuite("WI.CSSKeywordCompletions");
function addTestForPartialPropertyName({name, description, text, caretPosition, allowEmptyPrefix, expectedCompletions, expectedCompletionCount}) {
suite.addTestCase({
name,
description,
test() {
allowEmptyPrefix ??= false;
expectedCompletions ??= [];
expectedCompletionCount ??= -1;
// FIXME: <webkit.org/b/227157> Styles: Support completions mid-token.
caretPosition ??= text.length;
let completionResults = WI.CSSKeywordCompletions.forPartialPropertyName(text, {caretPosition, allowEmptyPrefix});
if (expectedCompletionCount >= 0)
InspectorTest.expectEqual(completionResults.completions.length, expectedCompletionCount, `Expected exactly ${expectedCompletionCount} completion results.`);
let completionStrings = completionResults.completions.map((completion) => WI.CSSCompletions.getCompletionText(completion));
// Because expected completions could be added at any time, just make sure the list contains our expected completions, instead of enforcing an exact match between expectations and reality.
let expectedCompletionsPresent = expectedCompletions.every((expectedCompletion) => {
if (!completionStrings.includes(expectedCompletion)) {
InspectorTest.fail(`Expected completion "${expectedCompletion}" in completions.`);
return false;
}
return true;
});
InspectorTest.expectThat(expectedCompletionsPresent, "All expected completions were present.");
}
});
}
addTestForPartialPropertyName({
name: "WI.CSSKeywordCompletions.forPartialPropertyName.emptyTextDisallowsEmptyPrefix",
description: "Test that for empty text, there should be no completions when `allowEmptyPrefix` is `false`.",
text: "",
allowEmptyPrefix: false,
expectedCompletionCount: 0,
});
addTestForPartialPropertyName({
name: "WI.CSSKeywordCompletions.forPartialPropertyName.emptyTextAllowsEmptyPrefix",
description: "Test that for empty text, there should be completions when `allowEmptyPrefix` is `true`.",
text: "",
allowEmptyPrefix: true,
expectedCompletions: ["border", "color", "margin", "padding"],
});
addTestForPartialPropertyName({
name: "WI.CSSKeywordCompletions.forPartialPropertyName.singleCharacterMatches",
description: "Test that for a common single character, there will be multiple completions available.",
text: "r",
expectedCompletions: ["r", "range", "resize", "right", "rotate", "row-gap", "rx", "ry"],
});
addTestForPartialPropertyName({
name: "WI.CSSKeywordCompletions.forPartialPropertyName.multipleCharacterMatches",
description: "Test that for a more specific set of characters, there will be some number of matches.",
text: "rang",
expectedCompletions: ["range"],
});
// FIXME: This test will fail after addressing <webkit.org/b/227157> Styles: Support completions mid-token.
addTestForPartialPropertyName({
name: "WI.CSSKeywordCompletions.forPartialPropertyName.midTokenNoCompletions",
description: "Test that completions are not provided when the caret is positioned within the token.",
text: "margin",
caretPosition: 1,
expectedCompletionCount: 0,
});
function addTestForPartialPropertyValue({name, description, propertyName, text, caretPosition, expectedPrefix, expectedCompletions, expectedCompletionCount, additionalFunctionValueCompletionsProvider}) {
suite.addTestCase({
name,
description,
test() {
caretPosition ??= text.length;
expectedPrefix ??= text;
expectedCompletions ??= [];
expectedCompletionCount ??= -1;
additionalFunctionValueCompletionsProvider ??= () => [];
let completionResults = WI.CSSKeywordCompletions.forPartialPropertyValue(text, propertyName, {caretPosition, additionalFunctionValueCompletionsProvider});
InspectorTest.expectEqual(completionResults.prefix, expectedPrefix, `Expected result prefix to be "${expectedPrefix}"`);
if (expectedCompletionCount >= 0)
InspectorTest.expectEqual(completionResults.completions.length, expectedCompletionCount, `Expected exactly ${expectedCompletionCount} completion results.`);
let completionStrings = completionResults.completions.map((completion) => WI.CSSCompletions.getCompletionText(completion));
// Because expected completions could be added at any time, just make sure the list contains our expected completions, instead of enforcing an exact match between expectations and reality.
let expectedCompletionsPresent = expectedCompletions.every((expectedCompletion) => {
if (!completionStrings.includes(expectedCompletion)) {
InspectorTest.fail(`Expected completion "${expectedCompletion}" in completions.`);
return false;
}
return true;
});
InspectorTest.expectThat(expectedCompletionsPresent, "All expected completions were present.");
}
});
}
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.EmptyTop",
description: "Test that an empty value provides the expected default completions.",
propertyName: "top",
text: "",
expectedCompletions: ["env()", "initial", "revert", "unset", "var()"],
});
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.EmptyColor",
description: "Test that color completions provide the color functions as completions.",
propertyName: "color",
text: "",
expectedCompletions: ["black", "blue", "green", "red", "white", "papayawhip", "color()", "color-contrast()", "color-mix()", "env()", "hsl()", "hsla()", "hwb()", "lab()", "lch()", "rgb()", "rgba()", "var()"],
});
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.PartialColor",
description: "Test that a partial color name that also matches a full color name still provides the other completion.",
propertyName: "color",
text: "papaya",
expectedCompletions: ["papayawhip"],
});
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.EmptyWordSpacing",
description: "Test that the `word-spacing` property provides its expected completions.",
propertyName: "word-spacing",
text: "",
expectedCompletions: ["normal", "calc()"],
});
// `border: 1px | red`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.MidLineBorder",
description: "Test that a completion can be performed between two other values.",
propertyName: "border",
text: "1px red",
caretPosition: 4,
expectedPrefix: "",
expectedCompletions: ["solid"],
});
// `top: env(|`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.EnvironmentFunctionCompletion",
description: "Test that a function completion can be performed inside a function without a closing parenthesis.",
propertyName: "top",
text: "env(",
expectedPrefix: "",
expectedCompletions: ["safe-area-inset-bottom", "safe-area-inset-left", "safe-area-inset-right", "safe-area-inset-top", "var()"],
});
// `top: env(|)`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.MidLineEnvironmentFunction",
description: " Test that a function completion can be performed inside a function with a closing parenthesis.",
propertyName: "top",
text: "env()",
caretPosition: 4,
expectedPrefix: "",
expectedCompletions: ["safe-area-inset-bottom", "safe-area-inset-left", "safe-area-inset-right", "safe-area-inset-top", "var()"],
});
// `grid-template-columns: repeat(au|`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.PartialFunctionValue",
description: "Test that completing a partial value inside a function produces expected completions.",
propertyName: "grid-template-columns",
text: "repeat(au",
expectedPrefix: "au",
expectedCompletions: ["auto-fill", "auto-fit"],
});
// `grid-template-columns: [linename1] 100px repeat(|, [linename2 linename3] 150px) [linename3] 100px [linename4]`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.ComplexMultiValueFunction",
description: " Test that performing a completion mid-line inside a function right before a separator character, like a comma, produces expected completions.",
propertyName: "grid-template-columns",
text: "[linename1] 100px repeat(, [linename2 linename3] 150px) [linename3] 100px [linename4]",
caretPosition: 25,
expectedPrefix: "",
expectedCompletions: ["auto-fill", "auto-fit", "var()"],
});
// `attr(|`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.AttributeFunction",
description: "Test that attribute function value completions from the custom provider are used.",
text: "attr(",
expectedPrefix: "",
expectedCompletions: ["class", "id", "var()"],
additionalFunctionValueCompletionsProvider: () => ["class", "id"],
});
// `attr(c|)`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.MidLineAttributeFunction",
description: "Test that attribute function value completions is inside a function with a closing parenthesis uses completions from the custom provider",
text: "attr(c)",
caretPosition: 6,
expectedPrefix: "c",
expectedCompletions: ["class"],
additionalFunctionValueCompletionsProvider: () => ["class", "id"],
});
// `var(|`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.VariableFunction",
description: "Test that variable function value completions from the custom provider are used.",
text: "var(",
expectedPrefix: "",
expectedCompletions: ["--one", "--two"],
additionalFunctionValueCompletionsProvider: () => ["--one", "--two"],
});
// `var(--o|`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.VariableFunctionFiltered",
description: "Test that variable function value completions from the custom provider are filtered.",
text: "var(--o",
expectedPrefix: "--o",
expectedCompletions: ["--one"],
additionalFunctionValueCompletionsProvider: () => ["--one", "--two"],
});
// `var(-x|`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.InvalidVariableName",
description: "Test that an invalid variable name is still used as a prefix",
text: "var(-x",
expectedPrefix: "-x",
expectedCompletions: [],
});
// `var(--|`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.IncompleteVariableName",
description: "Test that an incomplete variable name is still used as a prefix",
text: "var(--",
expectedPrefix: "--",
expectedCompletions: [],
});
// `env(--|`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.DashedEnvironmentVariableName",
description: "Test that a dashed name used within env() is entirely used as a prefix",
text: "env(--",
expectedPrefix: "--",
expectedCompletions: [],
});
// `-webkit|`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.VendorPrefixedValue",
description: "Test that a value that looks vendor-prefixed is entirely used as a prefix",
propertyName: "display",
text: "-webkit",
expectedPrefix: "-webkit",
expectedCompletions: ["-webkit-flex"],
});
// `calc(1 - |`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.SubtractionCalc",
description: "Test that a whitespace-separated minus sign in calc() isn't included in the prefix",
text: "calc(1 - ",
expectedPrefix: "",
expectedCompletions: [],
});
// `calc(1 + var(|))`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.VariableFunctionInCalc",
description: "Test that variable function value completions from the custom provider are used when the var() is nested inside a calc()",
text: "calc(1 + var())",
caretPosition: 13,
expectedPrefix: "",
expectedCompletions: ["--one", "--two"],
additionalFunctionValueCompletionsProvider: () => ["--one", "--two"],
});
// `hsl()a|`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.NoWhitespaceAfterFunction",
description: "Test that color completions are not offered immediately after a closing parenthesis",
propertyName: "background",
text: "hsl()a",
caretPosition: 6,
expectedPrefix: "",
expectedCompletionCount: 0
});
// `hsl() a|`
addTestForPartialPropertyValue({
name: "WI.CSSKeywordCompletions.forPartialPropertyValue.WhitespaceAfterFunction",
description: "Test that color completions are offered when a closing parenthesis is followed by whitespace",
propertyName: "background",
text: "hsl() a",
caretPosition: 7,
expectedPrefix: "a",
expectedCompletions: ["aliceblue", "antiquewhite"],
});
suite.runTestCasesAndFinish();
}
</script>
</head>
<body onload="runTest()">
<p>Testing WI.CSSKeywordCompletions.</p>
</body>
</html>