dom_glancy 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.ruby-version +1 -0
- data/.travis.yml +15 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +22 -0
- data/README.md +35 -0
- data/Rakefile +23 -0
- data/app/assets/javascripts/application.js +1 -0
- data/app/assets/stylesheets/1236_grid.css +21 -0
- data/app/assets/stylesheets/720_grid.css +33 -0
- data/app/assets/stylesheets/986_grid.css +24 -0
- data/app/assets/stylesheets/dom_glancy.css +134 -0
- data/app/assets/stylesheets/normalize.css +425 -0
- data/app/controllers/dom_glancy_application_controller.rb +8 -0
- data/app/controllers/dom_glancy_controller.rb +114 -0
- data/app/views/dom_glancy/about.html.erb +3 -0
- data/app/views/dom_glancy/artifacts.html.erb +16 -0
- data/app/views/dom_glancy/index.html.erb +12 -0
- data/app/views/dom_glancy/new.html.erb +15 -0
- data/app/views/dom_glancy/path_config.html.erb +8 -0
- data/app/views/dom_glancy/show.html.erb +42 -0
- data/app/views/layouts/dom_glancy.html.erb +32 -0
- data/app/views/shared/_dom_glancy_nav.html.erb +8 -0
- data/app/views/shared/_dom_set.html.erb +35 -0
- data/config/routes.rb +17 -0
- data/dom_glancy.gemspec +26 -0
- data/lib/dom_glancy/analysis.rb +141 -0
- data/lib/dom_glancy/dom_glancy.rb +121 -0
- data/lib/dom_glancy/element.rb +92 -0
- data/lib/dom_glancy/locations.rb +49 -0
- data/lib/dom_glancy/rails/engine.rb +7 -0
- data/lib/dom_glancy/svg.rb +71 -0
- data/lib/dom_glancy/version.rb +3 -0
- data/lib/dom_glancy.rb +7 -0
- data/test/page_objects/dom_glancy/about_page.rb +7 -0
- data/test/page_objects/dom_glancy/artifacts_page.rb +7 -0
- data/test/page_objects/dom_glancy/config_page.rb +19 -0
- data/test/page_objects/dom_glancy/index_page.rb +9 -0
- data/test/page_objects/dom_glancy/local_index_page.rb +7 -0
- data/test/page_objects/dom_glancy/new_page.rb +7 -0
- data/test/page_objects/dom_glancy/show_page.rb +15 -0
- data/test/page_objects/dom_glancy/viewer_page.rb +15 -0
- data/test/page_objects/navigation.rb +34 -0
- data/test/page_objects.rb +13 -0
- data/test/selenium/mapping_test.rb +118 -0
- data/test/selenium/viewer_test.rb +26 -0
- data/test/selenium_test_helper.rb +147 -0
- data/test/test_app/Gemfile +10 -0
- data/test/test_app/app/assets/stylesheets/local_app.css +25 -0
- data/test/test_app/app/controllers/application_controller.rb +2 -0
- data/test/test_app/app/controllers/local_controller.rb +8 -0
- data/test/test_app/app/views/layouts/local.html.erb +14 -0
- data/test/test_app/app/views/local/index.html.erb +45 -0
- data/test/test_app/config/database.yml +13 -0
- data/test/test_app/config/initializers/dom_glancy_initializer.rb +5 -0
- data/test/test_app/config/routes.rb +4 -0
- data/test/test_app/config.ru +31 -0
- data/test/test_app/test_app.rb +30 -0
- data/test/test_helper.rb +43 -0
- data/test/test_helpers/kracker_class_for_stubbing.rb +3 -0
- data/test/test_helpers/location_helpers.rb +28 -0
- data/test/test_objects/test_objects.rb +2031 -0
- data/test/unit/analysis_test.rb +111 -0
- data/test/unit/element_test.rb +47 -0
- data/test/unit/kracker_test.rb +79 -0
- data/test/unit/location_test.rb +23 -0
- data/watchr_script.rb +3 -0
- metadata +199 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
<div id="<%= finder_id %>">
|
2
|
+
<% if elements.length > 0 %>
|
3
|
+
<table class='kr--dom'>
|
4
|
+
<thead>
|
5
|
+
<tr>
|
6
|
+
<th>tag</th>
|
7
|
+
<th>id</th>
|
8
|
+
<th>class(s)</th>
|
9
|
+
<th>top</th>
|
10
|
+
<th>left</th>
|
11
|
+
<th>width</th>
|
12
|
+
<th>height</th>
|
13
|
+
<th>visible</th>
|
14
|
+
</tr>
|
15
|
+
</thead>
|
16
|
+
<tbody>
|
17
|
+
<% reset_cycle %>
|
18
|
+
<% elements.each do |element| %>
|
19
|
+
<tr onclick="highlightElement(<%= element[:js_id] %>);" class="<%= cycle("kr-dom_row_odd", "kr-dom_row_even") %>">
|
20
|
+
<td><%= element['tag'] %></td>
|
21
|
+
<td><%= element['id'] %></td>
|
22
|
+
<td><%= element['class'] %></td>
|
23
|
+
<td><%= element['top'] %></td>
|
24
|
+
<td><%= element['left'] %></td>
|
25
|
+
<td><%= element['width'] %></td>
|
26
|
+
<td><%= element['height'] %></td>
|
27
|
+
<td><%= element['visible'] %></td>
|
28
|
+
</tr>
|
29
|
+
<% end %>
|
30
|
+
</tbody>
|
31
|
+
</table>
|
32
|
+
<% else %>
|
33
|
+
<p>no elements found.</p>
|
34
|
+
<% end %>
|
35
|
+
</div>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
get 'dom_glancy' => "dom_glancy#index"
|
3
|
+
get 'dom_glancy/config' => "dom_glancy#path_config"
|
4
|
+
get 'dom_glancy/about' => "dom_glancy#about"
|
5
|
+
get 'dom_glancy/show/:diff_file' => "dom_glancy#show"
|
6
|
+
get 'dom_glancy/clear' => "dom_glancy#clear"
|
7
|
+
post 'dom_glancy/bless' => "dom_glancy#bless"#, :via => [:get, :post]
|
8
|
+
|
9
|
+
get 'dom_glancy/artifacts' => "dom_glancy#artifacts"
|
10
|
+
get 'dom_glancy/artifacts_delete/:file' => "dom_glancy#artifacts_delete"
|
11
|
+
get 'dom_glancy/artifacts_expand/:file' => "dom_glancy#artifacts_expand"
|
12
|
+
|
13
|
+
get 'dom_glancy/make_master/:file' => "dom_glancy#make_master"
|
14
|
+
get 'dom_glancy/delete_current/:file' => "dom_glancy#delete_current"
|
15
|
+
|
16
|
+
resources :dom_glancy
|
17
|
+
end
|
data/dom_glancy.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 'dom_glancy/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "dom_glancy"
|
8
|
+
spec.version = DomGlancy::VERSION
|
9
|
+
spec.authors = ["geordie"]
|
10
|
+
spec.email = ["george.speake@gmail.com"]
|
11
|
+
spec.description = %q{DOM Mapping}
|
12
|
+
spec.summary = %q{Map the page DOM and get some stats on it compared to a known default map.}
|
13
|
+
spec.homepage = "https://github.com/QuantumGeordie/dom_glancy"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
|
24
|
+
spec.add_dependency(%q<kramdown>, ["~> 1.1.0"])
|
25
|
+
spec.add_dependency 'capybara'
|
26
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module DomGlancy
|
2
|
+
|
3
|
+
def analyze(master_data, current_data, test_root = nil)
|
4
|
+
output_hash = {}
|
5
|
+
|
6
|
+
master_set = master_data.to_set
|
7
|
+
current_set = current_data.to_set
|
8
|
+
|
9
|
+
set_current_not_master = current_set - master_set
|
10
|
+
set_master_not_current = master_set - current_set
|
11
|
+
set_changed_master = Set.new
|
12
|
+
|
13
|
+
changed_element_pairs = []
|
14
|
+
if set_master_not_current.count > 0 || set_current_not_master.count > 0
|
15
|
+
|
16
|
+
ok_pairs = pairs_that_are_close_enough(set_current_not_master, set_master_not_current)
|
17
|
+
|
18
|
+
ok_pairs.each do |item1, item2|
|
19
|
+
set_current_not_master.delete(item1)
|
20
|
+
set_master_not_current.delete(item2)
|
21
|
+
end
|
22
|
+
|
23
|
+
changed_element_pairs = get_set_of_same_but_different(set_current_not_master, set_master_not_current)
|
24
|
+
|
25
|
+
changed_element_pairs.each do |item1, item2|
|
26
|
+
set_current_not_master.delete(item1)
|
27
|
+
set_current_not_master.delete(item2)
|
28
|
+
|
29
|
+
set_master_not_current.delete(item1)
|
30
|
+
set_master_not_current.delete(item2)
|
31
|
+
end
|
32
|
+
|
33
|
+
changed_element_pairs.select!{ |pair| !DOMElement.new(pair[0]).close_enough?(DOMElement.new(pair[1])) }
|
34
|
+
changed_element_pairs.each do |pair|
|
35
|
+
set_changed_master.add(pair.first)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
all_same = set_current_not_master.count == 0 && set_master_not_current.count == 0 && changed_element_pairs.count == 0
|
40
|
+
|
41
|
+
create_diff_file(set_current_not_master, set_master_not_current, set_changed_master, test_root) if test_root && !all_same
|
42
|
+
|
43
|
+
output_hash[:not_in_master] = set_current_not_master
|
44
|
+
output_hash[:not_in_current] = set_master_not_current
|
45
|
+
output_hash[:changed_element_pairs] = changed_element_pairs
|
46
|
+
output_hash[:same] = all_same
|
47
|
+
output_hash[:test_root] = test_root
|
48
|
+
output_hash
|
49
|
+
end
|
50
|
+
|
51
|
+
def make_svg(set_master_not_current, set_current_not_master, set_changed_master)
|
52
|
+
js_id = 0
|
53
|
+
set_master_not_current.each do |item|
|
54
|
+
item[:js_id] = js_id
|
55
|
+
js_id += 1
|
56
|
+
end
|
57
|
+
set_current_not_master.each do |item|
|
58
|
+
item[:js_id] = js_id
|
59
|
+
js_id += 1
|
60
|
+
end
|
61
|
+
set_changed_master.each do |item|
|
62
|
+
item[:js_id] = js_id
|
63
|
+
js_id += 1
|
64
|
+
end
|
65
|
+
|
66
|
+
rectangles = set_current_not_master.map { |item| item.merge(format__not_in_master) }
|
67
|
+
rectangles << set_master_not_current.map { |item| item.merge(format__not_in_current) }
|
68
|
+
rectangles << set_changed_master.map { |item| item.merge(format__same_but_different) }
|
69
|
+
rectangles.flatten!
|
70
|
+
|
71
|
+
generate_svg(rectangles)
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_diff_file(set_current_not_master, set_master_not_current, set_changed_master, test_root)
|
75
|
+
filename = DomGlancy.diff_filename(test_root)
|
76
|
+
svg = make_svg(set_current_not_master, set_master_not_current, set_changed_master)
|
77
|
+
File.open(filename, 'w') { |file| file.write(svg) }
|
78
|
+
save_set_info(test_root, 'current_not_master', set_current_not_master)
|
79
|
+
save_set_info(test_root, 'master_not_current', set_master_not_current)
|
80
|
+
save_set_info(test_root, 'changed_master', set_changed_master)
|
81
|
+
end
|
82
|
+
|
83
|
+
def save_set_info(test_root, suffix, data_set)
|
84
|
+
filename = File.join(DomGlancy.diff_file_location, "#{test_root}__#{suffix}__diff.yaml")
|
85
|
+
|
86
|
+
data_array = data_set.to_a
|
87
|
+
|
88
|
+
File.open(filename, 'w') { |file| file.write(data_array.to_yaml) }
|
89
|
+
end
|
90
|
+
|
91
|
+
def get_set_of_same_but_different(set1, set2)
|
92
|
+
same_but_different_pairs = []
|
93
|
+
set1.each do |item1|
|
94
|
+
element1 = DOMElement.new(item1)
|
95
|
+
set2.each do |item2|
|
96
|
+
element2 = DOMElement.new(item2)
|
97
|
+
if element1.same_element?(element2)
|
98
|
+
same_but_different_pairs << [item1, item2] #unless element1.close_enough?(element2)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
same_but_different_pairs
|
103
|
+
end
|
104
|
+
|
105
|
+
def pairs_that_are_close_enough(set1, set2)
|
106
|
+
ok_pairs = []
|
107
|
+
set1.each do |item1|
|
108
|
+
element1 = DOMElement.new(item1)
|
109
|
+
set2.each do |item2|
|
110
|
+
element2 = DOMElement.new(item2)
|
111
|
+
if element1.same_element?(element2) && element1.close_enough?(element2)
|
112
|
+
ok_pairs << [item1, item2]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
ok_pairs
|
117
|
+
end
|
118
|
+
|
119
|
+
def make_analysis_failure_report(analysis_data)
|
120
|
+
return '' if analysis_data[:same]
|
121
|
+
|
122
|
+
msg = ["\n------- DOM Comparison Failure ------"]
|
123
|
+
msg << "Elements not in master: #{analysis_data[:not_in_master].count}"
|
124
|
+
msg << "Elements not in current: #{analysis_data[:not_in_current].count}"
|
125
|
+
msg << "Changed elements: #{analysis_data[:changed_element_pairs].count}"
|
126
|
+
msg << "Files:"
|
127
|
+
msg << "\tcurrent: #{DomGlancy.current_filename(analysis_data[:test_root])}"
|
128
|
+
msg << "\tmaster: #{DomGlancy.master_filename(analysis_data[:test_root])}"
|
129
|
+
msg << "\tdifference: #{DomGlancy.diff_filename(analysis_data[:test_root])}"
|
130
|
+
msg << "Bless this current data set:"
|
131
|
+
msg << "\t#{blessing_copy_string(analysis_data[:test_root])}"
|
132
|
+
msg<< "-------------------------------------"
|
133
|
+
|
134
|
+
msg.join("\n")
|
135
|
+
end
|
136
|
+
|
137
|
+
def blessing_copy_string(test_root)
|
138
|
+
"cp #{DomGlancy.current_filename(test_root)} #{DomGlancy.master_filename(test_root)}"
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module DomGlancy
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
def page_map_same?(test_root)
|
5
|
+
purge_old_files_before_test(test_root)
|
6
|
+
|
7
|
+
result, msg = map_current_file(test_root)
|
8
|
+
return [result, msg] unless result
|
9
|
+
|
10
|
+
result, msg = master_file_exists?(test_root)
|
11
|
+
return [result, msg] unless result
|
12
|
+
|
13
|
+
result, msg, current_data = read_map_file(DomGlancy.current_filename(test_root))
|
14
|
+
return [result, msg] unless result
|
15
|
+
|
16
|
+
result, msg, master_data = read_map_file(DomGlancy.master_filename(test_root))
|
17
|
+
return [result, msg] unless result
|
18
|
+
|
19
|
+
analysis_data = analyze(master_data, current_data, test_root)
|
20
|
+
|
21
|
+
msg = make_analysis_failure_report(analysis_data)
|
22
|
+
result = analysis_data[:same]
|
23
|
+
|
24
|
+
File.delete DomGlancy.current_filename(test_root) if result
|
25
|
+
|
26
|
+
[result, msg]
|
27
|
+
end
|
28
|
+
|
29
|
+
def read_map_file(filename)
|
30
|
+
results = [true, '', nil]
|
31
|
+
begin
|
32
|
+
results[2] = YAML::load( File.open( filename ) )
|
33
|
+
rescue Exception => e
|
34
|
+
results = [false, "Error reading data from file: #{filename}", nil]
|
35
|
+
end
|
36
|
+
|
37
|
+
results
|
38
|
+
end
|
39
|
+
|
40
|
+
def map_current_file(test_root)
|
41
|
+
filename = DomGlancy.current_filename(test_root)
|
42
|
+
|
43
|
+
result = [true, '']
|
44
|
+
begin
|
45
|
+
data = perform_mapping_operation.to_yaml
|
46
|
+
File.open(filename, 'w') { |file| file.write(data) }
|
47
|
+
rescue Exception => e
|
48
|
+
result = [false, "map current file error: #{e.message}"]
|
49
|
+
end
|
50
|
+
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
def perform_mapping_operation
|
55
|
+
|
56
|
+
js = <<-JS
|
57
|
+
var dom_glancy = {
|
58
|
+
|
59
|
+
treeUp: function() {
|
60
|
+
var treeWalker = document.createTreeWalker(
|
61
|
+
document.body,
|
62
|
+
NodeFilter.SHOW_ELEMENT,
|
63
|
+
{ acceptNode: function(node) { return NodeFilter.FILTER_ACCEPT; } },
|
64
|
+
false
|
65
|
+
);
|
66
|
+
|
67
|
+
var nodeList = [];
|
68
|
+
|
69
|
+
while(treeWalker.nextNode()){
|
70
|
+
var cn = treeWalker.currentNode;
|
71
|
+
var node_details = {
|
72
|
+
"height" : cn.clientHeight,
|
73
|
+
"width" : cn.clientWidth,
|
74
|
+
"id" : cn.id,
|
75
|
+
"tag" : cn.tagName,
|
76
|
+
"class" : cn.className,
|
77
|
+
//"html" : cn.innerHTML,
|
78
|
+
"top" : cn.offsetTop,
|
79
|
+
"left" : cn.offsetLeft,
|
80
|
+
"visible" : dom_glancy.isVisible(cn)
|
81
|
+
}
|
82
|
+
nodeList.push(node_details);
|
83
|
+
}
|
84
|
+
|
85
|
+
return(nodeList);
|
86
|
+
},
|
87
|
+
|
88
|
+
isVisible: function(elem) {
|
89
|
+
return elem.offsetWidth > 0 || elem.offsetHeight > 0;
|
90
|
+
}
|
91
|
+
};
|
92
|
+
return dom_glancy.treeUp();
|
93
|
+
JS
|
94
|
+
|
95
|
+
page.driver.browser.execute_script(js)
|
96
|
+
end
|
97
|
+
|
98
|
+
def master_file_exists?(test_root)
|
99
|
+
filename = DomGlancy.master_filename(test_root)
|
100
|
+
result = File.exist?(filename)
|
101
|
+
msg = result ? '' : make_missing_master_failure_report(test_root)
|
102
|
+
[result, msg]
|
103
|
+
end
|
104
|
+
|
105
|
+
def make_missing_master_failure_report(test_root)
|
106
|
+
msg = ["\n------- DOM Comparison Failure ------"]
|
107
|
+
msg << "Master file does not exist. To make a new master from"
|
108
|
+
msg << "the current page, use this command:"
|
109
|
+
msg << "\t#{blessing_copy_string(test_root)}"
|
110
|
+
msg<< "-------------------------------------"
|
111
|
+
|
112
|
+
msg.join("\n")
|
113
|
+
end
|
114
|
+
|
115
|
+
def purge_old_files_before_test(test_root)
|
116
|
+
File.delete DomGlancy.current_filename(test_root) if File.exist?(DomGlancy.current_filename(test_root))
|
117
|
+
|
118
|
+
filename_pattern = File.join(DomGlancy.diff_file_location, "#{test_root}__*__diff.yaml")
|
119
|
+
Dir[filename_pattern].each { |file| file.delete(file) if File.exist?(file) }
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module DomGlancy
|
2
|
+
|
3
|
+
class DOMElement
|
4
|
+
## element looks like this in archive.
|
5
|
+
# {"id"=>"", "height"=>238, "visible"=>true, "tag"=>"DIV", "width"=>720, "class"=>"grid", "left"=>43, "top"=>14}
|
6
|
+
|
7
|
+
attr_accessor :id
|
8
|
+
attr_accessor :tag
|
9
|
+
attr_accessor :left
|
10
|
+
attr_accessor :top
|
11
|
+
attr_accessor :height
|
12
|
+
attr_accessor :width
|
13
|
+
attr_accessor :klass
|
14
|
+
attr_accessor :visible
|
15
|
+
attr_accessor :style
|
16
|
+
attr_accessor :similarity
|
17
|
+
|
18
|
+
def initialize(h = {})
|
19
|
+
@tag = h[:tag] || h['tag']
|
20
|
+
@left = h[:left] || h['left']
|
21
|
+
@top = h[:top] || h['top']
|
22
|
+
@height = h[:height] || h['height']
|
23
|
+
@width = h[:width] || h['width']
|
24
|
+
@klass = h[:class] || h['class']
|
25
|
+
@id = h[:id] || h['id']
|
26
|
+
@style = h[:style] || h['style']
|
27
|
+
@visible = h[:visible] || h['visible']
|
28
|
+
@similarity = h[:similarity] || h['similarity'] || 15
|
29
|
+
end
|
30
|
+
|
31
|
+
def same_element?(anOther)
|
32
|
+
same = same_tag?(anOther) &&
|
33
|
+
same_id?(anOther) &&
|
34
|
+
same_class?(anOther)
|
35
|
+
end
|
36
|
+
|
37
|
+
def all_same?(anOther)
|
38
|
+
same = same_element?(anOther) &&
|
39
|
+
similar_size?(anOther, 0) &&
|
40
|
+
similar_location?(anOther, 0) &&
|
41
|
+
same_size?(anOther) &&
|
42
|
+
same_visibility?(anOther)
|
43
|
+
end
|
44
|
+
|
45
|
+
def close_enough?(anOther)
|
46
|
+
r = same_element?(anOther) &&
|
47
|
+
similar_location?(anOther, @similarity) &&
|
48
|
+
similar_size?(anOther, @similarity) &&
|
49
|
+
same_style?(anOther) &&
|
50
|
+
same_visibility?(anOther)
|
51
|
+
end
|
52
|
+
|
53
|
+
def similar_size?(anOther, similarity = 0)
|
54
|
+
similar = (@height - anOther.height).abs <= similarity
|
55
|
+
similar && (@width - anOther.width).abs <= similarity
|
56
|
+
end
|
57
|
+
|
58
|
+
def similar_location?(anOther, similarity = 0)
|
59
|
+
similar = (@top - anOther.top).abs <= similarity
|
60
|
+
similar && (@left - anOther.left).abs <= similarity
|
61
|
+
end
|
62
|
+
|
63
|
+
def same_tag?(anOther)
|
64
|
+
@tag == anOther.tag
|
65
|
+
end
|
66
|
+
|
67
|
+
def same_location?(anOther)
|
68
|
+
(@left == anOther.left) && (@top == anOther.top)
|
69
|
+
end
|
70
|
+
|
71
|
+
def same_size?(anOther)
|
72
|
+
(@height == anOther.height) && (@width == anOther.width)
|
73
|
+
end
|
74
|
+
|
75
|
+
def same_class?(anOther)
|
76
|
+
@klass == anOther.klass
|
77
|
+
end
|
78
|
+
|
79
|
+
def same_id?(anOther)
|
80
|
+
@id == anOther.id
|
81
|
+
end
|
82
|
+
|
83
|
+
def same_visibility?(anOther)
|
84
|
+
@visible == anOther.visible
|
85
|
+
end
|
86
|
+
|
87
|
+
def same_style?(anOther)
|
88
|
+
@style == anOther.style
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module DomGlancy
|
2
|
+
|
3
|
+
@master_file_location = nil
|
4
|
+
@diff_file_location = nil
|
5
|
+
@current_file_location = nil
|
6
|
+
|
7
|
+
def self.master_file_location=(location)
|
8
|
+
@master_file_location = location
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.master_file_location
|
12
|
+
@master_file_location
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.diff_file_location=(location)
|
16
|
+
@diff_file_location = location
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.diff_file_location
|
20
|
+
@diff_file_location
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.current_file_location=(location)
|
24
|
+
@current_file_location = location
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.current_file_location
|
28
|
+
@current_file_location
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.create_comparison_directories
|
32
|
+
::FileUtils.mkdir_p(@master_file_location)
|
33
|
+
::FileUtils.mkdir_p(@diff_file_location)
|
34
|
+
::FileUtils.mkdir_p(@current_file_location)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.master_filename(test_root)
|
38
|
+
File.join(self.master_file_location, "#{test_root}_master.yaml")
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.current_filename(test_root)
|
42
|
+
File.join(self.current_file_location, "#{test_root}.yaml")
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.diff_filename(test_root)
|
46
|
+
File.join(self.diff_file_location, "#{test_root}_diff.html")
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module DomGlancy
|
2
|
+
|
3
|
+
def generate_svg(rectangles)
|
4
|
+
width, height = get_window_size_from_rectangles(rectangles)
|
5
|
+
s = svg_start(width, height)
|
6
|
+
|
7
|
+
rectangles.each do |rectangle|
|
8
|
+
rectangle_string = " <rect id='#{rectangle[:js_id]}' x = '#{rectangle['left']}' y = '#{rectangle['top']}' width = '#{rectangle['width']}' height = '#{rectangle['height']}' fill = '#{rectangle[:fill]}' stroke = '#{rectangle[:stroke]}' stroke-width = '#{rectangle[:stroke_width]}' fill-opacity = '#{rectangle[:opacity]}' />\n"
|
9
|
+
s += rectangle_string
|
10
|
+
end
|
11
|
+
|
12
|
+
s += svg_end
|
13
|
+
s += "\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_window_size_from_rectangles(rectangles)
|
17
|
+
width = 0
|
18
|
+
height = 0
|
19
|
+
|
20
|
+
rectangles.each do |rectangle|
|
21
|
+
rectangle_right = rectangle['left'].to_i + rectangle['width'].to_i
|
22
|
+
rectangle_bottom = rectangle['top'].to_i + rectangle['height'].to_i
|
23
|
+
width = rectangle_right if rectangle_right > width
|
24
|
+
height = rectangle_bottom if rectangle_bottom > height
|
25
|
+
end
|
26
|
+
|
27
|
+
[width, height]
|
28
|
+
end
|
29
|
+
|
30
|
+
def svg_start(width, height)
|
31
|
+
s = ["<?xml version='1.0' standalone='no'?>"]
|
32
|
+
s << " <!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>"
|
33
|
+
s << " <svg version = '1.1' width='#{width}px' height='#{height}px' border='2px' style='background-color:#FFFFFF;border:1px solid black;'>"
|
34
|
+
s << ''
|
35
|
+
|
36
|
+
s.join("\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
def svg_end
|
40
|
+
s = [' </svg>']
|
41
|
+
s << ''
|
42
|
+
|
43
|
+
s.join("\n")
|
44
|
+
end
|
45
|
+
|
46
|
+
def format__not_in_master
|
47
|
+
{
|
48
|
+
:stroke => 'blue',
|
49
|
+
:fill => 'white',
|
50
|
+
:stroke_width => '1',
|
51
|
+
:opacity => '0.5'
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def format__not_in_current
|
56
|
+
{
|
57
|
+
:stroke => 'red',
|
58
|
+
:fill => 'white',
|
59
|
+
:stroke_width => '1',
|
60
|
+
:opacity => '0.5'
|
61
|
+
}
|
62
|
+
end
|
63
|
+
def format__same_but_different
|
64
|
+
{
|
65
|
+
:stroke => 'orange',
|
66
|
+
:fill => 'white',
|
67
|
+
:stroke_width => '1',
|
68
|
+
:opacity => '0.5'
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
data/lib/dom_glancy.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module PageObjects
|
2
|
+
module DomGlancy
|
3
|
+
class ConfigPage < ViewerPage
|
4
|
+
path '/dom_glancy/config'
|
5
|
+
|
6
|
+
def master
|
7
|
+
node.find("#js-config_master").text
|
8
|
+
end
|
9
|
+
|
10
|
+
def current
|
11
|
+
node.find("#js-config_current").text
|
12
|
+
end
|
13
|
+
|
14
|
+
def diffs
|
15
|
+
node.find("#js-config_diffs").text
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module PageObjects
|
2
|
+
module DomGlancy
|
3
|
+
class ShowPage < ViewerPage
|
4
|
+
|
5
|
+
collection :not_master, :locator => "#js--not_master", :item_locator => 'table tbody tr'
|
6
|
+
collection :not_current, :locator => "#js--not_current", :item_locator => 'table tbody tr'
|
7
|
+
collection :changed, :locator => "#js--changed", :item_locator => 'table tbody tr'
|
8
|
+
|
9
|
+
def bless!
|
10
|
+
node.click_button 'Bless these differences'
|
11
|
+
IndexPage.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|