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 +4 -4
- data/lib/cyperful/driver.rb +6 -3
- data/lib/cyperful/framework_injections.rb +32 -24
- data/lib/cyperful/test_parser.rb +20 -7
- data/lib/cyperful/ui_server.rb +46 -1
- data/lib/cyperful.rb +6 -0
- data/public/assets/index--K1anXib.js +42 -0
- data/public/assets/index-Uj6YFMhM.css +1 -0
- data/public/assets/syntax-highlighter-worker-BSRAN01e.js +2798 -0
- data/public/frame-agent.js +41 -38
- data/public/index.html +4 -4
- metadata +5 -4
- data/public/assets/index-B_-TcqHl.js +0 -54
- data/public/assets/index-CDElGKtz.css +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ddb5aa08c0bf4e4821d84a2bd2ddb99a53563684b611ec8a481f95108ec04124
|
4
|
+
data.tar.gz: 89d6bb89b2c159a7f413616ba6e18066d0623d4c11efa15636f506069127fb8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d5660be1316a7e1e125d8fbc602dedcf5b7322867f8b073106c52d91ea3c56394f49073fc17c1dd1acb58125799815b54e574b0dd51d5a93ecee1e4cea8a32a
|
7
|
+
data.tar.gz: 0d430e0557fbd4494864e7136c49a7fa8288d03bb1c010590dbe5507d11749ef2673ec2baafec0275a2c8c1c9c96800284d8ba8ffdf1741da7b030d637d8e4e4
|
data/lib/cyperful/driver.rb
CHANGED
@@ -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
|
-
|
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:
|
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
|
-
#
|
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
|
data/lib/cyperful/test_parser.rb
CHANGED
@@ -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.
|
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
|
-
|
83
|
+
|
82
84
|
# e.g. `def test_my_test; ... end`
|
83
|
-
|
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
|
-
|
100
|
-
|
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.
|
131
|
+
unless Cyperful::TestParser.step_at_methods_set.include?(node.children[1])
|
119
132
|
return false
|
120
133
|
end
|
121
134
|
|
data/lib/cyperful/ui_server.rb
CHANGED
@@ -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
|