seeing_is_believing 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,6 +14,8 @@ describe SeeingIsBelieving do
14
14
  StringIO.new string
15
15
  end
16
16
 
17
+ let(:proving_grounds_dir) { File.expand_path '../../proving_grounds', __FILE__ }
18
+
17
19
  it 'takes a string or stream and returns a result of the line numbers (counting from 1) and each inspected result from that line' do
18
20
  input = "1+1\n'2'+'2'"
19
21
  output = [[1, ["2"]], [2, ['"22"']]]
@@ -88,6 +90,12 @@ describe SeeingIsBelieving do
88
90
 
89
91
  values_for("1 +
90
92
  2").should == [[], ['3']]
93
+
94
+ values_for("'\n1\n'").should == [[], [], ['"\n1\n"']]
95
+
96
+ # fails b/c parens should go around line 1, not around entire expression -.^
97
+ # values_for("<<HEREDOC\n1\nHEREDOC").should == [[], [], ['"\n1\n"']]
98
+ # values_for("<<-HEREDOC\n1\nHEREDOC").should == [[], [], ['"\n1\n"']]
91
99
  end
92
100
 
93
101
  it 'does not record expressions that end in a comment' do
@@ -98,26 +106,101 @@ describe SeeingIsBelieving do
98
106
 
99
107
  it 'has no output for empty lines' do
100
108
  values_for('').should == [[]]
109
+ values_for(' ').should == [[]]
110
+ values_for(" \n").should == [[]]
101
111
  values_for("1\n\n2").should == [['1'],[],['2']]
102
112
  end
103
113
 
104
114
  it 'stops executing on errors and reports them' do
105
- result = values_for("12\nraise Exception, 'omg!'\n12")
106
- result[0].should == ['12']
115
+ invoke("'no exception'").should_not have_exception
107
116
 
108
- result[1].size.should == 1
109
- exception = result[1].first
110
- exception.class.should == Exception
111
- exception.message.should == 'omg!'
117
+ result = invoke("12\nraise Exception, 'omg!'\n12")
118
+ result.should have_exception
119
+ result.exception.message.should == 'omg!'
120
+
121
+ result[1].should == ['12']
112
122
 
113
123
  result[2].should == []
114
- result.size.should == 3
124
+ result[2].exception.should == result.exception
125
+
126
+ result[3].should == []
127
+ result.to_a.size.should == 3
128
+
129
+ pending 'Not sure how to force the backtrace to render' do
130
+ result.exception.backtrace.should be_a_kind_of Array
131
+ end
132
+ end
133
+
134
+ it 'does not fuck up __LINE__ macro' do
135
+ values_for('__LINE__
136
+ __LINE__
137
+
138
+ def meth
139
+ __LINE__
140
+ end
141
+ meth
142
+
143
+ # comment
144
+ __LINE__').should == [['1'], ['2'], [], [], ['5'], ['nil'], ['5'], [], [], ['10']]
145
+ end
146
+
147
+ it 'does not try to record a return statement when that will break it' do
148
+ values_for("def meth \n return 1 \n end \n meth").should == [[], [], ['nil'], ['1']]
149
+ values_for("def meth \n return 1 if true \n end \n meth").should == [[], [], ['nil'], ['1']]
150
+ values_for("def meth \n return 1 if false \n end \n meth").should == [[], [], ['nil'], ['nil']]
151
+ values_for("-> { \n return 1 \n }.call" ).should == [[], [], ['1']]
152
+ pending "this doesn't work because the return detecting code is a very conservative regexp" do
153
+ values_for("-> { return 1 }.call" ).should == [['1']]
154
+ end
155
+ end
156
+
157
+ it 'does not affect its environment' do
158
+ invoke 'def Object.abc() end'
159
+ Object.should_not respond_to :abc
160
+ end
161
+
162
+ it 'captures the standard output and error' do
163
+ result = invoke "2.times { puts 'a', 'b' }
164
+ STDOUT.puts 'c'
165
+ $stdout.puts 'd'
166
+ STDERR.puts '1', '2'
167
+ $stderr.puts '3'
168
+ $stdout = $stderr
169
+ puts '4'"
170
+ result.stdout.should == "a\nb\n" "a\nb\n" "c\n" "d\n"
171
+ result.stderr.should == "1\n2\n" "3\n" "4\n"
172
+ result.should have_stdout
173
+ result.should have_stderr
174
+
175
+ result = invoke '1+1'
176
+ result.should_not have_stdout
177
+ result.should_not have_stderr
178
+ end
179
+
180
+ it 'defaults the filename to temp_dir/program.rb' do
181
+ result = invoke('print File.expand_path __FILE__')
182
+ File.basename(result.stdout).should == 'program.rb'
183
+ end
184
+
185
+ it 'can be told to run as a given file (in a given dir/with a given filename)' do
186
+ filename = File.join proving_grounds_dir, 'mah_file.rb'
187
+ FileUtils.rm_f filename
188
+ result = described_class.new('print File.expand_path __FILE__', filename: filename).call
189
+ result.stdout.should == filename
190
+ end
191
+
192
+ specify 'cwd is the directory of the file' do
193
+ filename = File.join proving_grounds_dir, 'mah_file.rb'
194
+ FileUtils.rm_f filename
195
+ result = described_class.new('print File.expand_path __FILE__', filename: filename).call
196
+ result = described_class.new('print File.expand_path(Dir.pwd)', filename: filename).call
197
+ result.stdout.should == proving_grounds_dir
198
+ end
199
+
200
+ it 'does not capture output from __END__ onward' do
201
+ values_for("1+1\nDATA.read\n__END__\n....").should == [['2'], ['"...."']]
115
202
  end
116
203
 
117
- # it ignores lines that end in comments
118
- # something about printing to stdout
119
- # something about printing to stderr
120
204
  # something about when the whole input is invalid
121
205
  # something about multi-line strings
122
- # does not fuck up __LINE__ macro
123
206
  end
@@ -3,8 +3,13 @@ require 'seeing_is_believing'
3
3
  describe SeeingIsBelieving::SyntaxAnalyzer do
4
4
  it 'knows if syntax is valid' do
5
5
  is_valid = lambda { |code| described_class.valid_ruby? code }
6
- is_valid['+'].should be_false
7
6
  is_valid['1+2'].should be_true
7
+ is_valid['+'].should be_false
8
+
9
+ # due to what are possibly bugs in Ripper
10
+ # these don't raise any errors, so have to check them explicitly
11
+ is_valid["'"].should be_false
12
+ is_valid["/"].should be_false
8
13
  end
9
14
 
10
15
  it 'knows if the last line is a comment' do
@@ -16,4 +21,110 @@ describe SeeingIsBelieving::SyntaxAnalyzer do
16
21
  is_comment["a # whatev \n b"].should be_false
17
22
  is_comment[""].should be_false
18
23
  end
24
+
25
+ # probably don't really need this many tests, but I'm unfamiliar with how thorough Ripper is
26
+ # and already found areas where it doesn't behave correctly
27
+ it 'knows if the code contains an unclosed string' do
28
+ unclosed_string = lambda { |code| described_class.unclosed_string? code }
29
+ [%(a),
30
+ %("a"),
31
+ %("a \n"),
32
+ %("a \n a"),
33
+ %(a \n" a"),
34
+ %(a \n' a'),
35
+ %('a' "b"),
36
+ %('a"b'),
37
+ %("a'b"),
38
+ %("a\\""),
39
+ %(%()),
40
+ %(%<>),
41
+ %(%[]),
42
+ %(%{}),
43
+ %(%Q()),
44
+ %(%q()),
45
+ %("\#{""}"),
46
+ %("\#{''}"),
47
+ %("\#{%(\#{%[\#{%[]}]})}"),
48
+ %(%{}),
49
+ %(%<>),
50
+ %(%..),
51
+ ].each do |string|
52
+ unclosed_string[string].should be_false, "Expected #{string.inspect} to be closed"
53
+ end
54
+
55
+ [%(a "),
56
+ %(a '),
57
+ %("a \n),
58
+ %(a \n 'a\n),
59
+ %("a"\n"b),
60
+ %("a" "b),
61
+ %("a" "b'),
62
+ %("a\\"),
63
+ %('a\\'),
64
+ %(%\(),
65
+ %(%<),
66
+ %(%[),
67
+ %(%{),
68
+ %(%Q[),
69
+ %(%q[),
70
+ %(%Q(\#{)),
71
+ %("\#{),
72
+ %("\#{'}"),
73
+ %("\#{"}"),
74
+ %("\#{%(\#{%[\#{%[}]})}"),
75
+ ].each do |string|
76
+ unclosed_string[string].should be_true, "Expected #{string.inspect} to be unclosed"
77
+ end
78
+ end
79
+
80
+ it 'knows if the code contains an unclosed regexp' do
81
+ unclosed_regexp = lambda { |code| described_class.unclosed_regexp? code }
82
+ [%(a),
83
+ %(/a/),
84
+ %(/a \n/),
85
+ %(/a \n a/),
86
+ %(a \n/ a/),
87
+ %(/a\\//),
88
+ %(/\#{//}/),
89
+ %(%r()),
90
+ %(%r{}),
91
+ %(%r<>),
92
+ %(%r..),
93
+ ].each do |code|
94
+ unclosed_regexp[code].should be_false, "Expected #{code.inspect} to be closed"
95
+ end
96
+
97
+ [%(a + /),
98
+ %(/a \n),
99
+ %(a \n /a\n),
100
+ %(/a/\n/b),
101
+ %(/a\\/),
102
+ %(%r\(),
103
+ %(%r<),
104
+ %(%r[),
105
+ %(%r{),
106
+ %(%r(\#{)),
107
+ %(%r[\#{),
108
+ %("\#{%r[}"),
109
+ ].each do |code|
110
+ unclosed_regexp[code].should be_true, "Expected #{code.inspect} to be unclosed"
111
+ end
112
+ end
113
+
114
+ # the commented out ones will require actual parsing to solve
115
+ it "knows if the code contains a return (can't capture a void value)" do
116
+ will_return = -> code { described_class.will_return? code }
117
+ will_return["return 1"].should be_true
118
+ will_return["return 1\n"].should be_true
119
+ will_return["return 1 if true"].should be_true
120
+ will_return["return 1 if false"].should be_true
121
+ will_return["o.return"].should be_false
122
+ will_return[":return"].should be_false
123
+ will_return["'return'"].should be_false
124
+ # will_return["'return\nreturn\nreturn'"].should be_false
125
+ will_return["def a\nreturn 1\nend"].should be_false
126
+ will_return["-> {\nreturn 1\n}"].should be_false
127
+ will_return["Proc.new {\nreturn 1\n}"].should be_false
128
+ # will_return["return \\\n1"].should be_true
129
+ end
19
130
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seeing_is_believing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-03 00:00:00.000000000 Z
12
+ date: 2013-01-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70251047915180 !ruby/object:Gem::Requirement
16
+ requirement: &70133565808080 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.12.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70251047915180
24
+ version_requirements: *70133565808080
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: cucumber
27
- requirement: &70251047914440 !ruby/object:Gem::Requirement
27
+ requirement: &70133565807280 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,7 +32,18 @@ dependencies:
32
32
  version: 1.2.1
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70251047914440
35
+ version_requirements: *70133565807280
36
+ - !ruby/object:Gem::Dependency
37
+ name: ichannel
38
+ requirement: &70133565806600 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 5.1.1
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70133565806600
36
47
  description: Records the results of every line of code in your file (intended to be
37
48
  like xmpfilter), inspired by Bret Victor's JavaScript example in his talk "Inventing
38
49
  on Principle"
@@ -52,13 +63,21 @@ files:
52
63
  - features/step_definitions/steps.rb
53
64
  - features/support/env.rb
54
65
  - lib/seeing_is_believing.rb
66
+ - lib/seeing_is_believing/error.rb
67
+ - lib/seeing_is_believing/evaluate_by_moving_files.rb
55
68
  - lib/seeing_is_believing/example_use.rb
56
69
  - lib/seeing_is_believing/expression_list.rb
70
+ - lib/seeing_is_believing/hard_core_ensure.rb
71
+ - lib/seeing_is_believing/has_exception.rb
57
72
  - lib/seeing_is_believing/result.rb
58
73
  - lib/seeing_is_believing/syntax_analyzer.rb
74
+ - lib/seeing_is_believing/the_matrix.rb
75
+ - lib/seeing_is_believing/tracks_line_numbers_seen.rb
59
76
  - lib/seeing_is_believing/version.rb
60
77
  - seeing_is_believing.gemspec
78
+ - spec/evaluate_by_moving_files_spec.rb
61
79
  - spec/expression_list_spec.rb
80
+ - spec/hard_core_ensure_spec.rb
62
81
  - spec/seeing_is_believing_spec.rb
63
82
  - spec/syntax_analyzer_spec.rb
64
83
  homepage: https://github.com/JoshCheek/seeing_is_believing
@@ -89,6 +108,8 @@ test_files:
89
108
  - features/binary.feature
90
109
  - features/step_definitions/steps.rb
91
110
  - features/support/env.rb
111
+ - spec/evaluate_by_moving_files_spec.rb
92
112
  - spec/expression_list_spec.rb
113
+ - spec/hard_core_ensure_spec.rb
93
114
  - spec/seeing_is_believing_spec.rb
94
115
  - spec/syntax_analyzer_spec.rb