mumuki-sqlite-runner 3.2.0 → 3.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/dataset.rb +1 -1
- data/lib/helpers.rb +10 -8
- data/lib/html_renderer.rb +26 -6
- data/lib/locales/en.yml +12 -0
- data/lib/locales/es-CL.yml +24 -0
- data/lib/locales/es.yml +12 -0
- data/lib/parsers/base_parser.rb +62 -0
- data/lib/parsers/datasets_parser.rb +33 -0
- data/lib/parsers/display_parser.rb +21 -0
- data/lib/parsers/final_dataset_parser.rb +29 -0
- data/lib/parsers/query_parser.rb +17 -0
- data/lib/sqlite_runner.rb +5 -6
- data/lib/test_hook.rb +34 -19
- data/lib/validation_hook.rb +15 -14
- data/lib/version_hook.rb +1 -1
- data/lib/view/rows_error.html.erb +49 -87
- data/lib/view/rows_success.html.erb +23 -39
- metadata +13 -14
- data/lib/parsers/common_test_parser.rb +0 -45
- data/lib/parsers/dataset_test_parser.rb +0 -29
- data/lib/parsers/display_test_parser.rb +0 -18
- data/lib/parsers/final_dataset_test_parser.rb +0 -14
- data/lib/parsers/invalid_test_parser.rb +0 -10
- data/lib/parsers/query_test_parser.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d47ec94e08c7d9c855d17bfedc35b1a7709d5d0e22682a2b129ad5425e14d17e
|
4
|
+
data.tar.gz: 4ffe138556f5a890a71e3cdcd816fdf596917a40527472a07d15907013abac6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 558a62973b1078fc23e3ad1ddeb668cc1738d5560229b3c76c2d8b775a659df22192dd8534054a3ad7db50a49d208b5075b3f610c1b41459e5cc34a8041717e2
|
7
|
+
data.tar.gz: '0187ab08320aa59793522521a3063f7aeb75ea18cc41684782d847249c11771d7aa28c452131b4562e3efbdef991c13ae07bc98088e2b84c1cb5d435782f91b1'
|
data/lib/dataset.rb
CHANGED
data/lib/helpers.rb
CHANGED
@@ -1,21 +1,23 @@
|
|
1
1
|
module Sqlite
|
2
2
|
module TestHelper
|
3
3
|
|
4
|
-
def
|
5
|
-
@
|
6
|
-
query: Sqlite::
|
7
|
-
display: Sqlite::
|
8
|
-
datasets: Sqlite::
|
9
|
-
final_dataset: Sqlite::
|
4
|
+
def parsers
|
5
|
+
@parsers ||= {
|
6
|
+
query: Sqlite::QueryParser,
|
7
|
+
display: Sqlite::DisplayParser,
|
8
|
+
datasets: Sqlite::DatasetsParser,
|
9
|
+
final_dataset: Sqlite::FinalDatasetParser,
|
10
10
|
}
|
11
|
-
@test_parsers.default = Sqlite::InvalidTestParser
|
12
11
|
end
|
13
12
|
|
14
|
-
def
|
13
|
+
def collect_tests(test)
|
15
14
|
tests = YAML.load test
|
16
15
|
tests = [tests] unless tests.kind_of? Array
|
17
16
|
tests.map(&:to_struct)
|
18
17
|
end
|
19
18
|
|
19
|
+
def fail!(*args)
|
20
|
+
raise Mumukit::RequestValidationError, I18n.t(*args)
|
21
|
+
end
|
20
22
|
end
|
21
23
|
end
|
data/lib/html_renderer.rb
CHANGED
@@ -5,26 +5,30 @@ module Sqlite
|
|
5
5
|
|
6
6
|
def render_success(result, message)
|
7
7
|
@message = message
|
8
|
-
@
|
9
|
-
@
|
8
|
+
@table_name = result[:table_name]
|
9
|
+
@header = result[:dataset].header
|
10
|
+
@rows = result[:dataset].rows
|
11
|
+
@extra_message = extra_message result
|
10
12
|
template_file_success.result binding
|
11
13
|
end
|
12
14
|
|
13
15
|
def render_error(result, solution, error)
|
14
16
|
@error = error
|
17
|
+
@table_name = result[:table_name]
|
15
18
|
@result = parse_dataset(result[:dataset].header, result[:dataset].rows)
|
16
19
|
@solution = parse_dataset(solution[:dataset].header, solution[:dataset].rows)
|
17
|
-
|
20
|
+
@expected_message = expected_message result
|
21
|
+
@obtained_message = I18n.t 'obtained'
|
18
22
|
template_file_error.result binding
|
19
23
|
end
|
20
24
|
|
21
25
|
protected
|
22
26
|
|
23
27
|
def parse_dataset(header, rows)
|
24
|
-
header_sign = header
|
28
|
+
header_sign = first_column(header)
|
25
29
|
rows = rows.map do |row|
|
26
30
|
{
|
27
|
-
sign: row
|
31
|
+
sign: first_column(row),
|
28
32
|
row: row
|
29
33
|
}
|
30
34
|
end
|
@@ -37,7 +41,7 @@ module Sqlite
|
|
37
41
|
},
|
38
42
|
rows: rows.map do |row|
|
39
43
|
{
|
40
|
-
sign:row[:sign],
|
44
|
+
sign: row[:sign],
|
41
45
|
class: diff_class_of(row[:sign]),
|
42
46
|
fields: row[:row]
|
43
47
|
}
|
@@ -46,6 +50,10 @@ module Sqlite
|
|
46
50
|
|
47
51
|
end
|
48
52
|
|
53
|
+
def first_column(row)
|
54
|
+
row.first.present? && row.first =~ /^[+-]$/ ? row.shift : '✓'
|
55
|
+
end
|
56
|
+
|
49
57
|
def diff_class_of(value)
|
50
58
|
case value
|
51
59
|
when '+'
|
@@ -57,6 +65,18 @@ module Sqlite
|
|
57
65
|
end
|
58
66
|
end
|
59
67
|
|
68
|
+
def extra_message(result)
|
69
|
+
result[:show_query] ? I18n.t('message.success.show_query', query: result[:query]) : ''
|
70
|
+
end
|
71
|
+
|
72
|
+
def expected_message(result)
|
73
|
+
if result[:show_query]
|
74
|
+
I18n.t('message.failure.show_query', query: result[:query])
|
75
|
+
else
|
76
|
+
I18n.t 'expected'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
60
80
|
def template_file_success
|
61
81
|
ERB.new File.read("#{__dir__}/view/rows_success.html.erb")
|
62
82
|
end
|
data/lib/locales/en.yml
CHANGED
@@ -1,12 +1,24 @@
|
|
1
1
|
en:
|
2
2
|
dataset: "Dataset %{number}"
|
3
|
+
default_table_name: 'Result'
|
4
|
+
expected: 'It was expected:'
|
5
|
+
obtained: 'It was obtained:'
|
3
6
|
message:
|
4
7
|
success:
|
5
8
|
query: 'Correct Query!'
|
9
|
+
show_query: 'The query `%{query}` returns:'
|
6
10
|
failure:
|
11
|
+
show_query: 'The query `%{query}` should return:'
|
12
|
+
semicolon_ending: 'You should finish each SQL statement with a semicolon (;)'
|
7
13
|
columns: 'Columns do not match'
|
8
14
|
rows: 'Rows do not match'
|
9
15
|
query: 'Queries do not match'
|
10
16
|
tests:
|
11
17
|
lint: "Invalid tests, It should be a valid YAML format. Try with this validator http://www.yamllint.com/"
|
18
|
+
type: "You need to declare field type:"
|
12
19
|
types: "Unsupported test type '%{type}'. Use one of these: datasets, query, display, final_dataset"
|
20
|
+
fields:
|
21
|
+
query: "For type:query you should use ONLY these fields: type (required), seed (optional), expected (required)"
|
22
|
+
datasets: "For type:datasets you should use ONLY these fields: type (required), seed (optional), expected (required)"
|
23
|
+
final_dataset: "For type:final_dataset you should use ONLY these fields: type (required), seed (optional), final (required), expected (required)"
|
24
|
+
display: "For type:display you should use ONLY these fields: type (required), seed (optional), query (required)"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
es:
|
2
|
+
dataset: "Set de datos %{number}"
|
3
|
+
default_table_name: 'Resultado'
|
4
|
+
expected: 'Se esperaba:'
|
5
|
+
obtained: 'Se obtuvo:'
|
6
|
+
message:
|
7
|
+
success:
|
8
|
+
query: '¡Consulta correcta!'
|
9
|
+
show_query: 'La consulta `%{query}` devolvió:'
|
10
|
+
failure:
|
11
|
+
show_query: 'Se esperaba que la consulta `%{query}` devolviera:'
|
12
|
+
semicolon_ending: 'Tienes que terminar cada sentencia SQL con punto y coma (;)'
|
13
|
+
columns: 'Las columnas no coinciden'
|
14
|
+
rows: 'Las filas no coinciden'
|
15
|
+
query: 'Las consultas no coinciden'
|
16
|
+
tests:
|
17
|
+
lint: "¡Tests inválidos! No tienen el formato YAML correcto. Puedes probar en este validador http://www.yamllint.com/"
|
18
|
+
type: "tienes que declarar el campo type:"
|
19
|
+
types: "El test type '%{type}' no está soportado. Tienes que usar uno de éstos: datasets, query, display, final_dataset"
|
20
|
+
fields:
|
21
|
+
query: "Para el type:query deberías usar ÚNICAMENTE estos campos: type (requerido), seed (opcional), expected (requerido)"
|
22
|
+
datasets: "Para el type:datasets deberías usar ÚNICAMENTE estos campos: type (requerido), seed (opcional), expected (requerido)"
|
23
|
+
final_dataset: "Para el type:final_dataset, deberías usar ÚNICAMENTE estos campos: type (requerido), seed (opcional), final (requerido), expected (requerido)"
|
24
|
+
display: "Para el type:display deberías usar ÚNICAMENTE estos campos: type (requerido), seed (opcional), query (requerido)"
|
data/lib/locales/es.yml
CHANGED
@@ -1,12 +1,24 @@
|
|
1
1
|
es:
|
2
2
|
dataset: "Set de datos %{number}"
|
3
|
+
default_table_name: 'Resultado'
|
4
|
+
expected: 'Se esperaba:'
|
5
|
+
obtained: 'Se obtuvo:'
|
3
6
|
message:
|
4
7
|
success:
|
5
8
|
query: '¡Consulta correcta!'
|
9
|
+
show_query: 'La consulta `%{query}` devolvió:'
|
6
10
|
failure:
|
11
|
+
show_query: 'Se esperaba que la consulta `%{query}` devolviera:'
|
12
|
+
semicolon_ending: 'Tenés que terminar cada sentencia SQL con punto y coma (;)'
|
7
13
|
columns: 'Las columnas no coinciden'
|
8
14
|
rows: 'Las filas no coinciden'
|
9
15
|
query: 'Las consultas no coinciden'
|
10
16
|
tests:
|
11
17
|
lint: "¡Tests inválidos! No tienen el formato YAML correcto. Podés probar en este validador http://www.yamllint.com/"
|
18
|
+
type: "Tenés que declarar el campo type:"
|
12
19
|
types: "El test type '%{type}' no está soportado. Tenés que usar uno de éstos: datasets, query, display, final_dataset"
|
20
|
+
fields:
|
21
|
+
query: "Para el type:query deberías usar ÚNICAMENTE estos campos: type (requerido), seed (opcional), expected (requerido)"
|
22
|
+
datasets: "Para el type:datasets deberías usar ÚNICAMENTE estos campos: type (requerido), seed (opcional), expected (requerido)"
|
23
|
+
final_dataset: "Para el type:final_dataset, deberías usar ÚNICAMENTE estos campos: type (requerido), seed (opcional), final (requerido), expected (requerido)"
|
24
|
+
display: "Para el type:display deberías usar ÚNICAMENTE estos campos: type (requerido), seed (opcional), query (requerido)"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Sqlite
|
2
|
+
class BaseParser
|
3
|
+
|
4
|
+
COMMENT = '-- NONE'
|
5
|
+
attr_reader :test_result
|
6
|
+
|
7
|
+
def parse_test(test)
|
8
|
+
@test = test
|
9
|
+
@test_result = transform_test
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_has_valid_fields?(test)
|
13
|
+
required = @fields[:required].sort
|
14
|
+
optional = @fields[:optional]
|
15
|
+
keys = process_alias test.to_h.keys.map(&:to_sym).sort
|
16
|
+
(keys - optional).eql? required
|
17
|
+
end
|
18
|
+
|
19
|
+
# A Parser can choose it's own solution or just return which is passed.
|
20
|
+
# This is default choice
|
21
|
+
def choose_solution(solution)
|
22
|
+
solution
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_final_query
|
26
|
+
''
|
27
|
+
end
|
28
|
+
|
29
|
+
def show_query?
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def table_name
|
34
|
+
has?(:result_alias) ? get(:result_alias) : I18n.t('default_table_name')
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def transform_test
|
40
|
+
{
|
41
|
+
seed: get_seed,
|
42
|
+
expected: get_expected
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def has?(key)
|
47
|
+
!@test[key.to_sym].blank?
|
48
|
+
end
|
49
|
+
|
50
|
+
def get(key)
|
51
|
+
@test[key.to_sym]
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_seed
|
55
|
+
has?(:seed) ? get(:seed).strip : ''
|
56
|
+
end
|
57
|
+
|
58
|
+
def process_alias(keys)
|
59
|
+
keys
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Sqlite
|
2
|
+
class DatasetsParser < BaseParser
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@fields = {
|
6
|
+
required: [:type, :expected],
|
7
|
+
optional: [:seed]
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
def choose_solution(_solution)
|
12
|
+
@solutions
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def transform_test
|
18
|
+
@solutions = strip_lines get(:expected)
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_expected
|
23
|
+
COMMENT
|
24
|
+
end
|
25
|
+
|
26
|
+
def strip_lines(array)
|
27
|
+
array.to_s
|
28
|
+
.split("\n")
|
29
|
+
.map(&:strip)
|
30
|
+
.join("\n")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Sqlite
|
2
|
+
class DisplayParser < BaseParser
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@fields = {
|
6
|
+
required: [:type, :query],
|
7
|
+
optional: [:seed]
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_final_query
|
12
|
+
get(:query)
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def get_expected
|
18
|
+
get_final_query
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Sqlite
|
2
|
+
class FinalDatasetParser < DatasetsParser
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@fields = {
|
6
|
+
required: [:type, :final, :expected],
|
7
|
+
optional: [:seed]
|
8
|
+
}
|
9
|
+
@alias = {
|
10
|
+
query: :final
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def show_query?
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_final_query
|
19
|
+
has?(:final) ? get(:final) : get(:query)
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def process_alias(keys)
|
25
|
+
keys.map { |item| @alias.include?(item) ? @alias[item] : item }
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
data/lib/sqlite_runner.rb
CHANGED
@@ -16,12 +16,11 @@ require_relative './version_hook'
|
|
16
16
|
require_relative './metadata_hook'
|
17
17
|
require_relative './html_renderer'
|
18
18
|
require_relative './multiple_executions_runner'
|
19
|
-
require_relative './parsers/
|
20
|
-
require_relative './parsers/
|
21
|
-
require_relative './parsers/
|
22
|
-
require_relative './parsers/
|
23
|
-
require_relative './parsers/
|
24
|
-
require_relative './parsers/invalid_test_parser'
|
19
|
+
require_relative './parsers/base_parser'
|
20
|
+
require_relative './parsers/query_parser'
|
21
|
+
require_relative './parsers/display_parser'
|
22
|
+
require_relative './parsers/datasets_parser'
|
23
|
+
require_relative './parsers/final_dataset_parser'
|
25
24
|
require_relative './helpers'
|
26
25
|
require_relative './test_hook'
|
27
26
|
require_relative './validation_hook'
|
data/lib/test_hook.rb
CHANGED
@@ -8,11 +8,6 @@ class SqliteTestHook < Mumukit::Templates::FileHook
|
|
8
8
|
isolated
|
9
9
|
include Sqlite::TestHelper
|
10
10
|
|
11
|
-
def initialize(config = nil)
|
12
|
-
super(config)
|
13
|
-
set_test_parsers_hash
|
14
|
-
end
|
15
|
-
|
16
11
|
def tempfile_extension
|
17
12
|
'.json'
|
18
13
|
end
|
@@ -23,12 +18,12 @@ class SqliteTestHook < Mumukit::Templates::FileHook
|
|
23
18
|
|
24
19
|
# Transform Mumuki Request into Docker file style
|
25
20
|
def compile_file_content(request)
|
26
|
-
|
27
|
-
|
21
|
+
parse_tests request.test
|
22
|
+
student_code = parse_student_code "#{request.content&.strip}#{get_final_query}"
|
28
23
|
{
|
29
24
|
init: "#{request.extra&.strip}",
|
30
|
-
student:
|
31
|
-
tests:
|
25
|
+
student: student_code,
|
26
|
+
tests: get_tests
|
32
27
|
}.to_json
|
33
28
|
end
|
34
29
|
|
@@ -52,7 +47,7 @@ class SqliteTestHook < Mumukit::Templates::FileHook
|
|
52
47
|
student = output['student']
|
53
48
|
expected = output['expected']
|
54
49
|
expected.map!.with_index do |expect, i|
|
55
|
-
@tests[i].
|
50
|
+
@tests[i].choose_solution expect
|
56
51
|
end
|
57
52
|
diff(expected, student)
|
58
53
|
end
|
@@ -60,7 +55,7 @@ class SqliteTestHook < Mumukit::Templates::FileHook
|
|
60
55
|
# Make diff between expected and student dataset result and mark each line one according comparision
|
61
56
|
def diff(expected, student)
|
62
57
|
zipped = expected.zip(student).map do |expected_i, student_i|
|
63
|
-
diff = Diffy::SplitDiff.new
|
58
|
+
diff = Diffy::SplitDiff.new expected_i << "\n", student_i << "\n"
|
64
59
|
choose_left_right(diff, expected_i, student_i).map { |e| post_process_diff e }
|
65
60
|
end
|
66
61
|
zipped.transpose.map { |dataset| post_process_datasets dataset }
|
@@ -72,33 +67,53 @@ class SqliteTestHook < Mumukit::Templates::FileHook
|
|
72
67
|
[expected, student]
|
73
68
|
end
|
74
69
|
|
70
|
+
# split lines grouping by diff mark & data content
|
71
|
+
# then append mark as dataset column & re join
|
75
72
|
def post_process_diff(data)
|
76
|
-
data.scan(/^(\s|-|\+)(.+)/)
|
77
|
-
.map { |mark, content| mark
|
73
|
+
data.scan(/^(\s|-|\+)*(.+)/)
|
74
|
+
.map { |mark, content| "#{proper_mark(mark)}#{content}" }
|
78
75
|
.join("\n")
|
79
76
|
end
|
80
77
|
|
78
|
+
def proper_mark(mark)
|
79
|
+
mark = mark.to_s
|
80
|
+
"#{mark}|" unless mark.blank?
|
81
|
+
end
|
82
|
+
|
81
83
|
# Transforms array datasets into hash with :id & :rows
|
82
84
|
def post_process_datasets(datasets)
|
83
85
|
datasets.map.with_index do |dataset, i|
|
84
86
|
{
|
85
87
|
id: i + 1,
|
86
|
-
dataset: Sqlite::Dataset.new(dataset)
|
88
|
+
dataset: Sqlite::Dataset.new(dataset),
|
89
|
+
table_name: @tests[i].table_name,
|
90
|
+
show_query: @tests[i].show_query?,
|
91
|
+
query: @tests[i].get_final_query
|
87
92
|
}
|
88
93
|
end
|
89
94
|
end
|
90
95
|
|
96
|
+
def parse_student_code(code)
|
97
|
+
code = code&.strip
|
98
|
+
fail! 'message.failure.semicolon_ending' unless code&.end_with? ';'
|
99
|
+
code
|
100
|
+
end
|
101
|
+
|
91
102
|
# This method receives a list of test cases and transforms each one according it parser
|
92
103
|
def parse_tests(tests)
|
93
|
-
@tests =
|
94
|
-
|
104
|
+
@tests = collect_tests(tests).map do |test|
|
105
|
+
parser = parsers[test.type.to_sym].new
|
106
|
+
parser.parse_test test
|
107
|
+
parser
|
95
108
|
end
|
96
|
-
|
109
|
+
end
|
110
|
+
|
111
|
+
def get_tests
|
112
|
+
@tests.map(&:test_result)
|
97
113
|
end
|
98
114
|
|
99
115
|
def get_final_query
|
100
|
-
|
101
|
-
tests.empty? ? '' : tests.first.get_final
|
116
|
+
@tests.map{ |t| t.get_final_query.to_s }.reject(&:empty?).join
|
102
117
|
end
|
103
118
|
|
104
119
|
# Initialize Metatest Framework with Checker & Runner
|
data/lib/validation_hook.rb
CHANGED
@@ -2,30 +2,31 @@ class SqliteValidationHook < Mumukit::Hook
|
|
2
2
|
|
3
3
|
include Sqlite::TestHelper
|
4
4
|
|
5
|
-
def initialize(config = nil)
|
6
|
-
super(config)
|
7
|
-
set_test_parsers_hash
|
8
|
-
end
|
9
|
-
|
10
5
|
def validate!(request)
|
11
6
|
lint_tests request.test
|
12
7
|
types_tests request.test
|
8
|
+
fields_of_test_types request.test
|
13
9
|
end
|
14
10
|
|
15
11
|
def lint_tests(tests)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
raise Mumukit::RequestValidationError, I18n.t('message.failure.tests.lint')
|
20
|
-
end
|
12
|
+
YAML.load tests
|
13
|
+
rescue
|
14
|
+
fail! 'message.failure.tests.lint'
|
21
15
|
end
|
22
16
|
|
23
17
|
def types_tests(tests)
|
24
|
-
# Assumes
|
25
|
-
|
26
|
-
|
27
|
-
|
18
|
+
# Assumes pass lint_tests
|
19
|
+
collect_tests(tests).each do |test|
|
20
|
+
fail! 'message.failure.tests.type' if test.type.blank?
|
21
|
+
fail!('message.failure.tests.types', type: test.type) unless parsers.has_key? test.type.to_sym
|
28
22
|
end
|
29
23
|
end
|
30
24
|
|
25
|
+
def fields_of_test_types(tests)
|
26
|
+
# Assumes pass types_tests
|
27
|
+
collect_tests(tests).each do |test|
|
28
|
+
parser = parsers[test.type.to_sym].new
|
29
|
+
fail! "message.failure.tests.fields.#{test.type}" unless parser.test_has_valid_fields? test
|
30
|
+
end
|
31
|
+
end
|
31
32
|
end
|
data/lib/version_hook.rb
CHANGED
@@ -1,29 +1,4 @@
|
|
1
1
|
<style>
|
2
|
-
table.sqlite_error {
|
3
|
-
width: auto;
|
4
|
-
}
|
5
|
-
table.sqlite_result {
|
6
|
-
border: none;
|
7
|
-
}
|
8
|
-
table.sqlite_solution {
|
9
|
-
border: none;
|
10
|
-
}
|
11
|
-
table.sqlite_error tr:nth-child(even) {
|
12
|
-
background-color: #EEEEEE;
|
13
|
-
}
|
14
|
-
table.sqlite_error tr:nth-child(odd) {
|
15
|
-
background-color: #FFFFFF;
|
16
|
-
}
|
17
|
-
table.sqlite_error th {
|
18
|
-
color: white;
|
19
|
-
font-weight: bold;
|
20
|
-
background-color: #2E2F30;
|
21
|
-
}
|
22
|
-
table.sqlite_error td {
|
23
|
-
width: auto;
|
24
|
-
text-align: left;
|
25
|
-
}
|
26
|
-
|
27
2
|
.required {
|
28
3
|
color: #5cb85c;
|
29
4
|
font-style: italic;
|
@@ -32,25 +7,6 @@
|
|
32
7
|
color: #d9534f;
|
33
8
|
font-style: italic;
|
34
9
|
}
|
35
|
-
|
36
|
-
.required :first-child,
|
37
|
-
.errored :first-child,
|
38
|
-
.nothing :first-child {
|
39
|
-
font-style: normal;
|
40
|
-
padding-left: 2px;
|
41
|
-
padding-right: 2px;
|
42
|
-
background-color: white;
|
43
|
-
border-left: none;
|
44
|
-
border-bottom: 1px solid white;
|
45
|
-
}
|
46
|
-
.required :first-child {
|
47
|
-
color: white;
|
48
|
-
background-color: #5cb85c;
|
49
|
-
}
|
50
|
-
.errored :first-child {
|
51
|
-
color: white;
|
52
|
-
background-color: #d9534f;
|
53
|
-
}
|
54
10
|
</style>
|
55
11
|
|
56
12
|
<h5><%= @error %></h5>
|
@@ -59,55 +15,61 @@
|
|
59
15
|
|
60
16
|
<!-- Result -->
|
61
17
|
<div class="col-md-6">
|
62
|
-
<h6
|
63
|
-
|
64
|
-
|
65
|
-
<
|
66
|
-
|
67
|
-
|
68
|
-
|
18
|
+
<h6><%= @expected_message %></h6>
|
19
|
+
|
20
|
+
<div class="mu-sql-table-rendered">
|
21
|
+
<header><%= @table_name %></header>
|
22
|
+
<table>
|
23
|
+
<thead>
|
24
|
+
<tr class="<%= @result[:header][:class] %>">
|
25
|
+
<th><%= @result[:header][:sign] %></th>
|
26
|
+
<% @result[:header][:fields].each do |field| %>
|
27
|
+
<th><%= field %></th>
|
28
|
+
<% end %>
|
29
|
+
</tr>
|
30
|
+
</thead>
|
31
|
+
<tbody>
|
32
|
+
<% @result[:rows].each do |row| %>
|
33
|
+
<tr class="<%= row[:class] %>">
|
34
|
+
<td><%= row[:sign] %></td>
|
35
|
+
<% row[:fields].each do |field| %>
|
36
|
+
<td><%= field %></td>
|
37
|
+
<% end %>
|
38
|
+
</tr>
|
69
39
|
<% end %>
|
70
|
-
|
71
|
-
</
|
40
|
+
</tbody>
|
41
|
+
</table>
|
42
|
+
</div>
|
43
|
+
|
72
44
|
|
73
|
-
<tbody>
|
74
|
-
<% @result[:rows].each do |row| %>
|
75
|
-
<tr class="<%= row[:class] %>">
|
76
|
-
<td><%= row[:sign] %></td>
|
77
|
-
<% row[:fields].each do |field| %>
|
78
|
-
<td><%= field %></td>
|
79
|
-
<% end %>
|
80
|
-
</tr>
|
81
|
-
<% end %>
|
82
|
-
</tbody>
|
83
|
-
</table>
|
84
45
|
</div>
|
85
46
|
|
86
47
|
<!-- Solution -->
|
87
48
|
<div class="col-md-6">
|
88
|
-
<h6
|
89
|
-
|
90
|
-
|
91
|
-
<
|
92
|
-
|
93
|
-
|
94
|
-
|
49
|
+
<h6><%= @obtained_message %></h6>
|
50
|
+
|
51
|
+
<div class="mu-sql-table-rendered">
|
52
|
+
<header><%= @table_name %></header>
|
53
|
+
<table>
|
54
|
+
<thead>
|
55
|
+
<tr class="<%= @result[:header][:class] %>">
|
56
|
+
<th><%= @result[:header][:sign] %></th>
|
57
|
+
<% @solution[:header][:fields].each do |field| %>
|
58
|
+
<th><%= field %></th>
|
59
|
+
<% end %>
|
60
|
+
</tr>
|
61
|
+
</thead>
|
62
|
+
<tbody>
|
63
|
+
<% @solution[:rows].each do |row| %>
|
64
|
+
<tr class="<%= row[:class] %>">
|
65
|
+
<td><%= row[:sign] %></td>
|
66
|
+
<% row[:fields].each do |field| %>
|
67
|
+
<td><%= field %></td>
|
68
|
+
<% end %>
|
69
|
+
</tr>
|
95
70
|
<% end %>
|
96
|
-
|
97
|
-
</
|
98
|
-
|
99
|
-
<tbody>
|
100
|
-
<% @solution[:rows].each do |row| %>
|
101
|
-
<tr class="<%= row[:class] %>">
|
102
|
-
<td><%= row[:sign] %></td>
|
103
|
-
<% row[:fields].each do |field| %>
|
104
|
-
<td><%= field %></td>
|
105
|
-
<% end %>
|
106
|
-
</tr>
|
107
|
-
<% end %>
|
108
|
-
</tbody>
|
109
|
-
</table>
|
71
|
+
</tbody>
|
72
|
+
</table>
|
73
|
+
</div>
|
110
74
|
</div>
|
111
75
|
</div>
|
112
|
-
|
113
|
-
|
@@ -1,42 +1,26 @@
|
|
1
|
-
<style>
|
2
|
-
table.sqlite_success {
|
3
|
-
width: auto;
|
4
|
-
border: none;
|
5
|
-
}
|
6
|
-
table.sqlite_success tr:nth-child(even) {
|
7
|
-
background-color: #DDDDDD;
|
8
|
-
}
|
9
|
-
table.sqlite_success tr:nth-child(odd) {
|
10
|
-
background-color: #FFFFFF;
|
11
|
-
}
|
12
|
-
table.sqlite_success th {
|
13
|
-
color: white;
|
14
|
-
font-weight: bold;
|
15
|
-
background-color: #BBBBBB;
|
16
|
-
}
|
17
|
-
table.sqlite_success td {
|
18
|
-
width: auto;
|
19
|
-
text-align: left;
|
20
|
-
}
|
21
|
-
</style>
|
22
|
-
|
23
1
|
<h5><%= message %></h5>
|
24
|
-
|
25
|
-
<
|
26
|
-
|
27
|
-
<% @header.each do |field| %>
|
28
|
-
<th><%= field %></th>
|
29
|
-
<% end %>
|
30
|
-
</tr>
|
31
|
-
</thead>
|
2
|
+
<% if @extra_message %>
|
3
|
+
<h6><%= @extra_message %></h6>
|
4
|
+
<% end %>
|
32
5
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
6
|
+
<div class="mu-sql-table-rendered">
|
7
|
+
<header><%= @table_name %></header>
|
8
|
+
<table>
|
9
|
+
<thead>
|
10
|
+
<tr>
|
11
|
+
<% @header.each do |field| %>
|
12
|
+
<th><%= field %></th>
|
38
13
|
<% end %>
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
14
|
+
</tr>
|
15
|
+
</thead>
|
16
|
+
<tbody>
|
17
|
+
<% @rows.each do |row| %>
|
18
|
+
<tr>
|
19
|
+
<% row.each do |field| %>
|
20
|
+
<td><%= field %></td>
|
21
|
+
<% end %>
|
22
|
+
</tr>
|
23
|
+
<% end %>
|
24
|
+
</tbody>
|
25
|
+
</table>
|
26
|
+
</div>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mumuki-sqlite-runner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leandro Di Lorenzo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mumukit
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '2.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '2.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -156,14 +156,14 @@ dependencies:
|
|
156
156
|
requirements:
|
157
157
|
- - "~>"
|
158
158
|
- !ruby/object:Gem::Version
|
159
|
-
version: '1
|
159
|
+
version: '3.1'
|
160
160
|
type: :development
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
|
-
version: '1
|
166
|
+
version: '3.1'
|
167
167
|
description:
|
168
168
|
email:
|
169
169
|
- leandro.jdl@gmail.com
|
@@ -177,15 +177,15 @@ files:
|
|
177
177
|
- lib/helpers.rb
|
178
178
|
- lib/html_renderer.rb
|
179
179
|
- lib/locales/en.yml
|
180
|
+
- lib/locales/es-CL.yml
|
180
181
|
- lib/locales/es.yml
|
181
182
|
- lib/metadata_hook.rb
|
182
183
|
- lib/multiple_executions_runner.rb
|
183
|
-
- lib/parsers/
|
184
|
-
- lib/parsers/
|
185
|
-
- lib/parsers/
|
186
|
-
- lib/parsers/
|
187
|
-
- lib/parsers/
|
188
|
-
- lib/parsers/query_test_parser.rb
|
184
|
+
- lib/parsers/base_parser.rb
|
185
|
+
- lib/parsers/datasets_parser.rb
|
186
|
+
- lib/parsers/display_parser.rb
|
187
|
+
- lib/parsers/final_dataset_parser.rb
|
188
|
+
- lib/parsers/query_parser.rb
|
189
189
|
- lib/sqlite_runner.rb
|
190
190
|
- lib/test_hook.rb
|
191
191
|
- lib/validation_hook.rb
|
@@ -211,8 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
211
211
|
- !ruby/object:Gem::Version
|
212
212
|
version: '0'
|
213
213
|
requirements: []
|
214
|
-
|
215
|
-
rubygems_version: 2.7.3
|
214
|
+
rubygems_version: 3.0.3
|
216
215
|
signing_key:
|
217
216
|
specification_version: 4
|
218
217
|
summary: SQLite Runner for Mumuki
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module Sqlite
|
2
|
-
module CommonTestParser
|
3
|
-
|
4
|
-
COMMENT = '-- NONE'
|
5
|
-
attr_reader :result, :final
|
6
|
-
required :parse, 'You need to implement parse method when use CommonTestParse mixin!'
|
7
|
-
|
8
|
-
def initialize(test)
|
9
|
-
@test = test
|
10
|
-
@result = parse test
|
11
|
-
end
|
12
|
-
|
13
|
-
def choose(solution)
|
14
|
-
solution
|
15
|
-
end
|
16
|
-
|
17
|
-
def has?(key)
|
18
|
-
!@test[key.to_sym].blank?
|
19
|
-
end
|
20
|
-
|
21
|
-
def get(key)
|
22
|
-
@test[key.to_sym]
|
23
|
-
end
|
24
|
-
|
25
|
-
def has_final?
|
26
|
-
# Only FinalDataset should have final query
|
27
|
-
false
|
28
|
-
end
|
29
|
-
|
30
|
-
def get_final
|
31
|
-
''
|
32
|
-
end
|
33
|
-
|
34
|
-
protected
|
35
|
-
|
36
|
-
def final_parse(test, override = {})
|
37
|
-
seed = test[:seed].blank? ? '' : test[:seed].strip
|
38
|
-
{
|
39
|
-
seed: override[:seed] || seed,
|
40
|
-
expected: override[:expected] || test[:expected].strip
|
41
|
-
}
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module Sqlite
|
2
|
-
class DatasetTestParser
|
3
|
-
|
4
|
-
include Sqlite::CommonTestParser
|
5
|
-
|
6
|
-
# test = {
|
7
|
-
# type: dataset,
|
8
|
-
# seed: INSERT INTO ...,
|
9
|
-
# expected: |
|
10
|
-
# id|field
|
11
|
-
# 1|row 1
|
12
|
-
# ...
|
13
|
-
# }
|
14
|
-
#
|
15
|
-
# return {
|
16
|
-
# seed: INSERT INTO ...,
|
17
|
-
# expected: -- NONE
|
18
|
-
# }
|
19
|
-
def parse(test)
|
20
|
-
@solutions = test[:expected].to_s.split("\n").map(&:strip).join("\n")
|
21
|
-
final_parse test, {expected: '-- NONE'}
|
22
|
-
end
|
23
|
-
|
24
|
-
def choose(_solution)
|
25
|
-
@solutions
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Sqlite
|
2
|
-
class DisplayTestParser
|
3
|
-
include Sqlite::CommonTestParser
|
4
|
-
|
5
|
-
def has_final?
|
6
|
-
has?(:query)
|
7
|
-
end
|
8
|
-
|
9
|
-
def get_final
|
10
|
-
# Assume has_final? is true
|
11
|
-
get(:query)
|
12
|
-
end
|
13
|
-
|
14
|
-
def parse(test)
|
15
|
-
final_parse test, { expected: get_final }
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module Sqlite
|
2
|
-
class QueryTestParser
|
3
|
-
|
4
|
-
include Sqlite::CommonTestParser
|
5
|
-
|
6
|
-
# test = {
|
7
|
-
# type: query,
|
8
|
-
# seed: INSERT INTO ...,
|
9
|
-
# expected: SELECT * FROM ...
|
10
|
-
# }
|
11
|
-
#
|
12
|
-
# return {
|
13
|
-
# seed: INSERT INTO ...,
|
14
|
-
# expected: SELECT * FROM ...
|
15
|
-
# }
|
16
|
-
def parse(test)
|
17
|
-
final_parse test
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|