cyperful 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 341d51e03119eed5f4354673d25c81f2630ee73bb48e29312a797db76b389f80
4
- data.tar.gz: f52e880307fa10e3529ebaac44d165e860bcb94e5913d9c0808732881ac96e63
3
+ metadata.gz: ddb5aa08c0bf4e4821d84a2bd2ddb99a53563684b611ec8a481f95108ec04124
4
+ data.tar.gz: 89d6bb89b2c159a7f413616ba6e18066d0623d4c11efa15636f506069127fb8b
5
5
  SHA512:
6
- metadata.gz: 5baea001193479787f029a38b800fc98fdd5eee46450eefdf6a874c16b890181f49c110c97fe1ae668d160d1c925996ce3d40fe8013dedfa342f015a0cdaa6b5
7
- data.tar.gz: d72eaed23330c7ebcc2c865685c0ee4c1854911f5680c5b7dc42d951d8ba5d9c77cb8e89a4a3609d33523f4cfd0b47c52685d3a15257ffbd9a3057b7de308806
6
+ metadata.gz: 4d5660be1316a7e1e125d8fbc602dedcf5b7322867f8b073106c52d91ea3c56394f49073fc17c1dd1acb58125799815b54e574b0dd51d5a93ecee1e4cea8a32a
7
+ data.tar.gz: 0d430e0557fbd4494864e7136c49a7fa8288d03bb1c010590dbe5507d11749ef2673ec2baafec0275a2c8c1c9c96800284d8ba8ffdf1741da7b030d637d8e4e4
@@ -61,7 +61,7 @@ class Cyperful::Driver
61
61
  @steps =
62
62
  Cyperful::TestParser.new(@test_class).steps_per_test.fetch(@test_name)
63
63
 
64
- editor = "vscode" # TODO: support other editors?
64
+ editor_scheme = Cyperful.config.editor_scheme
65
65
 
66
66
  @steps.each_with_index do |step, i|
67
67
  step.merge!(
@@ -70,11 +70,14 @@ class Cyperful::Driver
70
70
  start_at: nil,
71
71
  end_at: nil,
72
72
  paused_at: nil,
73
- permalink: "#{editor}://file/#{@source_filepath}:#{step.fetch(:line)}",
73
+ permalink:
74
+ if editor_scheme && !editor_scheme.empty?
75
+ "#{editor_scheme}://file/#{@source_filepath}:#{step.fetch(:line)}"
76
+ end,
74
77
  )
75
78
  end
76
79
 
77
- # NOTE: there can be multiple steps per line, this takes the last instance
80
+ # TODO: support multiple multiple steps per line, this takes only the last instance
78
81
  @step_per_line = @steps.index_by { |step| step[:line] }
79
82
 
80
83
  @current_step = nil
@@ -1,5 +1,29 @@
1
1
  require "action_dispatch/system_testing/driver"
2
2
 
3
+ # The Minitest test helper.
4
+ # TODO: support other test frameworks like RSpec
5
+ module Cyperful::SystemTestHelper
6
+ def setup
7
+ Cyperful.setup(self.class, self.method_name)
8
+ super
9
+ end
10
+
11
+ def teardown
12
+ error = passed? ? nil : failure
13
+
14
+ error = error.error if error.is_a?(Minitest::UnexpectedError)
15
+
16
+ Cyperful.teardown(error)
17
+ super
18
+ end
19
+
20
+ # Disable default screenshot on failure b/c we handle them ourselves.
21
+ # https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb#L156
22
+ def take_failed_screenshot
23
+ nil
24
+ end
25
+ end
26
+
3
27
  # we need to override the some Capybara::Session methods because they
4
28
  # control the top-level browser window, but we want them
5
29
  # to control the iframe instead
@@ -37,34 +61,14 @@ module PrependCapybaraWindow
37
61
  end
38
62
  Capybara::Window.prepend(PrependCapybaraWindow)
39
63
 
