view_spec 0.0.0 → 0.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 +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +267 -24
- data/app/controllers/concerns/view_specs/preview_actions.rb +37 -0
- data/app/controllers/view_spec_previews_controller.rb +3 -0
- data/app/views/view_specs/_group.html.erb +56 -0
- data/app/views/view_specs/_scenario.html.erb +55 -0
- data/app/views/view_specs/_spec.html.erb +18 -0
- data/app/views/view_specs/group/_notes.html.erb +14 -0
- data/app/views/view_specs/group/_preview.html.erb +19 -0
- data/app/views/view_specs/group/_raw.html.erb +7 -0
- data/app/views/view_specs/group/_source.html.erb +7 -0
- data/app/views/view_specs/previews/index.html.erb +22 -0
- data/lib/view_spec/collection.rb +43 -0
- data/lib/view_spec/config.rb +26 -3
- data/lib/view_spec/context.rb +40 -0
- data/lib/view_spec/dsl/controller.rb +7 -2
- data/lib/view_spec/dsl/groups.rb +2 -2
- data/lib/view_spec/dsl/layout.rb +7 -1
- data/lib/view_spec/dsl/notes.rb +22 -0
- data/lib/view_spec/dsl/params.rb +25 -15
- data/lib/view_spec/dsl/preview.rb +25 -0
- data/lib/view_spec/dsl/scenarios.rb +6 -6
- data/lib/view_spec/dsl/tests.rb +18 -0
- data/lib/view_spec/dsl/title.rb +1 -1
- data/lib/view_spec/engine.rb +20 -1
- data/lib/view_spec/entry.rb +62 -0
- data/lib/view_spec/entry_collection.rb +11 -0
- data/lib/view_spec/error.rb +4 -0
- data/lib/view_spec/executable_proc.rb +32 -0
- data/lib/view_spec/executable_string.rb +23 -0
- data/lib/view_spec/group.rb +17 -13
- data/lib/view_spec/group_collection.rb +4 -0
- data/lib/view_spec/group_context.rb +10 -0
- data/lib/view_spec/group_preview.rb +52 -0
- data/lib/view_spec/markdown.rb +20 -0
- data/lib/view_spec/markdown_renderer.rb +13 -0
- data/lib/view_spec/minitest/tests.rb +27 -0
- data/lib/view_spec/note.rb +44 -0
- data/lib/view_spec/param.rb +12 -2
- data/lib/view_spec/param_set.rb +17 -11
- data/lib/view_spec/preview.rb +44 -0
- data/lib/view_spec/registry.rb +7 -23
- data/lib/view_spec/renderable.rb +8 -7
- data/lib/view_spec/scenario.rb +5 -49
- data/lib/view_spec/scenario_collection.rb +4 -0
- data/lib/view_spec/scenario_context.rb +11 -0
- data/lib/view_spec/scenario_preview.rb +30 -0
- data/lib/view_spec/source_file.rb +22 -0
- data/lib/view_spec/spec.rb +3 -13
- data/lib/view_spec/spec_collection.rb +7 -0
- data/lib/view_spec/spec_context.rb +11 -0
- data/lib/view_spec/test_case.rb +10 -0
- data/lib/view_spec/test_helpers.rb +23 -0
- data/lib/view_spec/types/symbol.rb +1 -1
- data/lib/view_spec/utils.rb +42 -1
- data/lib/view_spec/version.rb +1 -1
- data/lib/view_spec.rb +16 -2
- metadata +67 -15
- data/app/views/view_spec/_group.html.erb +0 -20
- data/app/views/view_spec/_scenario.html.erb +0 -17
- data/app/views/view_spec/_spec.html.erb +0 -10
- data/lib/view_spec/dsl/context.rb +0 -54
- data/lib/view_spec/dsl.rb +0 -18
data/lib/view_spec/config.rb
CHANGED
@@ -8,14 +8,33 @@ module ViewSpec
|
|
8
8
|
config.preview_controller.is_a?(String) ? config.preview_controller.constantize : config.preview_controller
|
9
9
|
end
|
10
10
|
|
11
|
+
def preview_controller_name
|
12
|
+
preview_controller = config.preview_controller.is_a?(Class) ? config.preview_controller.name : config.preview_controller
|
13
|
+
preview_controller.underscore.sub(/_controller$/, "")
|
14
|
+
end
|
15
|
+
|
11
16
|
class << self
|
12
17
|
def defaults
|
13
18
|
ActiveSupport::OrderedOptions.new.merge!({
|
14
|
-
spec_paths: ["#{Rails.root}/view_specs"],
|
19
|
+
spec_paths: ["#{Rails.root}/test/view_specs"],
|
15
20
|
spec_files: [],
|
16
21
|
spec_file_suffix: "_vspec",
|
17
|
-
|
18
|
-
|
22
|
+
|
23
|
+
preview_controller: "ViewSpecPreviewsController",
|
24
|
+
preview_layout: nil,
|
25
|
+
preview_route: "rails/view_spec/previews",
|
26
|
+
show_previews: Rails.env.development? || Rails.env.test?,
|
27
|
+
|
28
|
+
markdown_extensions: {
|
29
|
+
tables: true,
|
30
|
+
fenced_code_blocks: true,
|
31
|
+
disable_indented_code_blocks: true,
|
32
|
+
strikethrough: true,
|
33
|
+
highlight: true,
|
34
|
+
with_toc_data: true,
|
35
|
+
lax_spacing: true,
|
36
|
+
escape_html: false
|
37
|
+
}
|
19
38
|
})
|
20
39
|
end
|
21
40
|
end
|
@@ -25,5 +44,9 @@ module ViewSpec
|
|
25
44
|
def config
|
26
45
|
@config ||= self.class.defaults
|
27
46
|
end
|
47
|
+
|
48
|
+
def constantize(arg)
|
49
|
+
arg.is_a?(String) ? arg.constantize : arg
|
50
|
+
end
|
28
51
|
end
|
29
52
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ViewSpec
|
2
|
+
class Context
|
3
|
+
def initialize(entry, defaults = {})
|
4
|
+
@entry = entry
|
5
|
+
|
6
|
+
defaults.to_h.each do |key, value|
|
7
|
+
instance_variable_set(:"@#{key}", value) if respond_to?(key, true)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def entries
|
12
|
+
@entries ||= EntryCollection.new
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def cascading_values
|
18
|
+
self.class.cascading_attrs.map do |key|
|
19
|
+
value = send(key)
|
20
|
+
value = (value.is_a?(Hash) || value.is_a?(Array)) ? value.dup : value
|
21
|
+
[key, value]
|
22
|
+
end.to_h
|
23
|
+
end
|
24
|
+
|
25
|
+
def caller_lang(location, fallback = nil)
|
26
|
+
lineno = location&.lineno if location.present?
|
27
|
+
lineno ? @entry.source_file.lang_from_line(lineno, fallback) : fallback
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
def cascading_attr(name)
|
32
|
+
cascading_attrs << name.to_sym
|
33
|
+
end
|
34
|
+
|
35
|
+
def cascading_attrs
|
36
|
+
@cascading_attrs ||= []
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -4,12 +4,17 @@ module ViewSpec
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
|
7
|
+
cascading_attr :controller
|
8
8
|
end
|
9
9
|
|
10
10
|
def controller(value = nil)
|
11
11
|
@controller = value unless value.nil?
|
12
|
-
|
12
|
+
controller_class(@controller || ViewSpec.config.preview_controller)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def controller_class(controller)
|
13
18
|
controller.is_a?(String) ? controller.camelize.constantize : controller
|
14
19
|
end
|
15
20
|
end
|
data/lib/view_spec/dsl/groups.rb
CHANGED
@@ -4,11 +4,11 @@ module ViewSpec
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
def groups
|
7
|
-
entries.filter { _1.
|
7
|
+
GroupCollection.new(entries.filter { _1.type == :group }.to_a)
|
8
8
|
end
|
9
9
|
|
10
10
|
def group(name, &block)
|
11
|
-
entries << Group.new(name,
|
11
|
+
entries << Group.new(name, @entry, cascading_values, &block)
|
12
12
|
entries.last
|
13
13
|
end
|
14
14
|
end
|
data/lib/view_spec/dsl/layout.rb
CHANGED
@@ -4,13 +4,19 @@ module ViewSpec
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
|
7
|
+
cascading_attr :layout
|
8
8
|
end
|
9
9
|
|
10
10
|
def layout(value = nil)
|
11
11
|
@layout = value unless value.nil?
|
12
12
|
@layout ||= ViewSpec.config.preview_layout
|
13
13
|
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def determine_layout(value = false)
|
18
|
+
(value == true) ? layout : value
|
19
|
+
end
|
14
20
|
end
|
15
21
|
end
|
16
22
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ViewSpec
|
2
|
+
module DSL
|
3
|
+
module Notes
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def notes(str = nil)
|
7
|
+
if str.nil?
|
8
|
+
@notes
|
9
|
+
else
|
10
|
+
executable = ExecutableString.new(str, caller_lang(caller_locations(1..1)&.first, :md))
|
11
|
+
@notes = Note.new(@entry, executable)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def notes?
|
18
|
+
notes.present?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/view_spec/dsl/params.rb
CHANGED
@@ -3,34 +3,44 @@ module ViewSpec
|
|
3
3
|
module Params
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
+
included do
|
7
|
+
cascading_attr :params_data
|
8
|
+
end
|
9
|
+
|
6
10
|
def param(name, cast_type = nil, **options)
|
7
|
-
|
11
|
+
params_data[name] = ParamData.new(cast_type, options)
|
8
12
|
end
|
9
13
|
|
10
|
-
def
|
11
|
-
|
14
|
+
def params_data
|
15
|
+
@params_data ||= {}
|
12
16
|
end
|
13
17
|
|
18
|
+
private
|
19
|
+
|
14
20
|
def resolve_params(values_hash = {})
|
15
|
-
values_hash = values_hash.to_h.
|
16
|
-
|
21
|
+
values_hash = values_hash.to_h.deep_symbolize_keys
|
22
|
+
return values_hash unless params_data.is_a?(Hash)
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
24
|
+
param_set = ParamSet.new
|
25
|
+
params_data.each do |key, param|
|
26
|
+
value = values_hash[key]
|
27
|
+
param_set.add(key, param.cast_type, value:, **param.options)
|
21
28
|
end
|
22
29
|
|
23
|
-
other_params = values_hash.reject { param_set.include?(_1) }
|
24
|
-
param_set.add(other_params)
|
25
|
-
|
26
30
|
param_set
|
27
31
|
end
|
28
32
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
+
def validate_params(values_hash = {})
|
34
|
+
required = resolve_params(values_hash).reject { _2.default? }
|
35
|
+
missing_names = required.map(&:first).reject { values_hash.key?(_1) }
|
36
|
+
if missing_names.any?
|
37
|
+
raise "Missing #{"param".pluralize(missing_names.size)} value for #{missing_names.join(", ")}"
|
38
|
+
else
|
39
|
+
true
|
40
|
+
end
|
33
41
|
end
|
42
|
+
|
43
|
+
ParamData = Struct.new(:cast_type, :options)
|
34
44
|
end
|
35
45
|
end
|
36
46
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ViewSpec
|
2
|
+
module DSL
|
3
|
+
module Preview
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def preview(tpl = nil, &block)
|
7
|
+
return @preview if tpl.nil? && !block_given?
|
8
|
+
|
9
|
+
@preview = if block
|
10
|
+
ExecutableProc.new(block)
|
11
|
+
elsif tpl.is_a?(String)
|
12
|
+
ExecutableString.new(tpl, caller_lang(caller_locations(1..1)&.first, :erb))
|
13
|
+
else
|
14
|
+
raise "Invalid preview argument (must be string or block)"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def preview?
|
21
|
+
preview.present?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -2,19 +2,19 @@ module ViewSpec
|
|
2
2
|
module DSL
|
3
3
|
module Scenarios
|
4
4
|
extend ActiveSupport::Concern
|
5
|
-
|
6
|
-
|
7
|
-
entries.map do |entry|
|
5
|
+
def scenarios(flatten: false)
|
6
|
+
items = entries.map do |entry|
|
8
7
|
if entry.type == :scenario
|
9
8
|
entry
|
10
|
-
elsif
|
11
|
-
entry.scenarios
|
9
|
+
elsif flatten && entry.type == :group
|
10
|
+
entry.scenarios.to_a
|
12
11
|
end
|
13
12
|
end.compact.flatten
|
13
|
+
ScenarioCollection.new(items.to_a)
|
14
14
|
end
|
15
15
|
|
16
16
|
def scenario(name, &block)
|
17
|
-
entries << Scenario.new(name,
|
17
|
+
entries << Scenario.new(name, @entry, cascading_values, &block)
|
18
18
|
entries.last
|
19
19
|
end
|
20
20
|
end
|
data/lib/view_spec/dsl/title.rb
CHANGED
data/lib/view_spec/engine.rb
CHANGED
@@ -7,8 +7,27 @@ module ViewSpec
|
|
7
7
|
config.view_spec = ViewSpec.config
|
8
8
|
|
9
9
|
config.after_initialize do |app|
|
10
|
+
opts = app.config.view_spec
|
11
|
+
|
12
|
+
if opts.show_previews
|
13
|
+
app.routes.prepend do
|
14
|
+
get(
|
15
|
+
opts.preview_route,
|
16
|
+
to: "#{opts.preview_controller_name}#index",
|
17
|
+
as: :view_spec_previews,
|
18
|
+
internal: true
|
19
|
+
)
|
20
|
+
|
21
|
+
get(
|
22
|
+
"#{opts.preview_route}/*spec@:entry",
|
23
|
+
to: "#{opts.preview_controller_name}#preview",
|
24
|
+
as: :view_spec_preview,
|
25
|
+
internal: true
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
10
30
|
if !app.config.cache_classes
|
11
|
-
opts = config.view_spec
|
12
31
|
reloader = Reloader.new(opts.spec_files, opts.spec_paths) do
|
13
32
|
ViewSpec.load!
|
14
33
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module ViewSpec
|
2
|
+
class Entry
|
3
|
+
delegate :type, to: :class
|
4
|
+
|
5
|
+
def initialize(subject, parent, context_defaults = {}, &block)
|
6
|
+
@context_defaults = context_defaults.to_h
|
7
|
+
@subject = Subject.new(subject)
|
8
|
+
@parent = parent
|
9
|
+
|
10
|
+
context.instance_exec(&block) if block
|
11
|
+
end
|
12
|
+
|
13
|
+
def title
|
14
|
+
if context.respond_to?(:title)
|
15
|
+
context.title || @subject.to_title
|
16
|
+
else
|
17
|
+
@subject.to_title
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def short_identifier
|
22
|
+
@subject.to_short_identifier
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :name, :short_identifier
|
26
|
+
|
27
|
+
def spec
|
28
|
+
@parent ? @parent.spec : self
|
29
|
+
end
|
30
|
+
|
31
|
+
def source_file
|
32
|
+
spec.source_file
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_partial_path
|
36
|
+
"view_specs/#{type}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def respond_to_missing?(name, include_private = false)
|
40
|
+
context.respond_to?(name, true) || super
|
41
|
+
end
|
42
|
+
|
43
|
+
def method_missing(name, ...)
|
44
|
+
context.respond_to?(name, true) ? context.send(name, ...) : super
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def context
|
50
|
+
@context ||= begin
|
51
|
+
context_class = "#{self.class.name}Context".constantize
|
52
|
+
context_class.new(self, @context_defaults)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class << self
|
57
|
+
def type
|
58
|
+
@type ||= name.demodulize.underscore.to_sym
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/view_spec/error.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
module ViewSpec
|
2
|
+
class ExecutableProc
|
3
|
+
def initialize(proc)
|
4
|
+
@executable = proc
|
5
|
+
end
|
6
|
+
|
7
|
+
def source
|
8
|
+
CGI.unescapeHTML inner_source.strip_heredoc.strip
|
9
|
+
end
|
10
|
+
|
11
|
+
def lang
|
12
|
+
:ruby
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_proc
|
16
|
+
@executable
|
17
|
+
end
|
18
|
+
|
19
|
+
alias_method :raw, :to_proc
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def inner_source
|
24
|
+
source = @executable.source.strip_heredoc
|
25
|
+
if source.match?(/^(\w+)\s*\{/)
|
26
|
+
source.match(/^(\w+)\s*\{(.*)\}\s?$/m)[2]
|
27
|
+
elsif source.match?(/^(\w+)\s*do/)
|
28
|
+
source.match(/^(\w+)\s*do(.*)end\s?$/m)[2]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ViewSpec
|
2
|
+
class ExecutableString
|
3
|
+
attr_reader :lang
|
4
|
+
|
5
|
+
def initialize(str, lang = nil)
|
6
|
+
@str = str
|
7
|
+
@executable = lambda { render inline: str, type: lang || :erb }
|
8
|
+
@lang = lang
|
9
|
+
end
|
10
|
+
|
11
|
+
def source
|
12
|
+
CGI.unescapeHTML @str.strip_heredoc.strip
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_proc
|
16
|
+
@executable
|
17
|
+
end
|
18
|
+
|
19
|
+
def raw
|
20
|
+
@str
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/view_spec/group.rb
CHANGED
@@ -1,24 +1,28 @@
|
|
1
1
|
module ViewSpec
|
2
|
-
class Group <
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
include DSL::Controller
|
2
|
+
class Group < Entry
|
3
|
+
def preview(**options)
|
4
|
+
GroupPreview.new(self, **options)
|
5
|
+
end
|
7
6
|
|
8
|
-
def
|
9
|
-
|
7
|
+
def preview?
|
8
|
+
scenarios.any? { _1.preview? }
|
10
9
|
end
|
11
10
|
|
12
|
-
def
|
13
|
-
|
11
|
+
def notes
|
12
|
+
if context.notes.present? || scenarios.filter { _1.notes? }.any?
|
13
|
+
ViewSpec.config.preview_controller.render(
|
14
|
+
partial: "view_specs/group/notes",
|
15
|
+
locals: {group: self, notes: context.notes}
|
16
|
+
)
|
17
|
+
end
|
14
18
|
end
|
15
19
|
|
16
|
-
def
|
17
|
-
|
20
|
+
def notes?
|
21
|
+
notes.present?
|
18
22
|
end
|
19
23
|
|
20
|
-
def
|
21
|
-
|
24
|
+
def to_param
|
25
|
+
short_identifier
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module ViewSpec
|
2
|
+
class GroupPreview < Preview
|
3
|
+
PARTIAL_PATHS = {
|
4
|
+
raw: "view_specs/group/raw",
|
5
|
+
source: "view_specs/group/source",
|
6
|
+
preview: "view_specs/group/preview"
|
7
|
+
}
|
8
|
+
|
9
|
+
def initialize(entry, partial: nil, **options)
|
10
|
+
@partial = partial
|
11
|
+
super(entry, **options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(view_context = nil)
|
15
|
+
render_in_layout(:preview, view_context).html_safe
|
16
|
+
end
|
17
|
+
|
18
|
+
def raw(view_context = nil)
|
19
|
+
html = render_in_layout(:raw, view_context)
|
20
|
+
CGI.unescapeHTML(html)
|
21
|
+
end
|
22
|
+
|
23
|
+
def source(view_context = nil)
|
24
|
+
render_in_layout(:source, view_context)
|
25
|
+
end
|
26
|
+
|
27
|
+
def lang
|
28
|
+
@entry.scenarios&.first&.preview&.lang || :ruby
|
29
|
+
end
|
30
|
+
|
31
|
+
alias_method :to_s, :call
|
32
|
+
alias_method :to_str, :call
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
attr_reader :assigns
|
37
|
+
|
38
|
+
def partial_for_format(format)
|
39
|
+
@partial.nil? ? PARTIAL_PATHS[format.to_sym] : @partial
|
40
|
+
end
|
41
|
+
|
42
|
+
def render_in_layout(format, view_context = nil)
|
43
|
+
@_output ||= {}
|
44
|
+
@_output[format] ||= begin
|
45
|
+
partial = partial_for_format(format)
|
46
|
+
locals = {group: @entry, params:}
|
47
|
+
|
48
|
+
renderer.render(partial:, locals:, assigns:, layout:).strip
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ViewSpec
|
2
|
+
class Markdown
|
3
|
+
def initialize
|
4
|
+
renderer = ViewSpec::MarkdownRenderer.new
|
5
|
+
@markdown = Redcarpet::Markdown.new(renderer, extensions)
|
6
|
+
end
|
7
|
+
|
8
|
+
def render(text = nil, &block)
|
9
|
+
text ||= block&.call
|
10
|
+
|
11
|
+
@markdown.render(text).html_safe unless text.nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def extensions
|
17
|
+
ViewSpec.config.markdown_extensions || {}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ViewSpec
|
2
|
+
class MarkdownRenderer < Redcarpet::Render::HTML
|
3
|
+
HTML_ELEMENT_MATCHER = /^(<([a-z\-]+)(?:\s[^>]*)?>((?:(?!<\/([a-z\-]+)>).)*)<\/([a-z\-]+)>)$/m
|
4
|
+
|
5
|
+
def paragraph(content)
|
6
|
+
if HTML_ELEMENT_MATCHER.match?(content.strip)
|
7
|
+
content.html_safe
|
8
|
+
else
|
9
|
+
"<p>#{content}</p>".html_safe
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ViewSpec
|
2
|
+
module Minitest
|
3
|
+
module Tests
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
# Execute tests in a Minitest test context.
|
8
|
+
# Tests are grouped by spec and scenario using nested classes.
|
9
|
+
ViewSpec.specs.each do |spec|
|
10
|
+
scenarios = spec.scenarios(flatten: true).filter(&:tests?)
|
11
|
+
if scenarios.any?
|
12
|
+
class_options = {base_class: ViewSpec::TestCase}
|
13
|
+
Utils.create_class(spec.lookup_path, self, **class_options) do
|
14
|
+
scenarios.each do |scenario|
|
15
|
+
test_case_name = "#{scenario.short_identifier.camelize}Test"
|
16
|
+
test_case_class = Utils.create_class(test_case_name, self, **class_options) do
|
17
|
+
define_method(:scenario) { scenario }
|
18
|
+
end
|
19
|
+
test_case_class.instance_exec(&scenario.tests)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|