apophis 0.1.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 +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +10 -0
- data/Rakefile +10 -0
- data/apophis.gemspec +26 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/apophis.rb +21 -0
- data/lib/apophis/appium_runner.rb +68 -0
- data/lib/apophis/dotty_timeout.rb +15 -0
- data/lib/apophis/genymotion_runner.rb +47 -0
- data/lib/apophis/runner.rb +66 -0
- data/lib/apophis/version.rb +3 -0
- metadata +115 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 2c083648aea56d926aba4f20f65b54fa63852853
|
|
4
|
+
data.tar.gz: 68ff4acc72d7de6b3fe84baa0f4f668eb79479f9
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6f1930ff4b7a77b4c555a54e91329ff53cf7006a2c2fedcbed60c7ab6ba51caf4ddc4abb0013247a68596898ea7515227ed88259caa06e3c7a0ac074c556247f
|
|
7
|
+
data.tar.gz: eded73ec96c9a0524dd15f6dc97f190cb8a22630328596df73a42124613a11a8b5b223e749a7a6d6a0b56b99d743275b829b5d9d8f5907040d0be371651de327
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016 Dotan Nahum
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
data/apophis.gemspec
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'apophis/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "apophis"
|
|
8
|
+
spec.version = Apophis::VERSION
|
|
9
|
+
spec.authors = ["Dotan Nahum"]
|
|
10
|
+
spec.email = ["jondotan@gmail.com"]
|
|
11
|
+
|
|
12
|
+
spec.summary = %q{}
|
|
13
|
+
spec.description = %q{}
|
|
14
|
+
spec.homepage = "https://github.com/jondot/apophis"
|
|
15
|
+
spec.license = "MIT"
|
|
16
|
+
|
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
18
|
+
spec.bindir = "exe"
|
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
20
|
+
spec.require_paths = ["lib"]
|
|
21
|
+
|
|
22
|
+
spec.add_dependency "appium_lib", "~> 8.0.2"
|
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
|
25
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
|
26
|
+
end
|
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "apophis"
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require "pry"
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require "irb"
|
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/lib/apophis.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require "apophis/version"
|
|
2
|
+
require 'appium_lib'
|
|
3
|
+
|
|
4
|
+
module Apophis
|
|
5
|
+
# Your code goes here...
|
|
6
|
+
BANNER =<<'EOF'
|
|
7
|
+
.__ .__.
|
|
8
|
+
_____ ______ ____ ______ | |__ |__| ______
|
|
9
|
+
\__ \ \____ \ / _ \\____ \| | \| |/ ___/
|
|
10
|
+
/ __ \| |_> > <_> ) |_> > Y \ |\___ \
|
|
11
|
+
(____ / __/ \____/| __/|___| /__/____ >
|
|
12
|
+
\/|__| |__| \/ \/
|
|
13
|
+
EOF
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
require 'apophis/dotty_timeout'
|
|
17
|
+
require 'apophis/appium_runner'
|
|
18
|
+
require 'apophis/genymotion_runner'
|
|
19
|
+
require 'apophis/runner'
|
|
20
|
+
|
|
21
|
+
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require 'open-uri'
|
|
2
|
+
|
|
3
|
+
class AppiumRunner
|
|
4
|
+
|
|
5
|
+
def doctor!
|
|
6
|
+
errors = []
|
|
7
|
+
errors << "No valid appium install, or not available to this environment." unless system('appium -v > /dev/null')
|
|
8
|
+
errors << "No valid unix tooling: lsof" unless system('lsof -v > /dev/null 2>&1')
|
|
9
|
+
|
|
10
|
+
raise errors.join("\n") unless errors.empty?
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def any?
|
|
14
|
+
appiums.size > 0
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def available?(port)
|
|
18
|
+
!!find(port)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def kill_and_wait(port, timeout=10)
|
|
22
|
+
DottyTimeout.timeout(timeout) do
|
|
23
|
+
kill(port)
|
|
24
|
+
!available?(port)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def kill(port)
|
|
29
|
+
app = find(port)
|
|
30
|
+
return unless app
|
|
31
|
+
Process.kill('KILL', app[:pid])
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def find(port)
|
|
35
|
+
appiums.find{|app| app[:url] =~ /:#{port}/}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def launch_and_wait(port=4500, timeout=20)
|
|
39
|
+
port = find_available_port(port)
|
|
40
|
+
Process.spawn("appium -p #{port} -bp #{port+1} > /dev/null 2>&1")
|
|
41
|
+
DottyTimeout.timeout(timeout){ available?(port) }
|
|
42
|
+
|
|
43
|
+
{ port: port }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def probe(candidate)
|
|
47
|
+
begin
|
|
48
|
+
Timeout.timeout(0.5) do
|
|
49
|
+
res = JSON.parse(open("#{ candidate }/status").read)
|
|
50
|
+
!!res["value"]
|
|
51
|
+
end
|
|
52
|
+
rescue
|
|
53
|
+
false
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def find_available_port(above)
|
|
58
|
+
Selenium::WebDriver::PortProber.above(above)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def appiums
|
|
62
|
+
`lsof -P -n -i -sTCP:LISTEN`.lines.map(&:chomp) \
|
|
63
|
+
.map{|ln| ln =~ /\D+\s(\d+)\s.*TCP\s+(.*):(\d+)\s+\(LISTEN\)/; { pid: $1.to_i, url: "http://#{$2}:#{$3}/wd/hub".sub('*', 'localhost')} }
|
|
64
|
+
.select{|app| app[:pid] > 0}
|
|
65
|
+
.select{|app| probe(app[:url])}
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
|
|
2
|
+
module Apophis
|
|
3
|
+
class GenymotionRunner
|
|
4
|
+
ADB = '$ANDROID_HOME/platform-tools/adb'.freeze
|
|
5
|
+
GM = '/Applications/Genymotion.app/Contents/MacOS/player.app/Contents/MacOS/player'.freeze
|
|
6
|
+
LAUNCH_WAIT = 5
|
|
7
|
+
SPLASH_SLEEP = 5
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def initialize(gmroot=nil)
|
|
11
|
+
@gm = gmroot || GM
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def doctor!
|
|
15
|
+
errors = []
|
|
16
|
+
errors << "No valid Android tooling installed / or ANDROID_HOME not set: adb" unless system("#{ADB} version > /dev/null")
|
|
17
|
+
errors << "Cannot find genymotion at #{@gm}" unless system("ls #{@gm} > /dev/null")
|
|
18
|
+
|
|
19
|
+
raise errors.join("\n") unless errors.empty?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def devices
|
|
23
|
+
out = `#{ADB} devices`
|
|
24
|
+
out.lines.map(&:chop).reject{|line|line.start_with?('*')}.reject(&:empty?)[1..-1]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def launch(name, timeout=180)
|
|
28
|
+
DottyTimeout.timeout(timeout) do
|
|
29
|
+
Process.spawn("#{@gm} --vm-name '#{name}' > /dev/null 2>&1", out:'/dev/null', err:'/dev/null')
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
wait_for_android_device(LAUNCH_WAIT)
|
|
33
|
+
return true
|
|
34
|
+
rescue
|
|
35
|
+
end
|
|
36
|
+
false
|
|
37
|
+
end
|
|
38
|
+
sleep(SPLASH_SLEEP)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def wait_for_android_device(timeout=5) #later, add an id for specific device
|
|
42
|
+
DottyTimeout.timeout(timeout) do
|
|
43
|
+
devices.size > 0
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module Apophis
|
|
2
|
+
class Runner
|
|
3
|
+
def initialize(log=nil)
|
|
4
|
+
@log = log
|
|
5
|
+
unless log
|
|
6
|
+
@log = Logger.new($stdout)
|
|
7
|
+
@log.formatter = proc do |severity, datetime, progname, msg|
|
|
8
|
+
date_format = datetime.strftime("%Y-%m-%d %H:%M:%S")
|
|
9
|
+
"[#{date_format}] #{severity}: #{msg}\n"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def start(caps)
|
|
15
|
+
@log.info "\n#{Apophis::BANNER}\n"
|
|
16
|
+
gm = GenymotionRunner.new
|
|
17
|
+
gm.doctor!
|
|
18
|
+
|
|
19
|
+
if caps[:runner] && caps[:runner][:genymotion] && gm.devices.empty?
|
|
20
|
+
@log.info '---> no android device found, launching genymotion...'
|
|
21
|
+
gm.launch(caps[:runner][:genymotion])
|
|
22
|
+
@log.info '---> devices available:'
|
|
23
|
+
@log.info gm.devices.join("\n")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
ar = AppiumRunner.new
|
|
27
|
+
ar.doctor!
|
|
28
|
+
|
|
29
|
+
appiums = ar.appiums
|
|
30
|
+
@log.info "appiums: #{appiums}"
|
|
31
|
+
if appiums.size > 0
|
|
32
|
+
@log.info '---> being a douch and killing all running appiums.'
|
|
33
|
+
@log.info '---> improve me later to map caps->device->device uuid->appium->appium session.'
|
|
34
|
+
appiums.each do |app|
|
|
35
|
+
@log.info "---> killing appium #{ app }"
|
|
36
|
+
ar.kill_and_wait(app[:port])
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
unless ar.any?
|
|
41
|
+
@log.info '---> no appium found. launching...'
|
|
42
|
+
launchinfo = ar.launch_and_wait
|
|
43
|
+
caps[:appium_lib][:port] = launchinfo[:port]
|
|
44
|
+
@log.info "---> done. wiring caps to appium #{launchinfo}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@log.info "---> starting driver..."
|
|
49
|
+
Appium::Driver.new(caps).start_driver
|
|
50
|
+
Appium.promote_appium_methods Minitest::Spec
|
|
51
|
+
@log.info "---> done"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#
|
|
55
|
+
# note: Appium::Driver.new(..).start_driver is
|
|
56
|
+
# sucky in that it populates $driver, which
|
|
57
|
+
# #promote_appium_methods rely on. We'll have no
|
|
58
|
+
# choice but chip-in on this nonsense when we
|
|
59
|
+
# want to do cleanups etc.
|
|
60
|
+
def cleanup
|
|
61
|
+
@log.info '---> cleaning up...'
|
|
62
|
+
$driver.driver_quit if $driver
|
|
63
|
+
@log.info '---> done.'
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: apophis
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Dotan Nahum
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2016-08-17 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: appium_lib
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 8.0.2
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 8.0.2
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: bundler
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.11'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.11'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '10.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '10.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: minitest
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '5.0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '5.0'
|
|
69
|
+
description: ''
|
|
70
|
+
email:
|
|
71
|
+
- jondotan@gmail.com
|
|
72
|
+
executables: []
|
|
73
|
+
extensions: []
|
|
74
|
+
extra_rdoc_files: []
|
|
75
|
+
files:
|
|
76
|
+
- ".gitignore"
|
|
77
|
+
- ".travis.yml"
|
|
78
|
+
- Gemfile
|
|
79
|
+
- LICENSE.txt
|
|
80
|
+
- README.md
|
|
81
|
+
- Rakefile
|
|
82
|
+
- apophis.gemspec
|
|
83
|
+
- bin/console
|
|
84
|
+
- bin/setup
|
|
85
|
+
- lib/apophis.rb
|
|
86
|
+
- lib/apophis/appium_runner.rb
|
|
87
|
+
- lib/apophis/dotty_timeout.rb
|
|
88
|
+
- lib/apophis/genymotion_runner.rb
|
|
89
|
+
- lib/apophis/runner.rb
|
|
90
|
+
- lib/apophis/version.rb
|
|
91
|
+
homepage: https://github.com/jondot/apophis
|
|
92
|
+
licenses:
|
|
93
|
+
- MIT
|
|
94
|
+
metadata: {}
|
|
95
|
+
post_install_message:
|
|
96
|
+
rdoc_options: []
|
|
97
|
+
require_paths:
|
|
98
|
+
- lib
|
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
|
+
requirements:
|
|
106
|
+
- - ">="
|
|
107
|
+
- !ruby/object:Gem::Version
|
|
108
|
+
version: '0'
|
|
109
|
+
requirements: []
|
|
110
|
+
rubyforge_project:
|
|
111
|
+
rubygems_version: 2.5.1
|
|
112
|
+
signing_key:
|
|
113
|
+
specification_version: 4
|
|
114
|
+
summary: ''
|
|
115
|
+
test_files: []
|