Skip to content

Commit cd27cc6

Browse files
authored
add analysis for lowest cohesion rules (#133)
1 parent 768cb44 commit cd27cc6

File tree

8 files changed

+96
-33
lines changed

8 files changed

+96
-33
lines changed

src/analyzer/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ module.exports = async rawCss => {
1717
const stylesheets = require('./stylesheets')({
1818
rawCss,
1919
atrules,
20-
rules,
20+
rules: css.rules,
2121
selectors,
22-
declarations,
2322
properties,
2423
values
2524
})
Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
1-
module.exports = (rules, declarations) => {
2-
const average = ((rules, declarations) => {
3-
if (declarations.total === 0) {
4-
return 0
1+
module.exports = rules => {
2+
const totalRules = rules.length
3+
const totalDeclarations =
4+
totalRules === 0
5+
? 0
6+
: rules.reduce((acc, curr) => acc + curr.declarations.length, 0)
7+
const rulesSortedByDeclarationCount = rules.sort(
8+
(a, b) => b.declarations.length - a.declarations.length
9+
)
10+
11+
if (totalRules === 0 || totalDeclarations === 0) {
12+
return {
13+
average: 0,
14+
min: {
15+
count: 0,
16+
value: null
17+
}
518
}
19+
}
620

7-
return declarations.total / rules.total
8-
})(rules, declarations)
21+
const [ruleWithMostDeclarations] = rulesSortedByDeclarationCount
922

1023
return {
11-
average
24+
average: totalDeclarations / totalRules,
25+
min: {
26+
count: ruleWithMostDeclarations.declarations.length,
27+
value: ruleWithMostDeclarations
28+
}
1229
}
1330
}

src/analyzer/stylesheets/index.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
1-
module.exports = ({
2-
rawCss,
3-
atrules,
4-
rules,
5-
selectors,
6-
declarations,
7-
properties,
8-
values
9-
}) => {
1+
module.exports = ({rawCss, atrules, rules, selectors, properties, values}) => {
102
const filesize = require('./size.js')(rawCss)
113
const simplicity = require('./simplicity.js')(rules, selectors)
12-
const cohesion = require('./cohesion.js')(rules, declarations)
4+
const cohesion = require('./cohesion.js')(rules)
135
const browserhacks = require('./browserhacks.js')(
146
atrules,
157
selectors,

src/analyzer/stylesheets/simplicity.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ module.exports = (rules, selectors) => {
33
return 0
44
}
55

6-
return rules.total / selectors.total
6+
return rules.length / selectors.total
77
}

test/analyzer/index.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const test = require('ava')
22
const analyzer = require('../..')
33

4-
test('Breaks with invalid CSS', async t => {
4+
test('it breaks with invalid CSS', async t => {
55
const cssWithSyntaxError = 'a { color red }'
66
const error = await t.throwsAsync(analyzer(cssWithSyntaxError))
77

@@ -11,11 +11,11 @@ test('Breaks with invalid CSS', async t => {
1111
)
1212
})
1313

14-
test('Passes with valid CSS', async t => {
14+
test('it passes with valid CSS', async t => {
1515
await t.notThrowsAsync(analyzer('body {}'))
1616
})
1717

18-
test('Returns the correct analysis object structure', async t => {
18+
test('it returns the correct analysis object structure', async t => {
1919
const actual = await analyzer('foo{}')
2020
const expected = {
2121
'atrules.charsets.total': 0,
@@ -103,6 +103,8 @@ test('Returns the correct analysis object structure', async t => {
103103
'selectors.browserhacks.unique': [],
104104
'selectors.browserhacks.totalUnique': 0,
105105
'stylesheets.cohesion.average': 0,
106+
'stylesheets.cohesion.min.count': 0,
107+
'stylesheets.cohesion.min.value': null,
106108
'stylesheets.filesize.compressed.brotli.compressionRatio': -0.8,
107109
'stylesheets.filesize.compressed.brotli.totalBytes': 9,
108110
'stylesheets.filesize.compressed.gzip.compressionRatio': -4,
Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,61 @@
11
const test = require('ava')
22
const analyze = require('../../../src/analyzer/stylesheets/cohesion')
33

4-
test('it calculates cohesion based on the ratio of total declarations and total rules', t => {
5-
const {average: actual} = analyze({total: 2}, {total: 4})
6-
t.is(actual, 2)
4+
test('it calculates average cohesion based on the ratio of total declarations and total rules', t => {
5+
const actual = analyze([
6+
{
7+
declarations: [
8+
{property: 'a', value: 'a'},
9+
{property: 'b', value: 'b'},
10+
{property: 'c', value: 'c'},
11+
{property: 'd', value: 'd'}
12+
]
13+
},
14+
{
15+
declarations: [{property: 'a', value: 'a'}, {property: 'b', value: 'b'}]
16+
}
17+
])
18+
t.is(actual.average, 3)
719
})
820

9-
test('it calculates cohesion correctly if there are no rules and/or declarations', t => {
10-
const {average: actual} = analyze({total: 0}, {total: 0})
11-
t.is(actual, 0)
21+
test('it calculates average cohesion correctly if there are no rules and/or declarations', t => {
22+
const actual = analyze([])
23+
t.is(actual.average, 0)
24+
})
25+
26+
test('it calculates lowest cohesion as the rule with the most declarations', t => {
27+
const ruleWithManyDeclarations = {
28+
selectors: ['test'],
29+
declarations: [
30+
{property: 'a', value: 'a'},
31+
{property: 'b', value: 'b'},
32+
{property: 'c', value: 'c'},
33+
{property: 'd', value: 'd'}
34+
]
35+
}
36+
const fixture = [
37+
ruleWithManyDeclarations,
38+
{
39+
declarations: [{property: 'a', value: 'a'}]
40+
}
41+
]
42+
const actual = analyze(fixture)
43+
44+
t.is(actual.min.count, 4)
45+
t.deepEqual(actual.min.value, ruleWithManyDeclarations)
46+
})
47+
48+
test('it calculates lowest cohesion correctly if there are no declarations', t => {
49+
const actualWithNoRules = analyze([])
50+
t.is(actualWithNoRules.min.count, 0)
51+
t.is(actualWithNoRules.min.value, null)
52+
53+
const actualWithNoDeclarations = analyze([
54+
{
55+
selectors: ['a'],
56+
declarations: []
57+
}
58+
])
59+
t.is(actualWithNoDeclarations.min.count, 0)
60+
t.is(actualWithNoDeclarations.min.value, null)
1261
})

test/analyzer/stylesheets/index.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ const analyze = require('../../../src/analyzer/stylesheets')
33

44
const FIXTURE = {
55
rawCss: '',
6+
rules: [],
67
selectors: {
78
total: 0,
89
browserhacks: {total: 0, totalUnique: 0}
910
},
10-
declarations: {total: 0},
1111
atrules: {
1212
mediaqueries: {browserhacks: {total: 0, totalUnique: 0}},
1313
supports: {browserhacks: {total: 0, totalUnique: 0}}
@@ -36,7 +36,11 @@ test('it responds with the correct structure', t => {
3636
},
3737
simplicity: 0,
3838
cohesion: {
39-
average: 0
39+
average: 0,
40+
min: {
41+
count: 0,
42+
value: null
43+
}
4044
},
4145
browserhacks: {
4246
total: 0,

test/analyzer/stylesheets/simplicity.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ const test = require('ava')
22
const analyze = require('../../../src/analyzer/stylesheets/simplicity')
33

44
test('it calculates simplicity based on the ratio of total selectors and total rules', t => {
5-
const actual = analyze({total: 1}, {total: 2})
5+
const actual = analyze([{}], {total: 2})
66
t.is(actual, 0.5)
77
})
88

99
// Necessary test case for CSS files that contain
1010
// only a couple of @font-face rules, like Google Fonts
1111
test('it calculates simplicity correctly if there are no rules and/or selectors', t => {
12-
const actual = analyze({total: 0}, {total: 0})
12+
const actual = analyze([], {total: 0})
1313
t.is(actual, 0)
1414
})

0 commit comments

Comments
 (0)