snapdragon 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,72 @@
1
+ module Snapdragon
2
+ class SpecFile
3
+ def initialize(path, line_number = nil)
4
+ @path = path
5
+ @line_number = line_number
6
+ end
7
+
8
+ def read
9
+ f = File.open(@path, 'r')
10
+ content = f.read
11
+ f.close
12
+ return content
13
+ end
14
+
15
+ def require_paths
16
+ f = File.open(@path, 'r')
17
+ lines = f.readlines
18
+ f.close
19
+
20
+ require_paths = []
21
+
22
+ lines.each do |line|
23
+ if line =~ /\/\/+\s+require_relative\(['"](.+)['"]\)\s+$/
24
+ require_paths << File.expand_path(File.join(File.dirname(@path), $1))
25
+ end
26
+ end
27
+
28
+ return require_paths
29
+ end
30
+
31
+ def filtered?
32
+ return true if @line_number
33
+ return false
34
+ end
35
+
36
+ def spec_query_param
37
+ return '' if !filtered?
38
+
39
+ # Work our way from the line number up to build the spec query param
40
+ # description
41
+ initial_line_number = @line_number
42
+ initial_line_index = initial_line_number - 1
43
+
44
+ f = open(@path, 'r')
45
+ lines = f.readlines
46
+ f.close
47
+
48
+ desc_components = []
49
+
50
+ already_been_inside_an_it = false
51
+ already_been_inside_a_describe = false
52
+ last_describe_indent_spaces = 1232131312
53
+
54
+ cur_line_index = initial_line_index
55
+ while cur_line_index >= 0
56
+ if lines[cur_line_index] =~ /it\s*\(\s*"(.+)"\s*,/ && !already_been_inside_an_it && !already_been_inside_a_describe # line matches it statement
57
+ desc_components.push($1)
58
+ already_been_inside_an_it = true
59
+ elsif lines[cur_line_index] =~ /(\s*)describe\s*\(\s*"(.+)"\s*,/ # line matches a describe block
60
+ if $1.length < last_describe_indent_spaces # use indent depth to identify parent
61
+ desc_components.push($2)
62
+ last_describe_indent_spaces = $1.length
63
+ end
64
+ already_been_inside_a_describe = true
65
+ end
66
+ cur_line_index -= 1
67
+ end
68
+
69
+ return desc_components.reverse.join(" ")
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,47 @@
1
+ module Snapdragon
2
+ class Suite
3
+ def initialize
4
+ @specs = []
5
+ @require_paths = Set.new
6
+ @filtered = false
7
+ @spec_query_param = ''
8
+ end
9
+
10
+ def add_spec_file(spec_file)
11
+ if spec_file.filtered?
12
+ @filtered = true
13
+ @spec_query_param = spec_file.spec_query_param
14
+ end
15
+ @specs << spec_file
16
+ @require_paths.merge(spec_file.require_paths)
17
+ end
18
+
19
+ def add_spec_files(spec_files)
20
+ spec_files.each do |spec|
21
+ add_spec_file(spec)
22
+ end
23
+ end
24
+
25
+ def spec_files
26
+ @specs
27
+ end
28
+
29
+ def output_spec_dependencies
30
+ require_content = ""
31
+ @require_paths.each do |require_path|
32
+ f = File.open(require_path, 'r')
33
+ require_content << f.read
34
+ f.close
35
+ end
36
+ return require_content
37
+ end
38
+
39
+ def spec_query_param
40
+ @spec_query_param
41
+ end
42
+
43
+ def filtered?
44
+ @filtered
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module Snapdragon
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE HTML>
2
+
3
+ <html>
4
+ <head>
5
+ </head>
6
+ <body>
7
+
8
+ <%= yield %>
9
+
10
+ </body>
11
+ </html>
@@ -0,0 +1,27 @@
1
+ <link rel="stylesheet" type="text/css" href="/jasmine-core/jasmine.css">
2
+ <script type="text/javascript" src="/jasmine-core/jasmine.js"></script>
3
+ <script type="text/javascript" src="/jasmine-core/jasmine-html.js"></script>
4
+
5
+ <script type="text/javascript" src="/resources/ConsoleReporter.js"></script>
6
+
7
+ <script type="text/javascript" src="/jasmine-core/boot.js"></script>
8
+
9
+ <script type="text/javascript">
10
+ // standard jasmine code to add console reporter in the jasmine runner
11
+ var env = jasmine.getEnv();
12
+ var consoleReporterFunc = getJasmineRequireObj().ConsoleReporter();
13
+ var consoleReporter = new consoleReporterFunc({});
14
+ env.addReporter(consoleReporter);
15
+ </script>
16
+
17
+ <script type="text/javascript">
18
+ // The implementation code the spec files being tested need
19
+ <%= @suite.output_spec_dependencies %>
20
+ </script>
21
+
22
+ <script type="text/javascript">
23
+ // The spec file contents
24
+ <% @suite.spec_files.each do |spec| %>
25
+ <%= spec.read %>
26
+ <% end %>
27
+ </script>
@@ -0,0 +1,26 @@
1
+ require 'sinatra/base'
2
+ require 'erb'
3
+
4
+ module Snapdragon
5
+ class WebApplication < Sinatra::Base
6
+ set :static, false
7
+ set :root, File.expand_path('.', File.dirname(__FILE__))
8
+
9
+ def initialize(app = nil, suite)
10
+ super()
11
+ @suite = suite
12
+ end
13
+
14
+ get "/run" do
15
+ erb :run
16
+ end
17
+
18
+ get "/jasmine-core/*" do |path|
19
+ send_file File.expand_path(File.join('../jasmine/lib/jasmine-core', path), File.dirname(__FILE__))
20
+ end
21
+
22
+ get "/resources/*" do |path|
23
+ send_file File.expand_path(File.join('resources', path), File.dirname(__FILE__))
24
+ end
25
+ end
26
+ end
data/lib/snapdragon.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "snapdragon/version"
2
+
3
+ module Snapdragon
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'snapdragon/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "snapdragon"
8
+ spec.version = Snapdragon::VERSION
9
+ spec.authors = ["Andrew De Ponte"]
10
+ spec.email = ["cyphactor@gmail.com"]
11
+ spec.description = %q{A Jasmine JavaScript test runner that lets you run tests on the command-line similar to RSpec.}
12
+ spec.summary = %q{A command-line Jasmine JavaScript test runner.}
13
+ spec.homepage = "http://github.com/reachlocal/snapdragon"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "capybara", "~> 2.1.0"
22
+ spec.add_dependency "poltergeist", "~> 1.3.0"
23
+ spec.add_dependency "sinatra", "~> 1.4.3"
24
+ spec.add_dependency "launchy", "~> 2.3.0"
25
+ spec.add_development_dependency "bundler", "~> 1.3"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rspec", "~> 2.13.0"
28
+ end
@@ -0,0 +1,221 @@
1
+ require_relative '../../../lib/snapdragon/cli_application'
2
+
3
+ describe Snapdragon::CliApplication do
4
+ describe "#initialize" do
5
+ it "stores a copy of the given command line arguments" do
6
+ cmd_line_args = stub('command_line_args')
7
+ cli_app = Snapdragon::CliApplication.new(cmd_line_args)
8
+ cli_app.instance_variable_get(:@args).should eq(cmd_line_args)
9
+ end
10
+
11
+ it "creates an empty Suite" do
12
+ Snapdragon::Suite.should_receive(:new)
13
+ Snapdragon::CliApplication.new(stub)
14
+ end
15
+
16
+ it "assigns the new Suite to an instance variable" do
17
+ suite = stub('suite')
18
+ Snapdragon::Suite.stub(:new).and_return(suite)
19
+ app = Snapdragon::CliApplication.new(stub)
20
+ app.instance_variable_get(:@suite).should eq(suite)
21
+ end
22
+ end
23
+
24
+ describe "#run" do
25
+ it "parses the given command line arguements" do
26
+ arguements = stub
27
+ app = Snapdragon::CliApplication.new(arguements)
28
+ app.should_receive(:parse_arguements).with(arguements)
29
+ app.stub(:run_suite)
30
+ app.run
31
+ end
32
+
33
+ it "runs the Jasmine suite" do
34
+ app = Snapdragon::CliApplication.new(['/some/path/to_some_spec.js'])
35
+ app.stub(:parse_arguements)
36
+ app.should_receive(:run_suite)
37
+ app.run
38
+ end
39
+
40
+ it "returns 0 representing success" do
41
+ app = Snapdragon::CliApplication.new(['/some/path/to_some_spec.js'])
42
+ app.stub(:parse_arguements)
43
+ app.stub(:run_suite)
44
+ app.run.should eq(0)
45
+ end
46
+ end
47
+
48
+ describe "#parse_arguements" do
49
+ let(:arguements) { ['some/path/to/some_spec.js:23', 'some/path/to/some_other_spec.js'] }
50
+ subject { Snapdragon::CliApplication.new(arguements) }
51
+
52
+ it "iterates over each of the arguments parsing each one" do
53
+ subject.should_receive(:parse_arguement).with('some/path/to/some_spec.js:23')
54
+ subject.should_receive(:parse_arguement).with('some/path/to/some_other_spec.js')
55
+ subject.send(:parse_arguements, arguements)
56
+ end
57
+ end
58
+
59
+ describe "#parse_arguement" do
60
+ subject { Snapdragon::CliApplication.new(stub) }
61
+
62
+ context "when the arg represents a file + line number" do
63
+ before do
64
+ subject.stub(:is_a_file_path_and_line_number?).and_return(true)
65
+ end
66
+
67
+ it "creates a SpecFile with the specified path and line number" do
68
+ Snapdragon::SpecFile.should_receive(:new).with('some/path/to/some_spec.js', 45).and_return(stub.as_null_object)
69
+ subject.send(:parse_arguement, 'some/path/to/some_spec.js:45')
70
+ end
71
+
72
+ it "appends the created SpecFile to the applications Suite" do
73
+ spec_file = stub('spec_file')
74
+ suite = mock('suite')
75
+ subject.instance_variable_set(:@suite, suite)
76
+ Snapdragon::SpecFile.stub(:new).and_return(spec_file)
77
+ suite.should_receive(:add_spec_file).with(spec_file)
78
+ subject.send(:parse_arguement, 'some/path/to/some_spec.js:45')
79
+ end
80
+ end
81
+
82
+ context "when the arg represents a file without a line number" do
83
+ before do
84
+ subject.stub(:is_a_file_path_and_line_number?).and_return(false)
85
+ subject.stub(:is_a_file_path?).and_return(true)
86
+ end
87
+
88
+ it "creates a SpecFile object with the specified path" do
89
+ Snapdragon::SpecFile.should_receive(:new).with('some/path/to/some_spec.js').and_return(stub.as_null_object)
90
+ subject.send(:parse_arguement, 'some/path/to/some_spec.js')
91
+ end
92
+
93
+ it "appends the created SpecFile to the application Suite" do
94
+ spec_file = stub('spec_file')
95
+ suite = mock('suite')
96
+ subject.instance_variable_set(:@suite, suite)
97
+ Snapdragon::SpecFile.stub(:new).and_return(spec_file)
98
+ suite.should_receive(:add_spec_file).with(spec_file)
99
+ subject.send(:parse_arguement, 'some/path/to/some_spec.js')
100
+ end
101
+ end
102
+
103
+ context "when the arg respesents a directory" do
104
+ before do
105
+ subject.stub(:is_a_file_path_and_line_number?).and_return(false)
106
+ subject.stub(:is_a_file_path?).and_return(false)
107
+ subject.stub(:is_a_directory?).and_return(true)
108
+ end
109
+
110
+ it "creates a SpecDirectory with the given directory path" do
111
+ Snapdragon::SpecDirectory.should_receive(:new).with('some/path/to/some_directory').and_return(stub(:spec_files => []))
112
+ subject.send(:parse_arguement, 'some/path/to/some_directory')
113
+ end
114
+
115
+ it "gets all of the SpecFiles recursively identified in the SpecDirectory path" do
116
+ spec_dir = mock
117
+ Snapdragon::SpecDirectory.stub(:new).and_return(spec_dir)
118
+ spec_dir.should_receive(:spec_files).and_return([])
119
+ subject.send(:parse_arguement, 'some/path/to/some_directory')
120
+ end
121
+
122
+ it "appends the SpecFiles to the application Suite" do
123
+ spec_dir = stub('spec_dir')
124
+ spec_files = stub('spec_files')
125
+ suite = mock('suite')
126
+ subject.instance_variable_set(:@suite, suite)
127
+ Snapdragon::SpecDirectory.stub(:new).and_return(spec_dir)
128
+ spec_dir.stub(:spec_files).and_return(spec_files)
129
+ suite.should_receive(:add_spec_files).with(spec_files)
130
+ subject.send(:parse_arguement, 'some/path/to/some_directory')
131
+ end
132
+ end
133
+ end
134
+
135
+ describe "#is_a_file_path_and_line_number?" do
136
+ let(:arguements) { stub('arguments') }
137
+ subject { Snapdragon::CliApplication.new(arguements) }
138
+
139
+ context "when it matches the pattern of a file path and line number" do
140
+ it "returns true" do
141
+ subject.send(:is_a_file_path_and_line_number?, 'some/path/to/some_spec.js:534').should be_true
142
+ end
143
+ end
144
+
145
+ context "when it does NOT match the pattern of a file path and line number" do
146
+ it "returns false" do
147
+ subject.send(:is_a_file_path_and_line_number?, 'some/path/to/some_spec.js').should be_false
148
+ end
149
+ end
150
+ end
151
+
152
+ describe "#is_a_file_path?" do
153
+ let(:arguements) { stub('arguments') }
154
+ subject { Snapdragon::CliApplication.new(arguements) }
155
+
156
+ context "when it matches the pattern of a file path" do
157
+ it "returns true" do
158
+ subject.send(:is_a_file_path?, 'some/path/to/some_spec.js').should be_true
159
+ end
160
+ end
161
+
162
+ context "when it does NOT match the pattern of a file path" do
163
+ it "returns false" do
164
+ subject.send(:is_a_file_path?, 'some/path/to/some.js').should be_false
165
+ end
166
+ end
167
+ end
168
+
169
+ describe "#is_a_directory?" do
170
+ let(:arguements) { stub('arguments') }
171
+ subject { Snapdragon::CliApplication.new(arguements) }
172
+
173
+ context "when it matches the pattern of a directory path" do
174
+ it "returns true" do
175
+ subject.send(:is_a_directory?, 'some/path/to/some_directory').should be_true
176
+ end
177
+ end
178
+
179
+ context "when it does NOT match the pattern of a directory path" do
180
+ it "returns false" do
181
+ subject.send(:is_a_directory?, 'some/path/to/some_spec.js').should be_false
182
+ end
183
+ end
184
+ end
185
+
186
+ describe "#run_suite" do
187
+ let(:arguements) { stub('arguments') }
188
+ subject { Snapdragon::CliApplication.new(arguements) }
189
+
190
+ it "creates a capybara session" do
191
+ Capybara::Session.should_receive(:new).and_return(stub.as_null_object)
192
+ subject.send(:run_suite)
193
+ end
194
+
195
+ context "when suite is filtered" do
196
+ before do
197
+ subject.instance_variable_set(:@suite, stub(:filtered? => true, :spec_query_param => 'some_query_param_spec_filter'))
198
+ end
199
+
200
+ it "visits /run with the spec query param in the capybara session" do
201
+ session = mock
202
+ Capybara::Session.stub(:new).and_return(session)
203
+ session.should_receive(:visit).with("/run?spec=some_query_param_spec_filter")
204
+ subject.send(:run_suite)
205
+ end
206
+ end
207
+
208
+ context "when suite is NOT filtered" do
209
+ before do
210
+ subject.instance_variable_set(:@suite, stub(:filtered? => false))
211
+ end
212
+
213
+ it "visits /run in that capybara session" do
214
+ session = mock
215
+ Capybara::Session.stub(:new).and_return(session)
216
+ session.should_receive(:visit).with('/run')
217
+ subject.send(:run_suite)
218
+ end
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../../../lib/snapdragon/spec_directory'
2
+
3
+ describe Snapdragon::SpecDirectory do
4
+ describe "#initialize" do
5
+ it "assigns the given directory path" do
6
+ spec_dir = Snapdragon::SpecDirectory.new('some/directory/path')
7
+ spec_dir.instance_variable_get(:@path).should eq('some/directory/path')
8
+ end
9
+ end
10
+
11
+ describe "#spec_files" do
12
+ it "needs to be tested"
13
+ end
14
+ end
@@ -0,0 +1,36 @@
1
+ require_relative "../../../lib/snapdragon/spec_file"
2
+
3
+ describe Snapdragon::SpecFile do
4
+ describe "#initialize" do
5
+ it "assigns the given path" do
6
+ spec_file = Snapdragon::SpecFile.new('some/path/to_some_spec.js')
7
+ spec_file.instance_variable_get(:@path).should eq('some/path/to_some_spec.js')
8
+ end
9
+
10
+ it "assigns the given line number" do
11
+ spec_file = Snapdragon::SpecFile.new('some/path/to_some_spec.js', 54)
12
+ spec_file.instance_variable_get(:@line_number).should eq(54)
13
+ end
14
+
15
+ it "line number defaults to nil when not assigned" do
16
+ spec_file = Snapdragon::SpecFile.new('some/path/to_some_spec.js')
17
+ spec_file.instance_variable_get(:@line_number).should eq(nil)
18
+ end
19
+ end
20
+
21
+ describe "#read" do
22
+ it "needs to be tested"
23
+ end
24
+
25
+ describe "#require_paths" do
26
+ it "needs to be tested"
27
+ end
28
+
29
+ describe "#filtered?" do
30
+ it "needs to be tested"
31
+ end
32
+
33
+ describe "#spec_query_param" do
34
+ it "needs to be tested"
35
+ end
36
+ end
@@ -0,0 +1,111 @@
1
+ require_relative '../../../lib/snapdragon/suite'
2
+
3
+ describe Snapdragon::Suite do
4
+ describe "#initialize" do
5
+ it "assigns an empty array to hold all the spec files" do
6
+ suite = Snapdragon::Suite.new
7
+ suite.instance_variable_get(:@specs).should eq([])
8
+ end
9
+
10
+ it "assigns an empty set to hold all the require files" do
11
+ suite = Snapdragon::Suite.new
12
+ suite.instance_variable_get(:@require_paths).should be_kind_of(Set)
13
+ end
14
+
15
+ it "assigns @filtered to an initial state of false" do
16
+ suite = Snapdragon::Suite.new
17
+ suite.instance_variable_get(:@filtered).should be_false
18
+ end
19
+
20
+ it "assigns @spec_query_param to an initial state of empty string" do
21
+ suite = Snapdragon::Suite.new
22
+ suite.instance_variable_get(:@spec_query_param).should eq('')
23
+ end
24
+ end
25
+
26
+ describe "#spec_files" do
27
+ it "returns the array of specs which the suite contains" do
28
+ spec_file = stub(:require_paths => [])
29
+ subject.instance_variable_set(:@specs, [spec_file])
30
+ subject.spec_files.should eq([spec_file])
31
+ end
32
+ end
33
+
34
+ describe "#add_spec_file" do
35
+ it "appends the given SpecFile to the suite of specs" do
36
+ spec_file = stub(:require_paths => [], :filtered? => false)
37
+ specs = mock
38
+ subject.instance_variable_set(:@specs, specs)
39
+ specs.should_receive(:<<).with(spec_file)
40
+ subject.add_spec_file(spec_file)
41
+ end
42
+
43
+ it "gets the require paths outlined in the spec" do
44
+ spec_file = mock(:filtered? => false)
45
+ spec_file.should_receive(:require_paths).and_return([])
46
+ subject.add_spec_file(spec_file)
47
+ end
48
+
49
+ it "contactinates the specs require paths to the suites require paths collection" do
50
+ spec_file = stub(:filtered? => false)
51
+ require_paths = stub
52
+ suite_require_paths = mock
53
+ subject.instance_variable_set(:@require_paths, suite_require_paths)
54
+ spec_file.stub(:require_paths).and_return(require_paths)
55
+ suite_require_paths.should_receive(:merge).with(require_paths)
56
+ subject.add_spec_file(spec_file)
57
+ end
58
+
59
+ context "when spec is filtered" do
60
+ it "assigns @filtered to true" do
61
+ spec_file = stub(:require_paths => [], :filtered? => true, :spec_query_param => '')
62
+ subject.add_spec_file(spec_file)
63
+ subject.instance_variable_get(:@filtered).should be_true
64
+ end
65
+
66
+ it "assigns @spec_query_parm to the spec_files spec_query_parma" do
67
+ spec_file = stub(:require_paths => [], :filtered? => true, :spec_query_param => 'some_spec_query_param')
68
+ subject.add_spec_file(spec_file)
69
+ subject.instance_variable_get(:@spec_query_param).should eq('some_spec_query_param')
70
+ end
71
+ end
72
+ end
73
+
74
+ describe "#add_spec_files" do
75
+ it "adds each of the spec files" do
76
+ spec_file_one = stub('spec_file_one')
77
+ spec_file_two = stub('spec_file_two')
78
+ subject.should_receive(:add_spec_file).with(spec_file_one)
79
+ subject.should_receive(:add_spec_file).with(spec_file_two)
80
+ subject.add_spec_files([spec_file_one, spec_file_two])
81
+ end
82
+ end
83
+
84
+ describe "#spec_files" do
85
+ it "returns the internal collection of spec files" do
86
+ specs = stub
87
+ subject.instance_variable_set(:@specs, specs)
88
+ subject.spec_files.should eq(specs)
89
+ end
90
+ end
91
+
92
+ describe "#output_spec_dependencies" do
93
+ it "needs to be tested"
94
+ end
95
+
96
+ describe "#spec_query_param" do
97
+ it "returns the suites spec_query_param" do
98
+ spec_query_param = stub
99
+ subject.instance_variable_set(:@spec_query_param, spec_query_param)
100
+ subject.spec_query_param.should eq(spec_query_param)
101
+ end
102
+ end
103
+
104
+ describe "#filtered?" do
105
+ it "returns the filtered state of the suite" do
106
+ filtered = stub
107
+ subject.instance_variable_set(:@filtered, filtered)
108
+ subject.filtered?.should eq(filtered)
109
+ end
110
+ end
111
+ end
File without changes