watchdoge 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: dc87007d94c7fcac5e1eafccc71c3aae806adf2b3e7448a1f65e126bb10e049b
4
+ data.tar.gz: 1e194cbde4a75ecd82f365bff1be0e736c07b92e5555491e32ab20bda7a1412a
5
+ SHA512:
6
+ metadata.gz: e27a802f2ea1a8b79d7ddf9638f3af28bacc90cbdf9a060d48e42c646ff334aae9431e0b898ef6c23d8311db2af06826edff0b321f393f3d652f8d4927cd639a
7
+ data.tar.gz: 50bd1bc2d8c3e21deb6e8bb112d2c1f68f3d518017d55be020617fd938dae623a41b99b89f46f0a55cec83e24b7d40783303a50d5a2cd71b155ecbde718c26aa
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ .doge_cookie/
2
+ .webdrivers/
3
+ lib/test.rb
@@ -0,0 +1,28 @@
1
+ require 'watir'
2
+
3
+ module WatchDoge
4
+ class Configuration
5
+ attr_accessor :base_dir
6
+ attr_accessor :web_drivers_dir
7
+ attr_accessor :engine
8
+ attr_accessor :cookie_pool
9
+ attr_accessor :notifications
10
+
11
+ def initialize
12
+ @base_dir = File.expand_path(File.dirname(__FILE__) + '/..')
13
+
14
+ @web_drivers_dir = @base_dir + "/.webdrivers"
15
+
16
+ # cuurently using local fs, probably support NoSQL also maybe?
17
+ @cookie_pool = @base_dir + '/.doge_cookie'
18
+
19
+ @engine = Watir::Browser
20
+
21
+ @notifications = {
22
+ # slack: {
23
+ # incoming_url: SLACK_WEBHOOK
24
+ # }
25
+ }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ require 'yaml'
2
+ require 'digest'
3
+
4
+ module WatchDoge
5
+ module CookiePool
6
+ class << self
7
+ def source uuid, uri = nil
8
+ suffix = "_#{Digest::MD5.hexdigest(uri.to_s)[0..5]}" if uri
9
+
10
+ "#{WatchDoge.configuration.cookie_pool}/#{uuid}#{suffix}"
11
+ end
12
+
13
+ # TODO: implement these two methods return Cookie object in future.
14
+ # def save uuid, json
15
+ # File.write source(uuid), json
16
+ # end
17
+
18
+ # def load uuid
19
+ # return "" unless File.exist? source(uuid)
20
+
21
+ # JSON.parse File.read(source(uuid))
22
+ # end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ module WatchDoge
2
+ module ImageDiff
3
+ OPACITY = 0.6
4
+ HIGHLIGHT_COLOR = "#F163FF#{(OPACITY * 256).to_i.to_s(16).upcase}"
5
+
6
+ class << self
7
+ def diff input_image, golden_image
8
+ return nil if input_image.pixels.hash == golden_image.pixels.hash
9
+
10
+ input_image.height.times do |y|
11
+ pixels = input_image.row(y)
12
+
13
+ if y >= golden_image.height
14
+ pixels.each_with_index do |pixel, x|
15
+ input_image.compose_pixel(x, y, HIGHLIGHT_COLOR)
16
+ end
17
+ else
18
+ golden_pixels = golden_image.row(y)
19
+
20
+ next if (pixels.hash == golden_pixels.hash)
21
+
22
+ pixels.each_with_index do |pixel, x|
23
+ input_image.compose_pixel(x, y, HIGHLIGHT_COLOR) if pixels[x] != golden_pixels[x]
24
+ end
25
+ end
26
+ end
27
+
28
+ input_image
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ require 'net_http_ssl_fix'
2
+ require 'webdrivers'
3
+
4
+ module WatchDoge
5
+ class << self
6
+ def install
7
+ Webdrivers.install_dir = configuration.web_drivers_dir
8
+
9
+ # TODO: Support other browser maybe?
10
+ Webdrivers::Geckodriver.update
11
+
12
+ Dir.mkdir configuration.cookie_pool unless File.directory? configuration.cookie_pool
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,40 @@
1
+ require 'chunky_png'
2
+ require 'json'
3
+ require 'net/http'
4
+ require 'uri'
5
+
6
+ module WatchDoge
7
+ module Notification
8
+ class Slack
9
+ def initialize opt
10
+ @incoming_url = opt[:incoming_url]
11
+ end
12
+
13
+ def push message
14
+ body = _slack_body(message).to_json
15
+ Net::HTTP.post URI(@incoming_url),
16
+ body,
17
+ "Content-Type" => "application/json"
18
+ end
19
+
20
+ private
21
+
22
+ def _slack_body message
23
+ case message
24
+ when String
25
+ {
26
+ text: message
27
+ }
28
+ when ChunkyPNG::Image
29
+ data = ['data:image/png;base64,', message.to_blob].pack('A*m').gsub(/\n/, '')
30
+
31
+ {
32
+ attachments: [{
33
+ image_url: data
34
+ }]
35
+ }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,28 @@
1
+ module WatchDoge
2
+ module Notification
3
+ Dir["#{File.expand_path File.dirname(__FILE__)}/notification/*.rb"].each {|file| require file }
4
+
5
+ class << self
6
+ def push message
7
+ sources = WatchDoge.configuration.notifications
8
+
9
+ raise "can't find notification sources in configuration" if sources.empty?
10
+
11
+ sources.each do |source_sym, source_args|
12
+ source_class = get_source_class source_sym
13
+ source = source_class.new source_args
14
+ source.push message
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def get_source_class source_sym
21
+ case source_sym
22
+ when :slack
23
+ WatchDoge::Notification::Slack
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module WatchDoge
2
+ Version = '0.0.1'
3
+ end
@@ -0,0 +1,118 @@
1
+ module WatchDoge
2
+ module PDFUtil
3
+ def pdf_screenshot
4
+ # no such thing as on_loaded for gecko pdf-viewer
5
+ sleep 3
6
+
7
+ firefox_pdf_viewer_id = 'viewer'
8
+ firefox_scaler_id = 'scaleSelect'
9
+ scale_factor = '0.75'
10
+
11
+ #resize to 75%
12
+ @core.select({id: firefox_scaler_id}).select(scale_factor)
13
+
14
+ fullpage_screenshot({id: firefox_pdf_viewer_id})
15
+ end
16
+ end
17
+
18
+ class Worker
19
+ include WatchDoge::PDFUtil
20
+
21
+ def initialize uuid, opt={}
22
+ _before_initialize
23
+
24
+ @uuid = uuid
25
+
26
+ default_opt = {
27
+ width: 1024,
28
+ height: 768,
29
+ headless: true
30
+ }.merge(opt)
31
+
32
+ @core = WatchDoge.configuration.engine.new :firefox, default_opt
33
+
34
+ # for generate uri hash
35
+ @landed_page = nil
36
+
37
+ # flag that cookie is loaded
38
+ @cookie_loaded = false
39
+
40
+ @width = default_opt[:width]
41
+ @height = default_opt[:height]
42
+
43
+ # initilize width/height
44
+ @core.window.resize_to @width, @height
45
+
46
+ _after_initialize
47
+ end
48
+
49
+ def fullpage_screenshot **kwargs
50
+ _resize_by_document(kwargs) do
51
+ return @core.screenshot
52
+ end
53
+ end
54
+
55
+ def close
56
+ _save_cookie
57
+ @core.close
58
+ end
59
+
60
+ def goto uri
61
+ @core.goto uri
62
+
63
+ @landed_page = uri
64
+
65
+ _load_cookie unless _cookie_loaded?
66
+
67
+ @core.refresh
68
+ end
69
+
70
+ # for dev only
71
+ def core
72
+ @core
73
+ end
74
+
75
+ private
76
+ # callbacks before/after init
77
+ def _before_initialize
78
+ Selenium::WebDriver::Firefox::Service.driver_path = WatchDoge.configuration.web_drivers_dir + "/geckodriver"
79
+ end
80
+ def _after_initialize
81
+ end
82
+
83
+ # for cookie load/save
84
+ def _cookie_loaded?
85
+ @cookie_loaded
86
+ end
87
+ def _save_cookie
88
+ @core.cookies.save WatchDoge::CookiePool.source(@uuid, @landed_page)
89
+ end
90
+ def _load_cookie
91
+ source = WatchDoge::CookiePool.source(@uuid, @landed_page)
92
+ return unless File.exist? source
93
+
94
+ @core.cookies.load source
95
+ @cookie_loaded = true
96
+ end
97
+
98
+ def _resize_by_document **kwargs
99
+ target =
100
+ if kwargs.empty?
101
+ @core.body
102
+ else
103
+ @core.element(**kwargs)
104
+ end
105
+
106
+ @core.window.resize_to [target.width, 5000].min, [target.height, 20000].min
107
+ yield
108
+ @core.window.resize_to @width, @height
109
+ end
110
+
111
+ # try delegate all methods to @core
112
+ def method_missing(method_name, *args)
113
+ result = @core.__send__(method_name, *args)
114
+
115
+ result
116
+ end
117
+ end
118
+ end
data/lib/watchdoge.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'pry'
2
+ require 'watchdoge/install'
3
+ require 'watchdoge/version'
4
+ require 'watchdoge/configuration'
5
+ require 'watchdoge/cookie_pool'
6
+ require 'watchdoge/worker'
7
+ require 'watchdoge/notification'
8
+ require 'watchdoge/image_diff'
9
+
10
+ module WatchDoge
11
+ class << self
12
+ def base_dir
13
+ configuration.base_dir
14
+ end
15
+
16
+ def configure(&block)
17
+ yield(configuration)
18
+ configuration
19
+ end
20
+
21
+ def configuration
22
+ @_configuration ||= Configuration.new
23
+ end
24
+ end
25
+ end
data/watchdoge.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'watchdoge'
3
+ s.version = '0.0.1'
4
+ s.date = '2019-07-22'
5
+ s.summary = "dogi"
6
+ s.description = "A collection of web test tools"
7
+ s.authors = ["Shen Lee"]
8
+ s.email = 'no-reply@gmail.com'
9
+ s.files = ["lib/watchdoge.rb"]
10
+ s.license = 'MIT'
11
+
12
+ s.files = `git ls-files`.split($/)
13
+ s.require_paths = ["lib"]
14
+
15
+ s.add_dependency "chunky_png", "~> 1.3", "> 1.3.10"
16
+ s.add_dependency "net_http_ssl_fix", "~> 0.0.10"
17
+ s.add_dependency "webdrivers", "~> 4.1", "> 4.1.0"
18
+ s.add_dependency "watir", "~> 6.16", "> 6.16.0"
19
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: watchdoge
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Shen Lee
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-07-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: chunky_png
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ - - ">"
21
+ - !ruby/object:Gem::Version
22
+ version: 1.3.10
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - - ">"
31
+ - !ruby/object:Gem::Version
32
+ version: 1.3.10
33
+ - !ruby/object:Gem::Dependency
34
+ name: net_http_ssl_fix
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.0.10
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.0.10
47
+ - !ruby/object:Gem::Dependency
48
+ name: webdrivers
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">"
52
+ - !ruby/object:Gem::Version
53
+ version: 4.1.0
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '4.1'
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">"
62
+ - !ruby/object:Gem::Version
63
+ version: 4.1.0
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '4.1'
67
+ - !ruby/object:Gem::Dependency
68
+ name: watir
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">"
72
+ - !ruby/object:Gem::Version
73
+ version: 6.16.0
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '6.16'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">"
82
+ - !ruby/object:Gem::Version
83
+ version: 6.16.0
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: '6.16'
87
+ description: A collection of web test tools
88
+ email: no-reply@gmail.com
89
+ executables: []
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - ".gitignore"
94
+ - lib/watchdoge.rb
95
+ - lib/watchdoge/configuration.rb
96
+ - lib/watchdoge/cookie_pool.rb
97
+ - lib/watchdoge/image_diff.rb
98
+ - lib/watchdoge/install.rb
99
+ - lib/watchdoge/notification.rb
100
+ - lib/watchdoge/notification/slack.rb
101
+ - lib/watchdoge/version.rb
102
+ - lib/watchdoge/worker.rb
103
+ - watchdoge.gemspec
104
+ homepage:
105
+ licenses:
106
+ - MIT
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubygems_version: 3.0.3
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: dogi
127
+ test_files: []