kolach-melomel 0.6.4

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.
@@ -0,0 +1,22 @@
1
+ When /^I set the "([^"]*)" (date chooser|date field) to "(\d{1,2}\/\d{1,2}\/\d{4})"$/ do |name, type, date_string|
2
+ Melomel::Cucumber.run! do
3
+ classes = Melomel::Flex.get_component_classes(type)
4
+ component = Melomel::Cucumber.find_labeled!(classes, name)
5
+ component.setFocus()
6
+ component.selectedDate = Melomel::Date.parse(date_string)
7
+ end
8
+ end
9
+
10
+ Then /^I should see the "([^"]*)" (date chooser|date field) set to "(\d{1,2}\/\d{1,2}\/\d{4})"$/ do |name, type, date_string|
11
+ Melomel::Cucumber.run! do
12
+ classes = Melomel::Flex.get_component_classes(type)
13
+ component = Melomel::Cucumber.find_labeled!(classes, name)
14
+ date = Melomel::Date.parse(date_string)
15
+ component.setFocus()
16
+
17
+ component.selectedDate.should_not be_nil
18
+ date.should_not be_nil
19
+ component.selectedDate.toLocaleDateString().should == date.toLocaleDateString()
20
+ end
21
+ end
22
+
@@ -0,0 +1,30 @@
1
+ When /^I select "([^"]*)" on the "([^"]*)" (combo box|list)$/ do |value, name, type|
2
+ Melomel::Cucumber.run! do
3
+ classes = Melomel::Flex.get_component_classes(type)
4
+ list = Melomel::Cucumber.find_labeled!(classes, name)
5
+ list.setFocus()
6
+ labels = Melomel.items_to_labels!(list, list.dataProvider)
7
+
8
+ # Loop over labels and set the selected index when we find a match
9
+ index = nil
10
+ labels.length.times do |i|
11
+ if labels[i] == value
12
+ index = i
13
+ end
14
+ end
15
+ raise "Cannot find '#{value}' on #{type}" if index.nil?
16
+
17
+ list.selectedIndex = index
18
+ end
19
+ end
20
+
21
+ Then /^I should see "([^"]*)" selected on the "([^"]*)" (combo box|list)$/ do |value, name, type|
22
+ Melomel::Cucumber.run! do
23
+ classes = Melomel::Flex.get_component_classes(type)
24
+ list = Melomel::Cucumber.find_labeled!(classes, name)
25
+ list.setFocus()
26
+ label = list.itemToLabel(list.selectedItem)
27
+ label.should == value
28
+ end
29
+ end
30
+
@@ -0,0 +1,20 @@
1
+ When /^I set the "([^"]*)" (slider) to "([^"]*)"$/ do |name, type, value|
2
+ Melomel::Cucumber.run! do
3
+ classes = Melomel::Flex.get_component_classes(type)
4
+ slider = Melomel::Cucumber.find_labeled!(classes, name)
5
+ slider.setFocus()
6
+ value = value.index('.') ? value.to_f : value.to_i
7
+ slider.value = value
8
+ end
9
+ end
10
+
11
+ Then /^I should see the "([^"]*)" (slider) set to "([^"]*)"$/ do |name, type, value|
12
+ Melomel::Cucumber.run! do
13
+ classes = Melomel::Flex.get_component_classes(type)
14
+ slider = Melomel::Cucumber.find_labeled!(classes, name)
15
+ slider.setFocus()
16
+ value = value.index('.') ? value.to_f : value.to_i
17
+ slider.value.should == value
18
+ end
19
+ end
20
+
@@ -0,0 +1,26 @@
1
+ When /^I type "([^"]*)" in the "([^"]*)" (text field|text area)$/ do |text, name, type|
2
+ Melomel::Cucumber.run! do
3
+ classes = Melomel::Flex.get_component_classes(type)
4
+ component = Melomel::Cucumber.find_labeled!(classes, name)
5
+ component.setFocus()
6
+ component.text = text
7
+ end
8
+ end
9
+
10
+ Then /^I should see "([^"]*)" in the "([^"]*)" (text field|text area|label)$/ do |text, name, type|
11
+ Melomel::Cucumber.run! do
12
+ classes = Melomel::Flex.get_component_classes(type)
13
+ component = Melomel::Cucumber.find_labeled!(classes, name)
14
+ component.setFocus()
15
+ component.text.should == text
16
+ end
17
+ end
18
+
19
+ Then /^I should not see "([^"]*)" in the "([^"]*)" (text field|text area|label)$/ do |text, name, type|
20
+ Melomel::Cucumber.run! do
21
+ classes = Melomel::Flex.get_component_classes(type)
22
+ component = Melomel::Cucumber.find_labeled!(classes, name)
23
+ component.setFocus()
24
+ component.text.should_not == text
25
+ end
26
+ end
@@ -0,0 +1,19 @@
1
+ module Melomel
2
+ # This class contains helper methods for working with Flash dates.
3
+ class Date
4
+ # Parses a date.
5
+ #
6
+ # text - The date string to parse.
7
+ #
8
+ # Example:
9
+ #
10
+ # Melomel::Date.parse('02/04/2010') # => <Melomel::ObjectProxy>
11
+ #
12
+ # Returns a proxy to a date object in Flash.
13
+ def self.parse(text)
14
+ date = Melomel.create_object!('Date')
15
+ date.time = Melomel.get_class!('Date').parse(text)
16
+ date
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ # This class is used for all errors returned from the Flash virtual machine.
2
+ module Melomel
3
+ class Error < StandardError
4
+ ############################################################################
5
+ #
6
+ # Constructor
7
+ #
8
+ ############################################################################
9
+
10
+ def initialize(object, error_id, message, name, stack_trace)
11
+ @object = object
12
+ @error_id = error_id
13
+ @message = message
14
+ @name = name
15
+ @stack_trace = stack_trace
16
+ end
17
+
18
+
19
+ ############################################################################
20
+ #
21
+ # Public Properties
22
+ #
23
+ ############################################################################
24
+
25
+ # A proxied reference to the original Flash error object.
26
+ #
27
+ # Returns a Melomel::ObjectProxy.
28
+ attr_reader :object
29
+
30
+ # The error identifier of the Flash error.
31
+ attr_reader :error_id
32
+
33
+ # The Flash error message.
34
+ attr_reader :message
35
+
36
+ # The name of the Flash error.
37
+ attr_reader :name
38
+
39
+ # The Flash stack trace. This is only available when using the Flash debug
40
+ # player or the AIR Debug Launcher (ADL).
41
+ attr_reader :stack_trace
42
+ end
43
+ end
@@ -0,0 +1,46 @@
1
+ module Melomel
2
+ # This class contains helper methods for working with Flex components.
3
+ class Flex
4
+ # Retrieves a list of classes associated with a commonly named component.
5
+ #
6
+ # name - The common name of the component.
7
+ #
8
+ # Example:
9
+ #
10
+ # Melomel.get_component_classes('button')
11
+ # # => ['mx.controls.Button', 'spark.components.Button']
12
+ #
13
+ # Returns a list of classes associated with a component's common name.
14
+ def self.get_component_classes(name)
15
+ case name.downcase
16
+ when 'alert' then ['mx.controls.Alert']
17
+ when 'button' then ['mx.controls.Button', 'spark.components.supportClasses.ButtonBase']
18
+ when 'check box' then ['mx.controls.CheckBox', 'spark.components.CheckBox']
19
+ when 'color picker' then ['mx.controls.ColorPicker']
20
+ when 'combo box' then ['mx.controls.ComboBox', 'spark.components.ComboBox']
21
+ when 'data grid' then ['mx.controls.DataGrid', 'mx.controls.AdvancedDataGrid']
22
+ when 'date chooser' then ['mx.controls.DateChooser']
23
+ when 'date field' then ['mx.controls.DateField']
24
+ when 'scroll bar' then ['mx.controls.HScrollBar', 'mx.controls.VScrollBar', 'spark.components.HScrollBar', 'spark.components.VScrollBar']
25
+ when 'slider' then ['mx.controls.HSlider', 'mx.controls.VSlider', 'spark.components.HSlider', 'spark.components.VSlider']
26
+ when 'image' then ['mx.controls.Image']
27
+ when 'label' then ['mx.controls.Label', 'spark.components.Label', 'spark.components.RichText']
28
+ when 'list' then ['mx.controls.List', 'spark.components.List']
29
+ when 'menu' then ['mx.controls.Menu']
30
+ when 'menu bar' then ['mx.controls.MenuBar']
31
+ when 'panel' then ['mx.containers.Panel', 'spark.components.Panel']
32
+ when 'stepper' then ['mx.controls.NumericStepper', 'spark.components.Spinner']
33
+ when 'pop up button' then ['mx.controls.PopUpButton']
34
+ when 'pop up menu button' then ['mx.controls.PopUpMenuButton']
35
+ when 'progress bar' then ['mx.controls.ProgressBar']
36
+ when 'radio button' then ['mx.controls.RadioButton', 'spark.components.RadioButton']
37
+ when 'rich text area' then ['mx.controls.RichTextEditor', 'spark.components.RichEditableText']
38
+ when 'tab' then ['mx.controls.tabBarClasses.Tab']
39
+ when 'text field' then ['mx.controls.TextInput', 'spark.components.TextInput']
40
+ when 'text area' then ['mx.controls.TextArea', 'spark.components.TextArea']
41
+ when 'tool tip' then ['mx.controls.ToolTip']
42
+ when 'tree' then ['mx.controls.Tree']
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,94 @@
1
+ # This class as a proxy to an object in the Flash virtual machine. Invoking
2
+ # methods, accessing properties or changing properties on this object will
3
+ # result in a command being sent to Flash to change or access the state of the
4
+ # object within the virtual machine. The Ruby object proxy holds no state.
5
+ #
6
+ # The object proxy works exactly as if the Flash object was a local Ruby object.
7
+ # To do this, the following aliases are made:
8
+ # * Method calls with method names ending in "=" are aliased to #set_property
9
+ # * Method calls without arguments are aliased to #get_property.
10
+ # * Method calls with arguments are aliased to #invoke_method
11
+ module Melomel
12
+ class ObjectProxy
13
+ attr_reader :bridge, :proxy_id
14
+
15
+ def initialize(bridge, proxy_id)
16
+ @bridge = bridge
17
+ @proxy_id = proxy_id
18
+ end
19
+
20
+ # Retrieves the value of a property for the proxied object.
21
+ def get_property(name)
22
+ @bridge.get_property(@proxy_id, name)
23
+ end
24
+
25
+ def get_property!(name)
26
+ @bridge.get_property!(@proxy_id, name)
27
+ end
28
+
29
+ # Sets the value of a property for the proxied object.
30
+ def set_property(name, value)
31
+ @bridge.set_property(@proxy_id, name, value)
32
+ end
33
+
34
+ # Sets the value of a property for the proxied object.
35
+ def set_property!(name, value)
36
+ @bridge.set_property!(@proxy_id, name, value)
37
+ end
38
+
39
+ # Invokes a method on the proxied object. Arguments passed into the method
40
+ # are passed through to the invoked method
41
+ def invoke_method(method_name, *args)
42
+ @bridge.invoke_method(@proxy_id, method_name, *args)
43
+ end
44
+
45
+ def invoke_method!(method_name, *args)
46
+ @bridge.invoke_method!(@proxy_id, method_name, *args)
47
+ end
48
+
49
+ alias :invoke :invoke_method
50
+
51
+ # Proxies all methods to the appropriate Flash objects.
52
+ def method_missing(symbol, *args)
53
+ method_name = symbol.to_s
54
+ last_char = method_name.to_s[-1,1]
55
+
56
+ # Methods ending in "=" are aliased to set_property
57
+ if last_char == '='
58
+ return set_property(method_name.chop, *args)
59
+ # Methods with arguments are methods
60
+ elsif args.length > 0
61
+ if last_char == '!'
62
+ return invoke_method!(method_name.chop, *args)
63
+ else
64
+ return invoke_method(method_name, *args)
65
+ end
66
+ # Methods with no arguments are aliased to get_property
67
+ else
68
+ if last_char == '!'
69
+ return get_property!(method_name.chop)
70
+ else
71
+ return get_property(method_name)
72
+ end
73
+ end
74
+ end
75
+
76
+ # Array accessor.
77
+ def [](index)
78
+ if index.is_a?(Fixnum)
79
+ get_property("[#{index}]")
80
+ else
81
+ get_property(index.to_s)
82
+ end
83
+ end
84
+
85
+ # Array mutator.
86
+ def []=(index, value)
87
+ if index.is_a?(Fixnum)
88
+ set_property("[#{index}]", value)
89
+ else
90
+ set_property(index.to_s, value)
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,3 @@
1
+ module Melomel
2
+ VERSION = "0.6.4"
3
+ end
data/lib/object.rb ADDED
@@ -0,0 +1,30 @@
1
+ class Object
2
+ # Recursively generates an object proxy for the object if it is a Hash or
3
+ # and Array.
4
+ #
5
+ # bridge - The bridge to use when generating a proxy.
6
+ #
7
+ # Returns a Melomel::ObjectProxy if it is a Hash or an Array. Otherwise
8
+ # returns the object itself.
9
+ def to_object_proxy(bridge)
10
+ proxy = self
11
+
12
+ # Convert each key/value pair in a Hash
13
+ if self.is_a?(Hash)
14
+ proxy = bridge.create_object('Object')
15
+ each_pair do |k,v|
16
+ v = v.to_object_proxy(bridge) unless v.nil?
17
+ proxy.set_property!(k, v)
18
+ end
19
+ # Convert each item in an Array.
20
+ elsif is_a?(Array)
21
+ proxy = bridge.create_object('Array')
22
+ each do |item|
23
+ item = item.to_object_proxy(bridge) unless item.nil?
24
+ proxy.push!(item)
25
+ end
26
+ end
27
+
28
+ return proxy
29
+ end
30
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require "bundler"
3
+ Bundler.setup
4
+ require 'minitest/autorun'
5
+ require 'mocha'
6
+
7
+ dir = File.dirname(File.expand_path(__FILE__))
8
+ $LOAD_PATH.unshift(File.join(dir, '..', 'lib'))
9
+ $LOAD_PATH.unshift(dir)
10
+
11
+ require 'melomel'
12
+
13
+ class RunnerTestCase < MiniTest::Unit::TestCase
14
+ def start_runner
15
+ # Make sure FLEX_HOME is defined
16
+ raise 'FLEX_HOME environment variable must be set' if ENV['FLEX_HOME'].nil?
17
+
18
+ # Open up the sandbox
19
+ @pid = fork do
20
+ exec("#{ENV['FLEX_HOME']}/bin/adl target/MelomelRunner-app.xml")
21
+ end
22
+ Process.detach(@pid)
23
+ end
24
+
25
+ def stop_runner
26
+ Process.kill('KILL', @pid)
27
+ end
28
+ end
data/test/sandbox.rb ADDED
@@ -0,0 +1,14 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), *%w[helper])
2
+
3
+ class SandboxTestCase < RunnerTestCase
4
+ def setup
5
+ start_runner
6
+ Melomel.connect()
7
+ end
8
+
9
+ def teardown
10
+ stop_runner
11
+ end
12
+
13
+ # Add tests here.
14
+ end
@@ -0,0 +1,61 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), *%w[helper])
2
+
3
+ class BridgeTestCase < MiniTest::Unit::TestCase
4
+ def setup
5
+ @bridge = Melomel::Bridge.new('localhost', 10101)
6
+ end
7
+
8
+ def connect
9
+ # Mock server
10
+ @server = mock('server')
11
+ TCPServer.stubs(:open).returns(@server)
12
+ TCPServer.any_instance.stubs(:close)
13
+
14
+ # Mock sockets
15
+ @socket = mock('socket')
16
+ @socket.expects(:gets).returns("<connect/>\x00")
17
+ @server.expects(:accept).returns(@socket)
18
+ @server.expects(:close)
19
+
20
+ # Attempt connection
21
+ @bridge.connect()
22
+ end
23
+
24
+ def test_should_send_messages_over_socket_connection
25
+ connect()
26
+ @socket.expects(:puts).with("<message/>\x00")
27
+ @bridge.send('<message/>')
28
+ end
29
+
30
+ def test_should_receive_messages_from_socket_connection
31
+ connect()
32
+ @socket.expects(:gets).returns("<message/>\x00")
33
+ assert_equal '<message/>', @bridge.receive()
34
+ end
35
+
36
+ def test_should_send_policy_file_and_connect
37
+ policy = '<?xml version="1.0"?><!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"><cross-domain-policy><allow-access-from domain="localhost" to-ports="10101"/></cross-domain-policy>';
38
+
39
+ # Mock server
40
+ server = mock('server')
41
+ server.expects(:close)
42
+ TCPServer.expects(:open).returns(server)
43
+
44
+ # Mock policy file
45
+ policy_socket = mock('policy_socket')
46
+ policy_socket.expects(:gets).returns("<policy-file-request/>\x00")
47
+ policy_socket.expects(:send).with(policy, 0)
48
+ policy_socket.expects(:flush)
49
+ policy_socket.expects(:close)
50
+
51
+ # Mock regular socket
52
+ socket = mock('socket')
53
+ socket.expects(:gets).returns("<connect/>\x00")
54
+
55
+ # Server should return policy socket first and then regular socket
56
+ server.stubs(:accept).returns(policy_socket, socket, nil)
57
+
58
+ # Attempt connection
59
+ @bridge.connect()
60
+ end
61
+ end