magic_test 0.0.1 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.standard.yml +3 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +34 -1
- data/README.md +25 -13
- data/Rakefile +1 -1
- data/app/views/magic_test/_context_menu.html +12 -5
- data/app/views/magic_test/_finders.html +11 -8
- data/app/views/magic_test/_javascript_helpers.html +8 -7
- data/app/views/magic_test/_listeners.html +1 -2
- data/app/views/magic_test/_support.html.erb +0 -4
- data/lib/generators/magic_test/install_generator.rb +12 -24
- data/lib/magic_test.rb +0 -3
- data/lib/magic_test/engine.rb +10 -2
- data/lib/magic_test/railtie.rb +1 -1
- data/lib/magic_test/support.rb +43 -25
- data/lib/magic_test/version.rb +1 -1
- data/lib/tasks/magic_test.rake +1 -1
- data/magic_test.gemspec +12 -11
- metadata +31 -3
- data/lib/generators/magic_test/templates/config/initializers/magic_test.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 971c5c9bfcc383b0a3fd3a57e18350e9882fd1f6b1727981df23c1fc54c232b7
|
4
|
+
data.tar.gz: eb63dddfd320adfde98accbb7b4b0f431ca2ecfba9e3db06def573c50c67dc2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ceea8c811fa91e0ad393495631c73e327e185bd92f28bb5ec3a0e79fa258564bd1a21577de6c2007fd73ffcff05ca8082c6570028f07e83a5ccf81615eac43b
|
7
|
+
data.tar.gz: b8d706a0287f1a9d2436ae7dbfca791d61d1de564f6d9d95a5ec7109dfb4bf7548983892474e7d27bbf167afb1cad2156f7734ed759ba52e9acd5267c718e0b6
|
data/.standard.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
magic_test (0.
|
4
|
+
magic_test (0.0.6)
|
5
5
|
capybara (~> 3.0)
|
6
6
|
pry
|
7
|
+
pry-stack_explorer
|
7
8
|
rails (~> 6.0)
|
8
9
|
|
9
10
|
GEM
|
@@ -70,6 +71,9 @@ GEM
|
|
70
71
|
zeitwerk (~> 2.3)
|
71
72
|
addressable (2.7.0)
|
72
73
|
public_suffix (>= 2.0.2, < 5.0)
|
74
|
+
ast (2.4.2)
|
75
|
+
binding_of_caller (1.0.0)
|
76
|
+
debug_inspector (>= 0.0.1)
|
73
77
|
builder (3.2.4)
|
74
78
|
capybara (3.35.3)
|
75
79
|
addressable
|
@@ -82,6 +86,7 @@ GEM
|
|
82
86
|
coderay (1.1.3)
|
83
87
|
concurrent-ruby (1.1.8)
|
84
88
|
crass (1.0.6)
|
89
|
+
debug_inspector (1.0.0)
|
85
90
|
erubi (1.10.0)
|
86
91
|
globalid (0.4.2)
|
87
92
|
activesupport (>= 4.2.0)
|
@@ -105,9 +110,15 @@ GEM
|
|
105
110
|
racc (~> 1.4)
|
106
111
|
nokogiri (1.11.1-x86_64-darwin)
|
107
112
|
racc (~> 1.4)
|
113
|
+
parallel (1.20.1)
|
114
|
+
parser (3.0.0.0)
|
115
|
+
ast (~> 2.4.1)
|
108
116
|
pry (0.14.0)
|
109
117
|
coderay (~> 1.1)
|
110
118
|
method_source (~> 1.0)
|
119
|
+
pry-stack_explorer (0.6.1)
|
120
|
+
binding_of_caller (~> 1.0)
|
121
|
+
pry (~> 0.13)
|
111
122
|
public_suffix (4.0.6)
|
112
123
|
racc (1.5.2)
|
113
124
|
rack (2.2.3)
|
@@ -139,8 +150,25 @@ GEM
|
|
139
150
|
method_source
|
140
151
|
rake (>= 0.8.7)
|
141
152
|
thor (~> 1.0)
|
153
|
+
rainbow (3.0.0)
|
142
154
|
rake (13.0.3)
|
143
155
|
regexp_parser (2.1.1)
|
156
|
+
rexml (3.2.4)
|
157
|
+
rubocop (1.10.0)
|
158
|
+
parallel (~> 1.10)
|
159
|
+
parser (>= 3.0.0.0)
|
160
|
+
rainbow (>= 2.2.2, < 4.0)
|
161
|
+
regexp_parser (>= 1.8, < 3.0)
|
162
|
+
rexml
|
163
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
164
|
+
ruby-progressbar (~> 1.7)
|
165
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
166
|
+
rubocop-ast (1.4.1)
|
167
|
+
parser (>= 2.7.1.5)
|
168
|
+
rubocop-performance (1.9.2)
|
169
|
+
rubocop (>= 0.90.0, < 2.0)
|
170
|
+
rubocop-ast (>= 0.4.0)
|
171
|
+
ruby-progressbar (1.11.0)
|
144
172
|
sprockets (4.0.2)
|
145
173
|
concurrent-ruby (~> 1.0)
|
146
174
|
rack (> 1, < 3)
|
@@ -148,9 +176,13 @@ GEM
|
|
148
176
|
actionpack (>= 4.0)
|
149
177
|
activesupport (>= 4.0)
|
150
178
|
sprockets (>= 3.0.0)
|
179
|
+
standard (0.13.0)
|
180
|
+
rubocop (= 1.10.0)
|
181
|
+
rubocop-performance (= 1.9.2)
|
151
182
|
thor (1.1.0)
|
152
183
|
tzinfo (2.0.4)
|
153
184
|
concurrent-ruby (~> 1.0)
|
185
|
+
unicode-display_width (2.0.0)
|
154
186
|
websocket-driver (0.7.3)
|
155
187
|
websocket-extensions (>= 0.1.0)
|
156
188
|
websocket-extensions (0.1.5)
|
@@ -167,6 +199,7 @@ DEPENDENCIES
|
|
167
199
|
magic_test!
|
168
200
|
minitest (~> 5.0)
|
169
201
|
rake (~> 13.0)
|
202
|
+
standard
|
170
203
|
|
171
204
|
BUNDLED WITH
|
172
205
|
2.2.0
|
data/README.md
CHANGED
@@ -1,10 +1,22 @@
|
|
1
1
|
# Magic Test
|
2
2
|
|
3
|
-
Magic Test allows you to write Rails system tests interactively through a combination of trial-and-error in a debugger session and also just simple clicking around in the application being tested, all without the slowness of constantly restarting the testing environment.
|
3
|
+
Magic Test allows you to write Rails system tests interactively through a combination of trial-and-error in a debugger session and also just simple clicking around in the application being tested, all without the slowness of constantly restarting the testing environment. You can [see some videos of it in action](https://twitter.com/andrewculver/status/1366062684802846721)!
|
4
4
|
|
5
|
-
|
5
|
+
> Magic Test is still in early development, and that includes the documentation. Any questions you have that aren't already address in the documentation should be [opened as issues](https://github.com/bullet-train-co/magic_test/issues/new) so they can be appropriately addressed in the documentation.
|
6
|
+
|
7
|
+
Magic Test was created by [Andrew Culver](http://twitter.com/andrewculver) and [Adam Pallozzi](https://twitter.com/adampallozzi).
|
8
|
+
|
9
|
+
## Sponsored By
|
10
|
+
|
11
|
+
<a href="https://bullettrain.co" target="_blank">
|
12
|
+
<img src="https://github.com/CanCanCommunity/cancancan/raw/develop/logo/bullet_train.png" alt="Bullet Train" width="400"/>
|
13
|
+
</a>
|
14
|
+
<br/>
|
15
|
+
<br/>
|
16
|
+
|
17
|
+
> Would you like to support Magic Test development and have your logo featured here? [Reach out!](http://twitter.com/andrewculver)
|
6
18
|
|
7
|
-
|
19
|
+
## Installation
|
8
20
|
|
9
21
|
Add this line to your application’s `Gemfile`:
|
10
22
|
|
@@ -18,14 +30,12 @@ Then run the following in your shell:
|
|
18
30
|
bundle install
|
19
31
|
```
|
20
32
|
|
21
|
-
Next, run the install generator
|
33
|
+
Next, run the install generator:
|
22
34
|
|
23
35
|
```
|
24
36
|
rails g magic_test:install
|
25
37
|
```
|
26
38
|
|
27
|
-
(If your application doesn't include jQuery, you'll need to let Magic Test know to include it as needed. Just add `no` to the end of the line above or adjust your configuration afterward in `config/initializers/magic_test.rb`. We'll only inject jQuery when Magic Test is actively running. It will never show up on CI.)
|
28
|
-
|
29
39
|
With this we will:
|
30
40
|
|
31
41
|
- Create a sample system test at `test/system/basics_test.rb` that invokes Magic Test.
|
@@ -33,7 +43,7 @@ With this we will:
|
|
33
43
|
|
34
44
|
Finally, because it’s hard for us to do automatically, you will need to add the following before any closing `</head>` tags in any of the files in `app/views/layouts`:
|
35
45
|
|
36
|
-
```
|
46
|
+
```ruby+erb
|
37
47
|
<%= render 'magic_test/support' if Rails.env.test? %>
|
38
48
|
```
|
39
49
|
|
@@ -54,13 +64,12 @@ This results in three windows:
|
|
54
64
|
|
55
65
|
If you have the screen real estate, we recommend organizing the three windows so you can see them all at the same time. This is the intended Magic Test developer experience.
|
56
66
|
|
57
|
-
|
58
|
-
|
59
|
-
Just add a call to `magic_test` anywhere you want to start interactively developing test behavior and run the test the same way we've described above.
|
67
|
+
> #### Using Magic Test in New or Existing Tests
|
68
|
+
> Just add a call to `magic_test` anywhere you want to start interactively developing test behavior and run the test the same way we've described above.
|
60
69
|
|
61
70
|
### Writing Tests Manually in the Debugger Console
|
62
71
|
|
63
|
-
You’re now free to
|
72
|
+
You’re now free to issue Capybara commands in the debugger and see their results in the Chrome browser. If you type something and you’re happy with the result, type `ok` and hit enter to have the last line or block of code you wrote added to the test.
|
64
73
|
|
65
74
|
When you’re done writing the test interactively, you can press <kbd>Control</kbd> + <kbd>D</kbd> to finish running the test.
|
66
75
|
|
@@ -80,16 +89,19 @@ If you want to add an assertion that some content exists on the page, simply hig
|
|
80
89
|
|
81
90
|
### Flushing In Browser Actions and Assertions to the Test File
|
82
91
|
|
83
|
-
The interactive actions you make in your app are not automatically written to your test. When you are ready to write your actions out to the test, go to the terminal window and type `flush`. This will flush all your recent actions out to the test file. It’s still early days for Magic Test, so you may find you need to clean up some of the output. Please don’t hesitate to submit new issues highlighting these scenarios so we can try to improve the results.
|
92
|
+
The interactive actions you make in your app are not automatically written to your test. When you are ready to write your actions out to the test, go to the terminal window and type `flush`. This will flush all your recent actions out to the test file. It’s still early days for Magic Test, so you may find you need to clean up some of the output. Please don’t hesitate to [submit new issues](https://github.com/bullet-train-co/magic_test/issues/new) highlighting these scenarios so we can try to improve the results.
|
84
93
|
|
85
94
|
### Ambiguous Labels and Elements
|
86
95
|
|
87
96
|
When generating test code, we check to ensure a given label or element identifier won’t result in multiple or ambiguous matches the next time a test runs. If that situation arises, we’ll try to generate the appropriate `within` blocks and selectors to ensure the target button or field is disambiguated.
|
88
97
|
|
98
|
+
## Acknowledgements
|
99
|
+
We'd like to thank [Florian Plank](https://twitter.com/polarblau), the author of [Capycorder](https://github.com/polarblau/capycorder). His earlier attempt at the same concept (implemented via a Chrome extension) was ahead of its time and provided us with great inspiration and lessons learned when solving this problem from another angle.
|
100
|
+
|
89
101
|
## Contributing
|
90
102
|
|
91
103
|
Bug reports and pull requests are welcome on GitHub at https://github.com/bullet-train-co/magic_test. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
92
104
|
|
93
105
|
## License
|
94
106
|
|
95
|
-
The
|
107
|
+
The Ruby Gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
<script>
|
2
|
+
function ready(fn) {
|
3
|
+
if (document.readyState !== 'loading'){
|
4
|
+
fn();
|
5
|
+
} else {
|
6
|
+
document.addEventListener('DOMContentLoaded', fn);
|
7
|
+
}
|
8
|
+
}
|
2
9
|
|
3
|
-
|
4
|
-
$(document).ready(function() {
|
10
|
+
ready(function() {
|
5
11
|
enableKeyboardShortcuts();
|
6
12
|
});
|
7
13
|
|
14
|
+
|
8
15
|
function enableKeyboardShortcuts() {
|
9
16
|
function keydown(event) {
|
10
17
|
if (event.ctrlKey && event.shiftKey && event.key === 'A') {
|
@@ -16,9 +23,9 @@
|
|
16
23
|
document.addEventListener('keydown', keydown, false);
|
17
24
|
|
18
25
|
function generateAssertion() {
|
19
|
-
var text = selectedText();
|
20
|
-
if (text.
|
21
|
-
var action = "assert page.has_content?
|
26
|
+
var text = selectedText().trim();
|
27
|
+
if (text.length > 0) {
|
28
|
+
var action = "assert page.has_content? '" + text.replace("'", "\\\'") + "'";
|
22
29
|
var testingOutput = JSON.parse(sessionStorage.getItem("testingOutput"));
|
23
30
|
var target = "";
|
24
31
|
var options = "";
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<script>
|
2
2
|
|
3
3
|
function getPathTo(element) {
|
4
|
-
if (element.tagName
|
4
|
+
if (element.tagName === 'HTML') {
|
5
5
|
return '/HTML[1]';
|
6
6
|
}
|
7
7
|
if (element===document.body) {
|
@@ -20,27 +20,30 @@
|
|
20
20
|
}
|
21
21
|
}
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
return
|
23
|
+
function visibleFilter(target){
|
24
|
+
var computedStyle = window.getComputedStyle(target);
|
25
|
+
return !(computedStyle.display === 'none' || computedStyle.visibility === 'hidden' || target.hidden)
|
26
26
|
}
|
27
27
|
|
28
28
|
|
29
29
|
function finderForElement(element) {
|
30
30
|
// Try to find just using the element tagName
|
31
31
|
var tagName = element.tagName.toLowerCase();
|
32
|
-
if (
|
32
|
+
if (document.querySelectorAll(tagName).length === 1) {
|
33
33
|
return `find('${tagName}')`;
|
34
34
|
}
|
35
35
|
// Try adding in the classes of the element
|
36
36
|
var classList = [].slice.apply(element.classList)
|
37
37
|
var classString = classList.length ? "." + classList.join('.') : "";
|
38
|
-
if (classList.length &&
|
38
|
+
if (classList.length && document.querySelectorAll(tagName + classList).length === 1) {
|
39
39
|
return `find('${tagName}${classString}')`;
|
40
40
|
}
|
41
41
|
// Try adding in the text of the element
|
42
42
|
var text = element.textContent.trim();
|
43
|
-
|
43
|
+
var targets = Array.from(document.querySelectorAll(`${tagName}${classString}`))
|
44
|
+
.filter(visibleFilter)
|
45
|
+
.filter((el) => el.textContent.includes(text))
|
46
|
+
if (text && targets.length === 1) {
|
44
47
|
return `find('${tagName}${classString}', text: '${text}')`;
|
45
48
|
}
|
46
49
|
// use the xpath to the element
|
@@ -48,4 +51,4 @@
|
|
48
51
|
}
|
49
52
|
|
50
53
|
|
51
|
-
</script>
|
54
|
+
</script>
|
@@ -1,29 +1,30 @@
|
|
1
1
|
<script text="text/javascript">
|
2
2
|
|
3
|
-
|
3
|
+
(function() {
|
4
4
|
console.log("🪄 Magic Test activated in the browser!")
|
5
5
|
initializeStorage();
|
6
6
|
initializeMutationObserver();
|
7
|
-
});
|
7
|
+
})();
|
8
8
|
|
9
9
|
function clickFunction(event) {
|
10
|
-
var
|
10
|
+
var element = event.target
|
11
|
+
var tagName = element.tagName
|
11
12
|
var action = ""
|
12
13
|
var target = ""
|
13
14
|
var options = ""
|
14
|
-
if (tagName == "BUTTON" || tagName == "A" || (tagName == "INPUT" &&
|
15
|
+
if (tagName == "BUTTON" || tagName == "A" || (tagName == "INPUT" && element.type == 'submit')) {
|
15
16
|
action = "click_on"
|
16
|
-
|
17
|
+
target = element.value || element.text
|
17
18
|
if (!target) {
|
18
19
|
return;
|
19
20
|
}
|
20
21
|
target = "\'" + target.trim().replace("'", "\\\'") + "\'"
|
21
22
|
} else if (tagName == "INPUT") {
|
22
23
|
let ignoreType = ['text', 'password', 'date', 'email', 'month', 'number', 'search']
|
23
|
-
if (ignoreType.includes(
|
24
|
+
if (ignoreType.includes(element.type)) {
|
24
25
|
return;
|
25
26
|
}
|
26
|
-
var path = getPathTo(
|
27
|
+
var path = getPathTo(element)
|
27
28
|
action = `find(:xpath, '${path}').click`
|
28
29
|
} else {
|
29
30
|
return;
|
@@ -4,6 +4,5 @@
|
|
4
4
|
document.addEventListener('keypress', function(e){keypressFunction(e)});
|
5
5
|
document.addEventListener('mouseover', function(evt){mutationStart(evt)}, true);
|
6
6
|
document.addEventListener('mouseover', function(){mutationEnd()}, false);
|
7
|
-
|
8
|
-
$(document).on('click', '*', function(event){clickFunction(event)});
|
7
|
+
document.addEventListener('click', function(event){clickFunction(event)});
|
9
8
|
</script>
|
@@ -1,8 +1,4 @@
|
|
1
1
|
<% if Rails.env.test? && ENV['MAGIC_TEST'].present? %>
|
2
|
-
<% unless MagicTest.jquery_already_included %>
|
3
|
-
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
|
4
|
-
<% end %>
|
5
|
-
|
6
2
|
<%= render 'magic_test/context_menu' %>
|
7
3
|
<%= render 'magic_test/key_codes' %>
|
8
4
|
<%= render 'magic_test/storage' %>
|
@@ -1,40 +1,28 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "rails/generators"
|
2
|
+
require "magic_test/engine"
|
3
3
|
|
4
4
|
module MagicTest
|
5
5
|
class InstallGenerator < Rails::Generators::Base
|
6
6
|
def self.source_paths
|
7
|
-
[MagicTest::Engine.root, File.expand_path(
|
8
|
-
end
|
9
|
-
|
10
|
-
argument :jquery_already_included, :type => :string, :default => 'yes'
|
11
|
-
|
12
|
-
# Override the attr_accessor generated by 'argument' so that
|
13
|
-
# subscription_owner_model is always returned lowercase.
|
14
|
-
def jquery_already_included
|
15
|
-
@jquery_already_included.strip.downcase.first == 'y'
|
7
|
+
[MagicTest::Engine.root, File.expand_path("../templates", __FILE__)]
|
16
8
|
end
|
17
9
|
|
18
10
|
def install
|
19
11
|
unless defined?(MagicTest)
|
20
12
|
gem_group :test do
|
21
|
-
gem
|
13
|
+
gem "magic_test"
|
22
14
|
end
|
23
15
|
end
|
24
16
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
gsub_file
|
29
|
-
gsub_file
|
30
|
-
gsub_file
|
31
|
-
gsub_file 'test/system/basics_test.rb', 'visit basics_url', 'visit root_url'
|
32
|
-
gsub_file 'test/system/basics_test.rb', 'assert_selector "h1", text: "Basic"', 'magic_test'
|
33
|
-
|
34
|
-
gsub_file 'test/application_system_test_case.rb', 'using: :headless_chrome', "using: (ENV['SHOW_TESTS'] ? :chrome : :headless_chrome)"
|
35
|
-
gsub_file 'test/application_system_test_case.rb', 'using: :headless_firefox', "using: (ENV['SHOW_TESTS'] ? :firefox : :headless_firefox)"
|
36
|
-
|
17
|
+
generate "system_test", "basic"
|
18
|
+
gsub_file "test/system/basics_test.rb", "# ", ""
|
19
|
+
gsub_file "test/system/basics_test.rb", "#", ""
|
20
|
+
gsub_file "test/system/basics_test.rb", "visiting the index", "getting started"
|
21
|
+
gsub_file "test/system/basics_test.rb", "visit basics_url", "visit root_url"
|
22
|
+
gsub_file "test/system/basics_test.rb", 'assert_selector "h1", text: "Basic"', "magic_test"
|
37
23
|
|
24
|
+
gsub_file "test/application_system_test_case.rb", "using: :headless_chrome", "using: (ENV['SHOW_TESTS'] ? :chrome : :headless_chrome)"
|
25
|
+
gsub_file "test/application_system_test_case.rb", "using: :headless_firefox", "using: (ENV['SHOW_TESTS'] ? :firefox : :headless_firefox)"
|
38
26
|
end
|
39
27
|
end
|
40
28
|
end
|
data/lib/magic_test.rb
CHANGED
data/lib/magic_test/engine.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require "magic_test/support"
|
2
|
+
require "pry"
|
3
|
+
require "pry-stack_explorer"
|
2
4
|
|
3
5
|
module MagicTest
|
4
6
|
class Engine < Rails::Engine
|
5
7
|
config.after_initialize do
|
6
|
-
if ENV[
|
8
|
+
if ENV["MAGIC_TEST"].present?
|
7
9
|
if defined? ActionDispatch::SystemTestCase
|
8
10
|
ActionDispatch::SystemTestCase.include MagicTest::Support
|
9
11
|
end
|
@@ -11,6 +13,12 @@ module MagicTest
|
|
11
13
|
if defined? ActionDispatch::IntegrationTest
|
12
14
|
ActionDispatch::IntegrationTest.include MagicTest::Support
|
13
15
|
end
|
16
|
+
|
17
|
+
if defined? RSpec
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.include MagicTest::Support, type: :system
|
20
|
+
end
|
21
|
+
end
|
14
22
|
end
|
15
23
|
end
|
16
24
|
end
|
data/lib/magic_test/railtie.rb
CHANGED
data/lib/magic_test/support.rb
CHANGED
@@ -3,14 +3,16 @@ module MagicTest
|
|
3
3
|
def assert_selected_exists
|
4
4
|
selected_text = page.evaluate_script("window.selectedText()")
|
5
5
|
return if selected_text.blank?
|
6
|
-
|
6
|
+
|
7
|
+
filepath, line = get_last_caller(caller)
|
8
|
+
|
7
9
|
contents = File.open(filepath).read.lines
|
8
10
|
chunks = contents.each_slice(line.to_i - 1 + @test_lines_written).to_a
|
9
11
|
indentation = chunks[1].first.match(/^(\s*)/)[0]
|
10
12
|
chunks.first << indentation + "assert(page.has_content?('#{selected_text.gsub("'", "\\\\'")}'))" + "\n"
|
11
13
|
@test_lines_written += 1
|
12
14
|
contents = chunks.flatten.join
|
13
|
-
File.open(filepath,
|
15
|
+
File.open(filepath, "w") do |file|
|
14
16
|
file.puts(contents)
|
15
17
|
end
|
16
18
|
end
|
@@ -19,24 +21,9 @@ module MagicTest
|
|
19
21
|
page.evaluate_script("trackKeystrokes()")
|
20
22
|
end
|
21
23
|
|
22
|
-
def get_last
|
23
|
-
history_lines = Readline::HISTORY.to_a.last(20)
|
24
|
-
i = 2
|
25
|
-
last = history_lines.last(2).first
|
26
|
-
last_block = [last]
|
27
|
-
if last == 'end' || last.first(4) == 'end '
|
28
|
-
i += 1
|
29
|
-
last_block.unshift(history_lines.last(i).first)
|
30
|
-
until !last_block.first.match(/^(\s+)/)&[0] do
|
31
|
-
i += 1
|
32
|
-
last_block.unshift(history_lines.last(i).first)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
return last_block
|
36
|
-
end
|
37
|
-
|
38
24
|
def flush
|
39
|
-
filepath, line = caller
|
25
|
+
filepath, line = get_last_caller(caller)
|
26
|
+
|
40
27
|
contents = File.open(filepath).read.lines
|
41
28
|
chunks = contents.each_slice(line.to_i - 1 + @test_lines_written).to_a
|
42
29
|
indentation = chunks[1].first.match(/^(\s*)/)[0]
|
@@ -48,11 +35,11 @@ module MagicTest
|
|
48
35
|
puts "(writing that to `#{filepath}`.)"
|
49
36
|
if output
|
50
37
|
output.each do |last|
|
51
|
-
chunks.first << indentation + "#{last[
|
38
|
+
chunks.first << indentation + "#{last["action"]} #{last["target"]}#{last["options"]}" + "\n"
|
52
39
|
@test_lines_written += 1
|
53
40
|
end
|
54
41
|
contents = chunks.flatten.join
|
55
|
-
File.open(filepath,
|
42
|
+
File.open(filepath, "w") do |file|
|
56
43
|
file.puts(contents)
|
57
44
|
end
|
58
45
|
# clear the testing output now.
|
@@ -60,11 +47,12 @@ module MagicTest
|
|
60
47
|
else
|
61
48
|
puts "`window.testingOutput` was empty in the browser. Something must be wrong on the browser side."
|
62
49
|
end
|
63
|
-
|
50
|
+
true
|
64
51
|
end
|
65
52
|
|
66
53
|
def ok
|
67
|
-
filepath, line = caller
|
54
|
+
filepath, line = get_last_caller(caller)
|
55
|
+
|
68
56
|
puts "(writing that to `#{filepath}`.)"
|
69
57
|
contents = File.open(filepath).read.lines
|
70
58
|
chunks = contents.each_slice(line.to_i - 1 + @test_lines_written).to_a
|
@@ -74,24 +62,54 @@ module MagicTest
|
|
74
62
|
@test_lines_written += 1
|
75
63
|
end
|
76
64
|
contents = chunks.flatten.join
|
77
|
-
File.open(filepath,
|
65
|
+
File.open(filepath, "w") do |file|
|
78
66
|
file.puts(contents)
|
79
67
|
end
|
80
|
-
|
68
|
+
true
|
81
69
|
end
|
82
70
|
|
83
71
|
def empty_cache
|
84
72
|
page.evaluate_script("sessionStorage.setItem('testingOutput', JSON.stringify([]))")
|
73
|
+
rescue Capybara::NotSupportedByDriverError => _
|
74
|
+
# TODO we need to add more robust instructions for this.
|
75
|
+
raise "You need to configure this test (or your test suite) to run in a real browser (Chrome, Firefox, etc.) in order for Magic Test to work. It also needs to run in non-headless mode if `ENV['MAGIC_TEST'].present?`"
|
85
76
|
end
|
86
77
|
|
87
78
|
def magic_test
|
88
79
|
empty_cache
|
89
80
|
@test_lines_written = 0
|
90
81
|
begin
|
82
|
+
# 👋 This isn't helpful context. Type `up` and hit enter to see where you really are.
|
91
83
|
binding.pry
|
92
84
|
rescue
|
93
85
|
retry
|
94
86
|
end
|
95
87
|
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def get_last
|
92
|
+
history_lines = Readline::HISTORY.to_a.last(20)
|
93
|
+
i = 2
|
94
|
+
last = history_lines.last(2).first
|
95
|
+
last_block = [last]
|
96
|
+
if last == "end" || last.first(4) == "end "
|
97
|
+
i += 1
|
98
|
+
last_block.unshift(history_lines.last(i).first)
|
99
|
+
until !last_block.first.match(/^(\s+)/) & [0]
|
100
|
+
i += 1
|
101
|
+
last_block.unshift(history_lines.last(i).first)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
last_block
|
106
|
+
end
|
107
|
+
|
108
|
+
# TODO this feels like it's going to end up burning people who have other support files in `test` or `spec` that don't include `helper` in the name.
|
109
|
+
def get_last_caller(caller)
|
110
|
+
caller.select { |s| s.include?("/test/") || s.include?("/spec/") }
|
111
|
+
.reject { |s| s.include?("helper") }
|
112
|
+
.first.split(":").first(2)
|
113
|
+
end
|
96
114
|
end
|
97
115
|
end
|
data/lib/magic_test/version.rb
CHANGED
data/lib/tasks/magic_test.rake
CHANGED
data/magic_test.gemspec
CHANGED
@@ -1,32 +1,33 @@
|
|
1
|
-
|
2
1
|
lib = File.expand_path("../lib", __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require "magic_test/version"
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name
|
8
|
-
spec.version
|
9
|
-
spec.authors
|
10
|
-
spec.email
|
6
|
+
spec.name = "magic_test"
|
7
|
+
spec.version = MagicTest::VERSION
|
8
|
+
spec.authors = ["Andrew Culver", "Adam Pallozzi"]
|
9
|
+
spec.email = ["andrew.culver@gmail.com", "adampallozzi@gmail.com"]
|
11
10
|
|
12
|
-
spec.summary
|
13
|
-
spec.homepage
|
14
|
-
spec.license
|
11
|
+
spec.summary = "Create system tests interactively."
|
12
|
+
spec.homepage = "https://github.com/bullet-train/magic_test"
|
13
|
+
spec.license = "MIT"
|
15
14
|
|
16
15
|
# Specify which files should be added to the gem when it is released.
|
17
16
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
18
|
-
spec.files
|
17
|
+
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
19
18
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
19
|
end
|
21
|
-
spec.bindir
|
22
|
-
spec.executables
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
22
|
spec.require_paths = ["lib"]
|
24
23
|
|
25
24
|
spec.add_development_dependency "bundler", "~> 2.0"
|
26
25
|
spec.add_development_dependency "rake", "~> 13.0"
|
27
26
|
spec.add_development_dependency "minitest", "~> 5.0"
|
27
|
+
spec.add_development_dependency "standard"
|
28
28
|
|
29
29
|
spec.add_dependency "pry"
|
30
|
+
spec.add_dependency "pry-stack_explorer"
|
30
31
|
spec.add_dependency "capybara", "~> 3.0"
|
31
32
|
spec.add_dependency "rails", "~> 6.0"
|
32
33
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: magic_test
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Culver
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2021-02
|
12
|
+
date: 2021-03-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -53,6 +53,20 @@ dependencies:
|
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '5.0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: standard
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
56
70
|
- !ruby/object:Gem::Dependency
|
57
71
|
name: pry
|
58
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,6 +81,20 @@ dependencies:
|
|
67
81
|
- - ">="
|
68
82
|
- !ruby/object:Gem::Version
|
69
83
|
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: pry-stack_explorer
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :runtime
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
70
98
|
- !ruby/object:Gem::Dependency
|
71
99
|
name: capybara
|
72
100
|
requirement: !ruby/object:Gem::Requirement
|
@@ -104,6 +132,7 @@ extensions: []
|
|
104
132
|
extra_rdoc_files: []
|
105
133
|
files:
|
106
134
|
- ".gitignore"
|
135
|
+
- ".standard.yml"
|
107
136
|
- ".travis.yml"
|
108
137
|
- CODE_OF_CONDUCT.md
|
109
138
|
- Gemfile
|
@@ -122,7 +151,6 @@ files:
|
|
122
151
|
- bin/console
|
123
152
|
- bin/setup
|
124
153
|
- lib/generators/magic_test/install_generator.rb
|
125
|
-
- lib/generators/magic_test/templates/config/initializers/magic_test.rb
|
126
154
|
- lib/magic_test.rb
|
127
155
|
- lib/magic_test/engine.rb
|
128
156
|
- lib/magic_test/railtie.rb
|