Skip to content

Commit b17661f

Browse files
authored
Rewrite selector tests (#115)
refs #81
1 parent c092085 commit b17661f

File tree

15 files changed

+438
-324
lines changed

15 files changed

+438
-324
lines changed

readme.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
# css-analyzer
22

33
[![NPM Version](https://img.shields.io/npm/v/@projectwallace/css-analyzer.svg)](https://www.npmjs.com/package/@projectwallace/css-analyzer)
4-
[![Build Status](https://travis-ci.org/projectwallace/css-analyzer.svg?branch=master)](https://travis-ci.org/projectwallace/css-analyzer) [![Known Vulnerabilities](https://snyk.io/test/github/projectwallace/css-analyzer/badge.svg)](https://snyk.io/test/github/projectwallace/css-analyzer) [![Coverage Status](https://coveralls.io/repos/github/projectwallace/css-analyzer/badge.svg?branch=master)](https://coveralls.io/github/projectwallace/css-analyzer?branch=master) ![Dependencies Status](https://img.shields.io/david/projectwallace/css-analyzer.svg) ![Dependencies Status](https://img.shields.io/david/dev/projectwallace/css-analyzer.svg) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo)
4+
[![Build Status](https://travis-ci.org/projectwallace/css-analyzer.svg?branch=master)](https://travis-ci.org/projectwallace/css-analyzer)
5+
[![Known Vulnerabilities](https://snyk.io/test/github/projectwallace/css-analyzer/badge.svg)](https://snyk.io/test/github/projectwallace/css-analyzer)
6+
[![Coverage Status](https://coveralls.io/repos/github/projectwallace/css-analyzer/badge.svg?branch=master)](https://coveralls.io/github/projectwallace/css-analyzer?branch=master)
7+
![Dependencies Status](https://img.shields.io/david/projectwallace/css-analyzer.svg)
8+
![Dependencies Status](https://img.shields.io/david/dev/projectwallace/css-analyzer.svg)
9+
[![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo)
10+
[![Project: Wallace](https://img.shields.io/badge/Project-Wallace-29c87d.svg)](https://www.projectwallace.com/oss)
511

612
> Analyze your CSS
713

src/analyzer/selectors/identifiers.js

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
const specificity = require('specificity')
22
const {caseInsensitive: stringCompare} = require('string-natural-compare')
33

4-
// Sort by identifiers count, then by alphabet
4+
// Sort by identifiers count (high to low), then by alphabet (A-Z)
55
function sortByIdentifiersCount(a, b) {
66
if (a.count === b.count) {
7-
return stringCompare(a, b)
7+
return stringCompare(a.value, b.value)
88
}
99

1010
return b.count - a.count
@@ -15,27 +15,33 @@ function getSelectorSpecificity(selector) {
1515
}
1616

1717
module.exports = selectors => {
18+
if (selectors.length === 0) {
19+
return {
20+
average: 0,
21+
top: [],
22+
max: {
23+
value: null,
24+
count: null
25+
}
26+
}
27+
}
28+
1829
const identifiersPerSelector = selectors
1930
.map(getSelectorSpecificity)
20-
.map(specificity => {
21-
return {
22-
value: specificity.selector,
23-
count: specificity.parts.length
24-
}
25-
})
31+
.map(specificity => ({
32+
value: specificity.selector,
33+
count: specificity.parts.length
34+
}))
2635

2736
const totalIdentifiers = identifiersPerSelector
28-
.map(selector => selector.count)
37+
.map(({count}) => count)
2938
.reduce((prev, curr) => prev + curr, 0)
3039

31-
const totalSelectors = selectors.length
32-
const average = totalIdentifiers / totalSelectors
33-
3440
const sorted = identifiersPerSelector.sort(sortByIdentifiersCount)
3541
const [max] = sorted
3642

3743
return {
38-
average,
44+
average: totalIdentifiers / selectors.length,
3945
max,
4046
top: sorted.slice(0, 5)
4147
}

src/analyzer/selectors/specificity.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
const specificity = require('specificity')
22

33
module.exports = selectors => {
4-
const all = [...new Set(selectors)]
4+
const all = [...selectors]
55
.sort()
6+
.reverse()
67
.sort(specificity.compare)
78
.reverse()
89

@@ -14,12 +15,7 @@ module.exports = selectors => {
1415

1516
return {
1617
value: selector,
17-
specificity: {
18-
a,
19-
b,
20-
c,
21-
d
22-
}
18+
specificity: {a, b, c, d}
2319
}
2420
})
2521
}

src/utils/uniquer.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,7 @@ module.exports = (values, sortFn) => {
88
...values.reduce((map, value) => {
99
return map.set(value, map.get(value) + 1 || 1)
1010
}, new Map())
11-
]
12-
// Create an array of [{value, count}]
13-
.map(value => {
14-
return {
15-
value: value[0],
16-
count: value[1]
17-
}
18-
})
11+
].map(([value, count]) => ({value, count}))
1912

2013
const sorted = reduced.map(el => el.value).sort(sortFn)
2114
const unique = sorted.map(value => reduced.find(r => r.value === value))
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const test = require('ava')
2+
const analyze = require('../../../src/analyzer/selectors/accessibility')
3+
4+
test('it responds with the correct structure', t => {
5+
const fixture = []
6+
const {total, totalUnique, unique} = analyze(fixture)
7+
8+
t.is(total, 0)
9+
t.is(totalUnique, 0)
10+
t.deepEqual(unique, [])
11+
})
12+
13+
test('it counts the total of all accessibility selectors', t => {
14+
const fixture = ['[aria-hidden]', '[aria-hidden]', 'img[role="presentation"]']
15+
const {total: actual} = analyze(fixture)
16+
const expected = 3
17+
18+
t.is(actual, expected)
19+
})
20+
21+
test('it counts the total of all unique accessibility selectors', t => {
22+
const fixture = ['[aria-hidden]', '[aria-hidden]', 'img[role="presentation"]']
23+
const {totalUnique: actual} = analyze(fixture)
24+
const expected = 2
25+
26+
t.is(actual, expected)
27+
})
28+
29+
test('it finds all unique accessibility selectors, sorts them and adds a count', t => {
30+
const fixture = ['[aria-hidden]', '[aria-hidden]', 'img[role="presentation"]']
31+
const {unique: actual} = analyze(fixture)
32+
const expected = [
33+
{
34+
value: '[aria-hidden]',
35+
count: 2
36+
},
37+
{
38+
value: 'img[role="presentation"]',
39+
count: 1
40+
}
41+
]
42+
43+
t.deepEqual(actual, expected)
44+
})
45+
46+
test('it does not report selectors that are not accessibility selectors', t => {
47+
const fixture = ['img[data-lazy]', '[hidden]']
48+
const {total, totalUnique, unique} = analyze(fixture)
49+
50+
t.is(total, 0)
51+
t.is(totalUnique, 0)
52+
t.deepEqual(unique, [])
53+
})

test/analyzer/selectors/browserhacks.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const test = require('ava')
2-
const analyze = require('../../../src/analyzer/selectors/browserhacks.js')
2+
const analyze = require('../../../src/analyzer/selectors/browserhacks')
33

44
test('It responds with the correct structure', t => {
55
const actual = analyze([])

test/analyzer/selectors/id.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
const test = require('ava')
2+
const analyze = require('../../../src/analyzer/selectors/id')
3+
4+
test('it responds with the correct structure', t => {
5+
const fixture = []
6+
const {total, totalUnique, unique} = analyze(fixture)
7+
8+
t.is(total, 0)
9+
t.is(totalUnique, 0)
10+
t.deepEqual(unique, [])
11+
})
12+
13+
test('it counts the total of all id selectors', t => {
14+
const fixture = ['#myId', '#myId', 'element#id', '.class #id #plus #two']
15+
const {total: actual} = analyze(fixture)
16+
const expected = 4
17+
18+
t.is(actual, expected)
19+
})
20+
21+
test('it counts the total of all unique id selectors', t => {
22+
const fixture = ['#myId', '#myId', 'element#id', '.class #id #plus #two']
23+
const {totalUnique: actual} = analyze(fixture)
24+
const expected = 3
25+
26+
t.is(actual, expected)
27+
})
28+
29+
test('it finds all unique id selectors, sorts them and adds a count', t => {
30+
const fixture = ['#myId', '#myId', 'element#id', '.class #id']
31+
const {unique: actual} = analyze(fixture)
32+
const expected = [
33+
{
34+
value: '#myId',
35+
count: 2
36+
},
37+
{
38+
value: '.class #id',
39+
count: 1
40+
},
41+
{
42+
value: 'element#id',
43+
count: 1
44+
}
45+
]
46+
47+
t.deepEqual(actual, expected)
48+
})
49+
50+
test('it does not report selectors that are not id selectors', t => {
51+
const fixture = ['class[href="#hash"]']
52+
const {total, totalUnique, unique} = analyze(fixture)
53+
54+
t.is(total, 0)
55+
t.is(totalUnique, 0)
56+
t.deepEqual(unique, [])
57+
})
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
const test = require('ava')
2+
const analyze = require('../../../src/analyzer/selectors/identifiers')
3+
4+
test('it responds with the correct structure', t => {
5+
const fixture = []
6+
const actual = analyze(fixture)
7+
const expected = {
8+
max: {
9+
value: null,
10+
count: null
11+
},
12+
top: [],
13+
average: 0
14+
}
15+
16+
t.deepEqual(actual, expected)
17+
})
18+
19+
const FIXTURE = ['a b c', 'a b', 'a b c d', 'a b c d e', 'a b c d e f']
20+
21+
test('it finds the selectors with the most identifiers and it sorts them by count', t => {
22+
const {top: actual} = analyze(FIXTURE)
23+
const expected = [
24+
{
25+
value: 'a b c d e f',
26+
count: 6
27+
},
28+
{
29+
value: 'a b c d e',
30+
count: 5
31+
},
32+
{
33+
value: 'a b c d',
34+
count: 4
35+
},
36+
{
37+
value: 'a b c',
38+
count: 3
39+
},
40+
{
41+
value: 'a b',
42+
count: 2
43+
}
44+
]
45+
46+
t.deepEqual(actual, expected)
47+
t.is(actual.length, 5)
48+
})
49+
50+
test('if selectors with the same identifier count are found, they are sorted alphabetically', t => {
51+
const fixture = ['y z', 'a b c', 'a b', 'a b c d', 'a b c d e', 'a b c d e f']
52+
const {top: actual} = analyze(fixture)
53+
const expected = [
54+
{
55+
value: 'a b c d e f',
56+
count: 6
57+
},
58+
{
59+
value: 'a b c d e',
60+
count: 5
61+
},
62+
{
63+
value: 'a b c d',
64+
count: 4
65+
},
66+
{
67+
value: 'a b c',
68+
count: 3
69+
},
70+
{
71+
value: 'a b',
72+
count: 2
73+
}
74+
]
75+
76+
t.deepEqual(actual, expected)
77+
})
78+
79+
test('it finds the selector with the most identifiers', t => {
80+
const {max: actual} = analyze(FIXTURE)
81+
82+
t.is(actual.count, 6)
83+
t.is(actual.value, 'a b c d e f')
84+
})
85+
86+
test('it calculates the average amount of identifiers per selector', t => {
87+
const {average: actual} = analyze(FIXTURE)
88+
89+
t.is(actual, 24 / 6)
90+
})

test/analyzer/selectors/index.js

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,33 @@
11
const test = require('ava')
2-
const testScope = require('../../utils/scope-tester.js')
2+
const analyze = require('../../../src/analyzer/selectors')
33

4-
const SCOPE = 'selectors'
4+
test('it responds with the correct structure', t => {
5+
const fixture = []
6+
const actual = analyze(fixture)
57

6-
test(SCOPE, async t => {
7-
const {actual, expected} = await testScope(SCOPE)
8-
t.deepEqual(actual[SCOPE], expected)
8+
t.is(actual.total, 0)
9+
t.is(actual.totalUnique, 0)
10+
11+
t.is(typeof actual.accessibility, 'object')
12+
t.is(typeof actual.specificity, 'object')
13+
t.is(typeof actual.identifiers, 'object')
14+
t.is(typeof actual.js, 'object')
15+
t.is(typeof actual.id, 'object')
16+
t.is(typeof actual.universal, 'object')
17+
})
18+
19+
test('it counts the total of all selectors', t => {
20+
const fixture = ['a', 'b', 'c', 'c']
21+
const {total: actual} = analyze(fixture)
22+
const expected = 4
23+
24+
t.is(actual, expected)
25+
})
26+
27+
test('it counts the total of all unique selectors', t => {
28+
const fixture = ['a', 'b', 'c', 'c']
29+
const {totalUnique: actual} = analyze(fixture)
30+
const expected = 3
31+
32+
t.is(actual, expected)
933
})

0 commit comments

Comments
 (0)