Skip to content

Commit 382eb52

Browse files
committed
Tests for new code in Attribute.
1 parent 1b95958 commit 382eb52

File tree

3 files changed

+80
-22
lines changed

3 files changed

+80
-22
lines changed

src/__tests__/attributes.js

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import process from "process";
2+
import Attribute from '../selectors/attribute';
13
import {test} from './util/helpers';
24

5+
process.throwDeprecation = true;
6+
37
test('attribute selector', '[href]', (t, tree) => {
48
t.deepEqual(tree.nodes[0].nodes[0].attribute, 'href');
59
t.deepEqual(tree.nodes[0].nodes[0].type, 'attribute');
@@ -393,8 +397,51 @@ test('non standard modifiers', '[href="foo" y]', (t, tree) => {
393397
t.deepEqual(tree.toString(), '[href="foo" y]');
394398
});
395399

396-
// This is a test case that fails in prettier. Not sure how to support it because I don't know that the range of allowed syntax is.
397-
// And even then, I'm not sure it makes sense.
398-
// test.skip('[nonstandard] function as attribute value', "[id=func('foo')]", (t, tree) => {
399-
// t.deepEqual(tree.toString(), '[href="foo" y]');
400-
// });
400+
test('deprecated constructor', '', (t) => {
401+
t.throws(
402+
() => {
403+
return new Attribute({value: '"foo"', attribute: "data-bar"});
404+
},
405+
"Constructing an Attribute selector with a value without specifying quoteMark is deprecated. Note: The value should be unescaped now."
406+
);
407+
});
408+
409+
test('deprecated get of raws.unquoted ', '', (t) => {
410+
t.throws(
411+
() => {
412+
let attr = new Attribute({value: 'foo', quoteMark: '"', attribute: "data-bar"});
413+
return attr.raws.unquoted;
414+
},
415+
"attr.raws.unquoted is deprecated. Call attr.value instead."
416+
);
417+
});
418+
419+
test('deprecated set of raws.unquoted ', '', (t) => {
420+
t.throws(
421+
() => {
422+
let attr = new Attribute({value: 'foo', quoteMark: '"', attribute: "data-bar"});
423+
attr.raws.unquoted = 'fooooo';
424+
},
425+
"Setting attr.raws.unquoted is deprecated and has no effect. attr.value is unescaped by default now."
426+
);
427+
});
428+
429+
test('smart quotes', '[data-foo=bar]', (t, tree) => {
430+
let attr = tree.nodes[0].nodes[0];
431+
attr.setValue('changed', {quoteMark: '"'});
432+
t.deepEqual(attr.toString(), '[data-foo="changed"]');
433+
attr.setValue('changed again', {quoteMark: "'", preferCurrentQuoteMark: true});
434+
t.deepEqual(attr.toString(), '[data-foo="changed again"]');
435+
attr.setValue('smart-ident', {smart: true});
436+
t.deepEqual(attr.toString(), '[data-foo=smart-ident]');
437+
attr.setValue('smart quoted', {smart: true});
438+
t.deepEqual(attr.toString(), '[data-foo=smart\\ quoted]');
439+
attr.setValue('smart quoted three spaces', {smart: true});
440+
t.deepEqual(attr.toString(), '[data-foo="smart quoted three spaces"]');
441+
attr.setValue('smart quoted three spaces', {smart: true, quoteMark: "'"});
442+
t.deepEqual(attr.toString(), "[data-foo='smart quoted three spaces']");
443+
attr.setValue("smart with 'single quotes'", {smart: true});
444+
t.deepEqual(attr.toString(), "[data-foo=\"smart with 'single quotes'\"]");
445+
attr.setValue('smart with "double quotes"', {smart: true});
446+
t.deepEqual(attr.toString(), "[data-foo='smart with \"double quotes\"']");
447+
});

src/__tests__/util/helpers.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,16 @@ export const parse = (input, transform) => {
66
return parser(transform).processSync(input);
77
};
88

9-
export function test (spec, input, callback, only = false, disabled = false) {
9+
export function test (spec, input, callback, only = false, disabled = false, serial = false) {
1010
let tester = only ? ava.only : ava;
11-
if (disabled) {
12-
tester = ava.skip;
13-
}
14-
if (only) {
15-
let e = new Error();
16-
console.error(e);
17-
}
11+
tester = disabled ? tester.skip : tester;
12+
tester = serial ? tester.serial : tester;
1813

1914
if (callback) {
2015
tester(`${spec} (tree)`, t => {
2116
let tree = parser().astSync(input);
2217
let debug = util.inspect(tree, false, null);
23-
callback.call(this, t, tree, debug);
18+
return callback.call(this, t, tree, debug);
2419
});
2520
}
2621

@@ -32,6 +27,7 @@ export function test (spec, input, callback, only = false, disabled = false) {
3227

3328
test.only = (spec, input, callback) => test(spec, input, callback, true);
3429
test.skip = (spec, input, callback) => test(spec, input, callback, false, true);
30+
test.serial = (spec, input, callback) => test(spec, input, callback, false, false, true);
3531

3632
export const throws = (spec, input, validator) => {
3733
ava(`${spec} (throws)`, t => {

src/selectors/attribute.js

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ export default class Attribute extends Namespace {
113113
*/
114114
setValue (value, options = {}) {
115115
this._value = value;
116-
this.quoteMark = this._determineQuoteMark(options);
116+
this._quoteMark = this._determineQuoteMark(options);
117+
this._syncRawValue();
117118
}
118119

119120
/**
@@ -137,7 +138,17 @@ export default class Attribute extends Namespace {
137138
if (escaped === v) {
138139
return Attribute.NO_QUOTE;
139140
} else {
140-
return this.preferredQuoteMark(options);
141+
let pref = this.preferredQuoteMark(options);
142+
if (pref === Attribute.NO_QUOTE) {
143+
// pick a quote mark that isn't none and see if it's smaller
144+
let quote = this.quoteMark || options.quoteMark || Attribute.DOUBLE_QUOTE;
145+
let opts = CSSESC_QUOTE_OPTIONS[quote];
146+
let quoteValue = cssesc(v, opts);
147+
if (quoteValue.length < escaped.length) {
148+
return quote;
149+
}
150+
}
151+
return pref;
141152
}
142153
} else if (numDoubleQuotes === numSingleQuotes) {
143154
return this.preferredQuoteMark(options);
@@ -199,13 +210,17 @@ export default class Attribute extends Namespace {
199210
return;
200211
}
201212
if (this._quoteMark !== quoteMark) {
202-
let rawValue = cssesc(this._value, CSSESC_QUOTE_OPTIONS[quoteMark]);
203-
if (rawValue === this._value) {
204-
delete this.raws.value;
205-
} else {
206-
this.raws.value = rawValue;
207-
}
208213
this._quoteMark = quoteMark;
214+
this._syncRawValue();
215+
}
216+
}
217+
218+
_syncRawValue () {
219+
let rawValue = cssesc(this._value, CSSESC_QUOTE_OPTIONS[this.quoteMark]);
220+
if (rawValue === this._value) {
221+
delete this.raws.value;
222+
} else {
223+
this.raws.value = rawValue;
209224
}
210225
}
211226

0 commit comments

Comments
 (0)