scss_lint 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/scss-lint +6 -0
- data/config/default.yml +205 -0
- data/data/prefixed-identifiers/base.txt +107 -0
- data/data/prefixed-identifiers/bourbon.txt +71 -0
- data/data/properties.txt +477 -0
- data/data/property-sort-orders/concentric.txt +134 -0
- data/data/property-sort-orders/recess.txt +149 -0
- data/data/property-sort-orders/smacss.txt +137 -0
- data/lib/scss_lint.rb +31 -0
- data/lib/scss_lint/cli.rb +215 -0
- data/lib/scss_lint/config.rb +251 -0
- data/lib/scss_lint/constants.rb +8 -0
- data/lib/scss_lint/control_comment_processor.rb +126 -0
- data/lib/scss_lint/engine.rb +56 -0
- data/lib/scss_lint/exceptions.rb +21 -0
- data/lib/scss_lint/file_finder.rb +68 -0
- data/lib/scss_lint/lint.rb +24 -0
- data/lib/scss_lint/linter.rb +161 -0
- data/lib/scss_lint/linter/bang_format.rb +52 -0
- data/lib/scss_lint/linter/border_zero.rb +39 -0
- data/lib/scss_lint/linter/color_keyword.rb +32 -0
- data/lib/scss_lint/linter/color_variable.rb +60 -0
- data/lib/scss_lint/linter/comment.rb +21 -0
- data/lib/scss_lint/linter/compass.rb +7 -0
- data/lib/scss_lint/linter/compass/property_with_mixin.rb +47 -0
- data/lib/scss_lint/linter/debug_statement.rb +10 -0
- data/lib/scss_lint/linter/declaration_order.rb +71 -0
- data/lib/scss_lint/linter/duplicate_property.rb +58 -0
- data/lib/scss_lint/linter/else_placement.rb +48 -0
- data/lib/scss_lint/linter/empty_line_between_blocks.rb +85 -0
- data/lib/scss_lint/linter/empty_rule.rb +11 -0
- data/lib/scss_lint/linter/final_newline.rb +20 -0
- data/lib/scss_lint/linter/hex_length.rb +56 -0
- data/lib/scss_lint/linter/hex_notation.rb +38 -0
- data/lib/scss_lint/linter/hex_validation.rb +23 -0
- data/lib/scss_lint/linter/id_selector.rb +10 -0
- data/lib/scss_lint/linter/import_path.rb +62 -0
- data/lib/scss_lint/linter/important_rule.rb +12 -0
- data/lib/scss_lint/linter/indentation.rb +197 -0
- data/lib/scss_lint/linter/leading_zero.rb +49 -0
- data/lib/scss_lint/linter/mergeable_selector.rb +60 -0
- data/lib/scss_lint/linter/name_format.rb +117 -0
- data/lib/scss_lint/linter/nesting_depth.rb +24 -0
- data/lib/scss_lint/linter/placeholder_in_extend.rb +22 -0
- data/lib/scss_lint/linter/property_count.rb +44 -0
- data/lib/scss_lint/linter/property_sort_order.rb +198 -0
- data/lib/scss_lint/linter/property_spelling.rb +49 -0
- data/lib/scss_lint/linter/property_units.rb +59 -0
- data/lib/scss_lint/linter/qualifying_element.rb +42 -0
- data/lib/scss_lint/linter/selector_depth.rb +64 -0
- data/lib/scss_lint/linter/selector_format.rb +102 -0
- data/lib/scss_lint/linter/shorthand.rb +139 -0
- data/lib/scss_lint/linter/single_line_per_property.rb +59 -0
- data/lib/scss_lint/linter/single_line_per_selector.rb +35 -0
- data/lib/scss_lint/linter/space_after_comma.rb +110 -0
- data/lib/scss_lint/linter/space_after_property_colon.rb +92 -0
- data/lib/scss_lint/linter/space_after_property_name.rb +27 -0
- data/lib/scss_lint/linter/space_before_brace.rb +72 -0
- data/lib/scss_lint/linter/space_between_parens.rb +35 -0
- data/lib/scss_lint/linter/string_quotes.rb +94 -0
- data/lib/scss_lint/linter/trailing_semicolon.rb +67 -0
- data/lib/scss_lint/linter/trailing_zero.rb +41 -0
- data/lib/scss_lint/linter/unnecessary_mantissa.rb +42 -0
- data/lib/scss_lint/linter/unnecessary_parent_reference.rb +49 -0
- data/lib/scss_lint/linter/url_format.rb +56 -0
- data/lib/scss_lint/linter/url_quotes.rb +27 -0
- data/lib/scss_lint/linter/variable_for_property.rb +30 -0
- data/lib/scss_lint/linter/vendor_prefix.rb +64 -0
- data/lib/scss_lint/linter/zero_unit.rb +39 -0
- data/lib/scss_lint/linter_registry.rb +26 -0
- data/lib/scss_lint/location.rb +38 -0
- data/lib/scss_lint/options.rb +109 -0
- data/lib/scss_lint/rake_task.rb +106 -0
- data/lib/scss_lint/reporter.rb +18 -0
- data/lib/scss_lint/reporter/config_reporter.rb +26 -0
- data/lib/scss_lint/reporter/default_reporter.rb +27 -0
- data/lib/scss_lint/reporter/files_reporter.rb +8 -0
- data/lib/scss_lint/reporter/json_reporter.rb +30 -0
- data/lib/scss_lint/reporter/xml_reporter.rb +33 -0
- data/lib/scss_lint/runner.rb +51 -0
- data/lib/scss_lint/sass/script.rb +78 -0
- data/lib/scss_lint/sass/tree.rb +168 -0
- data/lib/scss_lint/selector_visitor.rb +34 -0
- data/lib/scss_lint/utils.rb +112 -0
- data/lib/scss_lint/version.rb +4 -0
- data/spec/scss_lint/cli_spec.rb +177 -0
- data/spec/scss_lint/config_spec.rb +253 -0
- data/spec/scss_lint/engine_spec.rb +24 -0
- data/spec/scss_lint/file_finder_spec.rb +134 -0
- data/spec/scss_lint/linter/bang_format_spec.rb +121 -0
- data/spec/scss_lint/linter/border_zero_spec.rb +118 -0
- data/spec/scss_lint/linter/color_keyword_spec.rb +83 -0
- data/spec/scss_lint/linter/color_variable_spec.rb +155 -0
- data/spec/scss_lint/linter/comment_spec.rb +79 -0
- data/spec/scss_lint/linter/compass/property_with_mixin_spec.rb +55 -0
- data/spec/scss_lint/linter/debug_statement_spec.rb +21 -0
- data/spec/scss_lint/linter/declaration_order_spec.rb +575 -0
- data/spec/scss_lint/linter/duplicate_property_spec.rb +189 -0
- data/spec/scss_lint/linter/else_placement_spec.rb +106 -0
- data/spec/scss_lint/linter/empty_line_between_blocks_spec.rb +276 -0
- data/spec/scss_lint/linter/empty_rule_spec.rb +27 -0
- data/spec/scss_lint/linter/final_newline_spec.rb +49 -0
- data/spec/scss_lint/linter/hex_length_spec.rb +104 -0
- data/spec/scss_lint/linter/hex_notation_spec.rb +104 -0
- data/spec/scss_lint/linter/hex_validation_spec.rb +40 -0
- data/spec/scss_lint/linter/id_selector_spec.rb +62 -0
- data/spec/scss_lint/linter/import_path_spec.rb +300 -0
- data/spec/scss_lint/linter/important_rule_spec.rb +43 -0
- data/spec/scss_lint/linter/indentation_spec.rb +347 -0
- data/spec/scss_lint/linter/leading_zero_spec.rb +233 -0
- data/spec/scss_lint/linter/mergeable_selector_spec.rb +283 -0
- data/spec/scss_lint/linter/name_format_spec.rb +282 -0
- data/spec/scss_lint/linter/nesting_depth_spec.rb +114 -0
- data/spec/scss_lint/linter/placeholder_in_extend_spec.rb +63 -0
- data/spec/scss_lint/linter/property_count_spec.rb +104 -0
- data/spec/scss_lint/linter/property_sort_order_spec.rb +482 -0
- data/spec/scss_lint/linter/property_spelling_spec.rb +84 -0
- data/spec/scss_lint/linter/property_units_spec.rb +229 -0
- data/spec/scss_lint/linter/qualifying_element_spec.rb +125 -0
- data/spec/scss_lint/linter/selector_depth_spec.rb +159 -0
- data/spec/scss_lint/linter/selector_format_spec.rb +632 -0
- data/spec/scss_lint/linter/shorthand_spec.rb +198 -0
- data/spec/scss_lint/linter/single_line_per_property_spec.rb +73 -0
- data/spec/scss_lint/linter/single_line_per_selector_spec.rb +130 -0
- data/spec/scss_lint/linter/space_after_comma_spec.rb +332 -0
- data/spec/scss_lint/linter/space_after_property_colon_spec.rb +373 -0
- data/spec/scss_lint/linter/space_after_property_name_spec.rb +37 -0
- data/spec/scss_lint/linter/space_before_brace_spec.rb +829 -0
- data/spec/scss_lint/linter/space_between_parens_spec.rb +263 -0
- data/spec/scss_lint/linter/string_quotes_spec.rb +335 -0
- data/spec/scss_lint/linter/trailing_semicolon_spec.rb +304 -0
- data/spec/scss_lint/linter/trailing_zero_spec.rb +176 -0
- data/spec/scss_lint/linter/unnecessary_mantissa_spec.rb +67 -0
- data/spec/scss_lint/linter/unnecessary_parent_reference_spec.rb +98 -0
- data/spec/scss_lint/linter/url_format_spec.rb +55 -0
- data/spec/scss_lint/linter/url_quotes_spec.rb +73 -0
- data/spec/scss_lint/linter/variable_for_property_spec.rb +145 -0
- data/spec/scss_lint/linter/vendor_prefix_spec.rb +371 -0
- data/spec/scss_lint/linter/zero_unit_spec.rb +113 -0
- data/spec/scss_lint/linter_registry_spec.rb +50 -0
- data/spec/scss_lint/linter_spec.rb +292 -0
- data/spec/scss_lint/location_spec.rb +42 -0
- data/spec/scss_lint/options_spec.rb +34 -0
- data/spec/scss_lint/rake_task_spec.rb +43 -0
- data/spec/scss_lint/reporter/config_reporter_spec.rb +42 -0
- data/spec/scss_lint/reporter/default_reporter_spec.rb +73 -0
- data/spec/scss_lint/reporter/files_reporter_spec.rb +38 -0
- data/spec/scss_lint/reporter/json_reporter_spec.rb +96 -0
- data/spec/scss_lint/reporter/xml_reporter_spec.rb +103 -0
- data/spec/scss_lint/reporter_spec.rb +11 -0
- data/spec/scss_lint/runner_spec.rb +123 -0
- data/spec/scss_lint/selector_visitor_spec.rb +264 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/support/isolated_environment.rb +25 -0
- data/spec/support/matchers/report_lint.rb +48 -0
- metadata +328 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
|
|
4
|
+
describe SCSSLint::Config do
|
|
5
|
+
class SCSSLint::Linter::FakeConfigLinter < SCSSLint::Linter; end
|
|
6
|
+
|
|
7
|
+
module SCSSLint::Linter::SomeNamespace
|
|
8
|
+
class FakeLinter1 < SCSSLint::Linter; end
|
|
9
|
+
class FakeLinter2 < SCSSLint::Linter; end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:default_file) { File.open(described_class::DEFAULT_FILE).read }
|
|
13
|
+
|
|
14
|
+
# This complex stubbing bypasses the built-in caching of the methods, and at
|
|
15
|
+
# the same time gives us full control over the "default" configuration.
|
|
16
|
+
before do
|
|
17
|
+
described_class
|
|
18
|
+
.stub(:load_file_contents)
|
|
19
|
+
.with(described_class::DEFAULT_FILE)
|
|
20
|
+
.and_return(default_file)
|
|
21
|
+
|
|
22
|
+
described_class
|
|
23
|
+
.stub(:default_options_hash)
|
|
24
|
+
.and_return(described_class.send(:load_options_hash_from_file, described_class::DEFAULT_FILE))
|
|
25
|
+
|
|
26
|
+
described_class
|
|
27
|
+
.stub(:default)
|
|
28
|
+
.and_return(described_class.load(described_class::DEFAULT_FILE, merge_with_default: false))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe '.default' do
|
|
32
|
+
subject { described_class.default }
|
|
33
|
+
|
|
34
|
+
it 'has a configuration defined for all registered linters' do
|
|
35
|
+
SCSSLint::LinterRegistry.linters.map(&:new).each do |linter|
|
|
36
|
+
subject.linter_options(linter).should_not be_nil
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe '.load' do
|
|
42
|
+
let(:config_dir) { '/path/to' }
|
|
43
|
+
let(:file_name) { "/#{config_dir}/config.yml" }
|
|
44
|
+
|
|
45
|
+
let(:default_file) { <<-FILE }
|
|
46
|
+
linters:
|
|
47
|
+
FakeConfigLinter:
|
|
48
|
+
enabled: true
|
|
49
|
+
list: [1, 2, 3]
|
|
50
|
+
OtherFakeConfigLinter:
|
|
51
|
+
enabled: false
|
|
52
|
+
FILE
|
|
53
|
+
|
|
54
|
+
subject { described_class.load(file_name) }
|
|
55
|
+
|
|
56
|
+
before do
|
|
57
|
+
described_class.stub(:load_file_contents)
|
|
58
|
+
.with(file_name)
|
|
59
|
+
.and_return(config_file)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context 'with an empty config file' do
|
|
63
|
+
let(:config_file) { '' }
|
|
64
|
+
|
|
65
|
+
it 'returns the default configuration' do
|
|
66
|
+
subject.options.should == described_class.default.options
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'with a config file containing only comments' do
|
|
71
|
+
let(:config_file) { '# This is a comment' }
|
|
72
|
+
|
|
73
|
+
it 'returns the default configuration' do
|
|
74
|
+
subject.options.should == described_class.default.options
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context 'with a file configuring an unknown linter' do
|
|
79
|
+
let(:config_file) { 'linters: { MadeUpLinterName: { enabled: true } }' }
|
|
80
|
+
|
|
81
|
+
it 'stores a warning for the unknown linter' do
|
|
82
|
+
subject.warnings
|
|
83
|
+
.any? { |warning| warning.include?('MadeUpLinterName') }
|
|
84
|
+
.should be true
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
context 'with a config file setting the same configuration as the default' do
|
|
89
|
+
let(:config_file) { default_file }
|
|
90
|
+
|
|
91
|
+
it 'returns a configuration equivalent to the default' do
|
|
92
|
+
subject.options.should == described_class.default.options
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context 'with a config file setting the same subset of settings as the default' do
|
|
97
|
+
let(:config_file) { <<-FILE }
|
|
98
|
+
linters:
|
|
99
|
+
FakeConfigLinter:
|
|
100
|
+
enabled: true
|
|
101
|
+
FILE
|
|
102
|
+
|
|
103
|
+
it 'returns a configuration equivalent to the default' do
|
|
104
|
+
subject.options.should == described_class.default.options
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context 'with a config file setting a list value different from the default' do
|
|
109
|
+
let(:config_file) { <<-FILE }
|
|
110
|
+
linters:
|
|
111
|
+
FakeConfigLinter:
|
|
112
|
+
list: [4, 5, 6]
|
|
113
|
+
FILE
|
|
114
|
+
|
|
115
|
+
it 'overrides the default value with the new value' do
|
|
116
|
+
subject.options['linters']['FakeConfigLinter']['list'].should == [4, 5, 6]
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context 'when a wildcard is used for a namespaced linter' do
|
|
121
|
+
let(:default_file) { <<-FILE }
|
|
122
|
+
linters:
|
|
123
|
+
SomeNamespace::*:
|
|
124
|
+
enabled: false
|
|
125
|
+
FILE
|
|
126
|
+
|
|
127
|
+
let(:config_file) { <<-FILE }
|
|
128
|
+
linters:
|
|
129
|
+
SomeNamespace::*:
|
|
130
|
+
enabled: true
|
|
131
|
+
FILE
|
|
132
|
+
|
|
133
|
+
before do
|
|
134
|
+
SCSSLint::LinterRegistry.stub(:linters)
|
|
135
|
+
.and_return([SCSSLint::Linter::SomeNamespace::FakeLinter1,
|
|
136
|
+
SCSSLint::Linter::SomeNamespace::FakeLinter2])
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it 'returns the same options for all linters under that namespace' do
|
|
140
|
+
subject.linter_options(SCSSLint::Linter::SomeNamespace::FakeLinter1)
|
|
141
|
+
.should eq('enabled' => true)
|
|
142
|
+
subject.linter_options(SCSSLint::Linter::SomeNamespace::FakeLinter2)
|
|
143
|
+
.should eq('enabled' => true)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
describe '#linter_options' do
|
|
149
|
+
let(:config) { described_class.new(options) }
|
|
150
|
+
|
|
151
|
+
let(:linter_options) do
|
|
152
|
+
{
|
|
153
|
+
'enabled' => true,
|
|
154
|
+
'some_option' => 'some_value',
|
|
155
|
+
}
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
let(:options) do
|
|
159
|
+
{
|
|
160
|
+
'linters' => {
|
|
161
|
+
'FakeConfigLinter' => linter_options
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it 'returns the options for the specified linter' do
|
|
167
|
+
config.linter_options(SCSSLint::Linter::FakeConfigLinter.new)
|
|
168
|
+
.should == linter_options
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
describe '#excluded_file?' do
|
|
173
|
+
include_context 'isolated environment'
|
|
174
|
+
|
|
175
|
+
let(:config_dir) { 'path/to' }
|
|
176
|
+
let(:file_name) { "#{config_dir}/config.yml" }
|
|
177
|
+
let(:config) { described_class.load(file_name) }
|
|
178
|
+
|
|
179
|
+
before do
|
|
180
|
+
described_class.stub(:load_file_contents)
|
|
181
|
+
.with(file_name)
|
|
182
|
+
.and_return(config_file)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
context 'when no exclusion is specified' do
|
|
186
|
+
let(:config_file) { 'linters: {}' }
|
|
187
|
+
|
|
188
|
+
it 'does not exclude any files' do
|
|
189
|
+
config.excluded_file?('anything/you/want.scss').should be false
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
context 'when an exclusion is specified' do
|
|
194
|
+
let(:config_file) { "exclude: 'foo/bar/baz/**'" }
|
|
195
|
+
|
|
196
|
+
it 'does not exclude anything not matching the glob' do
|
|
197
|
+
config.excluded_file?("#{config_dir}/foo/bar/something.scss").should be false
|
|
198
|
+
config.excluded_file?("#{config_dir}/other/something.scss").should be false
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it 'excludes anything matching the glob' do
|
|
202
|
+
config.excluded_file?("#{config_dir}/foo/bar/baz/excluded.scss").should be true
|
|
203
|
+
config.excluded_file?("#{config_dir}/foo/bar/baz/dir/excluded.scss").should be true
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
describe '#excluded_file_for_linter?' do
|
|
209
|
+
include_context 'isolated environment'
|
|
210
|
+
|
|
211
|
+
let(:config_dir) { 'path/to' }
|
|
212
|
+
let(:file_name) { "#{config_dir}/config.yml" }
|
|
213
|
+
let(:config) { described_class.load(file_name) }
|
|
214
|
+
|
|
215
|
+
before do
|
|
216
|
+
described_class.stub(:load_file_contents)
|
|
217
|
+
.with(file_name)
|
|
218
|
+
.and_return(config_file)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
context 'when no exclusion is specified in linter' do
|
|
222
|
+
let(:config_file) { <<-FILE }
|
|
223
|
+
linters:
|
|
224
|
+
FakeConfigLinter:
|
|
225
|
+
enabled: true
|
|
226
|
+
FILE
|
|
227
|
+
|
|
228
|
+
it 'does not exclude any files' do
|
|
229
|
+
config.excluded_file_for_linter?(
|
|
230
|
+
"#{config_dir}/anything/you/want.scss",
|
|
231
|
+
SCSSLint::Linter::FakeConfigLinter.new
|
|
232
|
+
).should == false
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
context 'when an exclusion is specified in linter' do
|
|
237
|
+
let(:config_file) { <<-FILE }
|
|
238
|
+
linters:
|
|
239
|
+
FakeConfigLinter:
|
|
240
|
+
enabled: true
|
|
241
|
+
exclude:
|
|
242
|
+
- 'anything/you/want.scss'
|
|
243
|
+
FILE
|
|
244
|
+
|
|
245
|
+
it 'excludes file for the linter' do
|
|
246
|
+
config.excluded_file_for_linter?(
|
|
247
|
+
"#{config_dir}/anything/you/want.scss",
|
|
248
|
+
SCSSLint::Linter::FakeConfigLinter.new
|
|
249
|
+
).should == true
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe SCSSLint::Engine do
|
|
4
|
+
let(:engine) { described_class.new(code: scss) }
|
|
5
|
+
|
|
6
|
+
context 'when a @media directive is present' do
|
|
7
|
+
let(:scss) { <<-SCSS }
|
|
8
|
+
@media only screen {
|
|
9
|
+
}
|
|
10
|
+
SCSS
|
|
11
|
+
|
|
12
|
+
it 'has a parse tree' do
|
|
13
|
+
engine.tree.should_not be_nil
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context 'when the file being linted has an invalid byte sequence' do
|
|
18
|
+
let(:scss) { "\xC0\u0001" }
|
|
19
|
+
|
|
20
|
+
it 'raises a SyntaxError' do
|
|
21
|
+
expect { engine }.to raise_error(SCSSLint::FileEncodingError)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe SCSSLint::FileFinder do
|
|
4
|
+
let(:config) { SCSSLint::Config.default }
|
|
5
|
+
|
|
6
|
+
subject { described_class.new(config) }
|
|
7
|
+
|
|
8
|
+
describe '#find' do
|
|
9
|
+
include_context 'isolated environment'
|
|
10
|
+
|
|
11
|
+
subject { super().find(patterns) }
|
|
12
|
+
|
|
13
|
+
context 'when no patterns are given' do
|
|
14
|
+
let(:patterns) { [] }
|
|
15
|
+
|
|
16
|
+
context 'and there are no SCSS files under the current directory' do
|
|
17
|
+
it 'raises an error' do
|
|
18
|
+
expect { subject }.to raise_error SCSSLint::Exceptions::NoFilesError
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context 'and there are SCSS files under the current directory' do
|
|
23
|
+
before do
|
|
24
|
+
`touch blah.scss`
|
|
25
|
+
`mkdir -p more`
|
|
26
|
+
`touch more/more.scss`
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it { should == ['blah.scss', 'more/more.scss'] }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context 'and a default set of files is specified in the config' do
|
|
33
|
+
let(:files) { ['file1.scss', 'file2.scss'] }
|
|
34
|
+
|
|
35
|
+
before do
|
|
36
|
+
config.stub(:scss_files).and_return(files)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it { should == files }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'when files without valid extension are given' do
|
|
44
|
+
let(:patterns) { ['test.txt'] }
|
|
45
|
+
|
|
46
|
+
context 'and those files exist' do
|
|
47
|
+
before do
|
|
48
|
+
`touch test.txt`
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it { should == ['test.txt'] }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context 'and those files do not exist' do
|
|
55
|
+
it { should == ['test.txt'] }
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context 'when directories are given' do
|
|
60
|
+
let(:patterns) { ['some-dir'] }
|
|
61
|
+
|
|
62
|
+
context 'and those directories exist' do
|
|
63
|
+
before do
|
|
64
|
+
`mkdir -p some-dir`
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context 'and they contain SCSS files' do
|
|
68
|
+
before do
|
|
69
|
+
`touch some-dir/test.scss`
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it { should == ['some-dir/test.scss'] }
|
|
73
|
+
|
|
74
|
+
context 'and those SCSS files are excluded by the config' do
|
|
75
|
+
before do
|
|
76
|
+
config.exclude_file('some-dir/test.scss')
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'raises an error' do
|
|
80
|
+
expect { subject }.to raise_error SCSSLint::Exceptions::AllFilesFilteredError
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context 'and they contain CSS files' do
|
|
86
|
+
before do
|
|
87
|
+
`touch some-dir/test.css`
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it { should == ['some-dir/test.css'] }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context 'and they contain more directories with files with recognized extensions' do
|
|
94
|
+
before do
|
|
95
|
+
`mkdir -p some-dir/more-dir`
|
|
96
|
+
`touch some-dir/more-dir/test.scss`
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it { should == ['some-dir/more-dir/test.scss'] }
|
|
100
|
+
|
|
101
|
+
context 'and those SCSS files are excluded by the config' do
|
|
102
|
+
before do
|
|
103
|
+
config.exclude_file('**/*.scss')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'raises an error' do
|
|
107
|
+
expect { subject }.to raise_error SCSSLint::Exceptions::AllFilesFilteredError
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context 'and they contain no SCSS files' do
|
|
113
|
+
before do
|
|
114
|
+
`touch some-dir/test.txt`
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'raises an error' do
|
|
118
|
+
expect { subject }.to raise_error SCSSLint::Exceptions::NoFilesError
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
context 'and those directories do not exist' do
|
|
124
|
+
it { should == ['some-dir'] }
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
context 'when the same file is specified multiple times' do
|
|
129
|
+
let(:patterns) { ['test.scss'] * 3 }
|
|
130
|
+
|
|
131
|
+
it { should == ['test.scss'] }
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe SCSSLint::Linter::BangFormat do
|
|
4
|
+
context 'when no bang is used' do
|
|
5
|
+
let(:scss) { <<-SCSS }
|
|
6
|
+
p {
|
|
7
|
+
color: #000;
|
|
8
|
+
}
|
|
9
|
+
SCSS
|
|
10
|
+
|
|
11
|
+
it { should_not report_lint }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context 'when !important is used correctly' do
|
|
15
|
+
let(:scss) { <<-SCSS }
|
|
16
|
+
p {
|
|
17
|
+
color: #000 !important;
|
|
18
|
+
}
|
|
19
|
+
SCSS
|
|
20
|
+
|
|
21
|
+
it { should_not report_lint }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'when !important has no space before' do
|
|
25
|
+
let(:scss) { <<-SCSS }
|
|
26
|
+
p {
|
|
27
|
+
color: #000!important;
|
|
28
|
+
}
|
|
29
|
+
SCSS
|
|
30
|
+
|
|
31
|
+
it { should report_lint line: 2 }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context 'when !important has a space after' do
|
|
35
|
+
let(:scss) { <<-SCSS }
|
|
36
|
+
p {
|
|
37
|
+
color: #000 ! important;
|
|
38
|
+
}
|
|
39
|
+
SCSS
|
|
40
|
+
|
|
41
|
+
it { should report_lint line: 2 }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context 'when !important has a space after and config allows it' do
|
|
45
|
+
let(:linter_config) { { 'space_before_bang' => true, 'space_after_bang' => true } }
|
|
46
|
+
|
|
47
|
+
let(:scss) { <<-SCSS }
|
|
48
|
+
p {
|
|
49
|
+
color: #000 ! important;
|
|
50
|
+
}
|
|
51
|
+
SCSS
|
|
52
|
+
|
|
53
|
+
it { should_not report_lint }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context 'when !important has a space before but config does not allow it' do
|
|
57
|
+
let(:linter_config) { { 'space_before_bang' => false, 'space_after_bang' => true } }
|
|
58
|
+
|
|
59
|
+
let(:scss) { <<-SCSS }
|
|
60
|
+
p {
|
|
61
|
+
color: #000 ! important;
|
|
62
|
+
}
|
|
63
|
+
SCSS
|
|
64
|
+
|
|
65
|
+
it { should report_lint line: 2 }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context 'when !important has no spaces around and config allows it' do
|
|
69
|
+
let(:linter_config) { { 'space_before_bang' => false, 'space_after_bang' => false } }
|
|
70
|
+
|
|
71
|
+
let(:scss) { <<-SCSS }
|
|
72
|
+
p {
|
|
73
|
+
color: #000!important;
|
|
74
|
+
}
|
|
75
|
+
SCSS
|
|
76
|
+
|
|
77
|
+
it { should_not report_lint }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context 'when ! appears within a string' do
|
|
81
|
+
let(:scss) { <<-SCSS }
|
|
82
|
+
p:before { content: "!important"; }
|
|
83
|
+
p:before { content: "imp!ortant"; }
|
|
84
|
+
p:after { content: '!'; }
|
|
85
|
+
div:before { content: 'important!'; }
|
|
86
|
+
div:after { content: ' ! '; }
|
|
87
|
+
p[attr="foo!bar"] {};
|
|
88
|
+
p[attr='foo!bar'] {};
|
|
89
|
+
p[attr="!foobar"] {};
|
|
90
|
+
p[attr='foobar!'] {};
|
|
91
|
+
$foo: 'bar!';
|
|
92
|
+
$foo: "bar!";
|
|
93
|
+
$foo: "!bar";
|
|
94
|
+
$foo: "b!ar";
|
|
95
|
+
SCSS
|
|
96
|
+
|
|
97
|
+
it { should_not report_lint }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context 'when !<word> is not followed by a semicolon' do
|
|
101
|
+
let(:scss) { <<-SCSS }
|
|
102
|
+
.class {
|
|
103
|
+
margin: 0 !important
|
|
104
|
+
}
|
|
105
|
+
SCSS
|
|
106
|
+
|
|
107
|
+
it 'does not loop forever' do
|
|
108
|
+
subject.should_not report_lint
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context 'when property contains a list literal with an empty list' do
|
|
113
|
+
let(:scss) { <<-SCSS }
|
|
114
|
+
p {
|
|
115
|
+
content: 0 ();
|
|
116
|
+
}
|
|
117
|
+
SCSS
|
|
118
|
+
|
|
119
|
+
it { should_not report_lint }
|
|
120
|
+
end
|
|
121
|
+
end
|