diff --git a/spec/cucumber_spec.rb b/spec/cucumber_spec.rb new file mode 100644 index 0000000..eb9b9cd --- /dev/null +++ b/spec/cucumber_spec.rb @@ -0,0 +1,128 @@ +require 'spec/spec_helper' +require 'icuke' +require 'cucumber/step_mother' +require 'icuke/cucumber' +require 'icuke/simulate' + + +describe ICukeWorld do + + before(:each) do + @simulator = [] + @simulator.stub(:view) + @simulator.stub(:fire_event) + ICuke::Simulator.should_receive(:new).and_return(@simulator) + @cuke_world = ICukeWorld.new + @cuke_world.stub!(:sleep) + xml = File.read('spec/fixtures/controls_page.xml') + @cuke_world.stub(:response).and_return(xml) + end + + context "when performing a swipe" do + + before(:each) do + @simulator.should_receive(:fire_event) + end + + it "should begin swipe at center of screen" do + center_x, center_y = 160, 240 + ICuke::Simulate::Gestures::Swipe.should_receive(:new). + with(center_x, center_y, 160, 480, 0.015, {}) + @cuke_world.swipe(:down) + end + + it "should swipe to the bottom of the screen when swiping down" do + bottom_y = 480 + ICuke::Simulate::Gestures::Swipe.should_receive(:new). + with(160, 240, 160, bottom_y, 0.015, {}) + @cuke_world.swipe(:down) + end + + it "should swipe to the top of the screen when swiping up" do + top_y = 0 + ICuke::Simulate::Gestures::Swipe.should_receive(:new). + with(160, 240, 160, top_y, 0.015, {}) + @cuke_world.swipe(:up) + end + + it "should swipe to the left of the screen when swipping left" do + min_x = 0 + ICuke::Simulate::Gestures::Swipe.should_receive(:new). + with(160, 240, min_x, 240, 0.015, {}) + @cuke_world.swipe(:left) + end + + it "should swipe to the right of the screen when swipping right" do + max_x = 320 + ICuke::Simulate::Gestures::Swipe.should_receive(:new). + with(160, 240, max_x, 240, 0.015, {}) + @cuke_world.swipe(:right) + end + + end + + context "when performing a drag" do + + it "should fire an event" do + @simulator.should_receive(:fire_event) + @cuke_world.drag(1,2,3,4,{}) + end + + it "should simulate a swipe from source to destination" do + sx, sy, dx, dy = 10, 20, 30, 40 + ICuke::Simulate::Gestures::Drag.should_receive(:new). + with(sx, sy, dx, dy, 0.15, {}) + @cuke_world.drag(sx, sy, dx, dy, {}) + end + + end + + context "when performing a drag with a source" do + + it "should parse the input values" do + ICuke::Simulate::Gestures::Drag.should_receive(:new). + with(12, 24, 34, 44, 0.15, {}) + @cuke_world.drag_with_source("12,24", "34,44") + end + + end + + context "when draging a slider" do + + before(:each) do + @screen = [] + @screen.should_receive(:first_slider_element).at_least(:once) + @screen.should_receive(:find_slider_button).at_least(:once).and_return([244, 287]) + Screen.should_receive(:new).at_least(:once).and_return(@screen) + end + + it "should set the destination properly" do + {:up=>[244,267], :down=>[244,307], :right=>[264,287], :left=>[224,287]}.each do |d| + ICuke::Simulate::Gestures::Drag.should_receive(:new). + with(244, 287, d[1][0], d[1][1], 0.15, {}) + @cuke_world.drag_slider_to('Label', d[0], 20) + end + end + + end + + context "when draging a slider to a percentage value" do + + before(:each) do + @element = [] + @screen = [] + @screen.should_receive(:first_slider_element).and_return(@element) + @screen.should_receive(:find_slider_button).and_return([244, 287]) + Screen.should_receive(:new).and_return(@screen) + end + + it "should identify the destination on the screen" do + @screen.should_receive(:find_slider_percentage_location).with(@element, 30). + and_return([230, 287]) + ICuke::Simulate::Gestures::Drag.should_receive(:new). + with(244, 287, 230, 287, 0.15, {}) + @cuke_world.drag_slider_to_percentage("label", 30) + end + + end +end diff --git a/spec/fixtures/controls_page.xml b/spec/fixtures/controls_page.xml new file mode 100644 index 0000000..3bc3eef --- /dev/null +++ b/spec/fixtures/controls_page.xml @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_UISwitchSlider> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec/screen_spec.rb b/spec/screen_spec.rb new file mode 100644 index 0000000..c232bc4 --- /dev/null +++ b/spec/screen_spec.rb @@ -0,0 +1,173 @@ +require 'spec/spec_helper' +require 'icuke/screen' + +describe Screen do + before(:all) do + @xml = File.read('spec/fixtures/controls_page.xml') + end + + before(:each) do + @screen = Screen.new(@xml) + end + + context "when testing if an element exists" do + + it "should be able to search for a label" do + @screen.exists?("Customized Slider").should be_true + end + + it "should be able to search for a label within a scope" do + # why does this not work with any scope? + @screen.exists?("Customized Slider", "UIWindow").should be_true + end + + it "should be able to search for a value" do + @screen.exists?("50%").should be_true + end + + it "should be able to search for a node" do + @screen.exists?("UISlider").should be_true + end + + it "should know when an element is visible on the screen" do + @screen.visible?("Standard Slider").should be_true + end + + end + + context "when finding a tappable element" do + + it "should find an element with a button trait" do + @screen.first_tappable_element("Standard switch").name.should == "UISwitch" + end + + it "should find an element with an updates_frequently trait" do + @screen.first_tappable_element("Custom").name.should == "UIAccessibilityElementMockView" + end + + it "should find an element by its label" do + @screen.first_tappable_element("Customized Slider").name.should == "UILabel" + end + + it "should raise an exception when the element is not found" do + lambda{@screen.first_tappable_element("does_not_exist")}.should raise_error + end + + end + + context "when finding a slider element" do + + it "should find a slider by its label" do + @screen.first_slider_element("Standard slider").name.should == "UISlider" + end + + it "should find a slider by a UILabel withing the same parent" do + @screen.first_slider_element("Standard Slider").name.should == "UISlider" + end + + it "should raise an exception when the element is not found" do + lambda{@screen.first_slider_element("does_not_exist")}.should raise_error + end + + end + + context "when finding the button for a slider" do + + before(:each) do + @frame = {} + @element = {} + @element.should_receive(:child).at_least(:once).and_return(@frame) + end + + it "should find coordinates when slider is horizontal" do + set_frame_values(184,275,120,24) + {'50%' => 244, '100%' => 294, '75%' => 269, '25%' => 219, '0%' => 194}.each do |v| + @element['value'] = v[0] + x, y = @screen.find_slider_button(@element) + x.should == v[1] + y.should == 287 + end + end + + it "should find coordinates when slider is vertical" do + set_frame_values(184,175,24,120) + {'50%' => 235, '100%' => 285, '75%' => 260,'25%' => 210, '0%' => 185}.each do |v| + @element['value'] = v[0] + x,y = @screen.find_slider_button(@element) + x.should == 196 + y.should == v[1] + end + end + + end + + context "when finding a location corresponding to a percentage for a slider" do + + before(:each) do + @frame = {} + @element = {} + @element.should_receive(:child).at_least(:once).and_return(@frame) + end + + it "should find percentage coordinate when slider is horizontal" do + set_frame_values(184,275,120,24) + {50 => 244, 100 => 294, 75 => 269, 25 => 219, 0 => 194}.each do |v| + x,y = @screen.find_slider_percentage_location(@element, v[0]) + x.should == v[1] + y.should == 287 + end + end + + it "should find percentage coordinate when slider is vertical" do + set_frame_values(184,175,24,120) + {50 => 235, 100 => 285, 75 => 260, 25 => 210, 0 => 185}.each do |v| + x,y = @screen.find_slider_percentage_location(@element, v[0]) + x.should == 196 + y.should == v[1] + end + end + + end + + context "when finding the coordinates for a swipe" do + + it "should start the coordinates with the center of the screen" do + x,y,x2,y2 = @screen.swipe_coordinates(:down) + x.should == 160 + y.should == 240 + end + + it "should end the swipe at the top center when swiping up" do + x,y,x2,y2 = @screen.swipe_coordinates(:up) + x2.should == 160 + y2.should == 0 + end + + it "should end the swipe at the bottom center when swiping down" do + x,y,x2,y2 = @screen.swipe_coordinates(:down) + x2.should == 160 + y2.should == 480 + end + + it "should end the swipe at the right center when swiping right" do + x,y,x2,y2 = @screen.swipe_coordinates(:right) + x2.should == 320 + y2.should == 240 + end + + it "should end the swipe at the left center when swiping left" do + x,y,x2,y2 = @screen.swipe_coordinates(:left) + x2.should == 0 + y2.should == 240 + end + + end + + def set_frame_values(x, y, width, height) + @frame['x'] = x + @frame['y'] = y + @frame['width'] = width + @frame['height'] = height + end + +end diff --git a/spec/simulate_spec.rb b/spec/simulate_spec.rb new file mode 100644 index 0000000..ff91d49 --- /dev/null +++ b/spec/simulate_spec.rb @@ -0,0 +1,75 @@ +require 'spec/spec_helper' +require 'icuke' +require 'icuke/simulate' + +describe ICuke::Simulate::Events::Touch do + + before(:each) do + @touch = ICuke::Simulate::Events::Touch.new(:up, [[20, 30]]) + end + + it "should include the Location of the touch in the output" do + @touch.to_json.should include '"Location":{"X":20,"Y":30}' + end + + it "should include the proper event type in the output" do + @touch.to_json.should include '"Type":3001' + end + + it "should include the proper touch time (up/down)" do + @touch.to_json.should include '"Type":6' + @touch = ICuke::Simulate::Events::Touch.new(:down, [[20, 30]]) + @touch.to_json.should include '"Type":1' + end + + it "should include the proper window location" do + @touch.to_json.should include '"WindowLocation":{"X":20,"Y":30}' + end + +end + +describe ICuke::Simulate::Gestures::Tap do + + it "should generate a down and up touch" do + tap = ICuke::Simulate::Gestures::Tap.new(20, 30) + tap.to_json.should include touch_output(1, 20, 30) + tap.to_json.should include touch_output(6, 20, 30) + end + +end + +describe ICuke::Simulate::Gestures::Swipe do + + before(:each) do + @swipe = ICuke::Simulate::Gestures::Swipe.new(40, 60, 20, 30, 0.015, {}) + end + + it "should generate a down and up touch" do + @swipe.to_json.should include touch_output(1, 40, 60) + @swipe.to_json.should include touch_output(6, 20, 30) + end + + it "should generate move touches" do + move_x, move_y = calculate_move(40, 60, 20, 30, 1) + @swipe.to_json.should include touch_output(2, move_x, move_y) + end + + it "should generate multiple move touches when moving over distance" do + mx1, my1 = calculate_move(40, 60, 120, 130, 1) + @swipe = ICuke::Simulate::Gestures::Swipe.new(40, 60, 120, 130, 0.015, {}) + 4.times do |i| + x, y = calculate_move(40, 60, 120, 130, i+1) + @swipe.to_json.should include touch_output(2, x, y) + end + end + + it "should include the appropriate hold_for value in the output" do + times = timestamps(@swipe.to_json) + times[0].should == times[1] - 15000000 + end + +end + + + + diff --git a/spec/spec.opts b/spec/spec.opts new file mode 100644 index 0000000..391705b --- /dev/null +++ b/spec/spec.opts @@ -0,0 +1,4 @@ +--colour +--format progress +--loadby mtime +--reverse diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..8037125 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,67 @@ +require 'rubygems' + +$:.unshift(File.dirname(__FILE__) + '/../lib') +require 'icuke' +$:.unshift(File.dirname(__FILE__)) + +begin + require 'rspec' + require 'rspec/autorun' + Rspec.configure do |c| + c.color_enabled = true + c.before(:each) do + ::Term::ANSIColor.coloring = true + end + end +rescue LoadError + require 'spec' + require 'spec/autorun' + Spec::Runner.configure do |c| + c.before(:each) do + ::Term::ANSIColor.coloring = true + end + end +end + +require 'cucumber' + + +def calculate_move(x1, y1, x2, y2, step_num) + dx = x2 - x1 + dy = y2 - y1 + hypotenuse = Math.sqrt(dx*dx + dy*dy) + step = 25 / hypotenuse + return 40 + step_num * step * dx, 60 + step_num * step * dy +end + +def touch_output(type, x, y) + '{"Data":{"Paths":[{"Size":{"X":1.0,"Y":1.0},"Location":{"X":' + + x.to_s + + ',"Y":' + + y.to_s + + '}}],"Delta":{"X":1,"Y":1},"Type":' + + type.to_s + + '}' +end + +def timestamps(json) + segments = json.split('"Time":') + segments.delete_at 0 + timestamps = [] + segments.each do |segment| + timestamps << segment.split(',')[0].to_i + end + timestamps +end + + +def World +end +def After +end +def Given(something) +end +def When(something) +end +def Then(something) +end