scss_lint 0.38.0

Sign up to get free protection for your applications and to get access to all the features.
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,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe SCSSLint::Reporter do
4
+ class SCSSLint::Reporter::FakeReporter < SCSSLint::Reporter; end
5
+
6
+ describe '#descendants' do
7
+ it 'contains FakeReporter' do
8
+ SCSSLint::Reporter.descendants.should include(SCSSLint::Reporter::FakeReporter)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ describe SCSSLint::Runner do
4
+ let(:config_options) do
5
+ {
6
+ 'linters' => {
7
+ 'FakeLinter1' => { 'enabled' => true },
8
+ 'FakeLinter2' => { 'enabled' => false },
9
+ },
10
+ }
11
+ end
12
+
13
+ let(:config) { SCSSLint::Config.new(config_options) }
14
+ let(:runner) { described_class.new(config) }
15
+
16
+ before do
17
+ SCSSLint::LinterRegistry.stub(:linters)
18
+ .and_return([SCSSLint::Linter::FakeLinter1,
19
+ SCSSLint::Linter::FakeLinter2])
20
+ end
21
+
22
+ class SCSSLint::Linter::FakeLinter1 < SCSSLint::Linter; end
23
+ class SCSSLint::Linter::FakeLinter2 < SCSSLint::Linter; end
24
+
25
+ describe '#run' do
26
+ let(:files) { ['dummy1.scss', 'dummy2.scss'] }
27
+ subject { runner.run(files) }
28
+
29
+ before do
30
+ SCSSLint::Engine.stub(:new)
31
+ SCSSLint::Linter.any_instance.stub(:run)
32
+ end
33
+
34
+ it 'searches for lints in each file' do
35
+ runner.should_receive(:find_lints).exactly(files.size).times
36
+ subject
37
+ end
38
+
39
+ context 'when all linters are disabled' do
40
+ let(:config_options) do
41
+ {
42
+ 'linters' => {
43
+ 'FakeLinter1' => { 'enabled' => false },
44
+ 'FakeLinter2' => { 'enabled' => false },
45
+ },
46
+ }
47
+ end
48
+
49
+ before do
50
+ SCSSLint::Linter.any_instance
51
+ .stub(:run)
52
+ .and_raise(RuntimeError.new('Linter#run was called'))
53
+ end
54
+
55
+ it 'never runs a linter' do
56
+ expect { subject }.to_not raise_error
57
+ end
58
+ end
59
+
60
+ context 'when the engine raises a FileEncodingError' do
61
+ let(:error) do
62
+ SCSSLint::FileEncodingError.new('Some error message')
63
+ end
64
+
65
+ before do
66
+ SCSSLint::Engine.stub(:new).and_raise(error)
67
+ end
68
+
69
+ it 'records the error as a lint' do
70
+ subject.count.should == 2
71
+ end
72
+ end
73
+
74
+ context 'when files ere excluded for one linter' do
75
+ let(:config_options) do
76
+ {
77
+ 'linters' => {
78
+ 'FakeLinter1' => { 'enabled' => true,
79
+ 'exclude' => [File.expand_path('dummy1.scss'),
80
+ File.expand_path('dummy2.scss')] },
81
+ 'FakeLinter2' => { 'enabled' => false },
82
+ },
83
+ }
84
+ end
85
+
86
+ before do
87
+ SCSSLint::Linter::FakeLinter1.any_instance
88
+ .stub(:run)
89
+ .and_raise(RuntimeError.new('FakeLinter1#run was called'))
90
+ end
91
+
92
+ it 'does not run the linter for the disabled files' do
93
+ expect { subject }.to_not raise_error
94
+ end
95
+ end
96
+
97
+ context 'when a linter raises an error' do
98
+ let(:backtrace) { %w[file.rb:1 file.rb:2] }
99
+
100
+ let(:error) do
101
+ StandardError.new('Some error message').tap do |e|
102
+ e.set_backtrace(backtrace)
103
+ end
104
+ end
105
+
106
+ before do
107
+ runner.stub(:run_linter).and_raise(error)
108
+ end
109
+
110
+ it 'raises a LinterError' do
111
+ expect { subject }.to raise_error(SCSSLint::Exceptions::LinterError)
112
+ end
113
+
114
+ it 'has the name of the file the linter was checking' do
115
+ expect { subject }.to raise_error { |e| e.message.should include files.first }
116
+ end
117
+
118
+ it 'has the same backtrace as the original error' do
119
+ expect { subject }.to raise_error { |e| e.backtrace.should == backtrace }
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,264 @@
1
+ require 'spec_helper'
2
+
3
+ describe SCSSLint::SelectorVisitor do
4
+ describe '#visit' do
5
+ let(:engine) { SCSSLint::Engine.new(code: scss) }
6
+ before { RuleVisitor.new(visitor).run(engine) }
7
+
8
+ # Visits every rule in the given parse tree and passes the parsed selector
9
+ # to the given `selector_visitor`.
10
+ class RuleVisitor < Sass::Tree::Visitors::Base
11
+ def initialize(selector_visitor)
12
+ @selector_visitor = selector_visitor
13
+ end
14
+
15
+ def run(engine)
16
+ visit(engine.tree)
17
+ end
18
+
19
+ def visit_rule(node)
20
+ @selector_visitor.visit_selector(node.parsed_rules)
21
+ yield # Continue linting children
22
+ end
23
+ end
24
+
25
+ # Superclass for all the test selector visitors
26
+ class TrackingSelectorVisitor
27
+ include SCSSLint::SelectorVisitor
28
+
29
+ attr_reader :node_order
30
+
31
+ def initialize
32
+ @node_order = []
33
+ end
34
+ end
35
+
36
+ context 'when visitor defines visit_attribute' do
37
+ class TestAttributeVisitor < TrackingSelectorVisitor
38
+ def visit_attribute(attribute)
39
+ @node_order << attribute.name
40
+ end
41
+ end
42
+
43
+ let(:visitor) { TestAttributeVisitor.new }
44
+
45
+ let(:scss) { <<-SCSS }
46
+ [rel="nofollow"] {}
47
+ a[href="http"] {}
48
+ .class [data-count] {}
49
+ SCSS
50
+
51
+ it 'visits all attribute nodes' do
52
+ visitor.node_order.should == %w[rel href data-count]
53
+ end
54
+ end
55
+
56
+ context 'when visitor defines visit_class' do
57
+ class TestClassVisitor < TrackingSelectorVisitor
58
+ def visit_class(klass)
59
+ @node_order << klass.name
60
+ end
61
+ end
62
+
63
+ let(:visitor) { TestClassVisitor.new }
64
+
65
+ let(:scss) { <<-SCSS }
66
+ a.link {}
67
+ .menu .menu-item {}
68
+ .button[data-source], .overlay {}
69
+ SCSS
70
+
71
+ it 'visits all class nodes' do
72
+ visitor.node_order.should == %w[link menu menu-item button overlay]
73
+ end
74
+ end
75
+
76
+ context 'when visitor defines visit_element' do
77
+ class TestElementVisitor < TrackingSelectorVisitor
78
+ def visit_element(element)
79
+ @node_order << element.name
80
+ end
81
+ end
82
+
83
+ let(:visitor) { TestElementVisitor.new }
84
+
85
+ let(:scss) { <<-SCSS }
86
+ a, b {}
87
+ .class {}
88
+ i + p {}
89
+ SCSS
90
+
91
+ it 'visits all element nodes' do
92
+ visitor.node_order.should == %w[a b i p]
93
+ end
94
+ end
95
+
96
+ context 'when visitor defines visit_id' do
97
+ class TestIdVisitor < TrackingSelectorVisitor
98
+ def visit_id(id)
99
+ @node_order << id.name
100
+ end
101
+ end
102
+
103
+ let(:visitor) { TestIdVisitor.new }
104
+
105
+ let(:scss) { <<-SCSS }
106
+ #something, #thing {}
107
+ #object + #entity {}
108
+ SCSS
109
+
110
+ it 'visits all id nodes' do
111
+ visitor.node_order.should == %w[something thing object entity]
112
+ end
113
+ end
114
+
115
+ context 'when visitor defines visit_parent' do
116
+ class TestParentVisitor < TrackingSelectorVisitor
117
+ def visit_parent(parent)
118
+ @node_order << parent.line
119
+ end
120
+ end
121
+
122
+ let(:visitor) { TestParentVisitor.new }
123
+
124
+ let(:scss) { <<-SCSS }
125
+ p {
126
+ &.class {}
127
+ .container & {}
128
+ .nothing {}
129
+ }
130
+ SCSS
131
+
132
+ it 'visits all parent nodes' do
133
+ visitor.node_order.should == [2, 3]
134
+ end
135
+ end
136
+
137
+ context 'when visitor defines visit_placeholder' do
138
+ class TestPlaceholderVisitor < TrackingSelectorVisitor
139
+ def visit_placeholder(placeholder)
140
+ @node_order << placeholder.name
141
+ end
142
+ end
143
+
144
+ let(:visitor) { TestPlaceholderVisitor.new }
145
+
146
+ let(:scss) { <<-SCSS }
147
+ %placeholder, %other-placeholder {}
148
+ .button, %button {}
149
+ SCSS
150
+
151
+ it 'visits all placeholder nodes' do
152
+ visitor.node_order.should == %w[placeholder other-placeholder button]
153
+ end
154
+ end
155
+
156
+ context 'when visitor defines visit_pseudo' do
157
+ class TestPseudoVisitor < TrackingSelectorVisitor
158
+ def visit_pseudo(pseudo)
159
+ @node_order << pseudo.name
160
+ end
161
+ end
162
+
163
+ let(:visitor) { TestPseudoVisitor.new }
164
+
165
+ let(:scss) { <<-SCSS }
166
+ li:first-child, li:last-child {}
167
+ p {
168
+ &:first-letter {}
169
+ }
170
+ SCSS
171
+
172
+ it 'visits all pseudo-selector nodes' do
173
+ visitor.node_order.should == %w[first-child last-child first-letter]
174
+ end
175
+ end
176
+
177
+ context 'when visitor defines visit_universal' do
178
+ class TestUniversalVisitor < TrackingSelectorVisitor
179
+ def visit_universal(universal)
180
+ @node_order << universal.line
181
+ end
182
+ end
183
+
184
+ let(:visitor) { TestUniversalVisitor.new }
185
+
186
+ let(:scss) { <<-SCSS }
187
+ p > * {}
188
+ * {}
189
+ li {}
190
+ *:first-child {}
191
+ SCSS
192
+
193
+ it 'visits all universal-selector nodes' do
194
+ visitor.node_order.should == [1, 2, 4]
195
+ end
196
+ end
197
+
198
+ context 'when visitor defines visit_simple_sequence' do
199
+ class TestSimpleSequenceVisitor < TrackingSelectorVisitor
200
+ def visit_simple_sequence(seq)
201
+ @node_order << seq
202
+ end
203
+ end
204
+
205
+ let(:visitor) { TestSimpleSequenceVisitor.new }
206
+
207
+ let(:scss) { <<-SCSS }
208
+ a, b, p[lang] {}
209
+ a.link + b.word {}
210
+ li {}
211
+ ul > li {}
212
+ p span {}
213
+ SCSS
214
+
215
+ it 'visits all simple sequences' do
216
+ visitor.node_order.count.should == 10
217
+ end
218
+ end
219
+
220
+ context 'when visitor defines visit_sequence' do
221
+ class TestSequenceVisitor < TrackingSelectorVisitor
222
+ def visit_sequence(seq)
223
+ @node_order << seq
224
+ end
225
+ end
226
+
227
+ let(:visitor) { TestSequenceVisitor.new }
228
+
229
+ let(:scss) { <<-SCSS }
230
+ a, b, p[lang] {}
231
+ a.link + b.word {}
232
+ li {}
233
+ ul > li {}
234
+ p span {}
235
+ SCSS
236
+
237
+ it 'visits all sequences' do
238
+ visitor.node_order.count.should == 7
239
+ end
240
+ end
241
+
242
+ context 'when visitor defines visit_comma_sequence' do
243
+ class TestCommaSequenceVisitor < TrackingSelectorVisitor
244
+ def visit_comma_sequence(seq)
245
+ @node_order << seq
246
+ end
247
+ end
248
+
249
+ let(:visitor) { TestCommaSequenceVisitor.new }
250
+
251
+ let(:scss) { <<-SCSS }
252
+ a, b, p[lang] {}
253
+ a.link + b.word {}
254
+ li {}
255
+ ul > li {}
256
+ p span {}
257
+ SCSS
258
+
259
+ it 'visits all comma (i.e. selector) sequences' do
260
+ visitor.node_order.count.should == 5
261
+ end
262
+ end
263
+ end
264
+ end
@@ -0,0 +1,34 @@
1
+ require 'scss_lint'
2
+ require 'nokogiri'
3
+
4
+ Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each { |f| require f }
5
+
6
+ RSpec.configure do |config|
7
+ config.expect_with :rspec do |c|
8
+ c.syntax = [:expect, :should]
9
+ end
10
+
11
+ config.mock_with :rspec do |c|
12
+ c.syntax = :should
13
+ end
14
+
15
+ config.before(:each) do
16
+ # If running a linter spec, run the described linter against the CSS code
17
+ # for each example. This significantly DRYs up our linter specs to contain
18
+ # only tests, since all the setup code is now centralized here.
19
+ if described_class <= SCSSLint::Linter
20
+ initial_indent = scss[/\A(\s*)/, 1]
21
+ normalized_css = scss.gsub(/^#{initial_indent}/, '')
22
+
23
+ # Use the configuration settings defined by default unless a specific
24
+ # configuration has been provided for the test.
25
+ local_config = if respond_to?(:linter_config)
26
+ linter_config
27
+ else
28
+ SCSSLint::Config.default.linter_options(subject)
29
+ end
30
+
31
+ subject.run(SCSSLint::Engine.new(code: normalized_css), local_config)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,25 @@
1
+ require 'fileutils'
2
+ require 'tmpdir'
3
+
4
+ shared_context 'isolated environment' do
5
+ around do |example|
6
+ Dir.mktmpdir do |tmpdir|
7
+ original_home = ENV['HOME']
8
+
9
+ begin
10
+ virtual_home = File.expand_path(File.join(tmpdir, 'home'))
11
+ Dir.mkdir(virtual_home)
12
+ ENV['HOME'] = virtual_home
13
+
14
+ working_dir = File.join(tmpdir, 'work')
15
+ Dir.mkdir(working_dir)
16
+
17
+ Dir.chdir(working_dir) do
18
+ example.run
19
+ end
20
+ ensure
21
+ ENV['HOME'] = original_home
22
+ end
23
+ end
24
+ end
25
+ end