Commit 09bfd57f authored by meade's avatar meade Committed by Commit bot

Add a property test generator for testing the inline StylePropertyMap

This will allow easier testing of each property as we add support in
CSS Typed OM, as we will not have to hand-write exhaustive tests for each
property, and we will easily be able to add a new test that applies to
every element easily if we need to later.

The standard set of tests is:

*single-valued properties*
- Setting with a sequence of valid values throws
- Calling append with a valid value throws

*list-valued properties*
- Setting with a sequence of valid values works
- Setting with a sequence containing valid and invalid values throws
- Append succeeds with a valid value
- Appending a sequence of valid values succeeds
- Append throws when given an invalid value
- Append throws when given a sequence containing valid and invalid values
- GetAll when the property is set to a list returns all the properties

*common*
- Can be set to each valid keyword (automatically adds initial, inherit
    and unset)
- Can be set to each given valid instance of StyleValue
- Setting to an invalid type throws (automatically adds null, undefined,
    true, false, 1, 'hello', {}, and a fake keyword)
- Get returns the right KeywordValue when the property is set to each
    valid keyword
- Get returns the right StyleValue when the property is set to .cssText
    of each given valid StyleValue
- GetAll works when the property is set to a valid StyleValue instance
- Delete removes the style from the element
- GetProperties includes the name of the property when it is set
    to something

I've added example tests for "bottom" and "animation-direction", as
semi-random, convenient single-valued and list-valued properties.

Note that since getting CSSKeyword from a StylePropertyMap is not yet fully
supported, the new tests fail.

BUG=545318

