kracker 0.0.1
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 +21 -0
- data/.ruby-version +1 -0
- data/.travis.yml +14 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +22 -0
- data/README.md +33 -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/kracker.css +134 -0
- data/app/assets/stylesheets/normalize.css +425 -0
- data/app/controllers/kracker_application_controller.rb +8 -0
- data/app/controllers/kracker_controller.rb +114 -0
- data/app/views/kracker/about.html.erb +3 -0
- data/app/views/kracker/artifacts.html.erb +16 -0
- data/app/views/kracker/index.html.erb +12 -0
- data/app/views/kracker/new.html.erb +15 -0
- data/app/views/kracker/path_config.html.erb +8 -0
- data/app/views/kracker/show.html.erb +42 -0
- data/app/views/layouts/kracker.html.erb +32 -0
- data/app/views/shared/_dom_set.html.erb +35 -0
- data/app/views/shared/_kracker_nav.html.erb +8 -0
- data/config/routes.rb +17 -0
- data/kracker.gemspec +27 -0
- data/lib/kracker/analysis.rb +114 -0
- data/lib/kracker/element.rb +92 -0
- data/lib/kracker/kracker.rb +112 -0
- data/lib/kracker/locations.rb +49 -0
- data/lib/kracker/rails/engine.rb +7 -0
- data/lib/kracker/svg.rb +71 -0
- data/lib/kracker/version.rb +3 -0
- data/lib/kracker.rb +7 -0
- data/test/page_objects/kracker/about_page.rb +7 -0
- data/test/page_objects/kracker/artifacts_page.rb +7 -0
- data/test/page_objects/kracker/config_page.rb +19 -0
- data/test/page_objects/kracker/index_page.rb +9 -0
- data/test/page_objects/kracker/local_index_page.rb +7 -0
- data/test/page_objects/kracker/new_page.rb +7 -0
- data/test/page_objects/kracker/show_page.rb +15 -0
- data/test/page_objects/kracker/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 +98 -0
- data/test/selenium/viewer_test.rb +25 -0
- data/test/selenium_test_helper.rb +102 -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/kracker_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 +41 -0
- data/test/test_helpers/kracker_class_for_stubbing.rb +3 -0
- data/test/test_helpers/location_helpers.rb +29 -0
- data/test/test_objects/test_objects.rb +30 -0
- data/test/unit/analysis_test.rb +87 -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>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<div class="row" id="js-kr--nav"></a>
|
2
|
+
<a href="/kracker/" class="kr"><div class="slot-0 kr--nav">home</div></a>
|
3
|
+
<a href="/kracker/new" class="kr"><div class="slot-1 kr--nav">new</div></a>
|
4
|
+
<a href="/kracker/artifacts" class="kr"><div class="slot-2 kr--nav">artifacts</div></a>
|
5
|
+
<a href="/kracker/config" class="kr"><div class="slot-3 kr--nav">config</div></a>
|
6
|
+
<a href="/kracker/clear" class="kr"><div class="slot-4 kr--nav">clear</div></a>
|
7
|
+
<a href="/kracker/about" class="kr"><div class="slot-5 kr--nav">about</div></a>
|
8
|
+
</div>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
match 'kracker' => "kracker#index"
|
3
|
+
match 'kracker/config' => "kracker#path_config"
|
4
|
+
match 'kracker/about' => "kracker#about"
|
5
|
+
match 'kracker/show/:diff_file' => "kracker#show"
|
6
|
+
match 'kracker/clear' => "kracker#clear"
|
7
|
+
match 'kracker/bless' => "kracker#bless"
|
8
|
+
|
9
|
+
match 'kracker/artifacts' => "kracker#artifacts"
|
10
|
+
match 'kracker/artifacts_delete/:file' => "kracker#artifacts_delete"
|
11
|
+
match 'kracker/artifacts_expand/:file' => "kracker#artifacts_expand"
|
12
|
+
|
13
|
+
match 'kracker/make_master/:file' => "kracker#make_master"
|
14
|
+
match 'kracker/delete_current/:file' => "kracker#delete_current"
|
15
|
+
|
16
|
+
resources :kracker
|
17
|
+
end
|
data/kracker.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'kracker/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "kracker"
|
8
|
+
spec.version = Kracker::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/kracker"
|
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
|
+
|
27
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Kracker
|
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
|
+
changed_element_pairs = get_set_of_same_but_different(set_current_not_master, set_master_not_current)
|
16
|
+
|
17
|
+
changed_element_pairs.each do |item1, item2|
|
18
|
+
set_current_not_master.delete(item1)
|
19
|
+
set_current_not_master.delete(item2)
|
20
|
+
|
21
|
+
set_master_not_current.delete(item1)
|
22
|
+
set_master_not_current.delete(item2)
|
23
|
+
end
|
24
|
+
|
25
|
+
changed_element_pairs.select!{ |pair| !DOMElement.new(pair[0]).close_enough?(DOMElement.new(pair[1])) }
|
26
|
+
changed_element_pairs.each do |pair|
|
27
|
+
set_changed_master.add(pair.first)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
all_same = set_current_not_master.count == 0 && set_master_not_current.count == 0 && changed_element_pairs.count == 0
|
32
|
+
|
33
|
+
create_diff_file(set_current_not_master, set_master_not_current, set_changed_master, test_root) if test_root && !all_same
|
34
|
+
|
35
|
+
output_hash[:not_in_master] = set_current_not_master
|
36
|
+
output_hash[:not_in_current] = set_master_not_current
|
37
|
+
output_hash[:changed_element_pairs] = changed_element_pairs
|
38
|
+
output_hash[:same] = all_same
|
39
|
+
output_hash[:test_root] = test_root
|
40
|
+
output_hash
|
41
|
+
end
|
42
|
+
|
43
|
+
def make_svg(set_master_not_current, set_current_not_master)
|
44
|
+
js_id = 0
|
45
|
+
set_master_not_current.each do |item|
|
46
|
+
item[:js_id] = js_id
|
47
|
+
js_id += 1
|
48
|
+
end
|
49
|
+
set_current_not_master.each do |item|
|
50
|
+
item[:js_id] = js_id
|
51
|
+
js_id += 1
|
52
|
+
end
|
53
|
+
|
54
|
+
rectangles = set_current_not_master.map { |item| item.merge(format__not_in_master) }
|
55
|
+
rectangles << set_master_not_current.map { |item| item.merge(format__not_in_current) }
|
56
|
+
rectangles.flatten!
|
57
|
+
|
58
|
+
generate_svg(rectangles)
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_diff_file(set_current_not_master, set_master_not_current, set_changed_master, test_root)
|
62
|
+
filename = Kracker.diff_filename(test_root)
|
63
|
+
svg = make_svg(set_current_not_master, set_master_not_current)
|
64
|
+
File.open(filename, 'w') { |file| file.write(svg) }
|
65
|
+
save_set_info(test_root, 'current_not_master', set_current_not_master)
|
66
|
+
save_set_info(test_root, 'master_not_current', set_master_not_current)
|
67
|
+
save_set_info(test_root, 'changed_master', set_changed_master)
|
68
|
+
end
|
69
|
+
|
70
|
+
def save_set_info(test_root, suffix, data_set)
|
71
|
+
filename = File.join(Kracker.diff_file_location, "#{test_root}__#{suffix}__diff.yaml")
|
72
|
+
|
73
|
+
data_array = data_set.to_a
|
74
|
+
|
75
|
+
File.open(filename, 'w') { |file| file.write(data_array.to_yaml) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_set_of_same_but_different(set1, set2)
|
79
|
+
same_but_different_pairs = []
|
80
|
+
set1.each do |item1|
|
81
|
+
element1 = DOMElement.new(item1)
|
82
|
+
set2.each do |item2|
|
83
|
+
element2 = DOMElement.new(item2)
|
84
|
+
if element1.same_element?(element2)
|
85
|
+
same_but_different_pairs << [item1, item2] #unless element1.close_enough?(element2)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
same_but_different_pairs
|
90
|
+
end
|
91
|
+
|
92
|
+
def make_analysis_failure_report(analysis_data)
|
93
|
+
return '' if analysis_data[:same]
|
94
|
+
|
95
|
+
msg = ["\n------- DOM Comparison Failure ------"]
|
96
|
+
msg << "Elements not in master: #{analysis_data[:not_in_master].count}"
|
97
|
+
msg << "Elements not in current: #{analysis_data[:not_in_current].count}"
|
98
|
+
msg << "Changed elements: #{analysis_data[:changed_element_pairs].count}"
|
99
|
+
msg << "Files:"
|
100
|
+
msg << "\tcurrent: #{Kracker.current_filename(analysis_data[:test_root])}"
|
101
|
+
msg << "\tmaster: #{Kracker.master_filename(analysis_data[:test_root])}"
|
102
|
+
msg << "\tdifference: #{Kracker.diff_filename(analysis_data[:test_root])}"
|
103
|
+
msg << "Bless this current data set:"
|
104
|
+
msg << "\t#{blessing_copy_string(analysis_data[:test_root])}"
|
105
|
+
msg<< "-------------------------------------"
|
106
|
+
|
107
|
+
msg.join("\n")
|
108
|
+
end
|
109
|
+
|
110
|
+
def blessing_copy_string(test_root)
|
111
|
+
"cp #{Kracker.current_filename(test_root)} #{Kracker.master_filename(test_root)}"
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Kracker
|
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'] || 10
|
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,112 @@
|
|
1
|
+
module Kracker
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
def page_map_same?(test_root)
|
5
|
+
|
6
|
+
result, msg = map_current_file(test_root)
|
7
|
+
return [result, msg] unless result
|
8
|
+
|
9
|
+
result, msg = master_file_exists?(test_root)
|
10
|
+
return [result, msg] unless result
|
11
|
+
|
12
|
+
result, msg, current_data = read_map_file(Kracker.current_filename(test_root))
|
13
|
+
return [result, msg] unless result
|
14
|
+
|
15
|
+
result, msg, master_data = read_map_file(Kracker.master_filename(test_root))
|
16
|
+
return [result, msg] unless result
|
17
|
+
|
18
|
+
analysis_data = analyze(master_data, current_data, test_root)
|
19
|
+
|
20
|
+
msg = make_analysis_failure_report(analysis_data)
|
21
|
+
result = analysis_data[:same]
|
22
|
+
|
23
|
+
[result, msg]
|
24
|
+
end
|
25
|
+
|
26
|
+
def read_map_file(filename)
|
27
|
+
results = [true, '', nil]
|
28
|
+
begin
|
29
|
+
results[2] = YAML::load( File.open( filename ) )
|
30
|
+
rescue Exception => e
|
31
|
+
results = [false, "Error reading data from file: #{filename}", nil]
|
32
|
+
end
|
33
|
+
|
34
|
+
results
|
35
|
+
end
|
36
|
+
|
37
|
+
def map_current_file(test_root)
|
38
|
+
filename = Kracker.current_filename(test_root)
|
39
|
+
|
40
|
+
result = [true, '']
|
41
|
+
begin
|
42
|
+
data = perform_mapping_operation.to_yaml
|
43
|
+
File.open(filename, 'w') { |file| file.write(data) }
|
44
|
+
rescue Exception => e
|
45
|
+
result = [false, "map current file error: #{e.message}"]
|
46
|
+
end
|
47
|
+
|
48
|
+
result
|
49
|
+
end
|
50
|
+
|
51
|
+
def perform_mapping_operation
|
52
|
+
|
53
|
+
js = <<-JS
|
54
|
+
var kracker = {
|
55
|
+
|
56
|
+
treeUp: function() {
|
57
|
+
var treeWalker = document.createTreeWalker(
|
58
|
+
document.body,
|
59
|
+
NodeFilter.SHOW_ELEMENT,
|
60
|
+
{ acceptNode: function(node) { return NodeFilter.FILTER_ACCEPT; } },
|
61
|
+
false
|
62
|
+
);
|
63
|
+
|
64
|
+
var nodeList = [];
|
65
|
+
|
66
|
+
while(treeWalker.nextNode()){
|
67
|
+
var cn = treeWalker.currentNode;
|
68
|
+
var node_details = {
|
69
|
+
"height" : cn.clientHeight,
|
70
|
+
"width" : cn.clientWidth,
|
71
|
+
"id" : cn.id,
|
72
|
+
"tag" : cn.tagName,
|
73
|
+
"class" : cn.className,
|
74
|
+
//"html" : cn.innerHTML,
|
75
|
+
"top" : cn.offsetTop,
|
76
|
+
"left" : cn.offsetLeft,
|
77
|
+
"visible" : kracker.isVisible(cn)
|
78
|
+
}
|
79
|
+
nodeList.push(node_details);
|
80
|
+
}
|
81
|
+
|
82
|
+
return(nodeList);
|
83
|
+
},
|
84
|
+
|
85
|
+
isVisible: function(elem) {
|
86
|
+
return elem.offsetWidth > 0 || elem.offsetHeight > 0;
|
87
|
+
}
|
88
|
+
};
|
89
|
+
return kracker.treeUp();
|
90
|
+
JS
|
91
|
+
|
92
|
+
page.driver.browser.execute_script(js)
|
93
|
+
end
|
94
|
+
|
95
|
+
def master_file_exists?(test_root)
|
96
|
+
filename = Kracker.master_filename(test_root)
|
97
|
+
result = File.exist?(filename)
|
98
|
+
msg = result ? '' : make_missing_master_failure_report(test_root)
|
99
|
+
[result, msg]
|
100
|
+
end
|
101
|
+
|
102
|
+
def make_missing_master_failure_report(test_root)
|
103
|
+
msg = ["\n------- DOM Comparison Failure ------"]
|
104
|
+
msg << "Master file does not exist. To make a new master from"
|
105
|
+
msg << "the current page, use this command:"
|
106
|
+
msg << "\t#{blessing_copy_string(test_root)}"
|
107
|
+
msg<< "-------------------------------------"
|
108
|
+
|
109
|
+
msg.join("\n")
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Kracker
|
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
|
data/lib/kracker/svg.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
module Kracker
|
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/kracker.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module PageObjects
|
2
|
+
module Kracker
|
3
|
+
class ConfigPage < ViewerPage
|
4
|
+
path '/kracker/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 Kracker
|
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
|