smartdown 0.11.1 → 0.11.2

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.
@@ -84,9 +84,9 @@ module Smartdown
84
84
  private
85
85
 
86
86
  def transform_node(node)
87
- if node.elements.any?{|element| element.is_a? Smartdown::Model::Element::StartButton}
87
+ if node.is_start_page_node?
88
88
  Smartdown::Api::Coversheet.new(node)
89
- elsif node.elements.any?{|element| element.is_a? Smartdown::Model::NextNodeRules}
89
+ elsif node.is_question_node?
90
90
  if node.elements.any?{|element| element.class.to_s.include?("Smartdown::Model::Element::Question")}
91
91
  Smartdown::Api::QuestionPage.new(node)
92
92
  else
@@ -27,12 +27,15 @@ module Smartdown
27
27
  end
28
28
 
29
29
  def post_body
30
- elements_after_smartdown = elements.drop_while{|element| !smartdown_element?(element)}
30
+ elements_after_smartdown = elements.select{ |element| !next_node_element?(element) }
31
+ .reverse
32
+ .take_while{|element| !smartdown_element?(element)}
33
+ .reverse
31
34
  build_govspeak(elements_after_smartdown)
32
35
  end
33
36
 
34
37
  def next_nodes
35
- elements.select{ |element| element.is_a? Smartdown::Model::NextNodeRules }
38
+ elements.select{ |element| next_node_element? element }
36
39
  end
37
40
 
38
41
  def permitted_next_nodes
@@ -45,12 +48,18 @@ module Smartdown
45
48
  (element.is_a? Smartdown::Model::Element::MarkdownParagraph) || (element.is_a? Smartdown::Model::Element::MarkdownHeading)
46
49
  end
47
50
 
51
+ def next_node_element?(element)
52
+ (element.is_a? Smartdown::Model::NextNodeRules)
53
+ end
54
+
48
55
  def smartdown_element?(element)
49
56
  !markdown_element?(element)
50
57
  end
51
58
 
52
59
  def build_govspeak(elements)
53
- elements.select { |element| markdown_element?(element) }.map(&:content).join("\n")
60
+ elements.select { |element| markdown_element?(element) }
61
+ return nil if elements.empty?
62
+ elements.map(&:content).join("\n")
54
63
  end
55
64
  end
56
65
  end
@@ -1,3 +1,7 @@
1
+ require 'parslet'
2
+ require 'smartdown/parser/node_transform'
3
+ require 'smartdown/parser/predicates'
4
+
1
5
  module Smartdown
2
6
  class Engine
3
7
  class Interpolator
@@ -24,28 +24,28 @@ module Smartdown
24
24
  {}.merge(@initial_state)
25
25
  end
26
26
 
27
- def process(raw_responses, test_start_state = nil)
28
- #TODO: change interface to match started, raw_responses like API state...no need for shifting etc...
29
- state = test_start_state || build_start_state
30
- unprocessed_responses = raw_responses
27
+ def process(unprocessed_responses, test_start_state = nil)
28
+ state = test_start_state || build_start_state
29
+
31
30
  while !unprocessed_responses.empty? do
32
31
  current_node = flow.node(state.get(:current_node))
33
-
32
+ break if current_node.is_outcome_page_node?
33
+
34
34
  if current_node.is_start_page_node?
35
35
  # If it's a start page node, we've got to do something different because of the preceeding 'y' answer
36
- transition = Transition.new(state, current_node, unprocessed_responses.shift(1))
36
+ answers = unprocessed_responses.shift(1)
37
37
  else
38
38
  answers = current_node.questions.map do |question|
39
39
  question.answer_type.new(unprocessed_responses.shift, question)
40
40
  end
41
-
42
- unless answers.all?(&:valid?)
41
+ if answers.any?(&:invalid?)
43
42
  state = state.put(:current_answers, answers)
44
43
  break
45
44
  end
46
- transition = Transition.new(state, current_node, answers)
47
45
  end
48
- state = transition.next_state
46
+
47
+ transition = Transition.new(state, current_node, answers)
48
+ state = transition.next_state
49
49
  end
50
50
  state
51
51
  end
@@ -43,6 +43,10 @@ module Smartdown
43
43
  @error.nil?
44
44
  end
45
45
 
46
+ def invalid?
47
+ !valid?
48
+ end
49
+
46
50
  private
47
51
  def parse_other_object(comparison_object)
48
52
  if comparison_object.is_a? Base
@@ -37,6 +37,14 @@ module Smartdown
37
37
  @is_start_page_node ||= !!start_button
38
38
  end
39
39
 
40
+ def is_question_node?
41
+ @is_question_node ||= elements.any?{|element| element.is_a? Smartdown::Model::NextNodeRules}
42
+ end
43
+
44
+ def is_outcome_page_node?
45
+ @is_outcome_page_node ||= !is_start_page_node? && !is_question_node?
46
+ end
47
+
40
48
  private
41
49
 
42
50
  def markdown_blocks_before_question
@@ -1,3 +1,3 @@
1
1
  module Smartdown
2
- VERSION = "0.11.1"
2
+ VERSION = "0.11.2"
3
3
  end
@@ -0,0 +1,148 @@
1
+ require 'smartdown/api/node'
2
+ require 'smartdown/api/question'
3
+ require 'smartdown/api/date_question'
4
+ require 'smartdown/model/node'
5
+ require 'smartdown/model/front_matter'
6
+ require 'smartdown/model/next_node_rules'
7
+ require 'smartdown/model/element/question/date'
8
+ require 'smartdown/model/element/markdown_heading'
9
+ require 'smartdown/model/element/markdown_paragraph'
10
+
11
+ describe Smartdown::Api::Node do
12
+
13
+ subject(:node) { Smartdown::Api::Node.new(node_model) }
14
+
15
+ let(:node_name) { "New Oxford Dictionary of English" }
16
+ let(:front_matter) { Smartdown::Model::FrontMatter.new({}) }
17
+ let(:node_model) { Smartdown::Model::Node.new(node_name, elements, front_matter) }
18
+
19
+ let(:next_node_rules_content) {
20
+ %{ Rule 1: Do not talk about Fight Club.
21
+ Rule 2: Do not talk about Fight Club.
22
+ Rule 3: If someone says "stop" or goes limp, taps out the fight is over.
23
+ Rule 4: Only two guys to a fight.
24
+ Rule 5: One fight at a time.
25
+ Rule 6: No shirts, no shoes.
26
+ Rule 7: Fights will go on as long as they have to.
27
+ Rule 8: If this is your first night at Fight Club, you have to fight.} }
28
+ let(:next_node_rules) { Smartdown::Model::NextNodeRules.new(next_node_rules_content) }
29
+
30
+ let(:question_element) {
31
+ Smartdown::Model::Element::Question::Date.new(name, *args)
32
+ }
33
+ let(:aliaz) { nil }
34
+ let(:args) { [start_year, end_year, aliaz] }
35
+ let(:name) { "a question" }
36
+ let(:start_year) { nil }
37
+ let(:end_year) { nil }
38
+
39
+ let(:node_heading_content) { "hehehe" }
40
+ let(:node_heading) { Smartdown::Model::Element::MarkdownHeading.new(node_heading_content) }
41
+
42
+ let(:question_heading_content) { "Do you feel lucky?" }
43
+ let(:question_heading) { Smartdown::Model::Element::MarkdownHeading.new(question_heading_content) }
44
+
45
+ let(:body_content) { "I <3 bodyshopping" }
46
+ let(:body_element) {
47
+ Smartdown::Model::Element::MarkdownParagraph.new(body_content)
48
+ }
49
+
50
+ let(:post_body_content) { "hur hur such content" }
51
+ let(:post_body_element) {
52
+ Smartdown::Model::Element::MarkdownParagraph.new(post_body_content)
53
+ }
54
+
55
+ let(:other_post_body_content) { "Postman Pat and his black and white cat" }
56
+ let(:other_post_body_element) {
57
+ Smartdown::Model::Element::MarkdownParagraph.new(other_post_body_content)
58
+ }
59
+
60
+
61
+ context "with a body and post_body (and next node rules)" do
62
+ let(:elements) { [node_heading, body_element, question_heading, question_element, post_body_element, other_post_body_element, next_node_rules] }
63
+
64
+ describe "#body" do
65
+ it 'returns the content before the question element' do
66
+ body = [body_content, question_heading_content].join("\n")
67
+ expect(node.body).to eq(body)
68
+ end
69
+ end
70
+
71
+ describe '#post_body' do
72
+ it 'returns the content after the question element' do
73
+ post_body = [post_body_content, other_post_body_content].join("\n")
74
+ expect(node.post_body).to eq(post_body)
75
+ end
76
+ end
77
+ end
78
+
79
+ context "missing a body" do
80
+ let(:elements) { [question_element, post_body_element] }
81
+
82
+ describe "#body" do
83
+ it 'returns nil' do
84
+ expect(node.body).to eq(nil)
85
+ end
86
+ end
87
+
88
+ describe '#post_body' do
89
+ it 'returns the content after the question element' do
90
+ expect(node.post_body).to eq(post_body_content)
91
+ end
92
+ end
93
+ end
94
+
95
+ context "missing a post body" do
96
+ let(:elements) { [node_heading, body_element, question_heading, question_element] }
97
+
98
+ describe "#body" do
99
+ it 'returns the content before the question element' do
100
+ body = [body_content, question_heading_content].join("\n")
101
+ expect(node.body).to eq(body)
102
+ end
103
+ end
104
+
105
+ describe '#post_body' do
106
+ it 'returns nil' do
107
+ expect(node.post_body).to eq(nil)
108
+ end
109
+ end
110
+ end
111
+
112
+ context "missing a body and post body" do
113
+ let(:elements) { [question_element] }
114
+
115
+ describe "#body" do
116
+ it 'returns nil' do
117
+ expect(node.body).to eq(nil)
118
+ end
119
+ end
120
+
121
+ describe '#post_body' do
122
+ it 'returns nil' do
123
+ expect(node.post_body).to eq(nil)
124
+ end
125
+ end
126
+ end
127
+
128
+ context "without next node rules" do
129
+ let(:elements) { [node_heading, question_heading, question_element] }
130
+
131
+ describe "#next_nodes" do
132
+ it 'returns an empty list' do
133
+ expect(node.next_nodes).to eq([])
134
+ end
135
+ end
136
+ end
137
+
138
+ context "with next node rules" do
139
+ let(:elements) { [node_heading, question_heading, question_element, next_node_rules] }
140
+
141
+ describe "#next_nodes" do
142
+ it 'returns the next node rules in a list' do
143
+ expect(node.next_nodes).to eq([next_node_rules])
144
+ end
145
+ end
146
+ end
147
+
148
+ end
@@ -0,0 +1,38 @@
1
+ require 'smartdown/api/outcome'
2
+ require 'smartdown/model/node'
3
+ require 'smartdown/model/front_matter'
4
+ require 'smartdown/model/element/next_steps'
5
+
6
+ describe Smartdown::Api::Outcome do
7
+
8
+ subject(:outcome) { Smartdown::Api::Outcome.new(node) }
9
+
10
+ let(:node_name) { 'node.js' }
11
+ let(:front_matter) { Smartdown::Model::FrontMatter.new({}) }
12
+ let(:node) { Smartdown::Model::Node.new(node_name, elements, front_matter) }
13
+
14
+ let(:next_steps_content) { "discontentment" }
15
+ let(:next_steps) { Smartdown::Model::Element::NextSteps.new(next_steps_content) }
16
+
17
+
18
+ context "with next steps" do
19
+ let(:elements) { [next_steps] }
20
+
21
+ describe "#next_steps" do
22
+ it "returns the content for next steps" do
23
+ expect(outcome.next_steps).to eq(next_steps_content)
24
+ end
25
+ end
26
+ end
27
+
28
+ context "without next steps" do
29
+ let(:elements) { [] }
30
+
31
+ describe "#next_steps" do
32
+ it "returns nil" do
33
+ expect(outcome.next_steps).to eq(nil)
34
+ end
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,99 @@
1
+ require 'smartdown/api/question'
2
+ require 'smartdown/api/date_question'
3
+ require 'smartdown/model/element/question/date'
4
+ require 'smartdown/model/element/markdown_heading'
5
+ require 'smartdown/model/element/markdown_paragraph'
6
+
7
+ describe Smartdown::Api::Question do
8
+
9
+ subject(:question) { Smartdown::Api::Question.new(elements) }
10
+
11
+ let(:question_element) {
12
+ Smartdown::Model::Element::Question::Date.new(name, *args)
13
+ }
14
+ let(:aliaz) { nil }
15
+ let(:args) { [start_year, end_year, aliaz] }
16
+ let(:name) { "a question" }
17
+ let(:start_year) { nil }
18
+ let(:end_year) { nil }
19
+
20
+ let(:heading_content) { "hehehe" }
21
+ let(:heading) { Smartdown::Model::Element::MarkdownHeading}
22
+
23
+ let(:body_content) { 'I <3 bodyshopping' }
24
+ let(:body_element) {
25
+ Smartdown::Model::Element::MarkdownParagraph.new(body_content)
26
+ }
27
+
28
+ let(:post_body_content) { 'hur hur such content' }
29
+ let(:post_body_element) {
30
+ Smartdown::Model::Element::MarkdownParagraph.new(post_body_content)
31
+ }
32
+
33
+
34
+
35
+ context "with a body and post_body" do
36
+ let(:elements) { [heading, body_element, question_element, post_body_element] }
37
+
38
+ describe "#body" do
39
+ it 'returns the content before the question element' do
40
+ expect(question.body).to eq(body_content)
41
+ end
42
+ end
43
+
44
+ describe '#post_body' do
45
+ it 'returns the content after the question element' do
46
+ expect(question.post_body).to eq(post_body_content)
47
+ end
48
+ end
49
+ end
50
+
51
+ context "missing a body" do
52
+ let(:elements) { [heading, question_element, post_body_element] }
53
+
54
+ describe "#body" do
55
+ it 'returns nil' do
56
+ expect(question.body).to eq(nil)
57
+ end
58
+ end
59
+
60
+ describe '#post_body' do
61
+ it 'returns the content after the question element' do
62
+ expect(question.post_body).to eq(post_body_content)
63
+ end
64
+ end
65
+ end
66
+
67
+ context "missing a post body" do
68
+ let(:elements) { [heading, body_element, question_element] }
69
+
70
+ describe "#body" do
71
+ it 'returns the content before the question element' do
72
+ expect(question.body).to eq(body_content)
73
+ end
74
+ end
75
+
76
+ describe '#post_body' do
77
+ it 'returns nil' do
78
+ expect(question.post_body).to eq(nil)
79
+ end
80
+ end
81
+ end
82
+
83
+ context "missing a body and post body" do
84
+ let(:elements) { [heading, question_element] }
85
+
86
+ describe "#body" do
87
+ it 'returns nil' do
88
+ expect(question.body).to eq(nil)
89
+ end
90
+ end
91
+
92
+ describe '#post_body' do
93
+ it 'returns nil' do
94
+ expect(question.post_body).to eq(nil)
95
+ end
96
+ end
97
+ end
98
+
99
+ end
data/spec/engine_spec.rb CHANGED
@@ -186,6 +186,13 @@ describe Smartdown::Engine do
186
186
  it "recorded input is accessiable via question alias" do
187
187
  expect(subject.get("passport_type?")).to eq("greek")
188
188
  end
189
+
190
+ context "extra answers passed" do
191
+ let(:responses) { %w{yes greek I wanna be the very best like no one ever was} }
192
+ it "return current_node as outcome and ignores extra responses" do
193
+ expect(subject.get(:current_node)).to eq("outcome_no_visa_needed")
194
+ end
195
+ end
189
196
  end
190
197
 
191
198
  context "USA passport" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smartdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.1
4
+ version: 0.11.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-12-02 00:00:00.000000000 Z
12
+ date: 2014-12-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: parslet
16
- requirement: &10521380 !ruby/object:Gem::Requirement
16
+ requirement: &22904640 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.6.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *10521380
24
+ version_requirements: *22904640
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &10520820 !ruby/object:Gem::Requirement
27
+ requirement: &22903900 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 3.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *10520820
35
+ version_requirements: *22903900
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &10520420 !ruby/object:Gem::Requirement
38
+ requirement: &22903440 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,21 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *10520420
46
+ version_requirements: *22903440
47
+ - !ruby/object:Gem::Dependency
48
+ name: pry
49
+ requirement: &22902800 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *22902800
47
58
  - !ruby/object:Gem::Dependency
48
59
  name: gem_publisher
