moco 0.1.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/LICENSE +20 -0
- data/README.txt +67 -0
- data/Rakefile +15 -0
- data/bin/moco +6 -0
- data/lib/moco/ansi_escape.rb +37 -0
- data/lib/moco/application.rb +109 -0
- data/lib/moco/browser.rb +64 -0
- data/lib/moco/browser_error.rb +105 -0
- data/lib/moco/compile_error.rb +66 -0
- data/lib/moco/compiler.rb +151 -0
- data/lib/moco/compiler_option.rb +60 -0
- data/lib/moco/compiler_register.rb +29 -0
- data/lib/moco/compilers/coffee_compiler.rb +70 -0
- data/lib/moco/compilers/haml_compiler.rb +21 -0
- data/lib/moco/compilers/less_compiler.rb +15 -0
- data/lib/moco/compilers/markdown_compiler.rb +139 -0
- data/lib/moco/compilers/sass_compiler.rb +25 -0
- data/lib/moco/file_util.rb +54 -0
- data/lib/moco/log.rb +108 -0
- data/lib/moco/monitor.rb +83 -0
- data/lib/moco/options.rb +336 -0
- data/lib/moco/source_map.rb +22 -0
- data/lib/moco/support/error/error.css +22 -0
- data/lib/moco/support/error/error.html +7 -0
- data/lib/moco/support/error/error.js +58 -0
- data/lib/moco/support/reload.scpt +0 -0
- data/lib/moco.rb +44 -0
- data/moco.gemspec +35 -0
- data/moco.rb +35 -0
- data/src/error/error.coffee +49 -0
- data/src/reload.applescript +135 -0
- data/test/ansi_escape_test.rb +52 -0
- data/test/application_test.rb +40 -0
- data/test/browser_error_test.rb +101 -0
- data/test/browser_test.rb +29 -0
- data/test/compile_error_test.rb +82 -0
- data/test/compiler_option_test.rb +121 -0
- data/test/compiler_register_test.rb +41 -0
- data/test/compiler_test.rb +243 -0
- data/test/compilers/coffee_compiler_test.rb +117 -0
- data/test/compilers/haml_compiler_test.rb +86 -0
- data/test/compilers/less_compiler_test.rb +72 -0
- data/test/compilers/markdown_compiler_test.rb +211 -0
- data/test/compilers/sass_compiler_test.rb +84 -0
- data/test/file_util_test.rb +37 -0
- data/test/fixtures/_color.scss +1 -0
- data/test/fixtures/color.less +1 -0
- data/test/fixtures/css_lib.rb +2 -0
- data/test/fixtures/html_lib.rb +2 -0
- data/test/fixtures/js_lib.rb +2 -0
- data/test/fixtures/layout.html +13 -0
- data/test/fixtures/moco.rb +8 -0
- data/test/fixtures/options_lib.rb +2 -0
- data/test/fixtures/source.txt +1 -0
- data/test/monitor_test.rb +68 -0
- data/test/options_test.rb +177 -0
- data/test/test_helper.rb +57 -0
- metadata +270 -0
@@ -0,0 +1,243 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MoCo
|
4
|
+
|
5
|
+
describe Compiler do
|
6
|
+
|
7
|
+
describe 'require libraries' do
|
8
|
+
|
9
|
+
$LOAD_PATH.unshift(fixtures_path)
|
10
|
+
|
11
|
+
it 'will not require the library at the time of registration' do
|
12
|
+
JsCompiler.require_library('js_lib')
|
13
|
+
refute defined? JsLib
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'requires the library when the compiler is instantiated' do
|
17
|
+
CssCompiler.require_library('css_lib')
|
18
|
+
refute defined? CssLib
|
19
|
+
CssCompiler.new('')
|
20
|
+
assert defined? CssLib
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'requires the superclass libraries' do
|
24
|
+
HtmlCompiler.require_library('html_lib')
|
25
|
+
refute defined? HtmlLib
|
26
|
+
Class.new(Class.new(HtmlCompiler)).new('')
|
27
|
+
assert defined? HtmlLib
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'require uninstalled libraries' do
|
33
|
+
|
34
|
+
class CorruptCompiler < HtmlCompiler
|
35
|
+
require_library 'not_installed', 'not-installed-gem', '~> 2'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'raises a LoadError with installation instructions' do
|
39
|
+
e = assert_raises(Gem::LoadError) { CorruptCompiler.new('') }
|
40
|
+
assert_match "gem install not-installed-gem -v '~> 2'", e.message
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'compiler options' do
|
46
|
+
|
47
|
+
after { reset_options(HtmlCompiler) }
|
48
|
+
|
49
|
+
it 'sets the option' do
|
50
|
+
HtmlCompiler.set_option(:format, :html5)
|
51
|
+
assert_equal :html5, HtmlCompiler.options[:format]
|
52
|
+
assert_equal :html5, HtmlCompiler.new('').options[:format]
|
53
|
+
end
|
54
|
+
|
55
|
+
specify 'the default value is true' do
|
56
|
+
HtmlCompiler.set_option(:ugly)
|
57
|
+
assert_equal true, HtmlCompiler.options[:ugly]
|
58
|
+
end
|
59
|
+
|
60
|
+
specify 'updating the options hash directly has no effect' do
|
61
|
+
HtmlCompiler.options[:format] = :xhtml
|
62
|
+
compiler = HtmlCompiler.new('')
|
63
|
+
compiler.options[:format] = :xhtml
|
64
|
+
assert_empty HtmlCompiler.options
|
65
|
+
assert_empty compiler.options
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'the compiled filename' do
|
71
|
+
|
72
|
+
it 'cannot be equal to the source filename' do
|
73
|
+
e = assert_raises(Error) do
|
74
|
+
HtmlCompiler.new('index.html', Dir.pwd + '/index.html')
|
75
|
+
end
|
76
|
+
assert_match 'validate_filenames', e.backtrace.first
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'will keep the compiled filename unchanged, if provided' do
|
80
|
+
compiler = HtmlCompiler.new('source.md', 'compiled.xml', 'dir')
|
81
|
+
assert_equal 'compiled.xml', compiler.compiled_file
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'the compiled filename extension' do
|
87
|
+
|
88
|
+
def compiled_file(source_file)
|
89
|
+
JsCompiler.new(source_file).compiled_file
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'has the compiled extension' do
|
93
|
+
assert_equal 'script.js', compiled_file('script.coffee')
|
94
|
+
end
|
95
|
+
|
96
|
+
specify 'the compiler must implement compiled_extension' do
|
97
|
+
e = assert_raises(NotImplementedError) { Compiler.new('') }
|
98
|
+
assert_match 'compiled_extension', e.backtrace.first
|
99
|
+
end
|
100
|
+
|
101
|
+
describe 'nested source extension' do
|
102
|
+
|
103
|
+
it 'will not duplicate the compiled extension' do
|
104
|
+
assert_equal 'script.js', compiled_file('script.js.coffee')
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'will keep other extensions' do
|
108
|
+
assert_equal 'script.min.js', compiled_file('script.min.coffee')
|
109
|
+
end
|
110
|
+
|
111
|
+
specify 'not duplicate extension' do
|
112
|
+
assert_equal 'about_js.js', compiled_file('about_js.coffee')
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
describe 'nested compiled extension' do
|
118
|
+
|
119
|
+
class Minify < JsCompiler
|
120
|
+
define_singleton_method(:compiled_extension) { '.min.js' }
|
121
|
+
end
|
122
|
+
|
123
|
+
specify do
|
124
|
+
assert_equal 'script.min.js', Minify.new('script.js').compiled_file
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
describe 'no extensions' do
|
130
|
+
|
131
|
+
class Readme < Compiler
|
132
|
+
define_singleton_method(:compiled_extension) { '' }
|
133
|
+
end
|
134
|
+
|
135
|
+
specify 'the compiled extension is empty' do
|
136
|
+
assert_equal 'README', Readme.new('README.txt').compiled_file
|
137
|
+
end
|
138
|
+
|
139
|
+
specify 'the source file has no extension' do
|
140
|
+
assert_equal 'README.html', HtmlCompiler.new('README').compiled_file
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
describe 'the compiled filename directory' do
|
148
|
+
|
149
|
+
def compiled_file(source_file, compiled_dir = nil)
|
150
|
+
CssCompiler.new(source_file, nil, compiled_dir).compiled_file
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'has the same directory as the source file by default' do
|
154
|
+
assert_equal 'css/style.css', compiled_file('css/style.sass')
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'replaces the directory if one is provided' do
|
158
|
+
assert_equal 'css/style.css', compiled_file('style.scss', 'css')
|
159
|
+
assert_equal 'css/style.css', compiled_file('/sass/style.scss', 'css/')
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'removes the source directory if compiled_dir is empty' do
|
163
|
+
assert_equal 'style.css', compiled_file('templates/style.scss', '')
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
describe 'compile' do
|
169
|
+
|
170
|
+
class GoodCompiler < Compiler
|
171
|
+
define_method(:compiled_text) { 'The compiled text' }
|
172
|
+
end
|
173
|
+
|
174
|
+
let(:compiler) do
|
175
|
+
GoodCompiler.new(fixtures_path('source.txt'), tmp_dir + '/dir/out.txt')
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'reads the source file' do
|
179
|
+
assert_equal 'The source text', compiler.source_text
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'makes the necessary directories for the compiled file' do
|
183
|
+
compiler.compile
|
184
|
+
assert File.directory?(File.dirname(compiler.compiled_file))
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'writes the compiled text to the compiled file' do
|
188
|
+
compiler.compile
|
189
|
+
assert_equal 'The compiled text', File.read(compiler.compiled_file)
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
describe 'failed compilation' do
|
195
|
+
|
196
|
+
class BadCompiler < Compiler
|
197
|
+
define_method(:compiled_text) { raise 'The error text' }
|
198
|
+
end
|
199
|
+
|
200
|
+
let(:compiler) { BadCompiler.new('', tmp_dir + '/dir/out.txt') }
|
201
|
+
|
202
|
+
it 'raises a CompileError' do
|
203
|
+
assert_raises(CompileError) { compiler.compile }
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'writes the error message to the compiled file' do
|
207
|
+
compiler.compile rescue
|
208
|
+
assert_equal 'The error text', File.read(compiler.compiled_file)
|
209
|
+
end
|
210
|
+
|
211
|
+
specify 'the compiler must implement compiled_text' do
|
212
|
+
e = assert_raises(NotImplementedError) { JsCompiler.new('').compile }
|
213
|
+
assert_match 'compiled_text', e.backtrace.first
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
describe 'should_compile?' do
|
219
|
+
|
220
|
+
let(:compiler) { JsCompiler.new(tmp_dir + '/script.coffee') }
|
221
|
+
|
222
|
+
it 'is true if the compiled file does not exist' do
|
223
|
+
touch(compiler.source_file)
|
224
|
+
assert compiler.should_compile?
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'is true when the source file is updated' do
|
228
|
+
touch(compiler.compiled_file, :mtime => 0)
|
229
|
+
touch(compiler.source_file, :mtime => 1)
|
230
|
+
assert compiler.should_compile?
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'is false if the compiled file is up to date' do
|
234
|
+
touch(compiler.source_file)
|
235
|
+
touch(compiler.compiled_file)
|
236
|
+
refute compiler.should_compile?
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MoCo
|
4
|
+
|
5
|
+
describe CoffeeCompiler do
|
6
|
+
|
7
|
+
let(:compiler) { mock_compiler(CoffeeCompiler, 'alert yes') }
|
8
|
+
let(:compiled_text) { compiler.compiled_text }
|
9
|
+
|
10
|
+
it 'is registered for coffee files' do
|
11
|
+
assert_equal CoffeeCompiler, MoCo.compiler_for('coffee')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'is a JavaScript compiler' do
|
15
|
+
assert CoffeeCompiler < JsCompiler
|
16
|
+
assert_equal 'js', CoffeeCompiler.compiled_extension
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'compiles CoffeeScript into JavaScript' do
|
20
|
+
assert_match 'alert(true);', compiled_text
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'options' do
|
24
|
+
|
25
|
+
after { reset_options(CoffeeCompiler) }
|
26
|
+
|
27
|
+
it 'has a function wrapper by default' do
|
28
|
+
assert compiled_text.start_with?('(function() {')
|
29
|
+
assert compiled_text.strip.end_with?('}).call(this);')
|
30
|
+
end
|
31
|
+
|
32
|
+
specify 'the bare option disables the function wrapper' do
|
33
|
+
CoffeeCompiler.set_option(:bare)
|
34
|
+
assert_equal 'alert(true);', compiled_text.strip
|
35
|
+
end
|
36
|
+
|
37
|
+
specify 'the header includes the version number' do
|
38
|
+
CoffeeCompiler.set_option(:header)
|
39
|
+
version = CoffeeCompiler.context.run('return CoffeeScript.VERSION;')
|
40
|
+
assert_match "// Generated by CoffeeScript #{version}", compiled_text
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'source maps' do
|
46
|
+
|
47
|
+
before { CoffeeCompiler.set_option(:sourceMap) }
|
48
|
+
after { reset_options(CoffeeCompiler) }
|
49
|
+
|
50
|
+
let(:compiler) do
|
51
|
+
mock_compiler(CoffeeCompiler, 'alert', 'app.coffee', 'dir/the app.js')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'produces a source map with relative paths' do
|
55
|
+
compiler.compile
|
56
|
+
map = JSON.load(compiler.source_map_text)
|
57
|
+
assert_equal 3, map['version']
|
58
|
+
assert_equal 'the app.js', map['file']
|
59
|
+
assert_equal '../app.coffee', map['sources'].first
|
60
|
+
assert_match 'AAA', map['mappings']
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'adds a comment, with the source map URI, to the compiled text' do
|
64
|
+
assert_match '//@ sourceMappingURL=the%20app.js.map', compiled_text
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'will be saved to the same directory as the compiled file' do
|
68
|
+
assert_equal File.dirname(compiler.source_map_file),
|
69
|
+
File.dirname(compiler.compiled_file)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'writes the source map file' do
|
73
|
+
compiler = CoffeeCompiler.new('/script.coffee', nil, tmp_dir)
|
74
|
+
compiler.define_singleton_method(:source_text) { 'alert' }
|
75
|
+
compiler.compile
|
76
|
+
assert_equal compiler.source_map_text, File.read(compiler.source_map_file)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'compile error' do
|
82
|
+
|
83
|
+
let(:compiler) { mock_compiler(CoffeeCompiler, 'evil = (eval) ->') }
|
84
|
+
let(:error) { compiler.compile rescue $! }
|
85
|
+
|
86
|
+
it 'raises a CompileError' do
|
87
|
+
assert_raises(CompileError) { compiler.compile }
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'captures the error location' do
|
91
|
+
assert_equal 1, error.line
|
92
|
+
assert_equal 9, error.column
|
93
|
+
end
|
94
|
+
|
95
|
+
describe 'the error message' do
|
96
|
+
|
97
|
+
it 'removes the filename and location from the original message' do
|
98
|
+
message = error.error.message
|
99
|
+
assert message.start_with?('mock.coffee:1:9: error: parameter name')
|
100
|
+
|
101
|
+
message = error.message
|
102
|
+
assert message.start_with?('Parameter name')
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'marks the erroneous code with red (using ANSI escape codes)' do
|
106
|
+
message = error.message.split("\n")
|
107
|
+
assert_equal "evil = (\e[1;31meval\e[0m) ->", message[-2]
|
108
|
+
assert_equal "\e[1;31m ^^^^\e[0m" , message[-1]
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end if run_compiler_tests?(CoffeeCompiler)
|
116
|
+
|
117
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MoCo
|
4
|
+
|
5
|
+
describe HamlCompiler do
|
6
|
+
|
7
|
+
let(:compiler) { mock_compiler(HamlCompiler, '#haml= 2 + 2') }
|
8
|
+
|
9
|
+
it 'is registered for haml files' do
|
10
|
+
assert_equal HamlCompiler, MoCo.compiler_for('haml')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'is a Html compiler' do
|
14
|
+
assert HamlCompiler < HtmlCompiler
|
15
|
+
assert_equal 'html', HamlCompiler.compiled_extension
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'compiles haml into html' do
|
19
|
+
assert_equal "<div id='haml'>4</div>", compiler.compiled_text.strip
|
20
|
+
end
|
21
|
+
|
22
|
+
specify 'options are passed on to the haml compiler' do
|
23
|
+
HamlCompiler.set_option(:attr_wrapper, '@')
|
24
|
+
assert_match '<div id=@haml@>', compiler.compiled_text
|
25
|
+
reset_options(HamlCompiler)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'compile error' do
|
29
|
+
|
30
|
+
def compile(haml)
|
31
|
+
mock_compiler(HamlCompiler, haml, 'mock.haml').compile
|
32
|
+
rescue CompileError => error
|
33
|
+
error
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'removes the filename and line number from the error message' do
|
37
|
+
error = compile('.haml= [}')
|
38
|
+
refute_match 'mock.haml', error.message
|
39
|
+
refute_match /[:\d]/, error.message
|
40
|
+
|
41
|
+
# The original error
|
42
|
+
assert_match 'mock.haml:1:', error.error.message
|
43
|
+
assert_match 'mock.haml:2:', error.error.message
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'the line number' do
|
47
|
+
|
48
|
+
specify 'line numbers fetched from @line start at 1' do
|
49
|
+
error = compile(' %p')
|
50
|
+
assert_equal 1, error.line
|
51
|
+
|
52
|
+
# The original error
|
53
|
+
assert error.error.line
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'finds the line number in the backtrace' do
|
57
|
+
error = compile("\n.time= Date.tomorrow")
|
58
|
+
assert_equal 2, error.line
|
59
|
+
|
60
|
+
# The original error
|
61
|
+
refute defined? error.error.line
|
62
|
+
assert_match 'mock.haml:2:', error.error.backtrace.first
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'finds the line number in the error message' do
|
66
|
+
error = compile("\n\n.unbalanced= [}")
|
67
|
+
assert_equal 3, error.line
|
68
|
+
|
69
|
+
# The original error
|
70
|
+
assert_nil error.error.line
|
71
|
+
refute_match ':3:', error.error.backtrace.to_s
|
72
|
+
assert_match 'mock.haml:3:', error.error.message
|
73
|
+
end
|
74
|
+
|
75
|
+
specify 'line can be nil' do
|
76
|
+
error = compile("%p= eval '2 *** 10'")
|
77
|
+
assert_nil error.line
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end if run_compiler_tests?(HamlCompiler)
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MoCo
|
4
|
+
|
5
|
+
describe LessCompiler do
|
6
|
+
|
7
|
+
it 'is registered for less files' do
|
8
|
+
assert_equal LessCompiler, MoCo.compiler_for('less')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'is a CSS compiler' do
|
12
|
+
assert LessCompiler < CssCompiler
|
13
|
+
assert_equal 'css', LessCompiler.compiled_extension
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'compile' do
|
17
|
+
|
18
|
+
css = <<-EOF
|
19
|
+
.less {
|
20
|
+
color: #d9eef2;
|
21
|
+
}
|
22
|
+
EOF
|
23
|
+
|
24
|
+
less = <<-EOF
|
25
|
+
@blue: #D9EEF2;
|
26
|
+
.less {
|
27
|
+
color: @blue;
|
28
|
+
}
|
29
|
+
EOF
|
30
|
+
|
31
|
+
import = <<-EOF
|
32
|
+
@import 'color';
|
33
|
+
.less {
|
34
|
+
color: @blue;
|
35
|
+
}
|
36
|
+
EOF
|
37
|
+
|
38
|
+
[css, less, import].each { |style| style.gsub!(/^ {8}/, '') }
|
39
|
+
|
40
|
+
it 'compiles less into css' do
|
41
|
+
compiler = mock_compiler(LessCompiler, less)
|
42
|
+
assert_equal css, compiler.compiled_text
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'handles the @import directive' do
|
46
|
+
LessCompiler.set_option(:paths, [fixtures_path])
|
47
|
+
compiler = mock_compiler(LessCompiler, import)
|
48
|
+
assert_equal css, compiler.compiled_text
|
49
|
+
reset_options(LessCompiler)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'compile error' do
|
55
|
+
|
56
|
+
let(:compiler) do
|
57
|
+
mock_compiler(LessCompiler, '.less { color: @pink; }')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'raises a CompileError' do
|
61
|
+
assert_raises(CompileError) { compiler.compile }
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'has a line number' do
|
65
|
+
assert_equal 1, (compiler.compile rescue $!).line
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end if run_compiler_tests?(LessCompiler)
|
71
|
+
|
72
|
+
end
|