Skip to content

Commit

Permalink
Test::Plan can compile/generate test code.
Browse files Browse the repository at this point in the history
  • Loading branch information
apotonick committed Feb 9, 2024
1 parent d80f37d commit 38346e8
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 26 deletions.
2 changes: 2 additions & 0 deletions lib/trailblazer/workflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ module Workflow
require "trailblazer/workflow/state/discovery"
require "trailblazer/workflow/state/discovery/testing"
require "trailblazer/workflow/state/table"

require "trailblazer/workflow/test/plan"
13 changes: 13 additions & 0 deletions lib/trailblazer/workflow/state/discovery.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ class State
#
# {states} are lane positions: [activity, suspend] tuples.
module Discovery
module_function

# FIXME: move me somewhere else!
# "Deserialize" a {Position} from a serialized tuple.
# Opposite of {#id_tuple_for}.
def position_from_tuple(lanes, lane_id, task_id)
lane_activity = lanes[lane_id]
task = Trailblazer::Activity::Introspect.Nodes(lane_activity, id: task_id).task

Collaboration::Position.new(lane_activity, task)
end


module Present
# Maintains the following fields
# start_position: where we started
Expand Down
31 changes: 22 additions & 9 deletions lib/trailblazer/workflow/state/discovery/testing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ module Workflow
class State
module Discovery
module Testing
module_function

# DISCUSS: In the Testing JSON, we want
# 1. start event, start configuration, input => expected suspend configuration
# 2. a "comment" table above that which draws out the same in readable format.
def self.render_structure(states, lanes:, additional_state_data:, task_map:)
def self.render_structure(states, lanes:, additional_state_data:, lane_icons:)
present_states = Trailblazer::Workflow::State::Discovery.generate_from(states) # returns rows with [{activity, suspend, resumes}]

# FIXME: we're actually going through events here, not states!
Expand Down Expand Up @@ -40,25 +42,35 @@ def self.render_structure(states, lanes:, additional_state_data:, task_map:)

serialized_start_configuration = serialized_start_configuration.compact # FIXME: what the hecke is this?

