testable 0.4.0 → 0.5.0
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.
- checksums.yaml +4 -4
- data/.hound.yml +10 -0
- data/README.md +23 -7
- data/Rakefile +32 -0
- data/examples/testable-capybara-context.rb +64 -0
- data/examples/testable-capybara-rspec.rb +70 -0
- data/examples/testable-capybara.rb +46 -0
- data/examples/testable-watir-context.rb +5 -5
- data/lib/testable/capybara/dsl.rb +82 -0
- data/lib/testable/capybara/node.rb +30 -0
- data/lib/testable/capybara/page.rb +29 -0
- data/lib/testable/context.rb +6 -5
- data/lib/testable/extensions/core_ruby.rb +13 -0
- data/lib/testable/version.rb +1 -1
- data/lib/testable.rb +3 -0
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c59c802e12f855543871b0917b7043a6dca602714c79cf5624d0033b86f8ce68
|
4
|
+
data.tar.gz: 3011ecba1297734eff0491ce54f4b8192bc5bdafe61b2736598af3649b790455
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9b98f008221c0bd278f690f6aee6fe32c5ea84ffe3c55a977d015ef25100846291bf9a753080caffec7e13d8fcc81f9f3e757cdf7e9f980ab4ce0abf8289ae0
|
7
|
+
data.tar.gz: b977fd589e01f32b48af6ed449087c2a3db1d05ed0aa0f87ee2b74d876259695b61ec0d117f1691f426b77f285ed7809876324243fd0e1e2d42fdee5436df903
|
data/.hound.yml
CHANGED
@@ -2,6 +2,7 @@ AllCops:
|
|
2
2
|
Exclude:
|
3
3
|
- testable.gemspec
|
4
4
|
- spec/**/*
|
5
|
+
- examples/**/*
|
5
6
|
|
6
7
|
# Removing need for frozen string literal comment.
|
7
8
|
Style/FrozenStringLiteralComment:
|
@@ -75,3 +76,12 @@ Naming/PredicateName:
|
|
75
76
|
NameWhitelist:
|
76
77
|
- has_correct_title?
|
77
78
|
- has_correct_url?
|
79
|
+
|
80
|
+
# Sometimes this seems like a better way to do things.
|
81
|
+
Style/DoubleNegation:
|
82
|
+
Enabled: false
|
83
|
+
|
84
|
+
# This is entirely for the addition of the match? method to String
|
85
|
+
# and that's only needed if you are using an outdated Ruby.
|
86
|
+
Style/MultilineIfModifier:
|
87
|
+
Enabled: False
|
data/README.md
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
# Testable
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
> **Testable /ˈtestəb(ə)l/**
|
4
|
+
>
|
5
|
+
> _adjective_
|
6
|
+
>
|
7
|
+
> _able to be tested or tried._
|
6
8
|
|
7
|
-
|
9
|
+
----
|
8
10
|
|
9
|
-
Testable is
|
11
|
+
Testable is an automated test micro-framework that provides a thin wrapper around [Watir](http://watir.com/) and [Capybara](http://teamcapybara.github.io/capybara/). Testable is based on many ideas from tools like [SitePrism](https://github.com/natritmeyer/site_prism) and [Watirsome](https://github.com/p0deje/watirsome), while also being a logical evolution of my own tool, [Tapestry](https://github.com/jeffnyman/tapestry).
|
10
12
|
|
11
|
-
|
13
|
+
One of the core goals of Testable is to be a mediating influence between higher-level tests (acceptance criteria) and lower-level implementations of those tests. You can see some of the design principles for more details on what guided construction.
|
12
14
|
|
13
15
|
## Installation
|
14
16
|
|
@@ -34,7 +36,21 @@ You can also install Testable just as you would any other gem:
|
|
34
36
|
|
35
37
|
## Usage
|
36
38
|
|
37
|
-
Instructions coming soon.
|
39
|
+
Instructions will be coming soon. However, there are a series of scripts in the `examples` directory and a series of commands in the `Rakefile` that will let you execute those scripts.
|
40
|
+
|
41
|
+
## Design Principles
|
42
|
+
|
43
|
+
An automated test framework provides a machine-executable abstraction around testing and encodes a set of guiding principles and heuristics for writing tests-as-code.
|
44
|
+
|
45
|
+
One of the obstacles to covering the gap between principles of testing and the practice of testing is the mechanics of writing tests. These mechanics are focused on abstractions. A lot of the practice of testing comes down to that: finding the right abstractions.
|
46
|
+
|
47
|
+
An automated test framework should be capable of consuming your preferred abstractions because ultimately the automation is simply a tool that supports testing, which means how the framework encourages tests to be expressed should have high fidelity with how human tests would be expressed.
|
48
|
+
|
49
|
+
Testable is built around the the idea that automation should largely be small-footprint, low-fiction, and high-yield.
|
50
|
+
|
51
|
+
The code that a test-supporting micro-framework allows should be modular, promoting both high cohesion and low coupling, as well as promoting a single level of abstraction. These concepts together lead to lightweight design as well as support traits that make change affordable for tests.
|
52
|
+
|
53
|
+
That makes the automation code less expensive to maintain and easier to change. That, ultimately, has a positive impact on the cost of change but, more importantly, allows Testable to be fit within a cost of mistake model, where the goal is to get feedback as quickly as possible regarding when mistakes are made.
|
38
54
|
|
39
55
|
## Development
|
40
56
|
|
data/Rakefile
CHANGED
@@ -16,6 +16,18 @@ namespace :script_testable do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
namespace :script_capybara do
|
20
|
+
desc "Run the Testable Capybara script"
|
21
|
+
task :capybara do
|
22
|
+
system("ruby ./examples/testable-capybara.rb")
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Run the Testable Capybara context script"
|
26
|
+
task :context do
|
27
|
+
system("ruby ./examples/testable-capybara-context.rb")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
19
31
|
namespace :script_watir do
|
20
32
|
desc "Run the Testable Watir script"
|
21
33
|
task :watir do
|
@@ -26,6 +38,26 @@ namespace :script_watir do
|
|
26
38
|
task :test do
|
27
39
|
system("ruby ./examples/testable-watir-test.rb")
|
28
40
|
end
|
41
|
+
|
42
|
+
desc "Run the Testable Watir context script"
|
43
|
+
task :context do
|
44
|
+
system("ruby ./examples/testable-watir-context.rb")
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Run the Testable Watir events script"
|
48
|
+
task :events do
|
49
|
+
system("ruby ./examples/testable-watir-events.rb")
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "Run the Testable Watir ready script"
|
53
|
+
task :ready do
|
54
|
+
system("ruby ./examples/testable-watir-ready.rb")
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "Run the Testable Watir data setter script"
|
58
|
+
task :dataset do
|
59
|
+
system("ruby ./examples/testable-watir-datasetter.rb")
|
60
|
+
end
|
29
61
|
end
|
30
62
|
|
31
63
|
namespace :spec do
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH << "./lib"
|
3
|
+
|
4
|
+
require "rspec"
|
5
|
+
include RSpec::Matchers
|
6
|
+
|
7
|
+
require "testable"
|
8
|
+
include Testable::Context
|
9
|
+
|
10
|
+
Capybara.configure do |config|
|
11
|
+
config.run_server = false
|
12
|
+
config.default_driver = :selenium
|
13
|
+
config.app_host = "https://veilus.herokuapp.com"
|
14
|
+
end
|
15
|
+
|
16
|
+
class HomePage < Testable::Page
|
17
|
+
element :login_form, "#open"
|
18
|
+
element :username, "#username"
|
19
|
+
element :password, "#password"
|
20
|
+
element :login, "#login-button"
|
21
|
+
|
22
|
+
def path
|
23
|
+
"/"
|
24
|
+
end
|
25
|
+
|
26
|
+
def login_as_admin
|
27
|
+
login_form.click
|
28
|
+
username.set "admin"
|
29
|
+
password.set "admin"
|
30
|
+
login.click
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Navigation < Testable::Node
|
35
|
+
elements :items, "a"
|
36
|
+
|
37
|
+
element :page_list, "#navlist"
|
38
|
+
element :overlord, "#overlord"
|
39
|
+
element :planets, "#planets"
|
40
|
+
element :warp, "#warp"
|
41
|
+
element :stardate, "#stardate"
|
42
|
+
end
|
43
|
+
|
44
|
+
class MenuItem < Testable::Node
|
45
|
+
components :items, Navigation, "#areas"
|
46
|
+
end
|
47
|
+
|
48
|
+
class LandingPage < Testable::Page
|
49
|
+
component :navigation, Navigation, "#areas"
|
50
|
+
element :logo, "#site-image"
|
51
|
+
end
|
52
|
+
|
53
|
+
on_visit(HomePage).login_as_admin
|
54
|
+
|
55
|
+
on(LandingPage) do |action|
|
56
|
+
action.navigation.page_list.click
|
57
|
+
puts action.navigation.overlord.text
|
58
|
+
puts action.navigation.items
|
59
|
+
puts action.navigation.items[0].text
|
60
|
+
expect(action.navigation).to have_items
|
61
|
+
expect(action.navigation.items[0].text).to eq("Home")
|
62
|
+
expect(action.navigation.items.count).to be(8)
|
63
|
+
action.navigation.overlord.click
|
64
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH << "./lib"
|
3
|
+
|
4
|
+
# Run this with:
|
5
|
+
# rspec ./examples/testable-capybara-rspec.rb
|
6
|
+
|
7
|
+
require "rspec"
|
8
|
+
include RSpec::Matchers
|
9
|
+
|
10
|
+
require "testable"
|
11
|
+
include Testable::Context
|
12
|
+
|
13
|
+
require "capybara/rspec"
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.expose_dsl_globally = true
|
17
|
+
end
|
18
|
+
|
19
|
+
Capybara.configure do |config|
|
20
|
+
config.run_server = false
|
21
|
+
config.default_driver = :selenium
|
22
|
+
config.app_host = "https://veilus.herokuapp.com"
|
23
|
+
end
|
24
|
+
|
25
|
+
class HomePage < Testable::Page
|
26
|
+
element :login_form, "#open"
|
27
|
+
element :username, "#username"
|
28
|
+
element :password, "#password"
|
29
|
+
element :login, "#login-button"
|
30
|
+
|
31
|
+
def path
|
32
|
+
"/"
|
33
|
+
end
|
34
|
+
|
35
|
+
def login_as_admin
|
36
|
+
login_form.click
|
37
|
+
username.set "admin"
|
38
|
+
password.set "admin"
|
39
|
+
login.click
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Navigation < Testable::Node
|
44
|
+
elements :items, "a"
|
45
|
+
|
46
|
+
element :page_list, "#navlist"
|
47
|
+
element :overlord, "#overlord"
|
48
|
+
element :planets, "#planets"
|
49
|
+
element :warp, "#warp"
|
50
|
+
element :stardate, "#stardate"
|
51
|
+
end
|
52
|
+
|
53
|
+
class LandingPage < Testable::Page
|
54
|
+
component :navigation, Navigation, "#areas"
|
55
|
+
|
56
|
+
def go_to_overlord
|
57
|
+
navigation.page_list.click
|
58
|
+
navigation.overlord.click
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
feature "navigation" do
|
63
|
+
background do
|
64
|
+
on_visit(HomePage).login_as_admin
|
65
|
+
end
|
66
|
+
|
67
|
+
scenario "navigates to overlord" do
|
68
|
+
on(LandingPage).go_to_overlord
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH << "./lib"
|
3
|
+
|
4
|
+
require "rspec"
|
5
|
+
include RSpec::Matchers
|
6
|
+
|
7
|
+
require "testable"
|
8
|
+
|
9
|
+
Capybara.configure do |config|
|
10
|
+
config.run_server = false
|
11
|
+
config.default_driver = :selenium
|
12
|
+
config.app_host = "https://veilus.herokuapp.com"
|
13
|
+
end
|
14
|
+
|
15
|
+
class HomePage < Testable::Page
|
16
|
+
element :login_form, "#open"
|
17
|
+
element :username, "#username"
|
18
|
+
element :password, "#password"
|
19
|
+
element :login, "#login-button"
|
20
|
+
|
21
|
+
def path
|
22
|
+
"/"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
home_page = HomePage.visit
|
27
|
+
|
28
|
+
puts home_page.current?
|
29
|
+
expect(home_page).to be_current
|
30
|
+
|
31
|
+
puts home_page.find("article").text
|
32
|
+
|
33
|
+
puts home_page.login_form.inspect
|
34
|
+
|
35
|
+
puts home_page.has_login_form?
|
36
|
+
puts home_page.has_no_login_form?
|
37
|
+
|
38
|
+
expect(home_page).to have_login_form
|
39
|
+
|
40
|
+
# The next statement would (correctly) fail.
|
41
|
+
# expect(home_page).to have_no_login_form
|
42
|
+
|
43
|
+
home_page.login_form.click
|
44
|
+
home_page.username.set "admin"
|
45
|
+
home_page.password.set "admin"
|
46
|
+
home_page.login.click
|
@@ -50,11 +50,11 @@ end
|
|
50
50
|
Testable.start_browser :firefox
|
51
51
|
|
52
52
|
on_visit(Home) do
|
53
|
-
@
|
54
|
-
@
|
55
|
-
@
|
56
|
-
@
|
57
|
-
expect(@
|
53
|
+
@context.login_form.click
|
54
|
+
@context.username.set "admin"
|
55
|
+
@context.password(id: 'password').set "admin"
|
56
|
+
@context.login.click
|
57
|
+
expect(@context.message.text).to eq('You are now logged in as admin.')
|
58
58
|
end
|
59
59
|
|
60
60
|
on(Navigation) do |page|
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Testable
|
2
|
+
module DSL
|
3
|
+
# The DSL module is mixed into the Node class to provide the DSL for
|
4
|
+
# defining elements and components.
|
5
|
+
def self.included(caller)
|
6
|
+
caller.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
# The ClassMethods provide a set of macro-like methods for wrapping
|
11
|
+
# HTML fragments in Node objects.
|
12
|
+
|
13
|
+
# Defines an element that wraps an HTML fragment.
|
14
|
+
def element(name, selector, options = {})
|
15
|
+
define_method(name.to_s) do
|
16
|
+
Node.new(node: @node.find(selector, options))
|
17
|
+
end
|
18
|
+
|
19
|
+
define_helpers(name, selector)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Defines a collection of elements that wrap HTML fragments.
|
23
|
+
def elements(name, selector, options = {})
|
24
|
+
options = { minimum: 1 }.merge(options)
|
25
|
+
|
26
|
+
define_method(name.to_s) do
|
27
|
+
@node.all(selector, options).map do |node|
|
28
|
+
Node.new(node: node)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
define_helpers(name, selector)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Defines a component that wraps an HTML fragment.
|
36
|
+
def component(name, klass, selector, options = {})
|
37
|
+
unless klass < Node
|
38
|
+
raise ArgumentError, 'Must be given a subclass of Node'
|
39
|
+
end
|
40
|
+
|
41
|
+
define_method(name.to_s) do
|
42
|
+
klass.new(node: @node.find(selector, options))
|
43
|
+
end
|
44
|
+
|
45
|
+
define_helpers(name, selector)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Defines a collection of components that wrap HTML fragments.
|
49
|
+
def components(name, klass, selector, options = {})
|
50
|
+
unless klass < Node
|
51
|
+
raise ArgumentError, 'Must be given a subclass of Node'
|
52
|
+
end
|
53
|
+
|
54
|
+
options = { minimum: 1 }.merge(options)
|
55
|
+
|
56
|
+
define_method(name.to_s) do
|
57
|
+
@node.all(selector, options).map do |node|
|
58
|
+
klass.new(node: node)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
define_helpers(name, selector)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def define_helpers(name, selector)
|
68
|
+
define_existence_predicates(name, selector)
|
69
|
+
end
|
70
|
+
|
71
|
+
def define_existence_predicates(name, selector)
|
72
|
+
define_method("has_#{name}?") do
|
73
|
+
@node.has_selector?(selector)
|
74
|
+
end
|
75
|
+
|
76
|
+
define_method("has_no_#{name}?") do
|
77
|
+
@node.has_no_selector?(selector)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "testable/capybara/dsl"
|
2
|
+
|
3
|
+
module Testable
|
4
|
+
class Node
|
5
|
+
# The Node class represents a wrapped HTML page or fragment. It exposes all
|
6
|
+
# methods of the Cogent DSL, making sure that any Capybara API methods
|
7
|
+
# are passed to the node instance.
|
8
|
+
include DSL
|
9
|
+
|
10
|
+
attr_reader :node
|
11
|
+
|
12
|
+
# A Capybara node is being wrapped in a node instance.
|
13
|
+
def initialize(node:)
|
14
|
+
@node = node
|
15
|
+
end
|
16
|
+
|
17
|
+
# Any Capybara API calls will be sent to the node object.
|
18
|
+
def method_missing(name, *args, &block)
|
19
|
+
if @node.respond_to?(name)
|
20
|
+
@node.send(name, *args, &block)
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def respond_to_missing?(name, include_private = false)
|
27
|
+
@node.respond_to?(name) || super
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "capybara"
|
2
|
+
require "testable/capybara/node"
|
3
|
+
|
4
|
+
module Testable
|
5
|
+
class Page < Node
|
6
|
+
# The `Page` class wraps an HTML page with an application-specific API.
|
7
|
+
# This can be extended to define an API for manipulating the pages of
|
8
|
+
# the web application.
|
9
|
+
attr_reader :path
|
10
|
+
|
11
|
+
def self.visit
|
12
|
+
new.visit
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(node: Capybara.current_session, path: nil)
|
16
|
+
@node = node
|
17
|
+
@path = path
|
18
|
+
end
|
19
|
+
|
20
|
+
def visit
|
21
|
+
@node.visit(path)
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def current?
|
26
|
+
@node.current_path == path
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/testable/context.rb
CHANGED
@@ -14,8 +14,8 @@ module Testable
|
|
14
14
|
# on_visit(TestPage)
|
15
15
|
def on_visit(definition, &block)
|
16
16
|
create_active(definition)
|
17
|
-
@
|
18
|
-
verify_page(@
|
17
|
+
@context.visit
|
18
|
+
verify_page(@context)
|
19
19
|
call_block(&block)
|
20
20
|
end
|
21
21
|
|
@@ -54,6 +54,7 @@ module Testable
|
|
54
54
|
# whether a given page has been reached would make the context definition
|
55
55
|
# look sloppy.
|
56
56
|
def verify_page(context)
|
57
|
+
return unless defined?(context.url_match_attribute)
|
57
58
|
return if context.url_match_attribute.nil?
|
58
59
|
return if context.has_correct_url?
|
59
60
|
|
@@ -61,12 +62,12 @@ module Testable
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def create_active(definition)
|
64
|
-
@
|
65
|
+
@context = definition.new unless @context.is_a?(definition)
|
65
66
|
end
|
66
67
|
|
67
68
|
def call_block(&block)
|
68
|
-
yield @
|
69
|
-
@
|
69
|
+
yield @context if block
|
70
|
+
@context
|
70
71
|
end
|
71
72
|
end
|
72
73
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class String
|
2
|
+
# This is only required if using a version of Ruby before 2.4. A match?
|
3
|
+
# method for String was added in version 2.4.
|
4
|
+
def match?(string, pos = 0)
|
5
|
+
!!match(string, pos)
|
6
|
+
end unless //.respond_to?(:match?)
|
7
|
+
end
|
8
|
+
|
9
|
+
class FalseClass
|
10
|
+
def exists?
|
11
|
+
false
|
12
|
+
end
|
13
|
+
end
|
data/lib/testable/version.rb
CHANGED
data/lib/testable.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: testable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Nyman
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -156,6 +156,9 @@ files:
|
|
156
156
|
- Rakefile
|
157
157
|
- bin/console
|
158
158
|
- bin/setup
|
159
|
+
- examples/testable-capybara-context.rb
|
160
|
+
- examples/testable-capybara-rspec.rb
|
161
|
+
- examples/testable-capybara.rb
|
159
162
|
- examples/testable-info.rb
|
160
163
|
- examples/testable-watir-context.rb
|
161
164
|
- examples/testable-watir-datasetter.rb
|
@@ -165,9 +168,13 @@ files:
|
|
165
168
|
- examples/testable-watir.rb
|
166
169
|
- lib/testable.rb
|
167
170
|
- lib/testable/attribute.rb
|
171
|
+
- lib/testable/capybara/dsl.rb
|
172
|
+
- lib/testable/capybara/node.rb
|
173
|
+
- lib/testable/capybara/page.rb
|
168
174
|
- lib/testable/context.rb
|
169
175
|
- lib/testable/element.rb
|
170
176
|
- lib/testable/errors.rb
|
177
|
+
- lib/testable/extensions/core_ruby.rb
|
171
178
|
- lib/testable/extensions/data_setter.rb
|
172
179
|
- lib/testable/extensions/dom_observer.js
|
173
180
|
- lib/testable/extensions/dom_observer.rb
|
@@ -185,7 +192,7 @@ metadata:
|
|
185
192
|
source_code_uri: https://github.com/jeffnyman/testable
|
186
193
|
changelog_uri: https://github.com/jeffnyman/testable/blob/master/CHANGELOG.md
|
187
194
|
post_install_message: "\n(::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::) (::)\n
|
188
|
-
\ Testable 0.
|
195
|
+
\ Testable 0.5.0 has been installed.\n(::) (::) (::) (::) (::) (::) (::) (::) (::)
|
189
196
|
(::) (::) (::)\n "
|
190
197
|
rdoc_options: []
|
191
198
|
require_paths:
|