flok 0.0.100 → 0.0.101

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/app/drivers/chrome/README.md +6 -0
  3. data/app/drivers/chrome/Rakefile +1 -0
  4. data/app/drivers/chrome/build_context.rb +1 -0
  5. data/app/drivers/chrome/config.yml +4 -0
  6. data/app/drivers/chrome/spec/spec/dlink_spec.js +15 -0
  7. data/app/drivers/chrome/spec/spec/hook_spec.js +24 -0
  8. data/app/drivers/chrome/src/dlink.js +28 -0
  9. data/app/drivers/chrome/src/hook.js +29 -0
  10. data/app/kern/mod/dlink.js +16 -0
  11. data/app/kern/mod/event.js +7 -0
  12. data/app/kern/mod/hook.js +1 -0
  13. data/app/kern/services/dlink.rb +25 -0
  14. data/bin/flok +12 -3
  15. data/docs/compilation.md +1 -1
  16. data/docs/kernel_api.md +1 -1
  17. data/docs/kernel_handbook/hooks.md +4 -0
  18. data/docs/mod/dlink.md +18 -0
  19. data/docs/mod/hook.md +9 -0
  20. data/docs/project.md +3 -2
  21. data/docs/services/dlink.md +8 -0
  22. data/docs/user_handbook/hooks.md +106 -0
  23. data/lib/flok.rb +1 -0
  24. data/lib/flok/hooks_compiler.rb +174 -0
  25. data/lib/flok/project_template/config/hooks.rb +1 -0
  26. data/lib/flok/user_compiler.rb +56 -6
  27. data/lib/flok/user_compiler_templates/ctable.js.erb +4 -0
  28. data/lib/flok/user_hook_generators/goto.rb +74 -0
  29. data/lib/flok/user_hook_generators/helpers.rb +46 -0
  30. data/lib/flok/version.rb +1 -1
  31. data/spec/env/kern.rb +32 -16
  32. data/spec/etc/transition_complier_spec.rb +4 -0
  33. data/spec/iface/driver/hook_spec.rb +33 -0
  34. data/spec/iface/kern/dlink_spec.rb +25 -0
  35. data/spec/kern/assets/dlink_service/config0.rb +2 -0
  36. data/spec/kern/assets/dlink_service/controller0.rb +16 -0
  37. data/spec/kern/assets/hook_entry_points/controller0.rb +58 -0
  38. data/spec/kern/assets/hook_entry_points/controller0a.rb +27 -0
  39. data/spec/kern/dlink_service_spec.rb +50 -0
  40. data/spec/kern/hook_entry_points_and_manifest_spec.rb +155 -0
  41. data/spec/kern/hook_user_generators_spec.rb +139 -0
  42. metadata +36 -3
  43. data/docs/mod/intercept.md +0 -26
@@ -22,6 +22,10 @@ RSpec.describe "Transition compiler" do
22
22
  end
23
23
  end
24
24
 
25
+ it "Can insert a hook into ${controller_name}_will_goto and this hook is invoked" do
26
+
27
+ end
28
+
25
29
  it "Can load the ruby module" do
26
30
  compiler = Flok::TransitionCompiler
27
31
  end
