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.
Files changed (157) hide show
  1. checksums.yaml +7 -0
  2. data/bin/scss-lint +6 -0
  3. data/config/default.yml +205 -0
  4. data/data/prefixed-identifiers/base.txt +107 -0
  5. data/data/prefixed-identifiers/bourbon.txt +71 -0
  6. data/data/properties.txt +477 -0
  7. data/data/property-sort-orders/concentric.txt +134 -0
  8. data/data/property-sort-orders/recess.txt +149 -0
  9. data/data/property-sort-orders/smacss.txt +137 -0
  10. data/lib/scss_lint.rb +31 -0
  11. data/lib/scss_lint/cli.rb +215 -0
  12. data/lib/scss_lint/config.rb +251 -0
  13. data/lib/scss_lint/constants.rb +8 -0
  14. data/lib/scss_lint/control_comment_processor.rb +126 -0
  15. data/lib/scss_lint/engine.rb +56 -0
  16. data/lib/scss_lint/exceptions.rb +21 -0
  17. data/lib/scss_lint/file_finder.rb +68 -0
  18. data/lib/scss_lint/lint.rb +24 -0
  19. data/lib/scss_lint/linter.rb +161 -0
  20. data/lib/scss_lint/linter/bang_format.rb +52 -0
  21. data/lib/scss_lint/linter/border_zero.rb +39 -0
  22. data/lib/scss_lint/linter/color_keyword.rb +32 -0
  23. data/lib/scss_lint/linter/color_variable.rb +60 -0
  24. data/lib/scss_lint/linter/comment.rb +21 -0
  25. data/lib/scss_lint/linter/compass.rb +7 -0
  26. data/lib/scss_lint/linter/compass/property_with_mixin.rb +47 -0
  27. data/lib/scss_lint/linter/debug_statement.rb +10 -0
  28. data/lib/scss_lint/linter/declaration_order.rb +71 -0
  29. data/lib/scss_lint/linter/duplicate_property.rb +58 -0
  30. data/lib/scss_lint/linter/else_placement.rb +48 -0
  31. data/lib/scss_lint/linter/empty_line_between_blocks.rb +85 -0
  32. data/lib/scss_lint/linter/empty_rule.rb +11 -0
  33. data/lib/scss_lint/linter/final_newline.rb +20 -0
  34. data/lib/scss_lint/linter/hex_length.rb +56 -0
  35. data/lib/scss_lint/linter/hex_notation.rb +38 -0
  36. data/lib/scss_lint/linter/hex_validation.rb +23 -0
  37. data/lib/scss_lint/linter/id_selector.rb +10 -0
  38. data/lib/scss_lint/linter/import_path.rb +62 -0
  39. data/lib/scss_lint/linter/important_rule.rb +12 -0
  40. data/lib/scss_lint/linter/indentation.rb +197 -0
  41. data/lib/scss_lint/linter/leading_zero.rb +49 -0
  42. data/lib/scss_lint/linter/mergeable_selector.rb +60 -0
  43. data/lib/scss_lint/linter/name_format.rb +117 -0
  44. data/lib/scss_lint/linter/nesting_depth.rb +24 -0
  45. data/lib/scss_lint/linter/placeholder_in_extend.rb +22 -0
  46. data/lib/scss_lint/linter/property_count.rb +44 -0
  47. data/lib/scss_lint/linter/property_sort_order.rb +198 -0
  48. data/lib/scss_lint/linter/property_spelling.rb +49 -0
  49. data/lib/scss_lint/linter/property_units.rb +59 -0
  50. data/lib/scss_lint/linter/qualifying_element.rb +42 -0
  51. data/lib/scss_lint/linter/selector_depth.rb +64 -0
  52. data/lib/scss_lint/linter/selector_format.rb +102 -0
  53. data/lib/scss_lint/linter/shorthand.rb +139 -0
  54. data/lib/scss_lint/linter/single_line_per_property.rb +59 -0
  55. data/lib/scss_lint/linter/single_line_per_selector.rb +35 -0
  56. data/lib/scss_lint/linter/space_after_comma.rb +110 -0
  57. data/lib/scss_lint/linter/space_after_property_colon.rb +92 -0
  58. data/lib/scss_lint/linter/space_after_property_name.rb +27 -0
  59. data/lib/scss_lint/linter/space_before_brace.rb +72 -0
  60. data/lib/scss_lint/linter/space_between_parens.rb +35 -0
  61. data/lib/scss_lint/linter/string_quotes.rb +94 -0
  62. data/lib/scss_lint/linter/trailing_semicolon.rb +67 -0
  63. data/lib/scss_lint/linter/trailing_zero.rb +41 -0
  64. data/lib/scss_lint/linter/unnecessary_mantissa.rb +42 -0
  65. data/lib/scss_lint/linter/unnecessary_parent_reference.rb +49 -0
  66. data/lib/scss_lint/linter/url_format.rb +56 -0
  67. data/lib/scss_lint/linter/url_quotes.rb +27 -0
  68. data/lib/scss_lint/linter/variable_for_property.rb +30 -0
  69. data/lib/scss_lint/linter/vendor_prefix.rb +64 -0
  70. data/lib/scss_lint/linter/zero_unit.rb +39 -0
  71. data/lib/scss_lint/linter_registry.rb +26 -0
  72. data/lib/scss_lint/location.rb +38 -0
  73. data/lib/scss_lint/options.rb +109 -0
  74. data/lib/scss_lint/rake_task.rb +106 -0
  75. data/lib/scss_lint/reporter.rb +18 -0
  76. data/lib/scss_lint/reporter/config_reporter.rb +26 -0
  77. data/lib/scss_lint/reporter/default_reporter.rb +27 -0
  78. data/lib/scss_lint/reporter/files_reporter.rb +8 -0
  79. data/lib/scss_lint/reporter/json_reporter.rb +30 -0
  80. data/lib/scss_lint/reporter/xml_reporter.rb +33 -0
  81. data/lib/scss_lint/runner.rb +51 -0
  82. data/lib/scss_lint/sass/script.rb +78 -0
  83. data/lib/scss_lint/sass/tree.rb +168 -0
  84. data/lib/scss_lint/selector_visitor.rb +34 -0
  85. data/lib/scss_lint/utils.rb +112 -0
  86. data/lib/scss_lint/version.rb +4 -0
  87. data/spec/scss_lint/cli_spec.rb +177 -0
  88. data/spec/scss_lint/config_spec.rb +253 -0
  89. data/spec/scss_lint/engine_spec.rb +24 -0
  90. data/spec/scss_lint/file_finder_spec.rb +134 -0
  91. data/spec/scss_lint/linter/bang_format_spec.rb +121 -0
  92. data/spec/scss_lint/linter/border_zero_spec.rb +118 -0
  93. data/spec/scss_lint/linter/color_keyword_spec.rb +83 -0
  94. data/spec/scss_lint/linter/color_variable_spec.rb +155 -0
  95. data/spec/scss_lint/linter/comment_spec.rb +79 -0
  96. data/spec/scss_lint/linter/compass/property_with_mixin_spec.rb +55 -0
  97. data/spec/scss_lint/linter/debug_statement_spec.rb +21 -0
  98. data/spec/scss_lint/linter/declaration_order_spec.rb +575 -0
  99. data/spec/scss_lint/linter/duplicate_property_spec.rb +189 -0
  100. data/spec/scss_lint/linter/else_placement_spec.rb +106 -0
  101. data/spec/scss_lint/linter/empty_line_between_blocks_spec.rb +276 -0
  102. data/spec/scss_lint/linter/empty_rule_spec.rb +27 -0
  103. data/spec/scss_lint/linter/final_newline_spec.rb +49 -0
  104. data/spec/scss_lint/linter/hex_length_spec.rb +104 -0
  105. data/spec/scss_lint/linter/hex_notation_spec.rb +104 -0
  106. data/spec/scss_lint/linter/hex_validation_spec.rb +40 -0
  107. data/spec/scss_lint/linter/id_selector_spec.rb +62 -0
  108. data/spec/scss_lint/linter/import_path_spec.rb +300 -0
  109. data/spec/scss_lint/linter/important_rule_spec.rb +43 -0
  110. data/spec/scss_lint/linter/indentation_spec.rb +347 -0
  111. data/spec/scss_lint/linter/leading_zero_spec.rb +233 -0
  112. data/spec/scss_lint/linter/mergeable_selector_spec.rb +283 -0
  113. data/spec/scss_lint/linter/name_format_spec.rb +282 -0
  114. data/spec/scss_lint/linter/nesting_depth_spec.rb +114 -0
  115. data/spec/scss_lint/linter/placeholder_in_extend_spec.rb +63 -0
  116. data/spec/scss_lint/linter/property_count_spec.rb +104 -0
  117. data/spec/scss_lint/linter/property_sort_order_spec.rb +482 -0
  118. data/spec/scss_lint/linter/property_spelling_spec.rb +84 -0
  119. data/spec/scss_lint/linter/property_units_spec.rb +229 -0
  120. data/spec/scss_lint/linter/qualifying_element_spec.rb +125 -0
  121. data/spec/scss_lint/linter/selector_depth_spec.rb +159 -0
  122. data/spec/scss_lint/linter/selector_format_spec.rb +632 -0
  123. data/spec/scss_lint/linter/shorthand_spec.rb +198 -0
  124. data/spec/scss_lint/linter/single_line_per_property_spec.rb +73 -0
  125. data/spec/scss_lint/linter/single_line_per_selector_spec.rb +130 -0
  126. data/spec/scss_lint/linter/space_after_comma_spec.rb +332 -0
  127. data/spec/scss_lint/linter/space_after_property_colon_spec.rb +373 -0
  128. data/spec/scss_lint/linter/space_after_property_name_spec.rb +37 -0
  129. data/spec/scss_lint/linter/space_before_brace_spec.rb +829 -0
  130. data/spec/scss_lint/linter/space_between_parens_spec.rb +263 -0
  131. data/spec/scss_lint/linter/string_quotes_spec.rb +335 -0
  132. data/spec/scss_lint/linter/trailing_semicolon_spec.rb +304 -0
  133. data/spec/scss_lint/linter/trailing_zero_spec.rb +176 -0
  134. data/spec/scss_lint/linter/unnecessary_mantissa_spec.rb +67 -0
  135. data/spec/scss_lint/linter/unnecessary_parent_reference_spec.rb +98 -0
  136. data/spec/scss_lint/linter/url_format_spec.rb +55 -0
  137. data/spec/scss_lint/linter/url_quotes_spec.rb +73 -0
  138. data/spec/scss_lint/linter/variable_for_property_spec.rb +145 -0
  139. data/spec/scss_lint/linter/vendor_prefix_spec.rb +371 -0
  140. data/spec/scss_lint/linter/zero_unit_spec.rb +113 -0
  141. data/spec/scss_lint/linter_registry_spec.rb +50 -0
  142. data/spec/scss_lint/linter_spec.rb +292 -0
  143. data/spec/scss_lint/location_spec.rb +42 -0
  144. data/spec/scss_lint/options_spec.rb +34 -0
  145. data/spec/scss_lint/rake_task_spec.rb +43 -0
  146. data/spec/scss_lint/reporter/config_reporter_spec.rb +42 -0
  147. data/spec/scss_lint/reporter/default_reporter_spec.rb +73 -0
  148. data/spec/scss_lint/reporter/files_reporter_spec.rb +38 -0
  149. data/spec/scss_lint/reporter/json_reporter_spec.rb +96 -0
  150. data/spec/scss_lint/reporter/xml_reporter_spec.rb +103 -0
  151. data/spec/scss_lint/reporter_spec.rb +11 -0
  152. data/spec/scss_lint/runner_spec.rb +123 -0
  153. data/spec/scss_lint/selector_visitor_spec.rb +264 -0
  154. data/spec/spec_helper.rb +34 -0
  155. data/spec/support/isolated_environment.rb +25 -0
  156. data/spec/support/matchers/report_lint.rb +48 -0
  157. 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