{
start_position: {
tuple: [activity_id, triggered_catch_event_id],
start_p___FIXME = {
tuple: start=[activity_id, triggered_catch_event_id],
comment: ["before", Discovery.find_next_task_label(start_position.activity, start_position.task)]
},
}

{
start_position: start_p___FIXME,
start_configuration: serialized_start_configuration,
expected_lane_positions: expected_lane_positions,

expected_outcome: additional_state_data[[state.state_from_discovery_fixme.object_id, :outcome]],
expected_outcome: expected_outcome= additional_state_data[[state.state_from_discovery_fixme.object_id, :outcome]],

event_label: default_event_label(start_p___FIXME, expected_outcome: expected_outcome, lane_icons: lane_icons)
}
end
end

def default_event_label(tuple, expected_outcome:, **options)
event_label = Discovery.readable_name_for_catch_event(tuple, **options)

event_label += " ⛞" if expected_outcome == :failure # FIXME: what happens to :symbol after serialization?

event_label
end

# Render the "test plan" in readable form.
def self.render_comment_header(structure, lane_icons:)
cli_rows = structure.collect do |testing_row| # row = :start_position, :start_configuration, :expected_lane_positions
triggered_catch_event_label = Discovery.readable_name_for_catch_event(testing_row[:start_position], lane_icons: lane_icons)

triggered_catch_event_label += " ⛞" if testing_row[:expected_outcome] == :failure # FIXME: what happens to :symbol after serialization?
triggered_catch_event_label = testing_row[:event_label]

start_configuration = testing_row[:start_configuration].collect do |lane_position|
Discovery.readable_name_for_resume_event(lane_position, tuple: true)
Expand Down Expand Up @@ -172,6 +184,7 @@ def self.readable_name_for_resume_event_or_terminus(position, lane_icons:, tuple
Discovery.readable_name_for_resume_event(position, lane_icons: lane_icons, tuple: tuple)
end


end # Testing
end
end
Expand Down
49 changes: 49 additions & 0 deletions lib/trailblazer/workflow/test/plan.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
module Trailblazer
module Workflow
module Test
module Plan
# Code fragment with assertions for the discovered/configured test plan.
def self.for(test_structure, input:)
code_string = test_structure.collect do |row|


# raise row[:start_configuration].inspect
start_position = row[:start_position]


%(
# test: #{row[:event_label]}
start_tuple = #{start_position[:tuple]} # #{start_position[:comment]}
start_position = Trailblazer::Workflow::State::Discovery.position_from_tuple(lanes, *start_tuple)
# current position.
#DISCUSS: here, we could also ask the State layer for the start configuration, on a different level.
lane_positions = [#{row[:start_configuration].collect do |row|
"Trailblazer::Workflow::State::Discovery.position_from_tuple(lanes, *#{row[:tuple].inspect})"
end.join(", ")}]
configuration, (ctx, flow) = Trailblazer::Workflow::Collaboration::Synchronous.advance(
schema,
[{seq: []}, {throw: []}],
{}, # circuit_options
start_position: start_position,
lane_positions: lane_positions, # current position/"state"
message_flow: message_flow,
)
# TODO: test {:last_lane}.
assert_equal configuration.lane_positions.keys, [lane_activity, lane_activity_ui]
assert_equal configuration.lane_positions.values.inspect, %([{"resumes"=>["catch-before-#{}"], :semantic=>[:suspend, "from initial_lane_positions"]}, \
#<Trailblazer::Workflow::Event::Suspend resumes=["catch-before-#{}"] type=:suspend semantic=[:suspend, "suspend-Gateway_14h0q7a"]>])
assert_equal ctx.inspect, %({:seq=>[:create_form]})
)
end
end
end

end # Test
end
end
57 changes: 55 additions & 2 deletions test/collaboration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -531,15 +531,17 @@ def render_states(states, lanes:, additional_state_data:, task_map:)
testing_structure = Trailblazer::Workflow::State::Discovery::Testing.render_structure(
states,
lanes: {lane_activity => "lifecycle", lane_activity_ui => "UI", approver_activity => "approver"},
task_map: task_map,
additional_state_data: additional_state_data,
lane_icons: lane_icons = {"UI" => "☝", "lifecycle" => "⛾", "approver" => "☑"},
)

testing_json = JSON.pretty_generate(testing_structure)
# File.write "test/discovery_testing_json.json", testing_json
assert_equal testing_json, File.read("test/discovery_testing_json.json")

testing_comment_header = Trailblazer::Workflow::State::Discovery::Testing.render_comment_header(testing_structure, lane_icons: {"UI" => "☝", "lifecycle" => "⛾", "approver" => "☑"})

# This rendering can be based on testing_structure from {states} because it always happens directly after a discovery run.
testing_comment_header = Trailblazer::Workflow::State::Discovery::Testing.render_comment_header(testing_structure, lane_icons: lane_icons)
puts testing_comment_header
assert_equal testing_comment_header,
%(+----------------------+--------------------------------------------------------------------------------+--------------------------------------------------------------------------------+
Expand All @@ -563,6 +565,57 @@ def render_states(states, lanes:, additional_state_data:, task_map:)
+----------------------+--------------------------------------------------------------------------------+--------------------------------------------------------------------------------+
15 rows in set)

# TODO: we should be parsing the testing_json into {testing_structure} and generate a test plan from it
# test_plan = Test::Plan.build(
# json: testing_json,
# input: {
# "▶Create form" => {params: {}}
# "▶Update ⛞" => {params: {posting: {title: ""}}}
# }
# output: { # this is what we expect
# "▶Update ⛞" => {"contract.default" => ->(*) { errors }}
# }
# )

puts Trailblazer::Workflow::Test::Plan.for( # TODO: this is the 2nd step after parsing {testing_json}.
testing_structure,

input: {
"▶Create form" => {params: {}},
"▶Update ⛞" => {params: {posting: {title: ""}}},
}
)


lanes = ___lanes___.invert

# test: ☝ ▶Revise

start_tuple = ["UI", "catch-before-Activity_1wiumzv"] # ["before", "Revise"]
start_position = Trailblazer::Workflow::State::Discovery.position_from_tuple(lanes, *start_tuple)

# current position.
#DISCUSS: here, we could also ask the State layer for the start configuration, on a different level.
lane_positions = [Trailblazer::Workflow::State::Discovery.position_from_tuple(lanes, *["lifecycle", "suspend-Gateway_01p7uj7"]), Trailblazer::Workflow::State::Discovery.position_from_tuple(lanes, *["UI", "suspend-Gateway_1xs96ik"])]

configuration, (ctx, flow) = Trailblazer::Workflow::Collaboration::Synchronous.advance(
schema,
[{seq: []}, {throw: []}],
{}, # circuit_options

start_position: start_position,
lane_positions: lane_positions, # current position/"state"

message_flow: message_flow,
)










initial_lane_positions = Trailblazer::Workflow::Collaboration::Synchronous.initial_lane_positions(schema_hash[:lanes].values)
Expand Down
45 changes: 30 additions & 15 deletions test/discovery_testing_json.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@
]
}
],
"expected_outcome": "success"
"expected_outcome": "success",
"event_label": "☝ ▶Create form"
},
{
"start_position": {
Expand Down Expand Up @@ -177,7 +178,8 @@
]
}
],
"expected_outcome": "success"
"expected_outcome": "success",
"event_label": "☝ ▶Create"
},
{
"start_position": {
Expand Down Expand Up @@ -266,7 +268,8 @@
]
}
],
"expected_outcome": "failure"
"expected_outcome": "failure",
"event_label": "☝ ▶Create ⛞"
},
{
"start_position": {
Expand Down Expand Up @@ -358,7 +361,8 @@
]
}
],
"expected_outcome": "success"
"expected_outcome": "success",
"event_label": "☝ ▶Update form"
},
{
"start_position": {
Expand Down Expand Up @@ -451,7 +455,8 @@
]
}
],
"expected_outcome": "success"
"expected_outcome": "success",
"event_label": "☝ ▶Notify approver"
},
{
"start_position": {
Expand Down Expand Up @@ -543,7 +548,8 @@
]
}
],
"expected_outcome": "success"
"expected_outcome": "success",
"event_label": "☝ ▶Update"
},
{
"start_position": {
Expand Down Expand Up @@ -632,7 +638,8 @@
]
}
],
"expected_outcome": "failure"
"expected_outcome": "failure",
"event_label": "☝ ▶Notify approver ⛞"
},
{
"start_position": {
Expand Down Expand Up @@ -714,7 +721,8 @@
]
}
],
"expected_outcome": "success"
"expected_outcome": "success",
"event_label": "☝ ▶Delete? form"
},
{
"start_position": {
Expand Down Expand Up @@ -793,7 +801,8 @@
]
}
],
"expected_outcome": "success"
"expected_outcome": "success",
"event_label": "☝ ▶Publish"
},
{
"start_position": {
Expand Down Expand Up @@ -884,7 +893,8 @@
]
}
],
"expected_outcome": "failure"
"expected_outcome": "failure",
"event_label": "☝ ▶Update ⛞"
},
{
"start_position": {
Expand Down Expand Up @@ -959,7 +969,8 @@
]
}
],
"expected_outcome": "success"
"expected_outcome": "success",
"event_label": "☝ ▶Revise form"
},
{
"start_position": {
Expand Down Expand Up @@ -1033,7 +1044,8 @@
]
}
],
"expected_outcome": "success"
"expected_outcome": "success",
"event_label": "☝ ▶Delete"
},
{
"start_position": {
Expand Down Expand Up @@ -1115,7 +1127,8 @@
]
}
],
"expected_outcome": "success"
"expected_outcome": "success",
"event_label": "☝ ▶Cancel"
},
{
"start_position": {
Expand Down Expand Up @@ -1186,7 +1199,8 @@
]
}
],
"expected_outcome": "success"
"expected_outcome": "success",
"event_label": "☝ ▶Archive"
},
{
"start_position": {
Expand Down Expand Up @@ -1263,6 +1277,7 @@
]
}
],
"expected_outcome": "success"
"expected_outcome": "success",
"event_label": "☝ ▶Revise"
}
]

0 comments on commit 38346e8

Please sign in to comment.