40
- # The Minitest test helper.
41
- # TODO: support other test frameworks like RSpec
42
- module Cyperful::SystemTestHelper
43
- def setup
44
- Cyperful.setup(self.class, self.method_name)
45
- super
46
- end
47
-
48
- def teardown
49
- error = passed? ? nil : failure
50
-
51
- error = error.error if error.is_a?(Minitest::UnexpectedError)
52
-
53
- Cyperful.teardown(error)
54
- super
55
- end
56
-
57
- # Disable default screenshot on failure b/c we handle them ourselves.
58
- # https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb#L156
59
- def take_failed_screenshot
60
- nil
61
- end
62
- end
63
-
64
64
  module PrependSystemTestingDriver
65
65
  def initialize(...)
66
66
  super(...)
67
67
 
68
+ # SUPER NAIVE way to include the width/height of the sidebar/header
69
+ # in the new screen size
70
+ @screen_size = [@screen_size.fetch(0) + 300, @screen_size.fetch(1) + 60]
71
+
68
72
  prev_capabilities = @capabilities
69
73
  @capabilities =
70
74
  proc do |driver_opts|
@@ -81,6 +85,10 @@ module PrependSystemTestingDriver
81
85
  # make sure we're not in headless mode
82
86
  driver_opts.args.delete("--headless")
83
87
  driver_opts.args.delete("--headless=new")
88
+
89
+ # hide the "Chrome is being controlled by automated test software" infobar
90
+ driver_opts.args.delete("--enable-automation")
91
+ driver_opts.exclude_switches << "enable-automation"
84
92
  end
85
93
  end
86
94
  end
@@ -17,10 +17,12 @@ class Cyperful::TestParser
17
17
  current_scope
18
18
  status_code
19
19
  response_headers
20
+ title
21
+ query
20
22
  ]
21
23
 
22
- def self.step_at_methods
23
- @step_at_methods
24
+ def self.step_at_methods_set
25
+ @step_at_methods_set ||= @step_at_methods.to_set
24
26
  end
25
27
  def self.add_step_at_methods(*mods_or_methods)
26
28
  mods_or_methods.each do |mod_or_method|
@@ -78,9 +80,13 @@ class Cyperful::TestParser
78
80
 
79
81
  block_node = node.children[2]
80
82
  [test_method, block_node]
81
- else
83
+
82
84
  # e.g. `def test_my_test; ... end`
83
- # TODO
85
+ elsif node.type == :def && node.children[0].to_s.start_with?("test_")
86
+ test_method = node.children[0]
87
+
88
+ block_node = node.children[2]
89
+ [test_method, block_node]
84
90
  end
85
91
  end
86
92
  .compact
@@ -88,6 +94,10 @@ class Cyperful::TestParser
88
94
  out = []
89
95
  block_node.children.each { |child| find_test_steps(child, out) }
90
96
 
97
+ # de-duplicate steps by line number
98
+ # TODO: support multiple steps on the same line. `step_per_line = ...` needs to be refactored
99
+ out = out.reverse.uniq { |step| step[:line] }.reverse
100
+
91
101
  [test_method, out]
92
102
  end
93
103
  end
@@ -96,8 +106,10 @@ class Cyperful::TestParser
96
106
  return out unless ast&.is_a?(Parser::AST::Node)
97
107
 
98
108
  if ast.type == :send
99
- add_node(ast, out, depth)
100
- ast.children.each { |child| find_test_steps(child, out, depth) }
109
+ # e.g. `assert_equal current_path, "/"` should be a single step, not 2
110
+ unless add_node(ast, out, depth)
111
+ ast.children.each { |child| find_test_steps(child, out, depth) }
112
+ end
101
113
  elsif ast.type == :block
102
114
  method, _args, child = ast.children
103
115
 
@@ -105,6 +117,7 @@ class Cyperful::TestParser
105
117
 
106
118
  if method.type == :send
107
119
  depth += 1 if add_node(method, out, depth)
120
+
108
121
  method.children.each { |child| find_test_steps(child, out, depth) }
109
122
  end
110
123
 
@@ -115,7 +128,7 @@ class Cyperful::TestParser
115
128
  end
116
129
 
117
130
  private def add_node(node, out, depth)
