snapdragon 0.1.9 → 0.1.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fbdd1c01780d6cf840d1c324b4b410b3c624064b
4
- data.tar.gz: 469c7ba58f97d16cd7962a59553c83a8341067c8
3
+ metadata.gz: f3a7b0cc75a3e31b11e8b5e1ff8c9dedf268e281
4
+ data.tar.gz: dd8fac388619a5529c7947f0bfcdf4f25ca972d9
5
5
  SHA512:
6
- metadata.gz: c439d1a2fac54d154883624364f85e6cd39f283841ab0b4f9c1a090741b7ee1e3acff83b723d21f1fcf29b89d97fbb26fd35f2a03aad053e431f96fb40e94508
7
- data.tar.gz: 16403dfa69ed351d35ddf21f633f2fa854e9084d56689d70c2af3fc41993ebed8a8bdbf3186ff36c985dcceaa5016aee6ce5cdc864ed83c71308dc74591dca41
6
+ metadata.gz: 6c04bd17f44c3241ebf9f75e0306fd7afef3387f288655ef329b11e92e9af1a1abdf6d05658ee6929dd6923aa2b0d68a5a1844718c08e875d73802382671e318
7
+ data.tar.gz: 2162787b797a49f53c8f1de29172c973c1c68710efc92b9b21d153fc1ea334ccbe4c175a6e0f109d8912e608d9e31d0dc194721e99c2fd90335152c763e5e8b2
@@ -6,6 +6,12 @@ versions as well as provide a rough history.
6
6
 
7
7
  #### Next Release
8
8
 
9
+ #### v0.1.10
10
+
11
+ * added --format junit switch to make it output JUnit format for CI servers
12
+ * added -v and --version switches to notify users of the version
13
+ * added -h and --help switches to notify users of the proper usage
14
+
9
15
  #### v0.1.9
10
16
 
11
17
  * fixed bug preventing require\_relatives with no tailing whitespace from being
@@ -42,8 +42,7 @@ $ brew install phantomjs
42
42
 
43
43
  If you are a visual learner Brian Miller and I have put together a Free
