moco 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.txt +67 -0
  4. data/Rakefile +15 -0
  5. data/bin/moco +6 -0
  6. data/lib/moco/ansi_escape.rb +37 -0
  7. data/lib/moco/application.rb +109 -0
  8. data/lib/moco/browser.rb +64 -0
  9. data/lib/moco/browser_error.rb +105 -0
  10. data/lib/moco/compile_error.rb +66 -0
  11. data/lib/moco/compiler.rb +151 -0
  12. data/lib/moco/compiler_option.rb +60 -0
  13. data/lib/moco/compiler_register.rb +29 -0
  14. data/lib/moco/compilers/coffee_compiler.rb +70 -0
  15. data/lib/moco/compilers/haml_compiler.rb +21 -0
  16. data/lib/moco/compilers/less_compiler.rb +15 -0
  17. data/lib/moco/compilers/markdown_compiler.rb +139 -0
  18. data/lib/moco/compilers/sass_compiler.rb +25 -0
  19. data/lib/moco/file_util.rb +54 -0
  20. data/lib/moco/log.rb +108 -0
  21. data/lib/moco/monitor.rb +83 -0
  22. data/lib/moco/options.rb +336 -0
  23. data/lib/moco/source_map.rb +22 -0
  24. data/lib/moco/support/error/error.css +22 -0
  25. data/lib/moco/support/error/error.html +7 -0
  26. data/lib/moco/support/error/error.js +58 -0
  27. data/lib/moco/support/reload.scpt +0 -0
  28. data/lib/moco.rb +44 -0
  29. data/moco.gemspec +35 -0
  30. data/moco.rb +35 -0
  31. data/src/error/error.coffee +49 -0
  32. data/src/reload.applescript +135 -0
  33. data/test/ansi_escape_test.rb +52 -0
  34. data/test/application_test.rb +40 -0
  35. data/test/browser_error_test.rb +101 -0
  36. data/test/browser_test.rb +29 -0
  37. data/test/compile_error_test.rb +82 -0
  38. data/test/compiler_option_test.rb +121 -0
  39. data/test/compiler_register_test.rb +41 -0
  40. data/test/compiler_test.rb +243 -0
  41. data/test/compilers/coffee_compiler_test.rb +117 -0
  42. data/test/compilers/haml_compiler_test.rb +86 -0
  43. data/test/compilers/less_compiler_test.rb +72 -0
  44. data/test/compilers/markdown_compiler_test.rb +211 -0
  45. data/test/compilers/sass_compiler_test.rb +84 -0
  46. data/test/file_util_test.rb +37 -0
  47. data/test/fixtures/_color.scss +1 -0
  48. data/test/fixtures/color.less +1 -0
  49. data/test/fixtures/css_lib.rb +2 -0
  50. data/test/fixtures/html_lib.rb +2 -0
  51. data/test/fixtures/js_lib.rb +2 -0
  52. data/test/fixtures/layout.html +13 -0
  53. data/test/fixtures/moco.rb +8 -0
  54. data/test/fixtures/options_lib.rb +2 -0
  55. data/test/fixtures/source.txt +1 -0
  56. data/test/monitor_test.rb +68 -0
  57. data/test/options_test.rb +177 -0
  58. data/test/test_helper.rb +57 -0
  59. metadata +270 -0