49
- requirement: &10519900 !ruby/object:Gem::Requirement
60
+ requirement: &22902180 !ruby/object:Gem::Requirement
50
61
  none: false
51
62
  requirements:
52
63
  - - ! '>='
@@ -54,10 +65,10 @@ dependencies:
54
65
  version: '0'
55
66
  type: :development
56
67
  prerelease: false
57
- version_requirements: *10519900
68
+ version_requirements: *22902180
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: timecop
60
- requirement: &10519480 !ruby/object:Gem::Requirement
71
+ requirement: &22901520 !ruby/object:Gem::Requirement
61
72
  none: false
62
73
  requirements:
63
74
  - - ! '>='
@@ -65,7 +76,7 @@ dependencies:
65
76
  version: '0'
66
77
  type: :development
67
78
  prerelease: false
68
- version_requirements: *10519480
79
+ version_requirements: *22901520
69
80
  description:
70
81
  email: david.heath@digital.cabinet-office.gov.uk
71
82
  executables:
@@ -188,7 +199,10 @@ files:
188
199
  - spec/parser/snippet_pre_parser_spec.rb
189
200
  - spec/support/flow_input_interface.rb
190
201
  - spec/support/model_builder.rb
202
+ - spec/api/outcome_spec.rb
191
203
  - spec/api/state_spec.rb