Review-Url: https://codereview.chromium.org/2529043002
Cr-Commit-Position: refs/heads/master@{#435569}
parent 373df295
This is a testharness.js-based test.
PASS Setting animation-direction to normal
PASS Setting animation-direction to reverse
PASS Setting animation-direction to alternate
PASS Setting animation-direction to alternate-reverse
PASS Setting animation-direction to initial
PASS Setting animation-direction to inherit
PASS Setting animation-direction to unset
PASS Setting animation-direction to invalid value CSSSimpleLength throws
PASS Setting animation-direction to invalid value null throws
PASS Setting animation-direction to invalid value undefined throws
PASS Setting animation-direction to invalid value true throws
PASS Setting animation-direction to invalid value false throws
PASS Setting animation-direction to invalid value 1 throws
PASS Setting animation-direction to invalid value hello throws
PASS Setting animation-direction to invalid value [object Object] throws
PASS Setting animation-direction to invalid value CSSKeywordValue throws
FAIL Getting animation-direction when it is set to normal assert_true: result instanceof CSSKeywordValue: expected true got false
FAIL Getting animation-direction when it is set to reverse assert_true: result instanceof CSSKeywordValue: expected true got false
FAIL Getting animation-direction when it is set to alternate assert_true: result instanceof CSSKeywordValue: expected true got false
FAIL Getting animation-direction when it is set to alternate-reverse assert_true: result instanceof CSSKeywordValue: expected true got false
FAIL Getting animation-direction when it is set to initial assert_true: result instanceof CSSKeywordValue: expected true got false
FAIL Getting animation-direction when it is set to inherit assert_true: result instanceof CSSKeywordValue: expected true got false
FAIL Getting animation-direction when it is set to unset assert_true: result instanceof CSSKeywordValue: expected true got false
FAIL getAll for single-valued animation-direction assert_equals: Returned type is incorrect: expected "CSSKeywordValue" but got "CSSStyleValue"
FAIL getAll for list-valued animation-direction assert_equals: Expected getAll to return an array containing two instances of CSSStyleValue expected 2 but got 1
PASS Delete animation-direction removes the value form the styleMap
PASS animation-direction shows up in getProperties
FAIL Set animation-direction to a sequence assert_equals: expected "normal, normal" but got "normal normal"
PASS Set animation-direction to a sequence containing an invalid type
FAIL Appending a CSSKeywordValue to animation-direction assert_equals: expected "normal, normal" but got "normal normal"
FAIL Append a sequence to animation-direction assert_equals: expected "normal, normal" but got "normal normal"
PASS Appending an invalid value to animation-direction
PASS Append a sequence containing an invalid value to animation-direction
Harness: the test ran to completion.
<!DOCTYPE html>
<script src='../../../resources/testharness.js'></script>
<script src='../../../resources/testharnessreport.js'></script>
<script src='property-suite.js'></script>
<script>
runInlineStylePropertyMapTests( {
property: 'animation-direction',
validKeywords: [
'normal',
'reverse',
'alternate',
'alternate-reverse',
],
validObjects: [],
supportsMultiple: true,
invalidObjects: [new CSSSimpleLength(4, 'px')]
});
</script>
This is a testharness.js-based test.
PASS Setting bottom to auto
PASS Setting bottom to initial
PASS Setting bottom to inherit
PASS Setting bottom to unset
PASS Setting bottom to CSSSimpleLength with value 1px
PASS Setting bottom to CSSSimpleLength with value 2%
PASS Setting bottom to CSSSimpleLength with value 3em
PASS Setting bottom to CSSCalcLength with value calc(10% + 1px)
PASS Setting bottom to invalid value CSSNumberValue throws
PASS Setting bottom to invalid value null throws
PASS Setting bottom to invalid value undefined throws
PASS Setting bottom to invalid value true throws
PASS Setting bottom to invalid value false throws
PASS Setting bottom to invalid value 1 throws
PASS Setting bottom to invalid value hello throws
PASS Setting bottom to invalid value [object Object] throws
PASS Setting bottom to invalid value CSSKeywordValue throws
FAIL Getting bottom when it is set to auto assert_true: result instanceof CSSKeywordValue: expected true got false
FAIL Getting bottom when it is set to initial assert_true: result instanceof CSSKeywordValue: expected true got false
FAIL Getting bottom when it is set to inherit assert_true: result instanceof CSSKeywordValue: expected true got false
FAIL Getting bottom when it is set to unset assert_true: result instanceof CSSKeywordValue: expected true got false
PASS Getting bottom with a CSSSimpleLength whose value is 1px
PASS Getting bottom with a CSSSimpleLength whose value is 2%
PASS Getting bottom with a CSSSimpleLength whose value is 3em
FAIL Getting bottom with a CSSCalcLength whose value is calc(10% + 1px) assert_equals: typeof result expected "CSSCalcLength" but got "CSSStyleValue"
PASS getAll for single-valued bottom
PASS Delete bottom removes the value form the styleMap
PASS bottom shows up in getProperties
PASS Setting bottom to a sequence throws
PASS Appending to bottom throws
Harness: the test ran to completion.
<!DOCTYPE html>
<script src='../../../resources/testharness.js'></script>
<script src='../../../resources/testharnessreport.js'></script>
<script src='property-suite.js'></script>
<div id="testElement"></div>
<script>
runInlineStylePropertyMapTests({
property: 'bottom',
validKeywords: [
'auto'
],
validObjects: [
new CSSSimpleLength(1, 'px'),
new CSSSimpleLength(2, 'percent'),
new CSSSimpleLength(3, 'em'),
new CSSCalcLength({px: 1, percent: 10}),
],
supportsMultiple: false,
invalidObjects: [new CSSNumberValue(1)]
});
</script>
/**
* @fileoverview A standard set of tests for using a single property in an
* inline StylePropertyMap
* (https://www.w3.org/TR/css-typed-om-1/#the-stylepropertymap).
*
* Create a config object containing {
* validKeywords: array of strings,
* validObjects: array of CSSStyleValue instances that are valid for the
* property,
* supportsMultiple: boolean; whether the property supports a list of
* properties,
* invalidObjects: array of CSSStyleValue instances that are invalid for the
* property
* }
*
* Then, call runInlineStylePropertyMapTests to test the behavior of an inline
* StylePropertyMap for one CSS property for an element.
*
* Note that CSS-wide keywords, and non-CSSStyleValue invalid types do not need
* to be specified.
*
* If necessary, you can continue to define non-standard tests in your html
* file as usual.
*/
function runInlineStylePropertyMapTests(config) {
let element = document.createElement('div');
let validKeywords = config.validKeywords.concat([
// CSS-wide keywords
'initial',
'inherit',
'unset'
]);
let validObjects = config.validObjects;
let invalidObjects = config.invalidObjects.concat([
// No properties should take these values
null,
undefined,
true,
false,
1,
'hello',
{},
new CSSKeywordValue('notAKeyword')
]);
let validObject = validObjects.length ?
validObjects[0] : new CSSKeywordValue(validKeywords[0]);
let styleMap = element.styleMap;
runSetterTests(
config.property, validKeywords, validObjects, invalidObjects, element);
runGetterTests(config.property, validKeywords, validObjects, element);
runGetAllTests(
config.property, validObject, element, config.supportsMultiple);
runDeletionTests(config.property, validObject, element);
runGetPropertiesTests(config.property, validObject, element);
if (config.supportsMultiple) {
runSequenceSetterTests(
config.property, validObject, invalidObjects[0], element);
runAppendTests(
config.property, validObject, invalidObjects[0], element);
} else {
runMultipleValuesNotSupportedTests(
config.property, validObject, element);
}
}
function runSetterTests(
propertyName, validKeywords, validObjects, invalidObjects, element) {
for (let keyword of validKeywords) {
test(function() {
element.style = '';
element.styleMap.set(propertyName, new CSSKeywordValue(keyword));
assert_equals(element.style[propertyName], keyword);
}, 'Setting ' + propertyName + ' to ' + keyword);
}
for (let validObject of validObjects) {
test(function() {
element.style = '';
element.styleMap.set(propertyName, validObject);
assert_equals(element.style[propertyName], validObject.cssText);
}, 'Setting ' + propertyName + ' to ' + validObject.constructor.name +
' with value ' + validObject.cssText);
}
// Negative tests
for (let invalidObject of invalidObjects) {
let name = invalidObject instanceof CSSStyleValue ?
invalidObject.constructor.name : invalidObject;
test(function() {
assert_throws(new TypeError(), function() {
element.styleMap.set(propertyName, invalidObject);
});
}, 'Setting ' + propertyName + ' to invalid value ' + name + ' throws');
}
}
function runGetterTests(
propertyName, validKeywords, validObjects, element) {
for (let keyword of validKeywords) {
test(function() {
element.style[propertyName] = keyword;
let result = element.styleMap.get(propertyName);
assert_true(result instanceof CSSKeywordValue,
'result instanceof CSSKeywordValue:');
assert_equals(result.cssText, keyword);
}, 'Getting ' + propertyName + ' when it is set to ' + keyword);
}
for (let validObject of validObjects) {
test(function() {
element.style[propertyName] = validObject.cssText;
let result = element.styleMap.get(propertyName);
assert_equals(result.constructor.name, validObject.constructor.name,
'typeof result');
assert_equals(result.cssText, validObject.cssText);
}, 'Getting ' + propertyName + ' with a ' + validObject.constructor.name +
' whose value is ' + validObject.cssText);
}
}
function runSequenceSetterTests(
propertyName, validObject, invalidObject, element) {
test(function() {
element.style = '';
element.styleMap.set(propertyName, [validObject, validObject]);
assert_equals(
element.style[propertyName], validObject.cssText + ', ' +
validObject.cssText);
}, 'Set ' + propertyName + ' to a sequence');
test(function() {
let sequence = [validObject, invalidObject];
assert_throws(new TypeError(), function() {
element.styleMap.set(propertyName, sequence);
});
}, 'Set ' + propertyName + ' to a sequence containing an invalid type');
}
function runAppendTests(
propertyName, validObject, invalidObject, element) {
test(function() {
element.style = '';
element.styleMap.append(propertyName, validObject);
assert_equals(element.style[propertyName], validObject.cssText);
element.styleMap.append(propertyName, validObject);
assert_equals(
element.style[propertyName], validObject.cssText + ', ' +
validObject.cssText);
}, 'Appending a ' + validObject.constructor.name + ' to ' + propertyName);
test(function() {
element.style = '';
element.styleMap.append(propertyName, [validObject, validObject]);
assert_equals(
element.style[propertyName], validObject.cssText + ', ' +
validObject.cssText);
}, 'Append a sequence to ' + propertyName);
// Negative tests
test(function() {
assert_throws(new TypeError(), function() {
element.styleMap.append(propertyName, invalidObject);
});
}, 'Appending an invalid value to ' + propertyName);
test(function() {
let sequence = [validObject, invalidObject];
assert_throws(new TypeError(), function() {
element.styleMap.append(propertyName, sequence);
});
}, 'Append a sequence containing an invalid value to ' + propertyName);
}
function runGetAllTests(
propertyName, validObject, element, supportsMultiple) {
test(function() {
element.style = '';
assert_array_equals(element.styleMap.getAll(propertyName), []);
element.style[propertyName] = validObject.cssText;
let result = element.styleMap.getAll(propertyName);
assert_equals(result.length, 1,
'Expected getAll to retrieve an array containing a ' +
'single CSSStyleValue');
assert_equals(result[0].constructor.name, validObject.constructor.name,
'Returned type is incorrect:');
assert_equals(result[0].cssText, validObject.cssText);
}, 'getAll for single-valued ' + propertyName);
if (supportsMultiple) {
test(function() {
element.style = '';
element.styleMap.set(propertyName, [validObject, validObject]);
let result = element.styleMap.getAll(propertyName);
assert_equals(result.length, 2,
'Expected getAll to return an array containing two instances ' +
'of CSSStyleValue');
assert_true(result[0] instanceof CSSStyleValue,
'Expected first result to be an instance of CSSStyleValue');
assert_true(result[1] instanceof CSSStyleValue,
'Expected second result to be an instance of CSSStyleValue');
assert_equals(result[0].constructor.name, validObject.constructor.name);
assert_equals(result[1].constructor.name, validObject.constructor.name);
assert_equals(result[0].cssText, validObject.cssText);
assert_equals(result[1].cssText, validObject.cssText);
}, 'getAll for list-valued ' + propertyName);
}
}
function runDeletionTests(propertyName, validObject, element) {
test(function() {
element.style[propertyName] = validObject.cssText;
assert_not_equals(element.styleMap.get(propertyName), null);
element.styleMap.delete(propertyName);
assert_equals(element.style[propertyName], '');
assert_equals(element.styleMap.get(propertyName), null);
}, 'Delete ' + propertyName + ' removes the value form the styleMap');
}
function runGetPropertiesTests(propertyName, validObject, element) {
test(function() {
element.style = '';
assert_array_equals(element.styleMap.getProperties(), []);
element.styleMap.set(propertyName, validObject);
assert_array_equals(element.styleMap.getProperties(), [propertyName]);
}, propertyName + ' shows up in getProperties');
}
function runMultipleValuesNotSupportedTests(
propertyName, validObject, element) {
test(function() {
element.style = '';
assert_throws(new TypeError(), function() {
element.styleMap.set(propertyName, [validObject, validObject]);
});
}, 'Setting ' + propertyName + ' to a sequence throws');
test(function() {
element.style = '';
assert_throws(new TypeError(), function() {
element.styleMap.append(propertyName, validObject);
});
}, 'Appending to ' + propertyName + ' throws');
}
......@@ -124,7 +124,7 @@
// Animation Priority properties
animation-delay custom_all
animation-direction custom_all
animation-direction keywords=[normal|reverse|alternate|alternate-reverse], supports_multiple, custom_all
animation-duration custom_all
animation-fill-mode custom_all
animation-iteration-count keywords=[infinite], supports_multiple, custom_all
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment