stones-spec 1.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 61404af586ca76a2bbe93f918c43e9e5f96d6e27
4
+ data.tar.gz: 6a5c5604f68519886817fd96e6c8d1ebe811d2ec
5
+ SHA512:
6
+ metadata.gz: 30bfcb15abdf1f02ae85ba42def8c1d74bf91d0c5924fbc3be60a383a458e1cae152743a7c7ed0d560115746eb52f5f3160bf58a441371169f06aefd1c064ee2
7
+ data.tar.gz: c2c67ed0a00ff8c5ebe54f227448efc184f3e2fb40d55c19d0eed7f3bb2ec7f449519a1d9e1a8a8bfe975631abb7dbc526beec8b228fe3827670bc79dfa83435
data/lib/example.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'ostruct'
2
+
3
+ module StonesSpec
4
+ class Example < OpenStruct
5
+ def initialize(subject, attributes)
6
+ super attributes
7
+ @title = attributes[:title]
8
+ @subject = subject
9
+ @precondition = Precondition.from_example(self)
10
+ end
11
+
12
+ def execution_data(source)
13
+ { source: @subject.test_program(source, @precondition.arguments),
14
+ initial_board: @precondition.initial_board_gbb }
15
+ end
16
+
17
+ def execute!(files, parser)
18
+ parser.run(files[:source], files[:initial_board], files[:final_board])
19
+ end
20
+
21
+ def result(files, execution, postcondition)
22
+ if execution[:status] == :syntax_error
23
+ raise Gobstones::SyntaxError, execution[:result]
24
+ end
25
+
26
+ if execution[:status] == :runtime_error
27
+ raise Gobstones::AbortedError, execution[:result]
28
+ end
29
+
30
+ postcondition.validate(files[:initial_board].open.read, files[:final_board].open.read, execution[:result], execution[:status])
31
+ end
32
+
33
+ def title
34
+ @title || default_title
35
+ end
36
+
37
+ private
38
+
39
+ def default_title
40
+ @subject.default_title @precondition.arguments
41
+ end
42
+ end
43
+ end
data/lib/gobstones.rb ADDED
@@ -0,0 +1,26 @@
1
+ module StonesSpec
2
+ module Gobstones
3
+ def self.source_code_extension
4
+ 'gbs'
5
+ end
6
+
7
+ def self.board_extension
8
+ 'gbb'
9
+ end
10
+
11
+ class Error < Exception
12
+ end
13
+
14
+ class SyntaxError < Error
15
+ def status
16
+ :errored
17
+ end
18
+ end
19
+
20
+ class AbortedError < Error
21
+ def status
22
+ :aborted
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ class Hash
2
+ def map_values(&block)
3
+ Hash[self.map {|k, v| [k, block.call(k,v)] }]
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ class String
2
+ def start_with_lowercase?
3
+ first_letter = self[0]
4
+ first_letter.downcase == first_letter
5
+ end
6
+
7
+ def include_any?(other_strs)
8
+ other_strs.any? { |other| include? other }
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ require 'tempfile'
2
+
3
+ module StonesSpec
4
+ module WithTempfile
5
+
6
+ def write_tempfile(content, extension)
7
+ file = Tempfile.new %W(gobstones. .#{extension})
8
+ file.write content
9
+ file.close
10
+ file
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,55 @@
1
+ module StonesSpec
2
+ module Postcondition
3
+ class ExpectedBoom
4
+ include StonesSpec::WithGbbHtmlRendering
5
+
6
+ attr_reader :example, :error_type
7
+
8
+ def initialize(example)
9
+ @example = example
10
+ @error_type = known_error_types[example.error.to_sym]
11
+ end
12
+
13
+ def validate(initial_board_gbb, actual_final_board_gbb, result, status)
14
+ if status == :failed
15
+ check_right_error_type initial_board_gbb, result
16
+ else
17
+ boards = [['Tablero inicial', initial_board_gbb], ['Tablero final', actual_final_board_gbb]]
18
+ make_boards_output example.title, boards, :failed, failure_message
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def check_right_error_type(initial_board_gbb, result)
25
+ if error_type_matches? result
26
+ [example.title, :passed, make_error_output(result, initial_board_gbb)]
27
+ else
28
+ [example.title, :failed, "#{invalid_boom_type_message}\n#{make_error_output(result, initial_board_gbb)}"]
29
+ end
30
+ end
31
+
32
+ def error_type_matches?(result)
33
+ error_type[:matcher] =~ result
34
+ end
35
+
36
+ def known_error_types
37
+ {
38
+ out_of_board: { matcher: /La posición cae afuera del tablero/, friendly_message: 'caer fuera del tablero' },
39
+ no_stones: { matcher: /No hay bolitas de ese color/, friendly_message: 'no haber bolitas' },
40
+ unassigned_variable: { matcher: /podría no tener asignado ningún valor/, friendly_message: 'tener una variable sin asignar' },
41
+ wrong_argument_type: { matcher: /El argumento de .+ debería ser/, friendly_message: 'tipo erróneo de un argumento' },
42
+ wrong_arguments_quantity: { matcher: /Esperaba \d+ argumentos (.|\n)* Recibió \d+/, friendly_message: 'cantidad inválida de argumentos' }
43
+ }
44
+ end
45
+
46
+ def failure_message
47
+ 'Se esperaba que el programa hiciera BOOM pero se obtuvo un tablero final.'
48
+ end
49
+
50
+ def invalid_boom_type_message
51
+ "<p>Se esperaba que el programa hiciera BOOM por #{error_type[:friendly_message]}.</p>"
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,56 @@
1
+ module StonesSpec
2
+ module Postcondition
3
+ class ExpectedFinalBoard < ExpectedResult
4
+ attr_reader :check_head_position, :show_initial_board
5
+
6
+ def initialize(example, check_head_position, show_initial_board)
7
+ super example
8
+ @check_head_position = check_head_position
9
+ @show_initial_board = show_initial_board
10
+ end
11
+
12
+ def validate_expected_result(initial_board_gbb, actual_final_board_gbb, _result)
13
+ if matches_with_expected_board? Stones::Gbb.read actual_final_board_gbb
14
+ passed_result initial_board_gbb, actual_final_board_gbb
15
+ else
16
+ failed_result initial_board_gbb, example.final_board, actual_final_board_gbb
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def failed_result(initial_board_gbb, expected_board_gbb, actual_board_gbb)
23
+ boards = [
24
+ ['Tablero final esperado', expected_board_gbb],
25
+ ['Tablero final obtenido', actual_board_gbb]
26
+ ]
27
+
28
+ boards.unshift ['Tablero inicial', initial_board_gbb] if show_initial_board
29
+
30
+ make_boards_output example.title, boards, :failed
31
+ end
32
+
33
+ def passed_result(initial_board_gbb, actual_board_gbb)
34
+ boards = [
35
+ ['Tablero final', actual_board_gbb]
36
+ ]
37
+
38
+ boards.unshift ['Tablero inicial', initial_board_gbb] if show_initial_board
39
+
40
+ make_boards_output example.title, boards, :passed
41
+ end
42
+
43
+ def matches_with_expected_board?(actual_board)
44
+ if check_head_position
45
+ actual_board == final_board
46
+ else
47
+ actual_board.cells_equal? final_board
48
+ end
49
+ end
50
+
51
+ def final_board
52
+ Stones::Gbb.read example.final_board
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,44 @@
1
+ module StonesSpec
2
+ module Postcondition
3
+ class ExpectedReturnValue < ExpectedResult
4
+ def initialize(example, show_initial_board)
5
+ super example
6
+ @show_initial_board = show_initial_board
7
+ end
8
+
9
+ def validate_expected_result(initial_board_gbb, _actual_final_board_gbb, result)
10
+ normalized_actual_return = parse_success_output(result).strip
11
+
12
+ if normalized_actual_return == return_value
13
+ make_result(:passed, initial_board_gbb)
14
+ else
15
+ make_result(:failed, initial_board_gbb, "Se esperaba <b>#{return_value}</b> pero se obtuvo <b>#{normalized_actual_return}</b>")
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def parse_success_output(result)
22
+ first_return_value result || ''
23
+ end
24
+
25
+ def first_return_value(result)
26
+ result[/#1 -> (.+)/, 1]
27
+ end
28
+
29
+ def make_result(status, initial_board_gbb, output='')
30
+ title = "#{example.title} -> #{return_value}"
31
+
32
+ if @show_initial_board
33
+ make_boards_output title, [['Tablero inicial', initial_board_gbb]], status, output
34
+ else
35
+ [title, status, output]
36
+ end
37
+ end
38
+
39
+ def return_value
40
+ example.return.to_s
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,35 @@
1
+ module StonesSpec
2
+ module Postcondition
3
+ def self.from(example, check_head_position, show_initial_board)
4
+ if example.final_board
5
+ ExpectedFinalBoard.new(example, check_head_position, show_initial_board)
6
+ elsif example.return
7
+ ExpectedReturnValue.new(example, show_initial_board)
8
+ else
9
+ ExpectedBoom.new(example)
10
+ end
11
+ end
12
+
13
+ class ExpectedResult
14
+ include StonesSpec::WithGbbHtmlRendering
15
+
16
+ attr_reader :example
17
+
18
+ def initialize(example)
19
+ @example = example
20
+ end
21
+
22
+ def validate(initial_board_gbb, actual_final_board_gbb, result, status)
23
+ if status == :failed
24
+ [example.title, :failed, make_error_output(result, initial_board_gbb)]
25
+ else
26
+ validate_expected_result(initial_board_gbb, actual_final_board_gbb, result)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ require_relative './expected_boom'
34
+ require_relative './expected_final_board'
35
+ require_relative './expected_return_value'
@@ -0,0 +1,26 @@
1
+ module StonesSpec
2
+ class Precondition
3
+ attr_reader :initial_board_gbb
4
+
5
+ def self.from_example(example)
6
+ self.new example.initial_board, example.arguments
7
+ end
8
+
9
+ def initialize(initial_board, arguments)
10
+ @initial_board_gbb = initial_board || default_initial_board
11
+ @arguments = arguments
12
+ end
13
+
14
+ def arguments
15
+ @arguments || []
16
+ end
17
+
18
+ private
19
+
20
+ def default_initial_board
21
+ 'GBB/1.0
22
+ size 4 4
23
+ head 0 0'
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,77 @@
1
+ require_relative './with_gobstones_css'
2
+
3
+ module StonesSpec
4
+ class HtmlBoardRenderer
5
+ include StonesSpec::WithGobstonesCSS
6
+
7
+ def initialize(options = {})
8
+ @options = options
9
+ end
10
+
11
+ def render(board)
12
+ "<style type=\"text/css\">
13
+ #{render_css}</style>
14
+
15
+ #{render_html board}"
16
+ end
17
+
18
+ def method_missing(name)
19
+ @options[name]
20
+ end
21
+
22
+ def render_html(board)
23
+ width, height = board.size
24
+
25
+ "#{table_title}
26
+ #{html_row_titles width, 'top'}
27
+ #{(0...height).to_a.reverse.map {|y| html_row(board, y)}.join}#{html_row_titles width, 'bottom'}
28
+ </table>
29
+ "
30
+ end
31
+
32
+ def render_css
33
+ gobstones_css '9pt', 30
34
+ end
35
+
36
+ private
37
+
38
+ def table_title
39
+ base = "<table class=\"gbs_board\">"
40
+ caption ? base + "\n<caption>#{caption}</caption>" : base
41
+ end
42
+
43
+ def html_row(board, y)
44
+ " <tr>
45
+ <td class=\"lv\">#{y}</td>
46
+ #{(0...board.size[0]).map {|x| html_cell board, [x, y] }.join "\n"}
47
+ <td class=\"lv\">#{y}</td>
48
+ </tr>
49
+ "
50
+ end
51
+
52
+ def html_cell(board, position)
53
+ cell = board.cell_at position
54
+
55
+ " <td class=\"gc#{board.head_position == position ? ' gh' : ''}\">
56
+ <table>
57
+ <tr>#{html_stone cell, :black}#{html_stone cell, :blue}</tr>
58
+ <tr>#{html_stone cell, :red}#{html_stone cell, :green}</tr>
59
+ </table>
60
+ </td>"
61
+ end
62
+
63
+ def html_stone(cell, color)
64
+ quantity = cell[color]
65
+
66
+ if cell[color] == 0
67
+ '<td><div class="O"></div></td>'
68
+ else
69
+ "<td><div class=\"gbs_stone #{Stones::Color.all_with_names.invert[color][0]}\"><span>#{quantity}</span></div></td>"
70
+ end
71
+ end
72
+
73
+ def html_row_titles(width, caption)
74
+ "<tr><td class=\"lx #{caption}_left\"></td>#{(0...width).map {|x| "<td class=\"lh\">#{x}</td>"}.join}<td class=\"lx #{caption}_right\"></td></tr>"
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,55 @@
1
+ module StonesSpec
2
+ module WithGbbHtmlRendering
3
+ def get_html_board(caption, gbb_representation)
4
+ HtmlBoardRenderer.new(caption: caption).render(Stones::GbbReader.new.from_string gbb_representation)
5
+ end
6
+
7
+ def make_error_output(result, initial_board_gbb)
8
+ "#{get_html_board 'Tablero inicial', initial_board_gbb}\n#{get_boom_board initial_board_gbb}\n#{result}"
9
+ end
10
+
11
+ def make_boards_output(title, gbb_boards, status, extra = nil)
12
+ boards = gbb_boards.map { |gbb_with_caption| get_html_board *gbb_with_caption }.join("\n")
13
+ output = "<div>#{boards}</div>"
14
+
15
+ output = "<p>#{extra}</p>\n#{output}" if extra
16
+
17
+ [title, status, output]
18
+ end
19
+
20
+ private
21
+
22
+ def get_boom_board(initial_board_gbb)
23
+ gbb = empty_board_gbb_like initial_board_gbb
24
+
25
+ boom_css =
26
+ "<style type=\"text/css\">
27
+ table.boom {
28
+ background-image: url('#{boom_image_url}');
29
+ background-size: contain;
30
+ background-repeat: no-repeat;
31
+ background-position: center;
32
+ }
33
+ </style>"
34
+
35
+ without_header with_boom_css_class "#{boom_css}\n#{get_html_board '¡Se produjo BOOM!', gbb}"
36
+ end
37
+
38
+ def boom_image_url
39
+ 'https://raw.githubusercontent.com/mumuki/mumuki-gobstones-server/master/lib/assets/boom.png'
40
+ end
41
+
42
+ def empty_board_gbb_like(initial_board_gbb)
43
+ x, y = Stones::Gbb.read(initial_board_gbb).size
44
+ Stones::Gbb.write Stones::Board.empty(x, y)
45
+ end
46
+
47
+ def with_boom_css_class(html)
48
+ html.sub('class="gbs_board"', 'class="gbs_board boom"')
49
+ end
50
+
51
+ def without_header(html)
52
+ html.sub('class="gc gh"', 'class="gc"')
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,112 @@
1
+ module StonesSpec
2
+ module WithGobstonesCSS
3
+ def gobstones_css(font_size, size)
4
+ unit = 'px'
5
+
6
+ full_size = "#{size}#{unit}"
7
+ half_size = "#{size / 2}#{unit}"
8
+
9
+ "table.gbs_board {
10
+ border-style: none;
11
+ border: solid black 0px;
12
+ border-spacing: 0;
13
+ border-collapse: collapse;
14
+ font-family: Arial, Helvetica, sans-serif;
15
+ font-size: #{font_size};
16
+ display: inline-block;
17
+ vertical-align: top;
18
+ }
19
+ .gbs_board td {
20
+ margin: 0;
21
+ padding: 2px;
22
+ border: solid #888 1px;
23
+ width: #{full_size};
24
+ height: #{full_size};
25
+ }
26
+ .gbs_board td.gh { /* position of the header in the board */
27
+ margin: 0;
28
+ padding: 2px;
29
+ border: dotted #440 3px;
30
+ background: #dd8;
31
+ width: #{full_size};
32
+ height: #{full_size};
33
+ }
34
+ .gbs_board td.lv { /* labels at the side */
35
+ text-align: center;
36
+ vertical-align: middle;
37
+ border-style: none;
38
+ border: solid black 0px;
39
+ background: #ddd;
40
+ width: #{half_size};
41
+ }
42
+ .gbs_board td.lh { /* labels at the top / bottom */
43
+ text-align: center;
44
+ vertical-align: middle;
45
+ border-style: none;
46
+ border: solid black 0px;
47
+ background: #ddd;
48
+ height: #{half_size};
49
+ }
50
+ .gbs_board td.lx { /* corner */
51
+ border-style: none;
52
+ border: solid black 0px;
53
+ background: #ddd;
54
+ width: #{half_size};
55
+ height: #{half_size};
56
+ }
57
+ .gbs_board td.top_left {
58
+ -webkit-border-top-left-radius: 10px;
59
+ -moz-border-top-left-radius: 10px;
60
+ border-top-left-radius: 10px;
61
+ }
62
+ .gbs_board td.top_right {
63
+ -webkit-border-top-right-radius: 10px;
64
+ -moz-border-top-right-radius: 10px;
65
+ border-top-right-radius: 10px;
66
+ }
67
+ .gbs_board td.bottom_left {
68
+ -webkit-border-bottom-left-radius: 10px;
69
+ -moz-border-bottom-left-radius: 10px;
70
+ border-bottom-left-radius: 10px;
71
+ }
72
+ .gbs_board td.bottom_right {
73
+ -webkit-border-bottom-right-radius: 10px;
74
+ -moz-border-bottom-right-radius: 10px;
75
+ border-bottom-right-radius: 10px;
76
+ }
77
+ .gbs_board table.gc { /* cell table */
78
+ border-style: none;
79
+ border: solid black 0px;
80
+ }
81
+ .gbs_board .gc tr {
82
+ border-style: none;
83
+ border: 0px;
84
+ }
85
+ .gbs_board .gc td {
86
+ border-style: none;
87
+ border: solid black 0px;
88
+ width: #{half_size};
89
+ height: #{half_size};
90
+ text-align: center;
91
+ color: black;
92
+ }
93
+ .gbs_board .gc td div {
94
+ line-height: 2;
95
+ }
96
+ .gbs_board div.A { background: #88f; border: solid 1px #008; }
97
+ .gbs_board div.N { background: #aaa; border: solid 1px #222; }
98
+ .gbs_board div.R { background: #f88; border: solid 1px #800; }
99
+ .gbs_board div.V { background: #8f8; border: solid 1px #080; }
100
+ .gbs_board div.O { width: 20px; height: 20px; background: none; } /* empty */
101
+ .gbs_stone {
102
+ font-weight: bold;
103
+ font-size: 8pt;
104
+ width: 20px;
105
+ height: 20px;
106
+ -webkit-border-radius: 10px;
107
+ -moz-border-radius: 10px;
108
+ border-radius: 10px;
109
+ }"
110
+ end
111
+ end
112
+ end
data/lib/runner.rb ADDED
@@ -0,0 +1,45 @@
1
+ module StonesSpec
2
+ class Runner
3
+ include StonesSpec::WithTempfile
4
+
5
+ def initialize(parser)
6
+ @parser = parser
7
+ end
8
+
9
+ def run!(test_definition)
10
+ subject = Subject.from(test_definition[:subject])
11
+ source = test_definition[:source]
12
+ check_head_position = test_definition[:check_head_position]
13
+ show_initial_board = test_definition.fetch(:show_initial_board, true)
14
+
15
+ begin
16
+ [test_definition[:examples].map do |example_definition|
17
+ run_example!(example_definition, check_head_position, show_initial_board, source, subject)
18
+ end]
19
+ rescue Gobstones::AbortedError => e
20
+ test_definition[:expect_endless_while] ? [e.message, :passed] : [e.message, e.status]
21
+ rescue Gobstones::Error => e
22
+ [e.message, e.status]
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def run_example!(example_definition, check_head_position, show_initial_board, source, subject)
29
+ example = Example.new(subject, example_definition)
30
+
31
+ data = example.execution_data source
32
+ files = {
33
+ source: Gobstones.source_code_extension,
34
+ initial_board: Gobstones.board_extension,
35
+ final_board: Gobstones.board_extension
36
+ }.map_values { |name, extension| write_tempfile(data[name], extension) }
37
+
38
+ execution = example.execute! files, @parser
39
+
40
+ example.result files, execution, Postcondition.from(example, check_head_position, show_initial_board)
41
+ ensure
42
+ files.each_value(&:unlink)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,21 @@
1
+ module StonesSpec
2
+ end
3
+
4
+ require 'stones'
5
+
6
+ require_relative './helpers/string'
7
+ require_relative './helpers/hash'
8
+ require_relative './helpers/with_tempfile'
9
+
10
+ require_relative './version'
11
+ require_relative './gobstones'
12
+
13
+ require_relative './renderers/html_board_renderer'
14
+ require_relative './renderers/with_gbb_html_rendering'
15
+
16
+ require_relative './precondition'
17
+ require_relative './postcondition/postcondition'
18
+
19
+ require_relative './example'
20
+ require_relative './subject'
21
+ require_relative './runner'
data/lib/subject.rb ADDED
@@ -0,0 +1,80 @@
1
+ module StonesSpec
2
+ module Subject
3
+ def self.from(name)
4
+ if name
5
+ infer_subject_type_for(name).new(name)
6
+ else
7
+ Program
8
+ end
9
+ end
10
+
11
+ def self.infer_subject_type_for(string)
12
+ string.start_with_lowercase? ? StonesSpec::Subject::Function : StonesSpec::Subject::Procedure
13
+ end
14
+
15
+ module Program
16
+ def self.test_program(source, _arguments)
17
+ source
18
+ end
19
+
20
+ def self.default_title(_arguments)
21
+ nil
22
+ end
23
+
24
+ def self.ast_regexp
25
+ /AST\(entrypoint\s*program/
26
+ end
27
+
28
+ def self.default_expectations
29
+ [{ 'binding' => 'program', 'inspection' => 'HasBinding' }]
30
+ end
31
+ end
32
+
33
+ class Callable
34
+ def initialize(name)
35
+ @name = name
36
+ end
37
+
38
+ def call_string(arguments)
39
+ "#{@name}(#{arguments.join(', ')})"
40
+ end
41
+
42
+ def default_title(arguments)
43
+ call_string arguments
44
+ end
45
+
46
+ def default_expectations
47
+ [ { 'binding' => 'program', 'inspection' => 'Not:HasBinding' },
48
+ { 'binding' => "#{@name}", 'inspection' => 'HasBinding' } ]
49
+ end
50
+ end
51
+
52
+ class Procedure < Callable
53
+ def test_program(source, arguments)
54
+ "program {
55
+ #{call_string arguments}
56
+ }
57
+
58
+ #{source}"
59
+ end
60
+
61
+ def ast_regexp
62
+ /AST\(procedure\s*#{@name}$/
63
+ end
64
+ end
65
+
66
+ class Function < Callable
67
+ def test_program(source, arguments)
68
+ "program {
69
+ return (#{call_string arguments})
70
+ }
71
+
72
+ #{source}"
73
+ end
74
+
75
+ def ast_regexp
76
+ /AST\(function\s*#{@name}/
77
+ end
78
+ end
79
+ end
80
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module StonesSpec
2
+ VERSION = '1.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stones-spec
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Mumuki
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-12-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ruby-stones
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.4'
55
+ description:
56
+ email:
57
+ - mumuki@mumuki.org
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - lib/example.rb
63
+ - lib/gobstones.rb
64
+ - lib/helpers/hash.rb
65
+ - lib/helpers/string.rb
66
+ - lib/helpers/with_tempfile.rb
67
+ - lib/postcondition/expected_boom.rb
68
+ - lib/postcondition/expected_final_board.rb
69
+ - lib/postcondition/expected_return_value.rb
70
+ - lib/postcondition/postcondition.rb
71
+ - lib/precondition.rb
72
+ - lib/renderers/html_board_renderer.rb
73
+ - lib/renderers/with_gbb_html_rendering.rb
74
+ - lib/renderers/with_gobstones_css.rb
75
+ - lib/runner.rb
76
+ - lib/stones-spec.rb
77
+ - lib/subject.rb
78
+ - lib/version.rb
79
+ homepage: http://github.com/mumuki/stones-spec
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 2.5.1
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: Minimal test framework for Gobstones
103
+ test_files: []