rsel 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/docs/development.md +8 -3
- data/docs/examples.md +119 -0
- data/docs/history.md +9 -0
- data/docs/index.md +3 -1
- data/docs/locators.md +72 -0
- data/docs/scoping.md +19 -5
- data/docs/todo.md +4 -2
- data/docs/usage.md +2 -2
- data/lib/rsel/exceptions.rb +1 -1
- data/lib/rsel/selenium_test.rb +37 -132
- data/lib/rsel/support.rb +138 -0
- data/rsel.gemspec +1 -1
- data/spec/selenium_test_spec.rb +103 -12
- data/spec/spec_helper.rb +1 -10
- data/spec/support_spec.rb +48 -0
- data/test/app.rb +6 -6
- metadata +8 -39
- data/vendor/rubyslim-0.1.1/.gitignore +0 -7
- data/vendor/rubyslim-0.1.1/README.md +0 -159
- data/vendor/rubyslim-0.1.1/Rakefile +0 -21
- data/vendor/rubyslim-0.1.1/bin/rubyslim +0 -10
- data/vendor/rubyslim-0.1.1/lib/rubyslim/list_deserializer.rb +0 -69
- data/vendor/rubyslim-0.1.1/lib/rubyslim/list_executor.rb +0 -12
- data/vendor/rubyslim-0.1.1/lib/rubyslim/list_serializer.rb +0 -45
- data/vendor/rubyslim-0.1.1/lib/rubyslim/ruby_slim.rb +0 -61
- data/vendor/rubyslim-0.1.1/lib/rubyslim/slim_error.rb +0 -3
- data/vendor/rubyslim-0.1.1/lib/rubyslim/slim_helper_library.rb +0 -23
- data/vendor/rubyslim-0.1.1/lib/rubyslim/socket_service.rb +0 -53
- data/vendor/rubyslim-0.1.1/lib/rubyslim/statement.rb +0 -79
- data/vendor/rubyslim-0.1.1/lib/rubyslim/statement_executor.rb +0 -174
- data/vendor/rubyslim-0.1.1/lib/rubyslim/table_to_hash_converter.rb +0 -32
- data/vendor/rubyslim-0.1.1/lib/test_module/library_new.rb +0 -13
- data/vendor/rubyslim-0.1.1/lib/test_module/library_old.rb +0 -12
- data/vendor/rubyslim-0.1.1/lib/test_module/should_not_find_test_slim_in_here/test_slim.rb +0 -7
- data/vendor/rubyslim-0.1.1/lib/test_module/simple_script.rb +0 -9
- data/vendor/rubyslim-0.1.1/lib/test_module/test_chain.rb +0 -5
- data/vendor/rubyslim-0.1.1/lib/test_module/test_slim.rb +0 -86
- data/vendor/rubyslim-0.1.1/lib/test_module/test_slim_with_arguments.rb +0 -23
- data/vendor/rubyslim-0.1.1/lib/test_module/test_slim_with_no_sut.rb +0 -5
- data/vendor/rubyslim-0.1.1/rubyslim.gemspec +0 -22
- data/vendor/rubyslim-0.1.1/spec/instance_creation_spec.rb +0 -40
- data/vendor/rubyslim-0.1.1/spec/it8f_spec.rb +0 -8
- data/vendor/rubyslim-0.1.1/spec/list_deserializer_spec.rb +0 -66
- data/vendor/rubyslim-0.1.1/spec/list_executor_spec.rb +0 -187
- data/vendor/rubyslim-0.1.1/spec/list_serialzer_spec.rb +0 -38
- data/vendor/rubyslim-0.1.1/spec/method_invocation_spec.rb +0 -127
- data/vendor/rubyslim-0.1.1/spec/slim_helper_library_spec.rb +0 -80
- data/vendor/rubyslim-0.1.1/spec/socket_service_spec.rb +0 -98
- data/vendor/rubyslim-0.1.1/spec/spec_helper.rb +0 -6
- data/vendor/rubyslim-0.1.1/spec/statement_executor_spec.rb +0 -50
- data/vendor/rubyslim-0.1.1/spec/statement_spec.rb +0 -17
- data/vendor/rubyslim-0.1.1/spec/table_to_hash_converter_spec.rb +0 -31
@@ -1,159 +0,0 @@
|
|
1
|
-
Ruby Slim Protocol (V0.1)
|
2
|
-
=========================
|
3
|
-
|
4
|
-
Setup
|
5
|
-
-----
|
6
|
-
|
7
|
-
Put these command in a parent of the Ruby test pages.
|
8
|
-
|
9
|
-
!define TEST_SYSTEM {slim}
|
10
|
-
!define TEST_RUNNER {<wherever you put Ruby Slim>/lib/run_ruby_slim.rb}
|
11
|
-
!define COMMAND_PATTERN {ruby -I %p %m}
|
12
|
-
!define PATH_SEPARATOR {-I}
|
13
|
-
!path <wherever you put Ruby Slim>/lib
|
14
|
-
!path <any directory where you have ruby fixtures>
|
15
|
-
|
16
|
-
Paths can be relative. You should put the following in an appropriate SetUp page:
|
17
|
-
|
18
|
-
!|import|
|
19
|
-
|<ruby module of fixtures>|
|
20
|
-
|
21
|
-
You can have as many rows in this table as you like, one for each module that
|
22
|
-
contains fixtures. Note that this needs to be the *name* of the module as
|
23
|
-
written in the Ruby code, not the filename where the module is defined.
|
24
|
-
|
25
|
-
Ruby slim works a lot like Java slim. We tried to use ruby method naming
|
26
|
-
conventions. So if you put this in a table:
|
27
|
-
|
28
|
-
|SomeDecisionTable|
|
29
|
-
|input|get output?|
|
30
|
-
|1 |2 |
|
31
|
-
|
32
|
-
Then it will call the `set_input` and `get_output` functions of the
|
33
|
-
`SomeDecisionTable` class.
|
34
|
-
|
35
|
-
The `SomeDecisionTable` class would be written in a file called
|
36
|
-
`some_decision_table.rb`, like this (the file name must correspond to the class
|
37
|
-
name defined within, and the module name must match the one you are importing):
|
38
|
-
|
39
|
-
module MyModule
|
40
|
-
class SomeDecisionTable
|
41
|
-
def set_input(input)
|
42
|
-
@x = input
|
43
|
-
end
|
44
|
-
|
45
|
-
def get_output
|
46
|
-
@x
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
Note that there is no type information for the arguments of these functions, so
|
52
|
-
they will all be treated as strings. This is important to remember! All
|
53
|
-
arguments are strings. If you are expecting integers, you will have to convert
|
54
|
-
the strings to integers within your fixtures.
|
55
|
-
|
56
|
-
|
57
|
-
Hashes
|
58
|
-
------
|
59
|
-
|
60
|
-
There is one exception to the above rule. If you pass a HashWidget in a table,
|
61
|
-
then the argument will be converted to a Hash.
|
62
|
-
|
63
|
-
Consider, for example, this fixtures class:
|
64
|
-
|
65
|
-
module TestModule
|
66
|
-
class TestSlimWithArguments
|
67
|
-
def initialize(arg)
|
68
|
-
@arg = arg
|
69
|
-
end
|
70
|
-
|
71
|
-
def arg
|
72
|
-
@arg
|
73
|
-
end
|
74
|
-
|
75
|
-
def name
|
76
|
-
@arg[:name]
|
77
|
-
end
|
78
|
-
|
79
|
-
def addr
|
80
|
-
@arg[:addr]
|
81
|
-
end
|
82
|
-
|
83
|
-
def set_arg(hash)
|
84
|
-
@arg = hash
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
This corresponds to the following tables.
|
90
|
-
|
91
|
-
|script|test slim with arguments|!{name:bob addr:here}|
|
92
|
-
|check|name|bob|
|
93
|
-
|check|addr|here|
|
94
|
-
|
95
|
-
|script|test slim with arguments|gunk|
|
96
|
-
|check|arg|gunk|
|
97
|
-
|set arg|!{name:bob addr:here}|
|
98
|
-
|check|name|bob|
|
99
|
-
|check|addr|here|
|
100
|
-
|
101
|
-
Note the use of the HashWidgets in the table cells. These get translated into
|
102
|
-
HTML, which RubySlim recognizes and converts to a standard ruby `Hash`.
|
103
|
-
|
104
|
-
|
105
|
-
System Under Test
|
106
|
-
-----------------
|
107
|
-
|
108
|
-
If a fixture has a `sut` method that returns an object, then if a method called
|
109
|
-
by a test is not found in the fixture itself, then if it exists in the object
|
110
|
-
returned by `sut` it will be called. For example:
|
111
|
-
|
112
|
-
!|script|my fixture|
|
113
|
-
|func|1|
|
114
|
-
|
115
|
-
class MySystem
|
116
|
-
def func(x)
|
117
|
-
#this is the function that will be called.
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
class MyFixture
|
122
|
-
attr_reader :sut
|
123
|
-
|
124
|
-
def initialize
|
125
|
-
@sut = MySystem.new
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
Since the fixture `MyFixture` does not have a function named `func`, but it
|
130
|
-
_does_ have a method named `sut`, RubySlim will try to call `func` on the
|
131
|
-
object returned by `sut`.
|
132
|
-
|
133
|
-
|
134
|
-
Library Fixtures
|
135
|
-
----------------
|
136
|
-
|
137
|
-
Ruby Slim supports the `|Library|` feature of FitNesse. If you declare certain
|
138
|
-
classes to be libraries, then if a test calls a method, and the specified
|
139
|
-
fixture does not have it, and there is no specified `sut`, then the libraries
|
140
|
-
will be searched in reverse order (latest first). If the method is found, then
|
141
|
-
it is called.
|
142
|
-
|
143
|
-
For example:
|
144
|
-
|
145
|
-
|Library|
|
146
|
-
|echo fixture|
|
147
|
-
|
148
|
-
|script|
|
149
|
-
|check|echo|a|a|
|
150
|
-
|
151
|
-
class EchoFixture
|
152
|
-
def echo(x)
|
153
|
-
x
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
Here, even though no fixture was specified for the script table, since a
|
158
|
-
library was declared, functions will be called on it.
|
159
|
-
|
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'rake'
|
2
|
-
#require 'rcov/rcovtask'
|
3
|
-
require 'spec/rake/spectask'
|
4
|
-
|
5
|
-
task :default => :spec
|
6
|
-
|
7
|
-
desc "Run all spec tests"
|
8
|
-
Spec::Rake::SpecTask.new(:spec) do |t|
|
9
|
-
t.spec_files = Dir.glob('spec/**/*_spec.rb')
|
10
|
-
t.spec_opts = ['--color', '--format specdoc']
|
11
|
-
end
|
12
|
-
|
13
|
-
desc "Run all spec tests and generate coverage report"
|
14
|
-
Spec::Rake::SpecTask.new(:rcov) do |t|
|
15
|
-
t.spec_files = Dir.glob('spec/**/*_spec.rb')
|
16
|
-
# RCov doesn't like this part for some reason
|
17
|
-
#t.spec_opts = ['--color', '--format specdoc']
|
18
|
-
t.rcov = true
|
19
|
-
t.rcov_opts = %w{--exclude osx\/objc,gems\/,spec\/,features\/,lib\/test_module\/}
|
20
|
-
end
|
21
|
-
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'jcode'
|
2
|
-
|
3
|
-
module ListDeserializer
|
4
|
-
class SyntaxError < Exception
|
5
|
-
end
|
6
|
-
|
7
|
-
# De-serialize the given string, and return a Ruby-native list.
|
8
|
-
# Raises a SyntaxError if the string is empty or badly-formatted.
|
9
|
-
def self.deserialize(string)
|
10
|
-
raise SyntaxError.new("Can't deserialize null") if string.nil?
|
11
|
-
raise SyntaxError.new("Can't deserialize empty string") if string.empty?
|
12
|
-
raise SyntaxError.new("Serialized list has no starting [") if string[0..0] != "["
|
13
|
-
raise SyntaxError.new("Serialized list has no ending ]") if string[-1..-1] != "]"
|
14
|
-
Deserializer.new(string).deserialize
|
15
|
-
end
|
16
|
-
|
17
|
-
|
18
|
-
class Deserializer
|
19
|
-
def initialize(string)
|
20
|
-
@string = string;
|
21
|
-
end
|
22
|
-
|
23
|
-
def deserialize
|
24
|
-
@pos = 1
|
25
|
-
@list = []
|
26
|
-
number_of_items = consume_length
|
27
|
-
|
28
|
-
# For each item in the list
|
29
|
-
number_of_items.times do
|
30
|
-
length_of_item = consume_length
|
31
|
-
item = @string[@pos...@pos+length_of_item]
|
32
|
-
length_in_bytes = length_of_item
|
33
|
-
|
34
|
-
until (item.jlength > length_of_item) do
|
35
|
-
length_in_bytes += 1
|
36
|
-
item = @string[@pos...@pos+length_in_bytes]
|
37
|
-
end
|
38
|
-
|
39
|
-
length_in_bytes -= 1
|
40
|
-
item = @string[@pos...@pos+length_in_bytes]
|
41
|
-
|
42
|
-
# Ensure the ':' list-termination character is found
|
43
|
-
term_char = @string[@pos+length_in_bytes,1]
|
44
|
-
if term_char != ':'
|
45
|
-
raise SyntaxError.new("List termination character ':' not found" +
|
46
|
-
" (got '#{term_char}' instead)")
|
47
|
-
end
|
48
|
-
|
49
|
-
@pos += length_in_bytes+1
|
50
|
-
begin
|
51
|
-
sublist = ListDeserializer.deserialize(item)
|
52
|
-
@list << sublist
|
53
|
-
rescue ListDeserializer::SyntaxError
|
54
|
-
@list << item
|
55
|
-
end
|
56
|
-
end
|
57
|
-
@list
|
58
|
-
end
|
59
|
-
|
60
|
-
# Consume the 6-digit length prefix, and return the
|
61
|
-
# length as an integer.
|
62
|
-
def consume_length
|
63
|
-
length = @string[@pos...@pos+6].to_i
|
64
|
-
@pos += 7
|
65
|
-
length
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
require "rubyslim/statement"
|
2
|
-
require "rubyslim/statement_executor"
|
3
|
-
|
4
|
-
class ListExecutor
|
5
|
-
def initialize()
|
6
|
-
@executor = StatementExecutor.new
|
7
|
-
end
|
8
|
-
|
9
|
-
def execute(instructions)
|
10
|
-
instructions.collect {|instruction| Statement.execute(instruction, @executor)}
|
11
|
-
end
|
12
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'jcode'
|
2
|
-
|
3
|
-
module ListSerializer
|
4
|
-
# Serialize a list according to the SliM protocol.
|
5
|
-
#
|
6
|
-
# Lists are enclosed in square-brackets '[...]'. Inside the opening
|
7
|
-
# bracket is a six-digit number indicating the length of the list
|
8
|
-
# (number of items), then a colon ':', then the serialization of each
|
9
|
-
# list item. For example:
|
10
|
-
#
|
11
|
-
# [] => "[000000:]"
|
12
|
-
# ["hello"] => "[000001:000005:hello:]"
|
13
|
-
# [1] => "[000001:000001:1:]"
|
14
|
-
#
|
15
|
-
# Strings are preceded by a six-digit sequence indicating their length:
|
16
|
-
#
|
17
|
-
# "" => "000000:"
|
18
|
-
# "hello" => "000005:hello"
|
19
|
-
# nil => "000004:null"
|
20
|
-
#
|
21
|
-
# See spec/list_serializer_spec.rb for more examples.
|
22
|
-
#
|
23
|
-
def self.serialize(list)
|
24
|
-
result = "["
|
25
|
-
result += length_string(list.length)
|
26
|
-
|
27
|
-
# Serialize each item in the list
|
28
|
-
list.each do |item|
|
29
|
-
item = "null" if item.nil?
|
30
|
-
item = serialize(item) if item.is_a?(Array)
|
31
|
-
item = item.to_s
|
32
|
-
result += length_string(item.jlength)
|
33
|
-
result += item + ":"
|
34
|
-
end
|
35
|
-
|
36
|
-
result += "]"
|
37
|
-
end
|
38
|
-
|
39
|
-
|
40
|
-
# Return the six-digit prefix for an element of the given length.
|
41
|
-
def self.length_string(length)
|
42
|
-
sprintf("%06d:",length)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
@@ -1,61 +0,0 @@
|
|
1
|
-
require "rubyslim/socket_service"
|
2
|
-
require "rubyslim/list_deserializer"
|
3
|
-
require "rubyslim/list_serializer"
|
4
|
-
require "rubyslim/list_executor"
|
5
|
-
|
6
|
-
class RubySlim
|
7
|
-
def run(port)
|
8
|
-
@connected = true
|
9
|
-
@executor = ListExecutor.new
|
10
|
-
socket_service = SocketService.new()
|
11
|
-
socket_service.serve(port) do |socket|
|
12
|
-
serve_ruby_slim(socket)
|
13
|
-
end
|
14
|
-
|
15
|
-
while (@connected)
|
16
|
-
sleep(0.1)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# Read and execute instructions from the SliM socket, until a 'bye'
|
21
|
-
# instruction is reached. Each instruction is a list, serialized as a string,
|
22
|
-
# following the SliM protocol:
|
23
|
-
#
|
24
|
-
# length:command
|
25
|
-
#
|
26
|
-
# Where `length` is a 6-digit indicating the length in bytes of `command`,
|
27
|
-
# and `command` is a serialized list of instructions that may include any
|
28
|
-
# of the four standard instructions in the SliM protocol:
|
29
|
-
#
|
30
|
-
# Import: [<id>, import, <path>]
|
31
|
-
# Make: [<id>, make, <instance>, <class>, <arg>...]
|
32
|
-
# Call: [<id>, call, <instance>, <function>, <arg>...]
|
33
|
-
# CallAndAssign: [<id>, callAndAssign, <symbol>, <instance>, <function>, <arg>...]
|
34
|
-
#
|
35
|
-
# (from http://fitnesse.org/FitNesse.UserGuide.SliM.SlimProtocol)
|
36
|
-
#
|
37
|
-
def serve_ruby_slim(socket)
|
38
|
-
socket.puts("Slim -- V0.3");
|
39
|
-
said_bye = false
|
40
|
-
|
41
|
-
while !said_bye
|
42
|
-
length = socket.read(6).to_i # <length>
|
43
|
-
socket.read(1) # :
|
44
|
-
command = socket.read(length) # <command>
|
45
|
-
|
46
|
-
# Until a 'bye' command is received, deserialize the command, execute the
|
47
|
-
# instructions, and write a serialized response back to the socket.
|
48
|
-
if command.downcase != "bye"
|
49
|
-
instructions = ListDeserializer.deserialize(command);
|
50
|
-
results = @executor.execute(instructions)
|
51
|
-
response = ListSerializer.serialize(results);
|
52
|
-
socket.write(sprintf("%06d:%s", response.length, response))
|
53
|
-
socket.flush
|
54
|
-
else
|
55
|
-
said_bye = true
|
56
|
-
end
|
57
|
-
end
|
58
|
-
@connected = false
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
@@ -1,23 +0,0 @@
|
|
1
|
-
class SlimHelperLibrary
|
2
|
-
ACTOR_INSTANCE_NAME = "scriptTableActor"
|
3
|
-
attr_accessor :executor
|
4
|
-
|
5
|
-
def initialize(executor = nil)
|
6
|
-
@executor = executor
|
7
|
-
@fixtures = []
|
8
|
-
end
|
9
|
-
|
10
|
-
def get_fixture
|
11
|
-
executor.instance(ACTOR_INSTANCE_NAME)
|
12
|
-
end
|
13
|
-
|
14
|
-
def push_fixture
|
15
|
-
@fixtures << get_fixture
|
16
|
-
nil
|
17
|
-
end
|
18
|
-
|
19
|
-
def pop_fixture
|
20
|
-
executor.set_instance(ACTOR_INSTANCE_NAME, @fixtures.pop)
|
21
|
-
nil
|
22
|
-
end
|
23
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'socket'
|
2
|
-
require 'thread'
|
3
|
-
|
4
|
-
|
5
|
-
class SocketService
|
6
|
-
|
7
|
-
attr_reader :closed
|
8
|
-
|
9
|
-
def initialize()
|
10
|
-
@ropeSocket = nil
|
11
|
-
@group = ThreadGroup.new
|
12
|
-
@serviceThread = nil
|
13
|
-
end
|
14
|
-
|
15
|
-
def serve(port, &action)
|
16
|
-
@closed = false
|
17
|
-
@action = action
|
18
|
-
@ropeSocket = TCPServer.open(port)
|
19
|
-
@serviceThread = Thread.start {serviceTask}
|
20
|
-
@group.add(@serviceThread)
|
21
|
-
end
|
22
|
-
|
23
|
-
def pendingSessions
|
24
|
-
@group.list.size - ((@serviceThread != nil) ? 1 : 0)
|
25
|
-
end
|
26
|
-
|
27
|
-
def serviceTask
|
28
|
-
while true
|
29
|
-
Thread.start(@ropeSocket.accept) do |s|
|
30
|
-
serverTask(s)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def serverTask(s)
|
36
|
-
@action.call(s)
|
37
|
-
s.close
|
38
|
-
end
|
39
|
-
|
40
|
-
def close
|
41
|
-
@serviceThread.kill
|
42
|
-
@serviceThread = nil
|
43
|
-
@ropeSocket.close
|
44
|
-
waitForServers
|
45
|
-
@closed = true
|
46
|
-
end
|
47
|
-
|
48
|
-
def waitForServers
|
49
|
-
@group.list.each do |t|
|
50
|
-
t.join
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|