ronin-code-sql 2.0.0.beta1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +15 -0
  3. data/.rubocop.yml +13 -0
  4. data/.yardopts +1 -1
  5. data/ChangeLog.md +10 -1
  6. data/Gemfile +4 -0
  7. data/README.md +26 -16
  8. data/Rakefile +1 -0
  9. data/gemspec.yml +3 -3
  10. data/lib/ronin/code/sql/binary_expr.rb +35 -2
  11. data/lib/ronin/code/sql/clause.rb +19 -8
  12. data/lib/ronin/code/sql/clauses.rb +17 -15
  13. data/lib/ronin/code/sql/emittable.rb +9 -2
  14. data/lib/ronin/code/sql/emitter.rb +65 -26
  15. data/lib/ronin/code/sql/field.rb +31 -6
  16. data/lib/ronin/code/sql/fields.rb +1 -1
  17. data/lib/ronin/code/sql/function.rb +15 -4
  18. data/lib/ronin/code/sql/functions.rb +3 -15
  19. data/lib/ronin/code/sql/injection.rb +4 -4
  20. data/lib/ronin/code/sql/injection_expr.rb +1 -1
  21. data/lib/ronin/code/sql/literal.rb +17 -2
  22. data/lib/ronin/code/sql/literals.rb +1 -1
  23. data/lib/ronin/code/sql/mixin.rb +95 -0
  24. data/lib/ronin/code/sql/operators.rb +1 -1
  25. data/lib/ronin/code/sql/statement.rb +14 -3
  26. data/lib/ronin/code/sql/statement_list.rb +1 -1
  27. data/lib/ronin/code/sql/statements.rb +1 -1
  28. data/lib/ronin/code/sql/unary_expr.rb +24 -2
  29. data/lib/ronin/code/sql/version.rb +3 -3
  30. data/lib/ronin/code/sql.rb +5 -64
  31. data/lib/ronin/code/sqli.rb +30 -0
  32. data/ronin-code-sql.gemspec +5 -5
  33. metadata +10 -51
  34. data/spec/spec_helper.rb +0 -3
  35. data/spec/sql/binary_expr_examples.rb +0 -25
  36. data/spec/sql/binary_expr_spec.rb +0 -5
  37. data/spec/sql/clause_examples.rb +0 -43
  38. data/spec/sql/clause_spec.rb +0 -31
  39. data/spec/sql/clauses_spec.rb +0 -47
  40. data/spec/sql/emittable_spec.rb +0 -41
  41. data/spec/sql/emitter_spec.rb +0 -533
  42. data/spec/sql/field_spec.rb +0 -103
  43. data/spec/sql/fields_spec.rb +0 -40
  44. data/spec/sql/function_examples.rb +0 -30
  45. data/spec/sql/function_spec.rb +0 -25
  46. data/spec/sql/functions_spec.rb +0 -113
  47. data/spec/sql/injection_expr_spec.rb +0 -98
  48. data/spec/sql/injection_spec.rb +0 -172
  49. data/spec/sql/literal_spec.rb +0 -5
  50. data/spec/sql/literals_spec.rb +0 -46
  51. data/spec/sql/operators_spec.rb +0 -44
  52. data/spec/sql/statement_examples.rb +0 -39
  53. data/spec/sql/statement_list_spec.rb +0 -48
  54. data/spec/sql/statement_spec.rb +0 -38
  55. data/spec/sql/statements_spec.rb +0 -22
  56. data/spec/sql/unary_expr_examples.rb +0 -20
  57. data/spec/sql/unary_expr_spec.rb +0 -5
  58. data/spec/sql_spec.rb +0 -18
