Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement and test DOMTokenList.replace (fixes #8511) #9353

Merged
merged 2 commits into from Mar 25, 2016
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -139,6 +139,32 @@ impl DOMTokenListMethods for DOMTokenList {
self.element.set_tokenlist_attribute(&self.local_name, value);
}

// https://dom.spec.whatwg.org/#dom-domtokenlist-replace
fn Replace(&self, token: DOMString, new_token: DOMString) -> ErrorResult {
if token.is_empty() || new_token.is_empty() {
// Step 1.
return Err(Error::Syntax);
}
if token.contains(HTML_SPACE_CHARACTERS) || new_token.contains(HTML_SPACE_CHARACTERS) {
// Step 2.
return Err(Error::InvalidCharacter);
}
// Steps 3-4.
let token = Atom::from(token);
let new_token = Atom::from(new_token);
let mut atoms = self.element.get_tokenlist_attribute(&self.local_name);
if let Some(pos) = atoms.iter().position(|atom| *atom == token) {
if !atoms.contains(&new_token) {
atoms[pos] = new_token;
} else {
atoms.remove(pos);
}
}
// Step 5.
self.element.set_atomic_tokenlist_attribute(&self.local_name, atoms);
Ok(())
}

// https://dom.spec.whatwg.org/#concept-dtl-serialize
fn Stringifier(&self) -> DOMString {
self.element.get_string_attribute(&self.local_name)
@@ -18,6 +18,8 @@ interface DOMTokenList {
void remove(DOMString... tokens);
[Throws]
boolean toggle(DOMString token, optional boolean force);
[Throws]
void replace(DOMString token, DOMString newToken);

[Pure]
attribute DOMString value;
@@ -156,18 +156,9 @@
[DOMSettableTokenList interface object name]
expected: FAIL
[DOMTokenList interface: operation replace(DOMString,DOMString)]
expected: FAIL
[DOMTokenList interface: operation supports(DOMString)]
expected: FAIL
[DOMTokenList interface: document.body.classList must inherit property "replace" with the proper type (6)]
expected: FAIL
[DOMTokenList interface: calling replace(DOMString,DOMString) on document.body.classList with too few arguments must throw TypeError]
expected: FAIL
[DOMTokenList interface: document.body.classList must inherit property "supports" with the proper type (7)]
expected: FAIL
@@ -77,6 +77,13 @@
test(function () {
assert_throws( 'SYNTAX_ERR', function () { elem.classList.toggle(''); } );
}, '.toggle(empty_string) must throw a SYNTAX_ERR');
test(function () {
assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('', 'foo'); } );
assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('foo', ''); } );
assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('', 'foo bar'); } );
assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('foo bar', ''); } );
assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('', ''); } );
}, '.replace with empty_string must throw a SYNTAX_ERR');
test(function () {
assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.contains('a b'); } );
}, '.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
@@ -89,6 +96,20 @@
test(function () {
assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.toggle('a b'); } );
}, '.toggle(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
test(function () {
assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.replace('z', 'a b'); } );
assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.replace('a b', 'z'); } );
assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.replace('a b', 'b c'); } );
}, '.replace with string_with_spaces must throw a INVALID_CHARACTER_ERR');
test(function () {
var foo = document.createElement('div');
foo.className = 'token1 token2 token3'
foo.classList.replace('token1', 'token3');
assert_equals( foo.classList.length, 2 );
assert_false( foo.classList.contains('token1') );
assert_true( foo.classList.contains('token2') );
assert_true( foo.classList.contains('token3') );
}, '.replace with an already existing token')
elem.className = 'foo';
test(function () {
assert_equals( getComputedStyle(elem,null).fontStyle, 'italic', 'critical test; required by the testsuite' );
@@ -224,6 +245,58 @@
assert_false( elem.classList.contains('foo') );
assert_false( elem.classList.contains('FOO') );
}, 'classList.toggle must be case-sensitive when removing tokens');
test(function () {
secondelem.className = 'foo FOO'
secondelem.classList.replace('bar', 'baz');
assert_equals( secondelem.classList.length, 2 );
assert_equals( secondelem.classList + '', 'foo FOO', 'implicit' );
assert_equals( secondelem.classList.toString(), 'foo FOO', 'explicit' );
}, 'classList.replace replaces arguments passed, if they are present.');
test(function () {
secondelem.classList.replace('foo', 'bar');
assert_equals( secondelem.classList.length, 2 );
assert_equals( secondelem.classList + '', 'bar FOO', 'implicit' );
assert_equals( secondelem.classList.toString(), 'bar FOO', 'explicit' );
assert_false( secondelem.classList.contains('foo') );
assert_true( secondelem.classList.contains('bar') );
assert_true( secondelem.classList.contains('FOO') );
}, 'classList.replace must replace existing tokens');
test(function () {
assert_not_equals( getComputedStyle(secondelem,null).fontStyle, 'italic' );
}, 'classList.replace must not break case-sensitive CSS selector matching');
test(function () {
secondelem.className = 'token1 token2 token1'
secondelem.classList.replace('token1', 'token3');
assert_equals( secondelem.classList.length, 2 );
assert_false( secondelem.classList.contains('token1') );
assert_true( secondelem.classList.contains('token2') );
assert_true( secondelem.classList.contains('token3') );
}, 'classList.replace must replace duplicated tokens');
test(function () {
secondelem.className = 'token1 token2 token3';
secondelem.classList.replace('token2', 'token4');
assert_equals( secondelem.classList + '', 'token1 token4 token3', 'implicit' );
assert_equals( secondelem.classList.toString(), 'token1 token4 token3', 'explicit' );
}, 'classList.replace must collapse whitespace around replaced tokens');
test(function () {
secondelem.className = ' token1 token2 ';
secondelem.classList.replace('token2', 'token3');
assert_equals( secondelem.classList.length, 2 );
assert_equals( secondelem.classList + '', 'token1 token3', 'implicit' );
assert_equals( secondelem.classList.toString(), 'token1 token3', 'explicit' );
}, 'classList.replace must collapse whitespaces around each token');
test(function () {
secondelem.className = ' token1 token2 token1 ';
secondelem.classList.replace('token2', 'token3');
assert_equals( secondelem.classList + '', 'token1 token3', 'implicit' );
assert_equals( secondelem.classList.toString(), 'token1 token3', 'explicit' );
}, 'classList.replace must collapse whitespaces around each token and remove duplicates');
test(function () {
secondelem.className = ' token1 token2 token1 ';
secondelem.classList.replace('token1', 'token3');
assert_equals( secondelem.classList + '', 'token3 token2', 'implicit' );
assert_equals( secondelem.classList.toString(), 'token3 token2', 'explicit' );
}, 'classList.replace must collapse whitespace when replacing duplicate tokens');
test(function () {
assert_not_equals( getComputedStyle(elem,null).fontStyle, 'italic' );
}, 'CSS class selectors must stop matching when all classes have been removed');
@@ -245,6 +318,13 @@
WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
assert_equals( elem.classList[0], undefined );
}, 'classList[0] must be undefined when all classes have been removed');
test(function () {
var foo = document.createElement('div');
foo.classList.add();
assert_true( foo.hasAttribute('class') );
assert_equals( foo.classList + '', '', 'implicit' );
assert_equals( foo.classList.toString(), '', 'explicit' );
}, 'Invoking add or remove should set the class attribute');
// The ordered set parser must skip ASCII whitespace (U+0009, U+000A, U+000C, U+000D, and U+0020.)
test(function () {
var foo = document.createElement('div');
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.