44
44
  [Snapdragon](http://github.com/reachlocal/snapdragon) Screencast at [The Code
45
- Breakdown](http://codebreakdown.com) ([direct
46
- download](http://codebreakdown.com/screencasts/7/download)).
45
+ Breakdown](http://codebreakdown.com).
47
46
 
48
47
  [![It in Action](http://media.codebreakdown.com/thumbnails/tcb-0007-thumbnail-400x225.png)](http://codebreakdown.com)
49
48
 
@@ -3,7 +3,9 @@
3
3
  $LOAD_PATH.unshift ::File.expand_path(::File.dirname(__FILE__) + '/../lib')
4
4
 
5
5
  require 'rubygems'
6
+ require 'snapdragon/command_line_parser'
6
7
  require 'snapdragon/cli_application'
7
8
 
8
- app = Snapdragon::CliApplication.new(ARGV)
9
+ opts = Snapdragon::CommandLineParser.parse(ARGV)
10
+ app = Snapdragon::CliApplication.new(opts, ARGV)
9
11
  exit(app.run)
@@ -3,7 +3,9 @@
3
3
  $LOAD_PATH.unshift ::File.expand_path(::File.dirname(__FILE__) + '/../lib')
4
4
 
5
5
  require 'rubygems'
6
+ require 'snapdragon/command_line_parser'
6
7
  require 'snapdragon/cli_application'
7
8
 
8
- app = Snapdragon::CliApplication.new(ARGV)
9
+ opts = Snapdragon::CommandLineParser.parse(ARGV)
10
+ app = Snapdragon::CliApplication.new(opts, ARGV)
9
11
  app.serve
@@ -0,0 +1,2 @@
1
+ // This is here so that the spec_helper.js file can do a require_relative()
2
+ // directive and we can test that it is working properly.
@@ -13,9 +13,8 @@ Capybara.default_wait_time = 120 # 2 mins
13
13
 
14
14
  module Snapdragon
15
15
  class CliApplication
16
- def initialize(arguements)
17
- @args = arguements
18
- @suite = Snapdragon::Suite.new(arguements)
16
+ def initialize(options, paths)
17
+ @suite = Snapdragon::Suite.new(options, paths)
19
18
  end
20
19
 
21
20
  def run
@@ -0,0 +1,30 @@
1
+ require 'optparse'
2
+ require 'ostruct'
3
+ require_relative './version'
4
+
5
+ module Snapdragon
6
+ class CommandLineParser
7
+ def self.parse(args)
8
+ options = OpenStruct.new
9
+ options.format = "console"
10
+
11
+ opts = OptionParser.new do |opts|
12
+ opts.banner = "Usage: snapdragon [options] [files or directories]"
13
+ opts.on('-v', '--version', "Show the current version of this gem") do
14
+ puts "#{Snapdragon::VERSION}"; exit
15
+ end
16
+ opts.on('-h', '--help', "show usage") do
17
+ puts opts; exit
18
+ end
19
+ opts.on('-f', '--format [FORMAT]', "set output format") do |format|
20
+ options.format = format
21
+ end
22
+ if args.empty?
23
+ puts opts; exit
24
+ end
25
+ end
26
+ opts.parse!(args)
27
+ options
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,171 @@
1
+ /*
2
+ * This is the junit reporter provided in the jasmine-reporters project
3
+ * available at https://github.com/larrymyers/jasmine-reporters
4
+ */
5
+ (function() {
6
+
7
+ if (typeof jasmine == 'undefined') {
8
+ throw new Error("jasmine library does not exist in global namespace!");
9
+ }
10
+
11
+ function elapsed(startTime, endTime) {
12
+ return (endTime - startTime)/1000;
13
+ }
14
+
15
+ function ISODateString(d) {
16
+ function pad(n) { return n < 10 ? '0'+n : n; }
17
+
18
+ return d.getFullYear() + '-' +
19
+ pad(d.getMonth()+1) + '-' +
20
+ pad(d.getDate()) + 'T' +
21
+ pad(d.getHours()) + ':' +
22
+ pad(d.getMinutes()) + ':' +
23
+ pad(d.getSeconds());
24
+ }
25
+
26
+ function trim(str) {
27
+ return str.replace(/^\s+/, "" ).replace(/\s+$/, "" );
28
+ }
29
+
30
+ function escapeInvalidXmlChars(str) {
31
+ return str.replace(/\&/g, "&amp;")
32
+ .replace(/</g, "&lt;")
33
+ .replace(/\>/g, "&gt;")
34
+ .replace(/\"/g, "&quot;")
35
+ .replace(/\'/g, "&apos;");
36
+ }
37
+
38
+ var JUnitXmlReporter = function() {
39
+ this.useDotNotation = true;
40
+ };
41
+
42
+ JUnitXmlReporter.prototype = {
43
+ reportSpecStarting: function(spec) {
44
+ spec.startTime = new Date();
45
+
46
+ if (!spec.suite.startTime) {
47
+ spec.suite.startTime = spec.startTime;
48
+ }
49
+ },
50
+
51
+ reportSpecResults: function(spec) {
52
+ var results = spec.results();
53
+ spec.didFail = !results.passed();
54
+ spec.duration = elapsed(spec.startTime, new Date());
55
+ spec.output = '<testcase classname="' + this.getFullName(spec.suite) +
56
+ '" name="' + escapeInvalidXmlChars(spec.description) + '" time="' + spec.duration + '">';
57
+ if(results.skipped) {
58
+ spec.output = spec.output + "<skipped />";
59
+ }
60
+
61
+ var failure = "";
62
+ var failures = 0;
63
+ var resultItems = results.getItems();
64
+ for (var i = 0; i < resultItems.length; i++) {
65
+ var result = resultItems[i];
66
+
67
+ if (result.type == 'expect' && result.passed && !result.passed()) {
68
+ failures += 1;
69
+ failure += '<failure type="' + result.type + '" message="' + trim(escapeInvalidXmlChars(result.message)) + '">';
70
+ failure += escapeInvalidXmlChars(result.trace.stack || result.message);
71
+ failure += "</failure>";
72
+ }
73
+ }
74
+ if (failure) {
75
+ spec.output += failure;
76
+ }
77
+ spec.output += "</testcase>";
78
+ },
79
+
80
+ reportSuiteResults: function(suite) {
81
+ var results = suite.results();
82
+ var specs = suite.specs();
83
+ var specOutput = "";
84
+ // for JUnit results, let's only include directly failed tests (not nested suites')
85
+ var failedCount = 0;
86
+
87
+ suite.status = results.passed() ? 'Passed.' : 'Failed.';
88
+ if (results.totalCount === 0) { // todo: change this to check results.skipped
89
+ suite.status = 'Skipped.';
90
+ }
91
+
92
+ // if a suite has no (active?) specs, reportSpecStarting is never called
93
+ // and thus the suite has no startTime -- account for that here
94
+ suite.startTime = suite.startTime || new Date();
95
+ suite.duration = elapsed(suite.startTime, new Date());
96
+
97
+ for (var i = 0; i < specs.length; i++) {
98
+ failedCount += specs[i].didFail ? 1 : 0;
99
+ specOutput += "\n " + specs[i].output;
100
+ }
101
+ suite.output = '\n<testsuite name="' + this.getFullName(suite) +
102
+ '" errors="0" tests="' + specs.length + '" failures="' + failedCount +
103
+ '" time="' + suite.duration + '" timestamp="' + ISODateString(suite.startTime) + '">';
104
+ suite.output += specOutput;
105
+ suite.output += "\n</testsuite>";
106
+ },
107
+
108
+ reportRunnerResults: function(runner) {
109
+ var suites = runner.suites();
110
+ for (var i = 0; i < suites.length; i++) {
111
+ var suite = suites[i];
112
+ var output = '<?xml version="1.0" encoding="UTF-8" ?>';
113
+ // if we are consolidating, only write out top-level suites
114
+ if (suite.parentSuite) {
115
+ continue;
116
+ }
117
+ else {
118
+ output += "\n<testsuites>";
119
+ output += this.getNestedOutput(suite);
120
+ output += "\n</testsuites>";
121
+ this.print(output);
122
+ }
123
+ }
124
+ this.signalCapybaraTestsFinishedRunning();
125
+ },
126
+
127
+ signalCapybaraTestsFinishedRunning: function() {
128
+ var div = document.createElement('div');
129
+ div.id = 'testscomplete';
130
+ document.body.appendChild(div);
131
+ },
132
+
133
+ getNestedOutput: function(suite) {
134
+ var output = suite.output;
135
+ for (var i = 0; i < suite.suites().length; i++) {
136
+ output += this.getNestedOutput(suite.suites()[i]);
137
+ }
138
+ return output;
139
+ },
140
+
141
+ getFullName: function(suite, isFilename) {
142
+ var fullName;
143
+ if (this.useDotNotation) {
144
+ fullName = suite.description;
145
+ for (var parentSuite = suite.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
146
+ fullName = parentSuite.description + '.' + fullName;
147
+ }
148
+ }
149
+ else {
150
+ fullName = suite.getFullName();
151
+ }
152
+
153
+ // Either remove or escape invalid XML characters
154
+ if (isFilename) {
155
+ return fullName.replace(/[^\w]/g, "");
156
+ }
157
+ return escapeInvalidXmlChars(fullName);
158
+ },
159
+
160
+ print: function(str) {
161
+ var console = jasmine.getGlobal().console;
162
+
163
+ if (console && console.log) {
164
+ console.log(str);
165
+ }
166
+ }
167
+ };
168
+
169
+ // export public
170
+ jasmine.SnapdragonJUnitReporter = JUnitXmlReporter;
171
+ })();
@@ -2,10 +2,15 @@ require_relative './path'
2
2
 
3
3
  module Snapdragon
4
4
  class Suite
5
- def initialize(paths)
5
+ def initialize(options, paths)
6
+ @options = options
6
7
  @paths = paths
7
8
  end
8
9
 
10
+ def formatter
11
+ @options.format
12
+ end
13
+
9
14
  def spec_files
10
15
  spec_file_objs = []
11
16
 
@@ -1,3 +1,3 @@
1
1
  module Snapdragon
2
- VERSION = "0.1.9"
2
+ VERSION = "0.1.10"
3
3
  end
@@ -2,7 +2,11 @@
2
2
  <script type="text/javascript" src="/jasmine-core/jasmine.js"></script>
3
3
  <script type="text/javascript" src="/jasmine-core/jasmine-html.js"></script>
4
4
 
5
+ <% if @suite.formatter == "junit" %>
6
+ <script type="text/javascript" src="/resources/SnapdragonJUnitReporter.js"></script>
7
+ <% else %>
5
8
  <script type="text/javascript" src="/resources/SnapdragonConsoleReporter.js"></script>
9
+ <% end %>
6
10
 
7
11
  <!-- The implementation code the spec files being tested need -->
8
12
  <% @suite.require_file_relative_url_paths.each do |path| %>
@@ -20,16 +24,20 @@
20
24
  jasmineEnv.updateInterval = 1000;
21
25
 
22
26
  var htmlReporter = new jasmine.HtmlReporter();
23
-
24
27
  jasmineEnv.addReporter(htmlReporter);
25
28
 
26
- var snapdragonConsoleReporter = new jasmine.SnapdragonConsoleReporter({});
27
- jasmineEnv.addReporter(snapdragonConsoleReporter);
28
-
29
29
  jasmineEnv.specFilter = function(spec) {
30
30
  return htmlReporter.specFilter(spec);
31
31
  };
32
32
 
33
+ <% if @suite.formatter == "junit" %>
34
+ var snapdragonJUnitReporter = new jasmine.SnapdragonJUnitReporter();
35
+ jasmineEnv.addReporter(snapdragonJUnitReporter);
36
+ <% else %>
37
+ var snapdragonConsoleReporter = new jasmine.SnapdragonConsoleReporter({});
38
+ jasmineEnv.addReporter(snapdragonConsoleReporter);
39
+ <% end %>
40
+
33
41
  var currentWindowOnload = window.onload;
34
42
 
35
43
  window.onload = function() {
@@ -2,28 +2,23 @@ require_relative '../../../lib/snapdragon/cli_application'
2
2
 
3
3
  describe Snapdragon::CliApplication do
4
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
5
  it "creates an empty Suite" do
12
6
  Snapdragon::Suite.should_receive(:new)
13
- Snapdragon::CliApplication.new(stub)
7
+ Snapdragon::CliApplication.new(stub, stub)
14
8
  end
15
9
 
16
10
  it "assigns the new Suite to an instance variable" do
17
11
  suite = stub('suite')
18
12
  Snapdragon::Suite.stub(:new).and_return(suite)
19
- app = Snapdragon::CliApplication.new(stub)
13
+ app = Snapdragon::CliApplication.new(stub, stub)
20
14
  app.instance_variable_get(:@suite).should eq(suite)
21
15
  end
22
16
  end
23
17
 
24
18
  describe "#run" do
25
- let(:arguements) { stub('arguments') }
26
- subject { Snapdragon::CliApplication.new(arguements) }
19
+ let(:paths) { stub('paths') }
20
+ let(:options) { stub('options') }
21
+ subject { Snapdragon::CliApplication.new(options, paths) }
27
22
 
28
23
  it "creates a capybara session" do
29
24
  suite = stub(filtered?: false)
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ require_relative '../../../lib/snapdragon/command_line_parser'
3
+
4
+ describe Snapdragon::CommandLineParser do
5
+ describe "#parse" do
6
+ subject { Snapdragon::CommandLineParser }
7
+
8
+ it "display version information" do
9
+ output = capture_stdout { subject.parse(["-v"]) }
10
+ output.should match(/\d+\.\d+\.\d+/)
11
+ end
12
+
13
+ it "exit once version information is displayed" do
14
+ lambda { hide_stdout { subject.parse(["-v"]) } }.should raise_error(SystemExit)
15
+ end
16
+
17
+ it "display usage information" do
18
+ output = capture_stdout { subject.parse(["-h"]) }
19
+ output.should match(/Usage/)
20
+ end
21
+
22
+ it "exit once usage information is displayed" do
23
+ lambda { hide_stdout { subject.parse(["-h"]) } }.should raise_error(SystemExit)
24
+ end
25
+
26
+ context "no args supplied" do
27
+ it "exit" do
28
+ lambda { hide_stdout { subject.parse([]) } }.should raise_error(SystemExit)
29
+ end
30
+ end
31
+
32
+ context "args supplied" do
33
+ it "continue execution" do
34
+ lambda { subject.parse(["spec/hello_spec.rb"]) }.should_not raise_error(SystemExit)
35
+ end
36
+ end
37
+
38
+ context "when format is provided" do
39
+ it "sets the format value" do
40
+ subject.parse(["--format", "junit", "spec/hello_spec.rb"]).format.should eq "junit"
41
+ end
42
+ end
43
+
44
+ context "when format is not provided" do
45
+ it "defaults to console" do
46
+ subject.parse(["spec/hello_spec.rb"]).format.should eq "console"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -3,29 +3,49 @@ require_relative '../../../lib/snapdragon/suite'
3
3
  describe Snapdragon::Suite do
4
4
  describe "#initialize" do
5
5
  it "constucts an instance of a Suite given an array of paths" do
6
+ options = stub
6
7
  paths = [stub, stub, stub]
7
- Snapdragon::Suite.new(paths)
8
+ Snapdragon::Suite.new(options, paths)
8
9
  end
9
10
 
10
11
  it "stores the paths in an instance variable" do
12
+ options = stub
11
13
  paths = [stub, stub, stub]
12
- suite = Snapdragon::Suite.new(paths)
14
+ suite = Snapdragon::Suite.new(options, paths)
13
15
  suite.instance_variable_get(:@paths).should eq(paths)
14
16
  end
17
+
18
+ it 'stores the options in an instance variable' do
19
+ options = stub
20
+ paths = [stub, stub, stub]
21
+ suite = Snapdragon::Suite.new(options, paths)
22
+ suite.instance_variable_get(:@options).should eq(options)
23
+ end
24
+ end
25
+
26
+ describe "#formatter" do
27
+ it "returns the configured formatter to use" do
28
+ formatter = stub
29
+ options = stub(format: formatter)
30
+ suite = Snapdragon::Suite.new(options, stub)
31
+ suite.formatter.should eq (formatter)
32
+ end
15
33
  end
16
34
 
17
35
  describe "#spec_files" do
18
36
  it "creates a path object to represent the path" do
37
+ options = stub
19
38
  paths = ['path_a_str', 'path_b_str']
20
- suite = Snapdragon::Suite.new(paths)
39
+ suite = Snapdragon::Suite.new(options, paths)
21
40
  Snapdragon::Path.should_receive(:new).with('path_a_str').and_return(stub(spec_files: []))
22
41
  Snapdragon::Path.should_receive(:new).with('path_b_str').and_return(stub(spec_files: []))
23
42
  suite.spec_files
24
43
  end
25
44
 
26
45
  it "returns the collection of the spec files of all of the paths" do
46
+ options = stub
27
47
  paths = ['path_a_str', 'path_b_str']
28
- suite = Snapdragon::Suite.new(paths)
48
+ suite = Snapdragon::Suite.new(options, paths)
29
49
  spec_file_a = stub('spec_file_a'), spec_file_b = stub('spec_file_b')
30
50
  Snapdragon::Path.stub(:new).with('path_a_str').and_return(stub(spec_files: [spec_file_a]))
31
51
  Snapdragon::Path.stub(:new).with('path_b_str').and_return(stub(spec_files: [spec_file_b]))
@@ -0,0 +1,27 @@
1
+ # Capturing the stdout
2
+ # Need to rescue SystemExit
3
+ # https://github.com/cldwalker/hirb/blob/master/test/test_helper.rb
4
+ def capture_stdout(&block)
5
+ original_stdout = $stdout
6
+ fake_stdout = StringIO.new
7
+ $stdout = fake_stdout
8
+ begin
9
+ yield
10
+ rescue SystemExit
11
+ ensure
12
+ $stdout = original_stdout
13
+ end
14
+ return fake_stdout.string
15
+ end
16
+
17
+ # for hiding the stdout from tests
18
+ def hide_stdout(&block)
19
+ original_stdout = $stdout
20
+ fake_stdout = StringIO.new
21
+ $stdout = fake_stdout
22
+ begin
23
+ yield
24
+ ensure
25
+ $stdout = original_stdout
26
+ end
27
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snapdragon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew De Ponte
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-02 00:00:00.000000000 Z
11
+ date: 2013-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
@@ -113,7 +113,6 @@ description: A Jasmine JavaScript test runner that lets you run tests on the com
113
113
  email:
114
114
  - cyphactor@gmail.com
115
115
  executables:
116
- - build_jspec_filter.rb
117
116
  - snapdragon
118
117
  - snapdragon_server
119
118
  extensions: []
@@ -128,7 +127,6 @@ files:
128
127
  - LICENSE.txt
129
128
  - README.markdown
130
129
  - Rakefile
131
- - bin/build_jspec_filter.rb
132
130
  - bin/snapdragon
133
131
  - bin/snapdragon_server
134
132
  - example/spec/bar_spec.js
@@ -138,10 +136,12 @@ files:
138
136
  - example/src/jack.js
139
137
  - lib/snapdragon.rb
140
138
  - lib/snapdragon/cli_application.rb
139
+ - lib/snapdragon/command_line_parser.rb
141
140
  - lib/snapdragon/file_base.rb
142
141
  - lib/snapdragon/path.rb
143
142
  - lib/snapdragon/resources/.gitkeep
144
143
  - lib/snapdragon/resources/SnapdragonConsoleReporter.js
144
+ - lib/snapdragon/resources/SnapdragonJUnitReporter.js
145
145
  - lib/snapdragon/spec_directory.rb
146
146
  - lib/snapdragon/spec_file.rb
147
147
  - lib/snapdragon/suite.rb
@@ -151,6 +151,7 @@ files:
151
151
  - lib/snapdragon/web_application.rb
152
152
  - snapdragon.gemspec
153
153
  - spec/lib/snapdragon/cli_application_spec.rb
154
+ - spec/lib/snapdragon/command_line_parser_spec.rb
154
155
  - spec/lib/snapdragon/path_spec.rb
155
156
  - spec/lib/snapdragon/spec_directory_spec.rb
156
157
  - spec/lib/snapdragon/spec_file_spec.rb
@@ -192,6 +193,7 @@ specification_version: 4
192
193
  summary: A command-line Jasmine JavaScript test runner.
193
194
  test_files:
194
195
  - spec/lib/snapdragon/cli_application_spec.rb
196
+ - spec/lib/snapdragon/command_line_parser_spec.rb
195
197
  - spec/lib/snapdragon/path_spec.rb
196
198
  - spec/lib/snapdragon/spec_directory_spec.rb
197
199
  - spec/lib/snapdragon/spec_file_spec.rb
@@ -1,45 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- if ARGV[0].nil?
4
- exit(1)
5
- end
6
-
7
- jspec_file_path, initial_line_number = ARGV[0].split(':')
8
- if initial_line_number.nil?
9
- # Run the file without spec query param set
10
- else
11
- # Work our way from the line number up to build the spec query param
12
- # description
13
- initial_line_number = initial_line_number.to_i
14
-
15
- initial_line_index = initial_line_number - 1
16
-
17
- f = open(jspec_file_path, 'r')
18
- lines = f.readlines
19
- f.close
20
-
21
- desc_components = []
22
-
23
- already_been_inside_an_it = false
24
- already_been_inside_a_describe = false
25
- last_describe_indent_spaces = 1232131312
26
-
27
- cur_line_index = initial_line_index
28
- while cur_line_index >= 0
29
- if lines[cur_line_index] =~ /it\s*\(\s*"(.+)"\s*,/ && !already_been_inside_an_it && !already_been_inside_a_describe # line matches it statement
30
- desc_components.push($1)
31
- already_been_inside_an_it = true
32
- elsif lines[cur_line_index] =~ /(\s*)describe\s*\(\s*"(.+)"\s*,/ # line matches a describe block
33
- if $1.length < last_describe_indent_spaces # use indent depth to identify parent
34
- desc_components.push($2)
35
- last_describe_indent_spaces = $1.length
36
- end
37
- already_been_inside_a_describe = true
38
- end
39
- cur_line_index -= 1
40
- end
41
-
42
- puts desc_components.reverse.join(" ")
43
- end
44
-
45
-