118
- unless Cyperful::TestParser.step_at_methods.include?(node.children[1])
131
+ unless Cyperful::TestParser.step_at_methods_set.include?(node.children[1])
119
132
  return false
120
133
  end
121
134
 
@@ -1,4 +1,5 @@
1
1
  require "webrick/websocket"
2
+ require "webrick/httpproxy"
2
3
 
3
4
  # fix for: webrick-websocket incorrectly assumes `Upgrade` header is always present
4
5
  module FixWebrickWebsocketServer
@@ -34,9 +35,16 @@ class Cyperful::UiServer
34
35
  @server =
35
36
  WEBrick::Websocket::HTTPServer.new(
36
37
  Port: @port,
37
- DocumentRoot: File.join(Cyperful::ROOT_DIR, "public"),
38
38
  Logger: WEBrick::Log.new("/dev/null"),
39
39
  AccessLog: [],
40
+ **unless Cyperful::DEV_MODE
41
+ {
42
+ DocumentRoot: File.join(Cyperful::ROOT_DIR, "public"),
43
+ DocumentRootOptions: {
44
+ FancyIndexing: false,
45
+ },
46
+ }
47
+ end || {},
40
48
  )
41
49
 
42
50
  notify_queue = @notify_queue
@@ -118,6 +126,10 @@ class Cyperful::UiServer
118
126
  res["Content-Type"] = "application/json"
119
127
  res.status = 200
120
128
  end
129
+
130
+ if Cyperful::DEV_MODE
131
+ @server.mount("/", ReverseProxy, target_url: "http://localhost:3005")
132
+ end
121
133
  end
122
134
 
123
135
  def start_async
@@ -134,4 +146,37 @@ class Cyperful::UiServer
134
146
 
135
147
  @server.shutdown
136
148
  end
149
+
150
+ # super naive reverse proxy
151
+ class ReverseProxy < WEBrick::HTTPServlet::AbstractServlet
152
+ def initialize(server, config = {})
153
+ super
154
+ @target_url = config.fetch(:target_url)
155
+ @forward_headers = config[:forward_headers] || ["accept"]
156
+ end
157
+
158
+ def do_GET(request, response)
159
+ # Target server URL
160
+ target_uri = URI(@target_url)
161
+ target_uri.path = request.path
162
+ target_uri.query = request.query_string if request.query_string
163
+
164
+ # Create a new request to the target server with the original request path
165
+ target_request = Net::HTTP::Get.new(target_uri)
166
+ @forward_headers.each do |header|
167
+ target_request[header] = request[header]
168
+ end
169
+
170
+ # Send the request to the target server
171
+ target_response =
172
+ Net::HTTP.start(target_uri.host, target_uri.port) do |http|
173
+ http.request(target_request)
174
+ end
175
+
176
+ # Set the response from the target server as the response to send back to the client
177
+ response.status = target_response.code.to_i
178
+ response["Content-Type"] = target_response["content-type"]
179
+ response.body = target_response.body
180
+ end
181
+ end
137
182
  end
data/lib/cyperful.rb CHANGED
@@ -4,6 +4,10 @@ require "listen"
4
4
  module Cyperful
5
5
  ROOT_DIR = File.expand_path("..", __dir__)
6
6
 
7
+ # Add `CYPERFUL_DEV=1` to use the Vite dev hot-reloading server
8
+ # instead of the pre-built files in `public/`
9
+ DEV_MODE = !!ENV["CYPERFUL_DEV"]
10
+
7
11
  @current = nil
8
12
 
9
13
  class Config < Struct.new(
@@ -11,6 +15,7 @@ module Cyperful
11
15
  :auto_run_on_reload,
12
16
  :reload_test_files,
13
17
  # :reload_source_files, # not implemented yet
18
+ :editor_scheme,
14
19
  :history_recording, # EXPERIMENTAL
15
20
  keyword_init: true,
16
21
  )
@@ -19,6 +24,7 @@ module Cyperful
19
24
  port: 3004,
20
25
  auto_run_on_reload: true,
21
26
  reload_test_files: true,
27
+ editor_scheme: "vscode",
22
28
  history_recording: true,
23
29
  )
24
30
  end