@@ -0,0 +1,33 @@
1
+ Dir.chdir File.join File.dirname(__FILE__), '../../../'
2
+ require './spec/env/iface.rb'
3
+ require './spec/lib/helpers.rb'
4
+ require './spec/lib/io_extensions.rb'
5
+ require './spec/lib/rspec_extensions.rb'
6
+
7
+ RSpec.describe "iface:driver:hook" do
8
+ module_dep "hook"
9
+ include_context "iface:driver"
10
+
11
+ it "Can receive a hook event request with parameters" do
12
+ @ptr = SecureRandom.hex
13
+
14
+ #Simulate a hook event on the main queue
15
+ @pipe.puts [[0, 3, "if_hook_event", "test", {foo: "bar"}]].to_json
16
+
17
+ #Wait for response
18
+ @pipe.puts [[0, 0, "ping"]].to_json; @pipe.readline_timeout
19
+
20
+ #Get the value of the received event
21
+ @pipe.puts [[0, 1, "if_hook_spec_dump_rcvd_events"]].to_json
22
+
23
+ json = [
24
+ 1,
25
+ "if_hook_spec_dump_rcvd_events_res",
26
+ [{
27
+ "name" => "test",
28
+ "info" => {"foo" => "bar"}
29
+ }]
30
+ ]
31
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(json, 5.seconds)
32
+ end
33
+ end
@@ -0,0 +1,25 @@
1
+ Dir.chdir File.join File.dirname(__FILE__), '../../../'
2
+ require './spec/env/iface.rb'
3
+ require './spec/lib/helpers.rb'
4
+ require './spec/lib/io_extensions.rb'
5
+ require './spec/lib/rspec_extensions.rb'
6
+
7
+ RSpec.describe "iface:kern:net" do
8
+ module_dep "net"
9
+ include_context "iface:kern"
10
+
11
+ #A callback was registered in the kernel for testing purposes
12
+ it "A mock URL notify does receive the correct information" do
13
+ #Wait for response
14
+ @pipe.puts [0, "ping"].to_json; @pipe.readline_timeout
15
+
16
+ @pipe.puts [2, "int_dlink_notify", "http://test.com/foo", {"foo" => "bar"}].to_json
17
+ @pipe.puts [0, "get_int_dlink_spec"].to_json
18
+
19
+ res = [
20
+ [0, 1, "get_int_dlink_spec", ["http://test.com/foo", {"foo"=>"bar"}]]
21
+ ]
22
+
23
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
24
+ end
25
+ end
@@ -0,0 +1,2 @@
1
+ #Simple service config that uses built-in spec service to create a instance called 'spec'
2
+ service_instance :dlink, :dlink
@@ -0,0 +1,16 @@
1
+ controller :my_controller do
2
+ services :dlink
3
+
4
+ on_entry %{
5
+ dlink_res_params = null;
6
+ }
7
+
8
+ action :my_action do
9
+ on_entry %{
10
+ }
11
+
12
+ on "dlink_req", %{
13
+ dlink_res_params = params;
14
+ }
15
+ end
16
+ end
@@ -0,0 +1,58 @@
1
+ controller :my_controller do
2
+ spots "hello", "world"
3
+
4
+ macro :my_macro do
5
+ on "foo", %{
6
+ }
7
+
8
+ end
9
+
10
+ action :index do
11
+ on_entry %{
12
+ on_entry_base_pointer = __base__;
13
+ Embed("my_other_controller", "hello", {});
14
+ }
15
+
16
+ on "hello", %{
17
+ var x = 3;
18
+ }
19
+
20
+ my_macro
21
+ end
22
+
23
+ action :other do
24
+ on "test", %{
25
+ }
26
+ end
27
+ end
28
+
29
+ controller :my_other_controller do
30
+ action :index do
31
+ on_entry %{
32
+ my_other_controller_base = __base__;
33
+ }
34
+
35
+ on "back_clicked", %{
36
+ Goto("other");
37
+ }
38
+ end
39
+
40
+ action :other do
41
+ on "next_clicked", %{
42
+ Goto("other2");
43
+ }
44
+ end
45
+
46
+ action :other2 do
47
+ on "next_clicked", %{
48
+ Goto("has_back_also");
49
+ }
50
+ end
51
+
52
+
53
+ action :has_back_also do
54
+ on "back_clicked", %{
55
+ Goto("other");
56
+ }
57
+ end
58
+ end
@@ -0,0 +1,27 @@
1
+ controller :my_controller do
2
+ spots "hello", "world"
3
+
4
+ macro :my_macro do
5
+ on "foo", %{
6
+ }
7
+
8
+ end
9
+
10
+ action :index do
11
+ on_entry %{
12
+ on_entry_base_pointer = __base__;
13
+ }
14
+
15
+ on "hello", %{
16
+ var x = 3;
17
+ }
18
+
19
+ my_macro
20
+ end
21
+
22
+ action :other do
23
+ on "test", %{
24
+ Goto("index");
25
+ }
26
+ end
27
+ end
@@ -0,0 +1,50 @@
1
+ #The dlink service
2
+
3
+ Dir.chdir File.join File.dirname(__FILE__), '../../'
4
+ require './spec/env/kern.rb'
5
+ require './spec/lib/helpers.rb'
6
+ require './spec/lib/io_extensions.rb'
7
+ require './spec/lib/rspec_extensions.rb'
8
+ require 'zlib'
9
+
10
+ RSpec.describe "kern:dlink_service" do
11
+ include Zlib
12
+ include_context "kern"
13
+
14
+ it "Can use dlink service" do
15
+ ctx = flok_new_user File.read('./spec/kern/assets/dlink_service/controller0.rb'), File.read("./spec/kern/assets/dlink_service/config0.rb")
16
+ dump = ctx.evald %{
17
+ base = _embed("my_controller", 0, {}, null);
18
+
19
+ //Drain queue
20
+ int_dispatch([]);
21
+ }
22
+ end
23
+
24
+ it "Does send the controller the dlink_req when a dlink interrupt is sent" do
25
+ ctx = flok_new_user File.read('./spec/kern/assets/dlink_service/controller0.rb'), File.read("./spec/kern/assets/dlink_service/config0.rb")
26
+ dump = ctx.evald %{
27
+ dump.base = _embed("my_controller", 0, {}, null);
28
+
29
+ //Drain queue
30
+ int_dispatch([]);
31
+ }
32
+
33
+ @driver.int "int_dlink_notify", [
34
+ "http://google.com/test", {"foo" => "bar"}
35
+ ]
36
+
37
+ #Should not exist yet because of defered event
38
+ dump = ctx.evald %{ dump.dlink_res_params = dlink_res_params; }
39
+ expect(dump["dlink_res_params"]).to eq(nil)
40
+
41
+ #Drain the defered queue and check again
42
+ ctx.eval %{ for (var i = 0; i < 100; ++i) { int_dispatch([]); } }
43
+ dump = ctx.evald %{ dump.dlink_res_params = dlink_res_params; }
44
+
45
+ expect(dump["dlink_res_params"]).to eq({
46
+ "url" => "http://google.com/test",
47
+ "params" => {"foo" => "bar"}
48
+ })
49
+ end
50
+ end
@@ -0,0 +1,155 @@
1
+ #Tests to make sure the hook entry points act as the are defined in hooks.md
2
+ #and that the HookCompiler is able to correctly intercept them. Additionally,
3
+ #there are some tests here to verify the operation of the hooks compiler it's-self
4
+ #but the user-generated DSL related tests are in hook_user_generators_spec.rb
5
+
6
+ Dir.chdir File.join File.dirname(__FILE__), '../../'
7
+ require './spec/env/kern.rb'
8
+ require './spec/lib/helpers.rb'
9
+ require './spec/lib/io_extensions.rb'
10
+ require './spec/lib/rspec_extensions.rb'
11
+ require './lib/flok/hooks_compiler.rb'
12
+ require 'zlib'
13
+
14
+ RSpec.describe "kern:hook_entry_points" do
15
+ include Zlib
16
+ include_context "kern"
17
+
18
+ it "Can use the HooksManifest & HooksManifestEntry to properly select and insert code into a hooks compatible javascript file" do
19
+ #Since we are only looking at the HooksManifest & HooksManifestEntry, this dosen't necessarily need to be
20
+ #flok compatible things as only the compiler itself holds flok code. In this case, we are going to be replacing
21
+ #some of the hook entries with code that will insert into the order array. Any problems with identifying the correct
22
+ #hook entries will result in the order array being incorrect
23
+ src = <<eof
24
+ //HOOK_ENTRY[first] {}
25
+ //HOOK_ENTRY[foo] {"foos": ["a", "b", "c"]}
26
+ //HOOK_ENTRY[bar] {"name": "los"}
27
+ //HOOK_ENTRY[world] {"name": "los"}
28
+ //HOOK_ENTRY[test] {"name": "los"}
29
+ //HOOK_ENTRY[test2] {"name": "los2"}
30
+ //HOOK_ENTRY[hello] {"foos": ["a"]}
31
+ //HOOK_ENTRY[foo4] {"foos": ["a", "b", "c"]}
32
+ //HOOK_ENTRY[foo6] {"world": ["a", "b", "c"], "test": ["bar"]}
33
+ //HOOK_ENTRY[foo5] {}
34
+ //HOOK_ENTRY[foo6] {"world": ["a", "b", "c"]}
35
+ eof
36
+
37
+ #Create a new manifest which we will add all of our entries to
38
+ manifest = Flok::HooksManifest.new
39
+
40
+ ################################################################################
41
+ #Now we add some manifest entries to help process the above source
42
+ ################################################################################
43
+
44
+ manifest << Flok::HooksManifestEntry.new("first") {|params| next "1st"} #HOOK_ENTRY[first]
45
+ manifest << Flok::HooksManifestEntry.new("*", ->(p){p["foos"] and p["foos"].include? "b"}) {|params| next "2nd"} #'foos' containing 'b'
46
+ manifest << Flok::HooksManifestEntry.new("*", ->(p){p["name"] == "los" }) {|params| next "3rd"} #'name' == 'los'
47
+ manifest << Flok::HooksManifestEntry.new("test2", ->(p){p["name"] == "los2"}) {|params| next "4th"} #HOOK_ENTRY[test2] where 'name' == 'los'
48
+ manifest << Flok::HooksManifestEntry.new("*", ->(p){p["foos"] and p["foos"].include? "a"}) {|params| next "5th"} #'foos' containing 'a'
49
+ manifest << Flok::HooksManifestEntry.new("*", [->(p){p["world"] and p["world"].include? "a"}, ->(p){p["test"] and p["test"].include? "bar"}]) {|params| next "6th"} #'world' contains 'a' && 'test' contains 'bar'
50
+
51
+ #Process the src line-by-line with the manifesct
52
+ output_src = src.split("\n").map{|e| manifest.transform_line(e)}
53
+
54
+ expect(output_src.join("\n") + "\n").to eq(<<eof
55
+ 1st
56
+ 2nd
57
+ 5th
58
+ 3rd
59
+ 3rd
60
+ 3rd
61
+ 4th
62
+ 5th
63
+ 2nd
64
+ 5th
65
+ 6th
66
+ //HOOK_ENTRY[foo5] {}
67
+ //HOOK_ENTRY[foo6] {"world": ["a", "b", "c"]}
68
+ eof
69
+ )
70
+ end
71
+
72
+ it "Can use the HooksManifest & HooksManifestEntry to properly retrieve the correct set of parameters in the code block" do
73
+ #Here we are not testing the actual selection of proper hooks, but checking that once we have a selection
74
+ #does the code generator block get the correct static parameters? Specific parameters are tested in seperate
75
+ #tests for each hook
76
+ src = <<eof
77
+ //HOOK_ENTRY[foo] {"foos": ["a", "b", "c"], "hello": "world"}
78
+ eof
79
+
80
+ #Create a new manifest which we will add all of our entries to
81
+ manifest = Flok::HooksManifest.new
82
+
83
+ #Now we add our manifest entry that we will check parameters on
84
+ did_get = false
85
+ manifest << Flok::HooksManifestEntry.new("foo") do |params|
86
+ did_get = true
87
+ expect(params.to_json).to eq({"foos" => ["a", "b", "c"], "hello" => "world"}.to_json)
88
+ end
89
+
90
+ #Process the src line-by-line with the manifesct
91
+ output_src = src.split("\n").map{|e| manifest.transform_line(e)}
92
+
93
+ #Make sure we actually triggered on the entry
94
+ expect(did_get).to eq(true)
95
+ end
96
+
97
+ it "Can hook the controller_will_goto event with the correct hook entry information and has the variables mentioned in the docs" do
98
+ info = flok_new_user_with_src File.read('./spec/kern/assets/hook_entry_points/controller0a.rb')
99
+ src = info[:src]
100
+ ctx = info[:ctx]
101
+
102
+ manifest = Flok::HooksManifest.new
103
+ will_gotos_found = 0
104
+ from_to_action_pairs_found = []
105
+ entry = Flok::HooksManifestEntry.new("controller_will_goto") do |hook_info|
106
+ will_gotos_found += 1
107
+ #Static parameters
108
+ expect(hook_info["controller_name"]).to eq("my_controller")
109
+ expect(hook_info["might_respond_to"].to_set).to eq(["foo", "hello", "test"].to_set)
110
+ from_to_action_pairs_found << {hook_info["from_action"] => hook_info["to_action"]}
111
+
112
+ #actions_responds_to looks like {"action1" => ["event_a", ..."], "action2" => }...
113
+ #where each action list contains all the events this action responds to
114
+ expect(hook_info["actions_responds_to"]).to eq({"index" => ["hello", "foo"], "other" => ["test"]})
115
+
116
+ #Variables included
117
+ next %{
118
+ entry_params = {
119
+ old_action: old_action,
120
+ new_action: __info__.action,
121
+ };
122
+ }
123
+ end
124
+ manifest << entry
125
+
126
+ #Recompile source (We do this manually as we supplied no `config/hooks.rb` file)
127
+ src = Flok::HooksCompiler.compile src, manifest
128
+
129
+ #Expect to have found two will_goto entries given that there is one Goto request
130
+ #and one implicit Goto from the entry
131
+ expect(will_gotos_found).to eq(2)
132
+
133
+ #Expect to have gotten all the goto to/from action pairs
134
+ expect(from_to_action_pairs_found.to_set).to eq([{"other" => "index"}, {"choose_action" => "index"}].to_set)
135
+
136
+ #Re-evaluate the v8 instance
137
+ ctx = v8_flok
138
+ ctx.eval src
139
+
140
+ #Now load the controller
141
+ dump = ctx.evald %{
142
+ base = _embed("my_controller", 0, {}, null);
143
+
144
+ //Drain queue
145
+ int_dispatch([]);
146
+
147
+ dump.entry_params = entry_params;
148
+ }
149
+
150
+ #Verify the parametrs were set
151
+ expect(dump["entry_params"]).not_to eq(nil)
152
+ expect(dump["entry_params"]["old_action"]).to eq("choose_action")
153
+ expect(dump["entry_params"]["new_action"]).to eq("index")
154
+ end
155
+ end
@@ -0,0 +1,139 @@
1
+ #Relating to the conversion of the user's ./config/hooks.rb file into the equivalent HooksManifestEntrie(s) (This may cross-over into
2
+ #the HooksCompiler itself because we need to test side-effects)
3
+
4
+ Dir.chdir File.join File.dirname(__FILE__), '../../'
5
+ require './spec/env/kern.rb'
6
+ require './spec/lib/helpers.rb'
7
+ require './spec/lib/io_extensions.rb'
8
+ require './spec/lib/rspec_extensions.rb'
9
+ require './lib/flok/hooks_compiler.rb'
10
+ require 'zlib'
11
+
12
+ RSpec.describe "kern:hook_user_geenrators_spec" do
13
+ include Zlib
14
+ include_context "kern"
15
+
16
+ it "Can use the :goto hook generator for all controllers (no matchers)" do
17
+ hooks_src = %{
18
+ hook :goto => :goto do
19
+ #Select all
20
+ end
21
+ }
22
+
23
+ #Just expect this not to blow up
24
+ info = flok_new_user_with_src File.read('./spec/kern/assets/hook_entry_points/controller0.rb'), nil, nil, hooks_src
25
+ ctx = info[:ctx]
26
+
27
+ #Run the embed function
28
+ ctx.evald %{
29
+ dump.base = _embed("my_controller", 0, {}, null); // Embed the controller
30
+ int_dispatch([]); // Dispatch any events the are pending
31
+ }
32
+
33
+ #We should have sent out an event for the hook event twice as we have two controllers
34
+ @driver.ignore_up_to("if_hook_event", 0)
35
+ @driver.get "if_hook_event", 0
36
+ @driver.ignore_up_to("if_hook_event", 0)
37
+ end
38
+
39
+ it "Can use the :goto hook generator for a specific controller (by name) and receives a hook event" do
40
+ #Hook source code
41
+ hooks_src = %{
42
+ hook :goto => :goto do
43
+ controller "my_controller"
44
+ end
45
+ }
46
+
47
+ #Just expect this not to blow up
48
+ info = flok_new_user_with_src File.read('./spec/kern/assets/hook_entry_points/controller0.rb'), nil, nil, hooks_src
49
+ ctx = info[:ctx]
50
+
51
+ #Run the embed function
52
+ ctx.evald %{
53
+ dump.base = _embed("my_controller", 0, {}, null); // Embed the controller
54
+ int_dispatch([]); // Dispatch any events the are pending
55
+ }
56
+
57
+ @driver.ignore_up_to("if_hook_event", 0); @driver.get "if_hook_event", 0 #We should have sent out an event for the hook event
58
+ expect { @driver.ignore_up_to("if_hook_event", 0) }.to raise_error(/Waited for/) # At this point, we should have not received any events for if_hook_event, as we are not selecting the embedded controller
59
+ end
60
+
61
+ it "Can use the :goto hook generator for a controller with the to_action_responds_to constraint for various actions" do
62
+ #Hook source code
63
+ hooks_src = %{
64
+ hook :goto => :goto do
65
+ to_action_responds_to? "back_clicked"
66
+ end
67
+ }
68
+
69
+ #Get a new js context with the controllers source and the hooks source
70
+ info = flok_new_user_with_src File.read('./spec/kern/assets/hook_entry_points/controller0.rb'), nil, nil, hooks_src
71
+ File.write File.expand_path("~/Downloads/src.txt"), info[:src]
72
+ ctx = info[:ctx]
73
+
74
+ #Run the embed function
75
+ dump = ctx.evald %{
76
+ dump.base = _embed("my_controller", 0, {}, null); // Embed the controller
77
+ int_dispatch([]); // Dispatch any events the are pending
78
+ dump.my_other_controller_base = my_other_controller_base; // Grab the base address of 'my_other_controller'
79
+ }
80
+
81
+ #The index of my_other_controller contains the back_clicked event,
82
+ #and since this is embedded in the my_controller's index, this should have created an event
83
+ @driver.ignore_up_to("if_hook_event", 0)
84
+ event = @driver.get "if_hook_event", 0
85
+
86
+ #Now we switch to an action that dosen't contain a back_clicked event for my_other_controller, so it shouldn't have triggered any hook event
87
+ @driver.int "int_event", [ dump["my_other_controller_base"], "back_clicked", {} ]
88
+ expect { @driver.ignore_up_to("if_hook_event", 0) }.to raise_error(/Waited for/)
89
+
90
+ #Now we switch to the 3rd action which still contains no back_clicked
91
+ @driver.int "int_event", [ dump["my_other_controller_base"], "next_clicked", {} ]
92
+ expect { @driver.ignore_up_to("if_hook_event", 0) }.to raise_error(/Waited for/)
93
+
94
+ #Now we switch to the 4th action which *does* contains a back_clicked
95
+ @driver.int "int_event", [ dump["my_other_controller_base"], "next_clicked", {} ]
96
+ expect { @driver.ignore_up_to("if_hook_event", 0); @driver.get "if_hook_event", 0 }.not_to raise_error
97
+ end
98
+
99
+ it "Can use the :goto hook generator for a controller with the from_action_responds_to constraint for various actions" do
100
+ #Hook source code
101
+ hooks_src = %{
102
+ hook :goto => :goto do
103
+ from_action_responds_to? "back_clicked"
104
+ end
105
+ }
106
+
107
+ #Get a new js context with the controllers source and the hooks source
108
+ info = flok_new_user_with_src File.read('./spec/kern/assets/hook_entry_points/controller0.rb'), nil, nil, hooks_src
109
+ File.write File.expand_path("~/Downloads/src.txt"), info[:src]
110
+ ctx = info[:ctx]
111
+
112
+ #Run the embed function
113
+ dump = ctx.evald %{
114
+ dump.base = _embed("my_controller", 0, {}, null); // Embed the controller
115
+ int_dispatch([]); // Dispatch any events the are pending
116
+ dump.my_other_controller_base = my_other_controller_base; // Grab the base address of 'my_other_controller'
117
+ }
118
+
119
+ #Although the first action has a 'back_clicked', it is going to it so this shouldn't have raised an event
120
+ expect { @driver.ignore_up_to("if_hook_event", 0) }.to raise_error(/Waited for/)
121
+
122
+ #Now we switch to an action and our last action contained a back click
123
+ @driver.int "int_event", [ dump["my_other_controller_base"], "back_clicked", {} ]
124
+ expect { @driver.ignore_up_to("if_hook_event", 0); @driver.get "if_hook_event", 0 }.not_to raise_error
125
+
126
+ #Now we switch to the 3rd action and the last action didn't contain a back clicke
127
+ @driver.int "int_event", [ dump["my_other_controller_base"], "next_clicked", {} ]
128
+ expect { @driver.ignore_up_to("if_hook_event", 0) }.to raise_error(/Waited for/)
129
+
130
+ #Now we switch to the 4th action and the last action did not contain a back click
131
+ @driver.int "int_event", [ dump["my_other_controller_base"], "next_clicked", {} ]
132
+ expect { @driver.ignore_up_to("if_hook_event", 0) }.to raise_error(/Waited for/)
133
+
134
+ #Now we switch to the 2nd action and the last action had a back clicked
135
+ @driver.int "int_event", [ dump["my_other_controller_base"], "back_clicked", {} ]
136
+ expect { @driver.ignore_up_to("if_hook_event", 0); @driver.get "if_hook_event", 0 }.not_to raise_error
137
+ end
138
+
139
+ end