@@ -1,533 +0,0 @@
1
- require 'spec_helper'
2
- require 'ronin/code/sql/literal'
3
- require 'ronin/code/sql/unary_expr'
4
- require 'ronin/code/sql/binary_expr'
5
- require 'ronin/code/sql/field'
6
- require 'ronin/code/sql/statement'
7
- require 'ronin/code/sql/statement_list'
8
- require 'ronin/code/sql/emitter'
9
-
10
- describe Ronin::Code::SQL::Emitter do
11
- describe "#initialize" do
12
- context "without options" do
13
- it { expect(subject.space).to eq(' ') }
14
- it { expect(subject.quotes).to eq(:single) }
15
- end
16
- end
17
-
18
- describe "#emit_keyword" do
19
- context "when passed an Array of Symbols" do
20
- let(:keywords) { [:DROP, :TABLE] }
21
-
22
- it "should join the keywords" do
23
- expect(subject.emit_keyword(keywords)).to eq("DROP TABLE")
24
- end
25
-
26
- context "when :space is set" do
27
- subject { described_class.new(space: '/**/') }
28
-
29
- it "should join the keywords" do
30
- expect(subject.emit_keyword(keywords)).to eq("DROP/**/TABLE")
31
- end
32
- end
33
- end
34
-
35
- context "when case is :upper" do
36
- let(:keyword) { :select }
37
-
38
- subject { described_class.new(case: :upper) }
39
-
40
- it "should upcase the keyword" do
41
- expect(subject.emit_keyword(keyword)).to eq('SELECT')
42
- end
43
- end
44
-
45
- context "when case is :lower" do
46
- let(:keyword) { :SELECT }
47
-
48
- subject { described_class.new(case: :lower) }
49
-
50
- it "should upcase the keyword" do
51
- expect(subject.emit_keyword(keyword)).to eq('select')
52
- end
53
- end
54
-
55
- context "when case is :random" do
56
- let(:keyword) { :select }
57
-
58
- subject { described_class.new(case: :random) }
59
-
60
- it "should contain at least one upper-case character" do
61
- expect(subject.emit_keyword(keyword)).to match(/[SELECT]/)
62
- end
63
- end
64
-
65
- context "when case is nil" do
66
- subject { described_class.new(case: nil) }
67
-
68
- let(:keyword) { 'Select' }
69
-
70
- it "should emit the keyword as is" do
71
- expect(subject.emit_keyword(keyword)).to eq(keyword)
72
- end
73
- end
74
- end
75
-
76
- describe "#emit_operator" do
77
- context "when the operator is a symbol" do
78
- it "should emit a String" do
79
- expect(subject.emit_operator(:"!=")).to eq('!=')
80
- end
81
- end
82
-
83
- context "otherwise" do
84
- subject { described_class.new(case: :lower) }
85
-
86
- it "should emit a keyword" do
87
- expect(subject.emit_operator(:AS)).to eq('as')
88
- end
89
- end
90
- end
91
-
92
- describe "#emit_null" do
93
- it "should emit the NULL keyword" do
94
- expect(subject.emit_null).to eq('NULL')
95
- end
96
- end
97
-
98
- describe "#emit_false" do
99
- it "should emit 1=0" do
100
- expect(subject.emit_false).to eq('1=0')
101
- end
102
- end
103
-
104
- describe "#emit_true" do
105
- it "should emit 1=1" do
106
- expect(subject.emit_true).to eq('1=1')
107
- end
108
- end
109
-
110
- describe "#emit_integer" do
111
- it "should emit a String" do
112
- expect(subject.emit_integer(10)).to eq('10')
113
- end
114
- end
115
-
116
- describe "#emit_decimal" do
117
- it "should emit a String" do
118
- expect(subject.emit_decimal(2.5)).to eq('2.5')
119
- end
120
- end
121
-
122
- describe "#emit_string" do
123
- it "should emit a String" do
124
- expect(subject.emit_string("O'Brian")).to eq("'O''Brian'")
125
- end
126
-
127
- context "when :quotes is :double" do
128
- subject { described_class.new(quotes: :double) }
129
-
130
- it "should double quote Strings" do
131
- expect(subject.emit_string("O'Brian")).to eq("\"O'Brian\"")
132
- end
133
- end
134
- end
135
-
136
- describe "#emit_field" do
137
- subject { described_class.new(case: :upper) }
138
-
139
- let(:field) { Ronin::Code::SQL::Field.new(:id) }
140
-
141
- it "should emit the name as a keyword" do
142
- expect(subject.emit_field(field)).to eq('ID')
143
- end
144
-
145
- context "when the field has a parent" do
146
- let(:parent) { Ronin::Code::SQL::Field.new(:users) }
147
- let(:field) { Ronin::Code::SQL::Field.new(:id,parent) }
148
-
149
- it "should emit the parent then the field name" do
150
- expect(subject.emit_field(field)).to eq('USERS.ID')
151
- end
152
- end
153
- end
154
-
155
- describe "#emit_list" do
156
- it "should emit a ',' separated list" do
157
- expect(subject.emit_list([1,2,3,'foo'])).to eq("(1,2,3,'foo')")
158
- end
159
- end
160
-
161
- describe "#emit_assignments" do
162
- let(:values) { {x: 1, y: 2} }
163
-
164
- it "should emit a list of column names and values" do
165
- expect(subject.emit_assignments(values)).to eq('x=1,y=2')
166
- end
167
- end
168
-
169
- describe "#emit_argument" do
170
- context "when the value is a Statement" do
171
- let(:stmt) { Ronin::Code::SQL::Statement.new(:SELECT,1) }
172
-
173
- it "should wrap the statement in ( )" do
174
- expect(subject.emit_argument(stmt)).to eq('(SELECT 1)')
175
- end
176
- end
177
-
178
- context "otherwise" do
179
- let(:value) { 'hello' }
180
-
181
- it "should emit the value" do
182
- expect(subject.emit_argument(value)).to eq("'hello'")
183
- end
184
- end
185
- end
186
-
187
- describe "#emit_expression" do
188
- context "when the expression is a BinaryExpr" do
189
- context "when the operator is alphabetic" do
190
- subject { described_class.new(case: :upper) }
191
-
192
- let(:expr) { Ronin::Code::SQL::BinaryExpr.new(:id,:is,1) }
193
-
194
- it "should emit the operands and operator as a keyword with spaces" do
195
- expect(subject.emit_expression(expr)).to eq('ID IS 1')
196
- end
197
- end
198
-
199
- context "when the operator is symbolic" do
200
- let(:expr) { Ronin::Code::SQL::BinaryExpr.new(:id,:"=",1) }
201
-
202
- it "should emit the operands and operator without spaces" do
203
- expect(subject.emit_expression(expr)).to eq('id=1')
204
- end
205
- end
206
-
207
- context "when the left-hand operand is a Statement" do
208
- let(:expr) do
209
- Ronin::Code::SQL::BinaryExpr.new(
210
- Ronin::Code::SQL::Statement.new(:SELECT,1), :"=", 1
211
- )
212
- end
213
-
214
- it "should wrap the left-hand operand in parenthesis" do
215
- expect(subject.emit_expression(expr)).to eq('(SELECT 1)=1')
216
- end
217
- end
218
-
219
- context "when the right-hand operand is a Statement" do
220
- let(:expr) do
221
- Ronin::Code::SQL::BinaryExpr.new(
222
- 1, :"=", Ronin::Code::SQL::Statement.new(:SELECT,1)
223
- )
224
- end
225
-
226
- it "should wrap the left-hand operand in parenthesis" do
227
- expect(subject.emit_expression(expr)).to eq('1=(SELECT 1)')
228
- end
229
- end
230
- end
231
-
232
- context "when the expression is a UnaryExpr" do
233
- context "when the operator is upper-case alpha" do
234
- let(:expr) { Ronin::Code::SQL::UnaryExpr.new(:NOT,:admin) }
235
-
236
- it "should emit the operand and operator with spaces" do
237
- expect(subject.emit_expression(expr)).to eq('NOT admin')
238
- end
239
- end
240
-
241
- context "when the operator is symbolic" do
242
- let(:expr) { Ronin::Code::SQL::UnaryExpr.new(:"-",1) }
243
-
244
- it "should emit the operand and operator without spaces" do
245
- expect(subject.emit_expression(expr)).to eq('-1')
246
- end
247
- end
248
-
249
- context "when the operand is a Statement" do
250
- let(:expr) do
251
- Ronin::Code::SQL::UnaryExpr.new(
252
- :NOT, Ronin::Code::SQL::Statement.new(:SELECT,1)
253
- )
254
- end
255
-
256
- it "should wrap the operand in parenthesis" do
257
- expect(subject.emit_expression(expr)).to eq('NOT (SELECT 1)')
258
- end
259
- end
260
- end
261
- end
262
-
263
- describe "#emit_function" do
264
- let(:func) { Ronin::Code::SQL::Function.new(:NOW) }
265
-
266
- it "should emit the function name as a keyword" do
267
- expect(subject.emit_function(func)).to eq('NOW()')
268
- end
269
-
270
- context "with arguments" do
271
- let(:func) { Ronin::Code::SQL::Function.new(:MAX,1,2) }
272
-
273
- it "should emit the function arguments" do
274
- expect(subject.emit_function(func)).to eq('MAX(1,2)')
275
- end
276
- end
277
- end
278
-
279
- describe "#emit" do
280
- context "when passed nil" do
281
- it "should emit the NULL keyword" do
282
- expect(subject.emit(nil)).to eq('NULL')
283
- end
284
- end
285
-
286
- context "when passed true" do
287
- it "should emit true" do
288
- expect(subject.emit(true)).to eq('1=1')
289
- end
290
- end
291
-
292
- context "when passed false" do
293
- it "should emit false" do
294
- expect(subject.emit(false)).to eq('1=0')
295
- end
296
- end
297
-
298
- context "when passed an Integer" do
299
- it "should emit an integer" do
300
- expect(subject.emit(10)).to eq('10')
301
- end
302
- end
303
-
304
- context "when passed a Float" do
305
- it "should emit a decimal" do
306
- expect(subject.emit(2.5)).to eq('2.5')
307
- end
308
- end
309
-
310
- context "when passed a String" do
311
- it "should emit a string" do
312
- expect(subject.emit("O'Brian")).to eq("'O''Brian'")
313
- end
314
- end
315
-
316
- context "when passed a Literal" do
317
- let(:literal) { Ronin::Code::SQL::Literal.new(42) }
318
-
319
- it "should emit the value" do
320
- expect(subject.emit(literal)).to eq('42')
321
- end
322
- end
323
-
324
- context "when passed a Field" do
325
- let(:table) { Ronin::Code::SQL::Field.new(:users) }
326
- let(:column) { Ronin::Code::SQL::Field.new(:id,table) }
327
-
328
- it "should emit a field" do
329
- expect(subject.emit(column)).to eq('users.id')
330
- end
331
- end
332
-
333
- context "when passed a Symbol" do
334
- it "should emit a field" do
335
- expect(subject.emit(:id)).to eq('id')
336
- end
337
- end
338
-
339
- context "when passed an Array" do
340
- it "should emit a list" do
341
- expect(subject.emit([1,2,3,'foo'])).to eq("(1,2,3,'foo')")
342
- end
343
- end
344
-
345
- context "when passed a Hash" do
346
- it "should emit a list of assignments" do
347
- expect(subject.emit(x: 1, y: 2)).to eq('x=1,y=2')
348
- end
349
- end
350
-
351
- context "when passed a BinaryExpr" do
352
- let(:expr) { Ronin::Code::SQL::BinaryExpr.new(:id,:"=",1) }
353
-
354
- it "should emit an expression" do
355
- expect(subject.emit(expr)).to eq('id=1')
356
- end
357
- end
358
-
359
- context "when passed a UnaryExpr" do
360
- let(:expr) { Ronin::Code::SQL::UnaryExpr.new(:NOT,:admin) }
361
-
362
- it "should emit an expression" do
363
- expect(subject.emit(expr)).to eq('NOT admin')
364
- end
365
- end
366
-
367
- context "when passed a Function" do
368
- let(:func) { Ronin::Code::SQL::Function.new(:MAX,1,2) }
369
-
370
- it "should emit the function" do
371
- expect(subject.emit(func)).to eq('MAX(1,2)')
372
- end
373
- end
374
-
375
- context "when passed a Statment" do
376
- let(:stmt) { Ronin::Code::SQL::Statement.new(:SELECT,1) }
377
-
378
- it "should emit a statement" do
379
- expect(subject.emit(stmt)).to eq('SELECT 1')
380
- end
381
- end
382
-
383
- context "when the object responds to #to_sql" do
384
- let(:object) { double(:sql_object) }
385
- let(:sql) { "EXEC sp_configure 'xp_cmdshell', 0;" }
386
-
387
- it "should call #to_sql" do
388
- allow(object).to receive(:to_sql).and_return(sql)
389
-
390
- expect(subject.emit(object)).to eq(sql)
391
- end
392
- end
393
-
394
- context "otherwise" do
395
- let(:object) { Object.new }
396
-
397
- it "should raise an ArgumentError" do
398
- expect {
399
- subject.emit(object)
400
- }.to raise_error(ArgumentError)
401
- end
402
- end
403
- end
404
-
405
- describe "#emit_clause" do
406
- let(:clause) { Ronin::Code::SQL::Clause.new(:"NOT INDEXED") }
407
-
408
- it "should emit the clause keyword" do
409
- expect(subject.emit_clause(clause)).to eq("NOT INDEXED")
410
- end
411
-
412
- context "with an argument" do
413
- let(:argument) { 100 }
414
- let(:clause) { Ronin::Code::SQL::Clause.new(:LIMIT,argument) }
415
-
416
- it "should also emit the clause argument" do
417
- expect(subject.emit_clause(clause)).to eq("LIMIT #{argument}")
418
- end
419
- end
420
-
421
- context "with custom :space" do
422
- subject { described_class.new(space: '/**/') }
423
-
424
- let(:clause) { Ronin::Code::SQL::Clause.new(:LIMIT,100) }
425
-
426
- it "should emit the custom white-space deliminater" do
427
- expect(subject.emit_clause(clause)).to eq('LIMIT/**/100')
428
- end
429
- end
430
- end
431
-
432
- describe "#emit_clauses" do
433
- let(:clauses) do
434
- [
435
- Ronin::Code::SQL::Clause.new(:LIMIT, 100),
436
- Ronin::Code::SQL::Clause.new(:OFFSET, 10)
437
- ]
438
- end
439
-
440
- it "should emit multiple clauses" do
441
- expect(subject.emit_clauses(clauses)).to eq('LIMIT 100 OFFSET 10')
442
- end
443
-
444
- context "with custom :space" do
445
- subject { described_class.new(space: '/**/') }
446
-
447
- it "should emit the custom white-space deliminater" do
448
- expect(subject.emit_clauses(clauses)).to eq('LIMIT/**/100/**/OFFSET/**/10')
449
- end
450
- end
451
- end
452
-
453
- describe "#emit_statement" do
454
- subject { described_class.new(case: :lower) }
455
-
456
- context "without an argument" do
457
- let(:stmt) { Ronin::Code::SQL::Statement.new(:SELECT) }
458
-
459
- it "should emit the statment keyword" do
460
- expect(subject.emit_statement(stmt)).to eq('select')
461
- end
462
- end
463
-
464
- context "with an argument" do
465
- let(:stmt) { Ronin::Code::SQL::Statement.new(:SELECT,1) }
466
-
467
- it "should emit the statment argument" do
468
- expect(subject.emit_statement(stmt)).to eq('select 1')
469
- end
470
-
471
- context "when the argument is an Array" do
472
- let(:stmt) { Ronin::Code::SQL::Statement.new(:SELECT,[1,2,3]) }
473
-
474
- it "should emit a list" do
475
- expect(subject.emit_statement(stmt)).to eq('select (1,2,3)')
476
- end
477
-
478
- context "with only one element" do
479
- let(:stmt) { Ronin::Code::SQL::Statement.new(:SELECT,[1]) }
480
-
481
- it "should emit the element" do
482
- expect(subject.emit_statement(stmt)).to eq('select 1')
483
- end
484
- end
485
- end
486
-
487
- context "with custom :space" do
488
- subject { described_class.new(case: :lower, space: '/**/') }
489
-
490
- it "should emit the custom white-space deliminater" do
491
- expect(subject.emit_statement(stmt)).to eq('select/**/1')
492
- end
493
- end
494
- end
495
-
496
- context "with clauses" do
497
- let(:stmt) { Ronin::Code::SQL::Statement.new(:SELECT,1).offset(1).limit(100) }
498
-
499
- it "should emit the statment argument" do
500
- expect(subject.emit_statement(stmt)).to eq('select 1 offset 1 limit 100')
501
- end
502
-
503
- context "with custom :space" do
504
- subject { described_class.new(case: :lower, space: '/**/') }
505
-
506
- it "should emit the custom white-space deliminater" do
507
- expect(subject.emit_statement(stmt)).to eq('select/**/1/**/offset/**/1/**/limit/**/100')
508
- end
509
- end
510
- end
511
- end
512
-
513
- describe "#emit_statement_list" do
514
- let(:stmts) do
515
- sql = Ronin::Code::SQL::StatementList.new
516
- sql << Ronin::Code::SQL::Statement.new(:SELECT, 1)
517
- sql << Ronin::Code::SQL::Statement.new([:DROP, :TABLE], :users)
518
- sql
519
- end
520
-
521
- it "should emit multiple statements separated by '; '" do
522
- expect(subject.emit_statement_list(stmts)).to eq('SELECT 1; DROP TABLE users')
523
- end
524
-
525
- context "with custom :space" do
526
- subject { described_class.new(space: '/**/') }
527
-
528
- it "should emit the custom white-space deliminater" do
529
- expect(subject.emit_statement_list(stmts)).to eq('SELECT/**/1;/**/DROP/**/TABLE/**/users')
530
- end
531
- end
532
- end
533
- end
@@ -1,103 +0,0 @@
1
- require 'spec_helper'
2
- require 'ronin/code/sql/field'
3
-
4
- describe Ronin::Code::SQL::Field do
5
- describe "#initialize" do
6
- it "should convert name to a String" do
7
- expect(described_class.new(:table).name).to eq('table')
8
- end
9
-
10
- it "should default parent to nil" do
11
- expect(described_class.new('table').parent).to be_nil
12
- end
13
- end
14
-
15
- describe "parse" do
16
- context "when passed a single field" do
17
- let(:name) { "column" }
18
-
19
- subject { described_class.parse(name) }
20
-
21
- it "should parse the field name" do
22
- expect(subject.name).to eq(name)
23
- end
24
-
25
- it "should not have a parent" do
26
- expect(subject.parent).to be_nil
27
- end
28
- end
29
-
30
- context "when parsing multiple fields" do
31
- let(:parent) { "table" }
32
- let(:name) { "column" }
33
-
34
- subject { described_class.parse("#{parent}.#{name}") }
35
-
36
- it "should parse the field name" do
37
- expect(subject.name).to eq(name)
38
- end
39
-
40
- it "should parse the parent field" do
41
- expect(subject.parent.name).to eq(parent)
42
- end
43
- end
44
- end
45
-
46
- describe "#to_s" do
47
- context "when parent is nil" do
48
- let(:name) { "column" }
49
-
50
- subject { described_class.new(name) }
51
-
52
- it "should return the name" do
53
- expect(subject.to_s).to eq(name)
54
- end
55
- end
56
-
57
- context "when parent is set" do
58
- let(:parent) { "table" }
59
- let(:name) { "column" }
60
-
61
- subject { described_class.new(name,described_class.new(parent)) }
62
-
63
- it "should return the name" do
64
- expect(subject.to_s).to eq("#{parent}.#{name}")
65
- end
66
- end
67
- end
68
-
69
- describe "#method_missing" do
70
- context "at depth 1" do
71
- subject { described_class.new('table') }
72
-
73
- it "should allow accessing sub-fields" do
74
- expect(subject.column.name).to eq('column')
75
- end
76
- end
77
-
78
- context "at depth 2" do
79
- subject { described_class.new('table',described_class.new('db')) }
80
-
81
- it "should allow accessing sub-fields" do
82
- expect(subject.column.name).to eq('column')
83
- end
84
- end
85
-
86
- context "at depth 3" do
87
- subject do
88
- described_class.new(
89
- 'column',
90
- described_class.new(
91
- 'table', described_class.new('db')
92
- )
93
- )
94
- end
95
-
96
- it "should not allow accessing sub-fields" do
97
- expect {
98
- subject.column
99
- }.to raise_error(NoMethodError)
100
- end
101
- end
102
- end
103
- end
@@ -1,40 +0,0 @@
1
- require 'spec_helper'
2
- require 'ronin/code/sql/fields'
3
-
4
- describe Ronin::Code::SQL::Fields do
5
- subject { Object.new.extend(described_class) }
6
-
7
- describe "#respond_to_missing?" do
8
- it "should return true" do
9
- expect(subject).to respond_to(:foo)
10
- end
11
- end
12
-
13
- it { expect(subject.to_ary).to be_nil }
14
-
15
- describe "#method_missing" do
16
- let(:name) { 'users' }
17
-
18
- context "when called with no arguments and no block" do
19
- it "should create a Field" do
20
- expect(subject.send(name).name).to eq(name)
21
- end
22
- end
23
-
24
- context "when called with arguments" do
25
- it "should raise a NoMethodError" do
26
- expect {
27
- subject.sned(name,1,2,3)
28
- }.to raise_error(NoMethodError)
29
- end
30
- end
31
-
32
- context "when called with a block" do
33
- it "should raise a NoMethodError" do
34
- expect {
35
- subject.sned(name) { 1 + 1 }
36
- }.to raise_error(NoMethodError)
37
- end
38
- end
39
- end
40
- end
@@ -1,30 +0,0 @@
1
- require 'spec_helper'
2
-
3
- shared_examples_for "Function" do |method,arguments=[],additional_arguments=[]|
4
- describe "##{method}" do
5
- let(:name) { method.upcase }
6
- let(:func) { subject.send(method,*arguments) }
7
-
8
- it "should create a #{method.upcase} function" do
9
- expect(func.name).to eq(name)
10
- end
11
-
12
- unless arguments.empty?
13
- it "should set the arguments" do
14
- expect(func.arguments).to eq(arguments)
15
- end
16
- end
17
-
18
- unless additional_arguments.empty?
19
- context "when passed additional arguments" do
20
- let(:func) { subject.send(method,*additional_arguments) }
21
-
22
- it "should set the arguments" do
23
- expect(func.arguments).to eq(additional_arguments)
24
- end
25
- end
26
- end
27
- end
28
- end
29
-
30
-