204
+ - spec/api/node_spec.rb
205
+ - spec/api/question_spec.rb
192
206
  - spec/api/date_question_spec.rb
193
207
  - spec/api/previous_question_spec.rb
194
208
  - spec/spec_helper.rb
@@ -269,7 +283,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
269
283
  version: '0'
270
284
  segments:
271
285
  - 0
272
- hash: -3693296040115547194
286
+ hash: 3333648473832850396
273
287
  required_rubygems_version: !ruby/object:Gem::Requirement
274
288
  none: false
275
289
  requirements:
@@ -278,7 +292,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
278
292
  version: '0'
279
293
  segments:
280
294
  - 0
281
- hash: -3693296040115547194
295
+ hash: 3333648473832850396
282
296
  requirements: []
283
297
  rubyforge_project:
284
298
  rubygems_version: 1.8.11
@@ -311,7 +325,10 @@ test_files:
311
325
  - spec/parser/snippet_pre_parser_spec.rb
312
326
  - spec/support/flow_input_interface.rb
313
327
  - spec/support/model_builder.rb
328
+ - spec/api/outcome_spec.rb
314
329
  - spec/api/state_spec.rb
330
+ - spec/api/node_spec.rb
331
+ - spec/api/question_spec.rb
315
332
  - spec/api/date_question_spec.rb
316
333
  - spec/api/previous_question_spec.rb
317
334
  - spec/spec_helper.rb