lackie 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :development do
4
+ gem 'bundler', '~> 1.0.7'
5
+ end
6
+
7
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,57 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ lackie (0.1.0)
5
+ rack (~> 1.2.1)
6
+ rest-client (~> 1.4.2)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ builder (2.1.2)
12
+ cgi_multipart_eof_fix (2.5.0)
13
+ cucumber (0.10.0)
14
+ builder (>= 2.1.2)
15
+ diff-lcs (~> 1.1.2)
16
+ gherkin (~> 2.3.2)
17
+ json (~> 1.4.6)
18
+ term-ansicolor (~> 1.0.5)
19
+ daemons (1.0.10)
20
+ diff-lcs (1.1.2)
21
+ fastthread (1.0.1)
22
+ gem_plugin (0.2.3)
23
+ gherkin (2.3.3)
24
+ json (~> 1.4.6)
25
+ json (1.4.6)
26
+ mime-types (1.16)
27
+ mongrel (1.1.5)
28
+ cgi_multipart_eof_fix (>= 2.4)
29
+ daemons (>= 1.0.3)
30
+ fastthread (>= 1.0.1)
31
+ gem_plugin (>= 0.2.3)
32
+ rack (1.2.1)
33
+ relevance-rcov (0.9.2.1)
34
+ rest-client (1.4.2)
35
+ mime-types (>= 1.16)
36
+ rspec (2.2.0)
37
+ rspec-core (~> 2.2)
38
+ rspec-expectations (~> 2.2)
39
+ rspec-mocks (~> 2.2)
40
+ rspec-core (2.3.1)
41
+ rspec-expectations (2.3.0)
42
+ diff-lcs (~> 1.1.2)
43
+ rspec-mocks (2.3.0)
44
+ term-ansicolor (1.0.5)
45
+
46
+ PLATFORMS
47
+ ruby
48
+
49
+ DEPENDENCIES
50
+ bundler (~> 1.0.7)
51
+ cucumber (~> 0.10.0)
52
+ lackie!
53
+ mongrel (~> 1.1.5)
54
+ rack (~> 1.2.1)
55
+ relevance-rcov (~> 0.9.2.1)
56
+ rest-client (~> 1.4.2)
57
+ rspec (~> 2.2.0)
data/README.rdoc ADDED
@@ -0,0 +1,65 @@
1
+ = Lackie
2
+
3
+ == Warning
4
+
5
+ I haven't used Lackie to develop an application yet. But I have used it in
6
+ various browsers including firefox, chrome and the samsung maple emulator.
7
+
8
+ == About
9
+
10
+ Lackie enables automation of remote applications using an HTTP middleman:
11
+
12
+ Ruby Client -> Lackie Service <- Remote App
13
+
14
+ Lackie automates applications running in environments that are difficult to
15
+ control remotely. Lackie requires minimal support in target environments:
16
+ scheduling (e.g. window.setInterval) and HTTP client capabilities (e.g. ajax).
17
+
18
+ Where it's difficult to programmatically launch the remote application, it can
19
+ be started manually before the automation begins. Lackie effectively "attaches"
20
+ itself to the running "zombie" application.
21
+
22
+ Lackie uses an HTTP service as a proxy for application automation commands:
23
+
24
+ 1. application surrenders control to automation
25
+ 2. the surrendered application polls Lackie for commands
26
+ 3. the automator sends a command to Lackie
27
+ 4. the application executes the command and sends the result to Lackie
28
+ 5. the automator polls Lackie and receives the result (or error)
29
+
30
+ == Usage
31
+
32
+ Lackie is implemented as rack middleware, so:
33
+
34
+ require 'rack'
35
+ require 'lackie'
36
+ require 'lackie/rack'
37
+
38
+ Rack::Builder.app do
39
+ use Lackie::Rack::Middleware
40
+ run MyApp
41
+ end
42
+
43
+ It will intercept all requests where the path starts with /lackie/
44
+
45
+ Lackie expects remote applications to:
46
+
47
+ 1. poll the middleware for commands expressed as strings
48
+ 2. execute those commands when they appear
49
+ 3. send string results back to the middleware
50
+
51
+ == Example
52
+
53
+ The source code includes an example rack app:
54
+
55
+ rackup features/support/config.ru
56
+
57
+ Open this URL in your browser of choice:
58
+
59
+ http://localhost:9292/example_app/app.html
60
+
61
+ Now you can execute commands in the remote application:
62
+
63
+ require 'rubygems'
64
+ require 'lackie'
65
+ Lackie::RemoteControl.new("localhost", 9292).exec("1 + 2") # => "3"
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc "Run all specs with rcov"
5
+ RSpec::Core::RakeTask.new(:rcov) do |t|
6
+ t.rcov = true
7
+ t.rcov_opts = %w{--exclude gems\/,spec\/,features\/}
8
+ end
9
+
10
+ desc "Run all specs, then all features"
11
+ task :default do
12
+ system("rspec spec && cucumber features")
13
+ end
@@ -0,0 +1,19 @@
1
+ Feature: Remote Control
2
+ In order to automate remote applications with HTTP client capabilities
3
+ As a client
4
+ I want to surrender applications as javascript lackies
5
+
6
+ Scenario: Remote Execution
7
+ Given I have surrendered my web page as a lackie
8
+ When I tell the lackie to execute "1 + 1"
9
+ Then I should see a result with the value "2"
10
+
11
+ Scenario: Remote Execution Error
12
+ Given I have surrendered my web page as a lackie
13
+ When I tell the lackie to execute "(function() { throw 'whoopsie'; })()"
14
+ Then I should see an error with the message "whoopsie"
15
+
16
+ Scenario: Remote Log
17
+ Given I have surrendered my web page as a lackie
18
+ When I tell the lackie to log "yipee"
19
+ Then I should see a result with the value "yipee"
@@ -0,0 +1,23 @@
1
+ Given /^I have surrendered my web page as a lackie$/ do
2
+ browse_example_app
3
+ end
4
+
5
+ When /^I tell the lackie to log "([^\"]*)"$/ do |message|
6
+ @response = remote_control.log(message)
7
+ end
8
+
9
+ When /^I tell the lackie to execute "([^\"]*)"$/ do |script|
10
+ begin
11
+ @response = remote_control.exec(script)
12
+ rescue => e
13
+ @error = e
14
+ end
15
+ end
16
+
17
+ Then /^I should see a result with the value "([^\"]*)"$/ do |value|
18
+ @response.to_s.should == value
19
+ end
20
+
21
+ Then /^I should see an error with the message "([^\"]*)"$/ do |message|
22
+ @error.message.should == message
23
+ end
@@ -0,0 +1,7 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ $:.unshift(File.dirname(__FILE__))
3
+
4
+ require 'lackie/rack'
5
+ require 'example_app'
6
+
7
+ run ExampleApp.build
@@ -0,0 +1,54 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ $:.unshift(File.dirname(__FILE__))
3
+
4
+ require 'rack'
5
+ require 'mongrel'
6
+ require 'selenium-webdriver'
7
+ require 'lackie'
8
+ require 'lackie/rack'
9
+ require 'example_app'
10
+
11
+ module LackieWorld
12
+ def remote_control
13
+ Lackie::RemoteControl.new(host, port)
14
+ end
15
+
16
+ def browse_example_app
17
+ web_driver.get "http://#{host}:#{port}/example_app/app.html"
18
+ end
19
+
20
+ private
21
+
22
+ def host
23
+ "localhost"
24
+ end
25
+
26
+ def port
27
+ 6663
28
+ end
29
+
30
+ def web_driver
31
+ @@web_driver ||= begin
32
+ start_server
33
+ driver = Selenium::WebDriver.for :firefox
34
+ at_exit { driver.close }
35
+ driver
36
+ end
37
+ end
38
+
39
+ def start_server
40
+ rack_server = nil
41
+ rack_thread = Thread.new do
42
+ ::Rack::Handler::Mongrel.run(ExampleApp.build, :Host => host, :Port => port) do |server|
43
+ rack_server = server
44
+ end
45
+ end
46
+ at_exit do
47
+ rack_server.stop
48
+ rack_thread.kill
49
+ end
50
+ sleep 0.05 while rack_server.nil?
51
+ end
52
+ end
53
+
54
+ World(LackieWorld)
@@ -0,0 +1,13 @@
1
+ <html>
2
+ <head>
3
+ <title>Lackie: Surrendered Web Page Example</title>
4
+ </head>
5
+ <body>
6
+
7
+ <!-- Lackie::RemoteControl#log creates elements under #LackieLog, if it exists -->
8
+ <div id="LackieLog" style="background-color:#ffffff"></div>
9
+
10
+ <script type="text/javascript" src="/lackie/surrender"></script>
11
+
12
+ </body>
13
+ </html>
@@ -0,0 +1,9 @@
1
+ class ExampleApp
2
+ def self.build
3
+ ::Rack::Builder.app do
4
+ use Lackie::Rack::Middleware
5
+ use Rack::Static, :urls => ["/example_app"], :root => File.dirname(__FILE__)
6
+ run lambda { |e| [404, {'Content-Type' => 'text/html'}, ['Not Found']] }
7
+ end
8
+ end
9
+ end
data/lackie.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
3
+ require "lackie"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'lackie'
7
+ s.version = Lackie::VERSION
8
+ s.authors = ['Josh Chisholm']
9
+ s.description = 'Automates remote applications using an HTTP middleman'
10
+ s.summary = "lackie-#{s.version}"
11
+ s.email = 'joshuachisholm@gmail.com'
12
+ s.homepage = 'http://github.com/joshski/lackie'
13
+
14
+ s.add_dependency 'rack', '~> 1.2.1'
15
+ s.add_dependency 'rest-client', '~> 1.4.2'
16
+
17
+ s.add_development_dependency 'rspec', '~> 2.2.0'
18
+ s.add_development_dependency 'cucumber', '~> 0.10.0'
19
+ s.add_development_dependency 'mongrel', '~> 1.1.5'
20
+ s.add_development_dependency 'relevance-rcov', '~> 0.9.2.1'
21
+
22
+ s.rubygems_version = "1.3.7"
23
+ s.files = `git ls-files`.split("\n")
24
+ s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
25
+ s.extra_rdoc_files = ["README.rdoc"]
26
+ s.require_path = "lib"
27
+ end