@@ -0,0 +1,211 @@
1
+ require 'test_helper'
2
+
3
+ module MoCo
4
+
5
+ describe MarkdownCompiler do
6
+
7
+ after { reset_options(MarkdownCompiler) }
8
+
9
+ let(:markdown) { '#Title' }
10
+ let(:compiler) { mock_compiler(MarkdownCompiler, markdown) }
11
+ let(:compiled_text) { compiler.compiled_text.strip }
12
+
13
+ it 'is registered for md and markdown files' do
14
+ assert_equal MarkdownCompiler, MoCo.compiler_for('md')
15
+ assert_equal MarkdownCompiler, MoCo.compiler_for('markdown')
16
+ end
17
+
18
+ it 'is a Html compiler' do
19
+ assert MarkdownCompiler < HtmlCompiler
20
+ assert_equal 'html', MarkdownCompiler.compiled_extension
21
+ end
22
+
23
+ it 'compiles markdown into html' do
24
+ assert_equal '<h1>Title</h1>', compiled_text
25
+ end
26
+
27
+ specify 'the options are used to specify markdown extensions' do
28
+ MarkdownCompiler.set_option(:space_after_headers)
29
+ assert_equal '<p>#Title</p>', compiled_text
30
+ end
31
+
32
+ specify 'the options are passed on to the html renderer' do
33
+ MarkdownCompiler.set_option(:with_toc_data)
34
+ assert_equal '<h1 id="toc_0">Title</h1>', compiled_text
35
+ end
36
+
37
+ describe 'the :smarty option' do
38
+
39
+ before { MarkdownCompiler.set_option(:smarty) }
40
+
41
+ let(:markdown) { '# ...' }
42
+
43
+ it 'performs SmartyPants substitutions' do
44
+ assert_equal '<h1>&hellip;</h1>', compiled_text
45
+ end
46
+
47
+ it 'works with the Pygments renderer' do
48
+ MarkdownCompiler.set_option(:pygments)
49
+ assert_equal '<h1>&hellip;</h1>', compiled_text
50
+ end
51
+
52
+ it 'works with the table of contents renderer' do
53
+ MarkdownCompiler.set_option(:toc)
54
+ assert_match '<a href="#toc_0">&hellip;</a>', compiled_text
55
+ end
56
+
57
+ end
58
+
59
+ describe 'the :toc option' do
60
+
61
+ before { MarkdownCompiler.set_option(:toc) }
62
+
63
+ it 'produces a table of contents' do
64
+ assert_match '<a href="#toc_0">Title</a>', compiled_text
65
+ assert_match '<h1 id="toc_0">Title</h1>', compiled_text
66
+ end
67
+
68
+ end
69
+
70
+ describe 'the :layout option' do
71
+
72
+ before { MarkdownCompiler.set_option(:layout, layout_file) }
73
+
74
+ let(:layout_file) { fixtures_path('layout.html') }
75
+ let(:layout) { File.read(layout_file) }
76
+
77
+ it 'replaces {{BODY}} with the rendered markdown' do
78
+ assert_match '<article>{{BODY}}</article>', layout
79
+ assert_match "<article><h1>Title</h1>\n</article>", compiled_text
80
+ end
81
+
82
+ describe '{{TOC}}' do
83
+
84
+ before { MarkdownCompiler.set_option(:toc) }
85
+
86
+ it 'replaces {{TOC}} with the table of contents' do
87
+ assert_match '<nav>{{TOC}}</nav>', layout
88
+ assert_match "<nav><ul>\n<li>\n<a href", compiled_text
89
+ end
90
+
91
+ it 'removes {{TOC}} if there is no table of contents' do
92
+ MarkdownCompiler.set_option(:toc, false)
93
+ assert_match '<nav></nav>', compiled_text
94
+ end
95
+
96
+ it 'adds the toc to the {{BODY}} if there is no {{TOC}} tag' do
97
+ layout_file = tmp_dir + '/layout.html'
98
+ FileUtil.write(layout_file, layout.sub('{{TOC}}', ''))
99
+
100
+ MarkdownCompiler.set_option(:layout, layout_file)
101
+ assert_match "<article><ul>\n<li>\n<a href=", compiled_text
102
+ assert_match "Title</h1>\n</article>", compiled_text
103
+ end
104
+
105
+ end
106
+
107
+ describe '{{TITLE}}' do
108
+
109
+ it 'replaces {{TITLE}} with the first h1 element' do
110
+ assert_match '<title>{{TITLE}}</title>', layout
111
+ assert_match '<title>Title</title>', compiled_text
112
+ end
113
+
114
+ it 'accepts an h1 element with attributes' do
115
+ MarkdownCompiler.set_option(:toc)
116
+ assert_match '<title>Title</title>', compiled_text
117
+ end
118
+
119
+ it 'removes nested tags from the title' do
120
+ markdown = '# The [![Home](logo.png)](/index.html) Title'
121
+ compiler = mock_compiler(MarkdownCompiler, markdown)
122
+ assert_match '<title>The Title</title>', compiler.compiled_text
123
+ end
124
+
125
+ it 'replaces {{TITLE}} with the filename if there are no h1 elements' do
126
+ compiler = mock_compiler(MarkdownCompiler, '## h2')
127
+ assert_match '<title>mock.md</title>', compiler.compiled_text
128
+ end
129
+
130
+ end
131
+
132
+ it 'replaces {{FILE}} with the filename' do
133
+ assert_match '<span>{{FILE}}</span>', layout
134
+ assert_match '<span>mock.md</span>', compiled_text
135
+ end
136
+
137
+ end
138
+
139
+ describe 'the :pygments option' do
140
+
141
+ before { MarkdownCompiler.set_option(:pygments) }
142
+
143
+ def code_block(statement, language)
144
+ code_block = "```#{language}\n#{statement}\n```"
145
+ mock_compiler(MarkdownCompiler, code_block).compiled_text.strip
146
+ end
147
+
148
+ it 'adds syntax highlighting hooks to fenced code blocks' do
149
+ expected = '<div class="highlight"><pre><span class="nb">puts</span>'
150
+ assert_match expected, code_block('puts', 'RUBY')
151
+ end
152
+
153
+ it 'ignores code blocks with no language specified' do
154
+ expected = "<pre><code>puts\n</code></pre>"
155
+ assert_equal expected, code_block('puts', nil)
156
+ end
157
+
158
+ it 'adds a class for unknown languages' do
159
+ expected = "<pre><code class=\"dummy\">puts\n</code></pre>"
160
+ assert_equal expected, code_block('puts', 'dummy')
161
+ end
162
+
163
+ it 'escapes the html' do
164
+ expected = '&quot;&#39;&lt;&amp;&gt;'
165
+ assert_match expected, code_block(%("'<&>'"), 'ruby')
166
+ assert_match expected, code_block(%("'<&>'"), nil)
167
+ end
168
+
169
+ describe 'the :pygments options are passed on to Pygments' do
170
+
171
+ let(:markdown) { "```ruby\nputs\nputs\nputs\nputs\n\n```" }
172
+
173
+ it 'accepts a Hash' do
174
+ MarkdownCompiler.set_option(:pygments, :linenos => 'inline')
175
+ assert_equal 'inline', MarkdownCompiler.options[:pygments][:linenos]
176
+ assert_match '<span class="lineno">1</span>', compiled_text
177
+ end
178
+
179
+ it 'accepts an Array' do
180
+ MarkdownCompiler.set_option(:pygments, [:hl_lines, 2, 3])
181
+ assert_equal [2, 3], MarkdownCompiler.options[:pygments][:hl_lines]
182
+ compiled_text.split(/\n/).each_with_index do |line, index|
183
+ if [2, 3].include?(index + 1)
184
+ assert_match '<span class="hll">', line
185
+ else
186
+ refute_match '<span class="hll">', line
187
+ end
188
+ end
189
+ end
190
+
191
+ it 'can set an option to false' do
192
+ MarkdownCompiler.set_option(:pygments, ['stripnl', false])
193
+ assert_equal false, MarkdownCompiler.options[:pygments]['stripnl']
194
+ assert_match "\n\n</pre></div>", compiled_text
195
+ end
196
+
197
+ it 'can be repeated' do
198
+ MarkdownCompiler.set_option(:pygments, 'noclasses')
199
+ MarkdownCompiler.set_option(:pygments, ['style', 'vim'])
200
+ assert_equal true, MarkdownCompiler.options[:pygments]['noclasses']
201
+ assert_equal 'vim', MarkdownCompiler.options[:pygments]['style']
202
+ assert_match '<span style="color: #cd00cd">puts', compiled_text
203
+ end
204
+
205
+ end
206
+
207
+ end
208
+
209
+ end if run_compiler_tests?(MarkdownCompiler)
210
+
211
+ end
@@ -0,0 +1,84 @@
1
+ require 'test_helper'
2
+
3
+ module MoCo
4
+
5
+ describe SassCompiler do
6
+
7
+ it 'is registered for sass and scss files' do
8
+ assert_equal SassCompiler, MoCo.compiler_for('sass')
9
+ assert_equal SassCompiler, MoCo.compiler_for('scss')
10
+ end
11
+
12
+ it 'is a CSS compiler' do
13
+ assert SassCompiler < CssCompiler
14
+ assert_equal 'css', SassCompiler.compiled_extension
15
+ end
16
+
17
+ it 'selects the correct syntax' do
18
+ assert_equal :sass, SassCompiler.new('style.sass').options[:syntax]
19
+ assert_equal :scss, SassCompiler.new('style.scss').options[:syntax]
20
+ end
21
+
22
+ describe 'compile' do
23
+
24
+ css = <<-EOF
25
+ .sass {
26
+ color: #ce4dd6; }
27
+ EOF
28
+
29
+ sass = <<-EOF
30
+ $pink: #CE4DD6
31
+ .sass
32
+ color: $pink
33
+ EOF
34
+
35
+ scss = <<-EOF
36
+ $pink: #CE4DD6;
37
+ .sass { color: $pink; }
38
+ EOF
39
+
40
+ import = <<-EOF
41
+ @import 'color';
42
+ .sass { color: $pink; }
43
+ EOF
44
+
45
+ [css, sass, scss, import].each { |style| style.gsub!(/^ {8}/, '') }
46
+
47
+ it 'compiles sass into css' do
48
+ compiler = mock_compiler(SassCompiler, sass, 'style.sass')
49
+ assert_equal css, compiler.compiled_text
50
+ end
51
+
52
+ it 'compiles scss into css' do
53
+ compiler = mock_compiler(SassCompiler, scss, 'style.scss')
54
+ assert_equal css, compiler.compiled_text
55
+ end
56
+
57
+ it 'handles the @import directive' do
58
+ SassCompiler.set_option(:load_paths, [fixtures_path])
59
+ compiler = mock_compiler(SassCompiler, import, 'style.scss')
60
+ assert_equal css, compiler.compiled_text
61
+ reset_options(SassCompiler)
62
+ end
63
+
64
+ end
65
+
66
+ describe 'compile error' do
67
+
68
+ let(:compiler) do
69
+ mock_compiler(SassCompiler, '.sass { color: $blue; }', 'style.scss')
70
+ end
71
+
72
+ it 'raises a CompileError' do
73
+ assert_raises(CompileError) { compiler.compile }
74
+ end
75
+
76
+ it 'has a line number' do
77
+ assert_equal 1, (compiler.compile rescue $!).line
78
+ end
79
+
80
+ end
81
+
82
+ end if run_compiler_tests?(SassCompiler)
83
+
84
+ end
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+
3
+ module MoCo
4
+
5
+ describe FileUtil do
6
+
7
+ describe 'normalized extension' do
8
+
9
+ specify do
10
+ assert_equal 'less', FileUtil.normalized_extension('less')
11
+ end
12
+
13
+ it 'removes the period' do
14
+ assert_equal 'less', FileUtil.normalized_extension('.less')
15
+ end
16
+
17
+ it 'accepts a symbol' do
18
+ assert_equal 'less', FileUtil.normalized_extension(:less)
19
+ end
20
+
21
+ it 'accepts a filename' do
22
+ assert_equal 'sass', FileUtil.normalized_extension('/dir/file.sass')
23
+ end
24
+
25
+ it 'works with spaces' do
26
+ assert_equal 'sass', FileUtil.normalized_extension(' file with spaces .sass ')
27
+ end
28
+
29
+ it 'works with nested extensions' do
30
+ assert_equal 'sass', FileUtil.normalized_extension('file.css.sass')
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1 @@
1
+ $pink: #CE4DD6;
@@ -0,0 +1 @@
1
+ @blue: #D9EEF2;
@@ -0,0 +1,2 @@
1
+ class CssLib
2
+ end
@@ -0,0 +1,2 @@
1
+ class HtmlLib
2
+ end
@@ -0,0 +1,2 @@
1
+ class JsLib
2
+ end
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>{{TITLE}}</title>
6
+ <link rel="stylesheet" href="style.css" />
7
+ </head>
8
+ <body>
9
+ <span>{{FILE}}</span>
10
+ <nav>{{TOC}}</nav>
11
+ <article>{{BODY}}</article>
12
+ </body>
13
+ </html>
@@ -0,0 +1,8 @@
1
+ MoCo.args '--no-reload -o txt:preserve:pre: .'
2
+
3
+ class TextCompiler < MoCo::HtmlCompiler
4
+ register 'txt'
5
+ set_option :ugly
6
+ end
7
+
8
+ TextCompiler.set_option(:format, :html5)
@@ -0,0 +1,2 @@
1
+ class OptionsLib
2
+ end
@@ -0,0 +1 @@
1
+ The source text
@@ -0,0 +1,68 @@
1
+ require 'test_helper'
2
+
3
+ module MoCo
4
+
5
+ describe Monitor do
6
+
7
+ before { skip unless __FILE__ == $0 }
8
+
9
+ def tmp
10
+ Pathname.new(tmp_dir).realpath().to_s
11
+ end
12
+
13
+ def updated(&block)
14
+ updated = []
15
+ thread = Thread.new do
16
+ monitor.monitor { |file| updated << file }
17
+ end
18
+ sleep 0.05
19
+ yield
20
+ sleep 0.5
21
+ thread.kill
22
+ updated.sort
23
+ end
24
+
25
+ let(:dirs) { [tmp, tmp].sort }
26
+ let(:files) { %W[#{dirs[0]}/file.haml #{dirs[1]}/nested/dir/file.sass] }
27
+ let(:txt_file) { "#{dirs[1]}/file.txt" }
28
+
29
+ describe 'monitor directories' do
30
+
31
+ let(:monitor) { Monitor.new([], dirs, [:sass, :haml]) }
32
+
33
+ it 'captures new files' do
34
+ assert_equal files, updated { touch(files) }
35
+ end
36
+
37
+ it 'captures file updates' do
38
+ touch(files, :mtime => 0)
39
+ assert_equal files, updated { touch(files) }
40
+ end
41
+
42
+ it 'ignores files with other extensions' do
43
+ assert_empty updated { touch(txt_file) }
44
+ end
45
+
46
+ it 'lists all the files currently being monitored' do
47
+ Dir.mkdir("#{dirs[0]}/dir.sass")
48
+ assert_empty monitor.files
49
+ touch(files + [txt_file])
50
+ assert_equal files, monitor.files.sort
51
+ end
52
+
53
+ end
54
+
55
+ describe 'monitor files' do
56
+
57
+ let(:monitor) { Monitor.new(files, [], []) }
58
+
59
+ it 'captures file updates' do
60
+ touch(files, :mtime => 0)
61
+ assert_equal files, updated { touch(files + [txt_file]) }
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,177 @@
1
+ require 'test_helper'
2
+
3
+ module MoCo
4
+
5
+ describe Options do
6
+
7
+ class MockOptions < Options
8
+ define_method(:load_moco_files) {}
9
+ define_method(:validate_files) {}
10
+ define_method(:display_help) {}
11
+ end
12
+
13
+ def parse(args = '')
14
+ MockOptions.parse(args.shellsplit)
15
+ end
16
+
17
+ describe 'parse command line options' do
18
+
19
+ it 'sets the default options' do
20
+ assert_equal Options.new.default_options, parse
21
+ end
22
+
23
+ it 'sets boolean options' do
24
+ assert_equal true, parse('--force')[:force]
25
+ assert_equal false, parse('--no-force')[:force]
26
+ end
27
+
28
+ it 'sets array options' do
29
+ assert_equal %w[Chrome], parse('-b Chrome')[:browsers]
30
+ assert_equal %w[Chrome], parse('-b Chrome,Chrome')[:browsers]
31
+ assert_equal %w[Chrome Opera], parse('-b Chrome,Opera')[:browsers]
32
+ assert_equal %w[Chrome Opera], parse('-b Chrome -b Opera')[:browsers]
33
+ end
34
+
35
+ describe 'the compile option' do
36
+
37
+ it 'sets the compile flag' do
38
+ assert_equal true, parse('-c sass')[:compile]
39
+ assert_equal true, parse('--compile')[:compile]
40
+ assert_equal false, parse('--no-compile')[:compile]
41
+ end
42
+
43
+ it 'sets the compile extensions' do
44
+ assert_equal ['sass'], parse('--compile .sass')[:compile_exts]
45
+ end
46
+
47
+ it 'raises an OptionError if an extension is unregistered' do
48
+ assert_raises(OptionError) { parse('-c cofe') }
49
+ end
50
+
51
+ end
52
+
53
+ describe 'setting compiler options' do
54
+
55
+ it 'sets the options' do
56
+ parse('--option haml:ugly -o haml:preserve:pre:code')
57
+ assert_equal true, HamlCompiler.options[:ugly]
58
+ assert_equal %w[pre code], HamlCompiler.options[:preserve]
59
+ reset_options(HamlCompiler)
60
+ end
61
+
62
+ it 'raises an OptionError if the option key is missing' do
63
+ assert_raises(OptionError) { parse('-o haml') }
64
+ end
65
+
66
+ it 'raises an OptionError if the extension is unregistered' do
67
+ assert_raises(OptionError) { parse('-o aml:ugly') }
68
+ end
69
+
70
+ end
71
+
72
+ it 'sets the source map flag' do
73
+ parse('--source-map')
74
+ assert_equal true, CoffeeCompiler.options[:sourceMap]
75
+ reset_options(CoffeeCompiler)
76
+ end
77
+
78
+ it 'requires the library' do
79
+ refute defined? OptionsLib
80
+ parse('--require ' + fixtures_path('options_lib'))
81
+ assert defined? OptionsLib
82
+ end
83
+
84
+ end
85
+
86
+ describe 'parse command line path arguments' do
87
+
88
+ before { MockOptions.send(:define_method, :validate_files) { super() } }
89
+ after { MockOptions.send(:define_method, :validate_files) {} }
90
+
91
+ let(:dir) { fixtures_path }
92
+ let(:file) { fixtures_path('moco.rb') }
93
+
94
+ it 'sets the source files and directories' do
95
+ assert_equal [file], parse("#{dir} #{file}")[:source_files]
96
+ assert_equal [dir], parse("#{dir} #{file}")[:source_dirs]
97
+ end
98
+
99
+ it 'sets the compiled files and directories' do
100
+ assert_equal '/file', parse("#{file}:/file")[:compiled_files][file]
101
+ assert_equal '/dir', parse("#{dir}:/dir")[:compiled_dirs][dir]
102
+ end
103
+
104
+ it 'raises an OptionError if no path is provided' do
105
+ assert_raises(OptionError) { parse }
106
+ end
107
+
108
+ it 'raises an OptionError if the path does not exists' do
109
+ assert_raises(OptionError) { parse('no_such_file') }
110
+ end
111
+
112
+ it 'raises an OptionError if the compiled file is a directory' do
113
+ assert_raises(OptionError) { parse("#{file}:#{dir}") }
114
+ end
115
+
116
+ it 'raises an OptionError if the compiled directory is a file' do
117
+ assert_raises(OptionError) { parse("#{dir}:#{file}") }
118
+ end
119
+
120
+ end
121
+
122
+ describe 'the moco file' do
123
+
124
+ before do
125
+ moco_file = fixtures_path('moco.rb')
126
+ MockOptions.send(:define_method, :load_moco_files) { load moco_file }
127
+ end
128
+
129
+ after do
130
+ MockOptions.send(:define_method, :load_moco_files) {}
131
+ Options.instance_variable_set(:@args, nil)
132
+ reset_register
133
+ end
134
+
135
+ it 'can register new compilers' do
136
+ parse
137
+ assert_equal TextCompiler, MoCo.compiler_for('txt')
138
+ end
139
+
140
+ it 'sets compiler options' do
141
+ parse
142
+ assert_equal ['pre'], TextCompiler.options[:preserve]
143
+ assert_equal :html5, TextCompiler.options[:format]
144
+ assert_equal true, TextCompiler.options[:ugly]
145
+ end
146
+
147
+ it 'sets general options' do
148
+ assert_equal false, parse[:reload]
149
+ end
150
+
151
+ specify 'the command line options have precedence' do
152
+ assert_equal true, parse('-r -o txt:format:xml')[:reload]
153
+ assert_equal 'xml', TextCompiler.options[:format]
154
+ end
155
+
156
+ specify 'MoCo.args expects a shell escaped string' do
157
+ MoCo.args(%(-o txt:foo:'The "Quote"'))
158
+ MoCo.args(%(-o txt:bar:The\\ \\"Quote\\"))
159
+ parse
160
+ assert_equal 'The "Quote"', TextCompiler.options[:foo]
161
+ assert_equal 'The "Quote"', TextCompiler.options[:bar]
162
+ end
163
+
164
+ it 'finds the moco files in the current working directory' do
165
+ current_dir = Dir.pwd
166
+ Dir.chdir(tmp_dir)
167
+ touch([Dir.pwd + '/moco.rb', Dir.pwd + '/.moco'])
168
+ assert_includes Options.moco_files, Dir.pwd + '/moco.rb'
169
+ assert_includes Options.moco_files, Dir.pwd + '/.moco'
170
+ Dir.chdir(current_dir)
171
+ end
172
+
173
+ end
174
+
175
+ end
176
+
177
+ end
@@ -0,0 +1,57 @@
1
+ require File.expand_path('../../lib/moco', __FILE__)
2
+ require 'minitest/autorun'
3
+ require 'tmpdir'
4
+
5
+ COMPILERS = MoCo.compilers
6
+ TMP_DIR = Dir.mktmpdir('MoCo')
7
+
8
+ MiniTest::Unit.after_tests do
9
+ FileUtils.rm_rf(TMP_DIR)
10
+ end
11
+
12
+ def tmp_dir
13
+ Dir.mktmpdir(nil, TMP_DIR)
14
+ end
15
+
16
+ def fixtures_path(file = nil)
17
+ fixtures_dir = File.expand_path('../fixtures', __FILE__)
18
+ file ? File.join(fixtures_dir, file) : fixtures_dir
19
+ end
20
+
21
+ def touch(files, options = {})
22
+ Array(files).each do |file|
23
+ FileUtils.makedirs(File.dirname(file))
24
+ FileUtils.touch(file, options)
25
+ end
26
+ end
27
+
28
+ def reset_register
29
+ register = MoCo::CompilerRegister.instance
30
+ register.instance_variable_set(:@compilers, COMPILERS.dup)
31
+ end
32
+
33
+ def reset_options(klass)
34
+ klass.instance_variable_set(:@options, {})
35
+ end
36
+
37
+ def run_compiler_tests?(klass)
38
+ klass.new('')
39
+ rescue LoadError => e
40
+ warn "Skipping #{klass} tests (#{e.message.split("\n").first})"
41
+ end
42
+
43
+ def mock_compiler(klass, source_text, source_file = nil, compiled_file = nil)
44
+ source_file ||= "mock.#{MoCo.compilers.invert[klass]}"
45
+ mock = klass.new(source_file, compiled_file)
46
+ mock.define_singleton_method(:source_text) { source_text }
47
+ mock.define_singleton_method(:write_file) { |filename, text| }
48
+ mock
49
+ end
50
+
51
+ unless respond_to?(:define_singleton_method)
52
+ Object.send(:define_method, :define_singleton_method) do |name, &block|
53
+ singleton = class << self; self end
54
+ singleton.send(:define_method, name, &block)
55
+ end
56
+ Object.send(:public, :define_singleton_method)
57
+ end