From 31c2be768feb9a1e8aa6dd0ebb89ffce4d3f0fce Mon Sep 17 00:00:00 2001 From: jvelilla Date: Mon, 29 Apr 2013 18:02:33 -0300 Subject: [PATCH] Created new classes to represent a web driver. Added Examples, clean code --- library/test/selenium/examples/application.e | 27 ++ library/test/selenium/examples/example_1.e | 58 +++ library/test/selenium/examples/examples.ecf | 19 + library/test/selenium/src/enum.e | 37 ++ .../executor}/command_executor.e | 21 +- .../src/protocol/se_json_wire_protocol.e | 144 +++++- .../protocol/se_json_wire_protocol_commands.e | 30 +- library/test/selenium/src/se_button.e | 95 ++++ library/test/selenium/src/se_by.e | 16 +- library/test/selenium/src/se_cookie.e | 2 +- .../src/{se_window.e => se_dimension.e} | 14 +- library/test/selenium/src/se_point.e | 41 ++ library/test/selenium/src/web_driver.e | 444 ++++++++++++++++++ library/test/selenium/src/web_element.e | 109 ++++- library/test/selenium/test/application.e | 3 + 15 files changed, 1012 insertions(+), 48 deletions(-) create mode 100644 library/test/selenium/examples/application.e create mode 100644 library/test/selenium/examples/example_1.e create mode 100644 library/test/selenium/examples/examples.ecf create mode 100644 library/test/selenium/src/enum.e rename library/test/selenium/src/{ => protocol/executor}/command_executor.e (97%) create mode 100644 library/test/selenium/src/se_button.e rename library/test/selenium/src/{se_window.e => se_dimension.e} (74%) create mode 100644 library/test/selenium/src/se_point.e create mode 100644 library/test/selenium/src/web_driver.e diff --git a/library/test/selenium/examples/application.e b/library/test/selenium/examples/application.e new file mode 100644 index 00000000..d86e9d89 --- /dev/null +++ b/library/test/selenium/examples/application.e @@ -0,0 +1,27 @@ +note + description : "project application root class" + date : "$Date$" + revision : "$Revision$" + +class + APPLICATION + +inherit + ARGUMENTS + +create + make + +feature {NONE} -- Initialization + + make + -- Run application. + do + execute_example1 + end + + execute_example1 + do + (create {EXAMPLE_1}).test + end +end diff --git a/library/test/selenium/examples/example_1.e b/library/test/selenium/examples/example_1.e new file mode 100644 index 00000000..d905bfd7 --- /dev/null +++ b/library/test/selenium/examples/example_1.e @@ -0,0 +1,58 @@ +note + description: "Summary description for {EXAMPLE_1}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + EXAMPLE_1 + +feature -- Access + test + local + web_driver: SE_JSON_WIRE_PROTOCOL + capabilities: SE_CAPABILITIES + l_session : SE_SESSION + do + create web_driver.make + if attached web_driver.status as l_status then + create capabilities.make + capabilities.set_browser_name ("chrome") + l_session:= web_driver.create_session_with_desired_capabilities (capabilities) + if attached l_session as l_s then + + -- navigate to www.google.com + web_driver.navigate_to_url (l_s.session_id, "http://www.google.com/") + + -- Find the text input element by its name + if attached {WEB_ELEMENT} web_driver.search_element (l_s.session_id, (create {SE_BY}).name ("q")) as l_element then + -- search something + web_driver.send_event(l_s.session_id, l_element.element,<<"Eiffel Room">>) + + -- Submit Form + web_driver.element_submit (l_s.session_id, l_element.element) + + if attached web_driver.page_title (l_s.session_id) as l_page then + print ("Page Name" + l_page) + end + end + end + + end + end + +-- // And now use this to visit Google +-- driver.get("http://www.google.com"); + +-- // Find the text input element by its name +-- WebElement element = driver.findElement(By.name("q")); + +-- // Enter something to search for +-- element.sendKeys("Cheese!"); + +-- // Now submit the form. WebDriver will find the form for us from the element +-- element.submit(); + +-- // Check the title of the page +-- System.out.println("Page title is: " + driver.getTitle()); +end diff --git a/library/test/selenium/examples/examples.ecf b/library/test/selenium/examples/examples.ecf new file mode 100644 index 00000000..15c5511b --- /dev/null +++ b/library/test/selenium/examples/examples.ecf @@ -0,0 +1,19 @@ + + + + + + + + + + + /EIFGENs$ + /.svn$ + /CVS$ + + + + diff --git a/library/test/selenium/src/enum.e b/library/test/selenium/src/enum.e new file mode 100644 index 00000000..21f7fc76 --- /dev/null +++ b/library/test/selenium/src/enum.e @@ -0,0 +1,37 @@ +note + description: "Summary description for {ENUM}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + ENUM + +feature -- Access + + is_valid_state: BOOLEAN + -- Is the value of the enumeration valid? + do + Result := is_valid_value (value) + end + + value: INTEGER + -- The current value of the enumeration. + + set_value (a_value: INTEGER) + require + is_valid_value (a_value) + do + value := a_value + end + + is_valid_value (a_value: INTEGER): BOOLEAN + -- Can `a_value' be used in a `set_value' feature call? + deferred + end + +invariant + is_valid_state + +end -- class ENUM + diff --git a/library/test/selenium/src/command_executor.e b/library/test/selenium/src/protocol/executor/command_executor.e similarity index 97% rename from library/test/selenium/src/command_executor.e rename to library/test/selenium/src/protocol/executor/command_executor.e index 5c41923c..f21575af 100644 --- a/library/test/selenium/src/command_executor.e +++ b/library/test/selenium/src/protocol/executor/command_executor.e @@ -202,22 +202,24 @@ feature -- Commands Result := new_response (a_session_id, resp) end - execute + execute (a_session_id : STRING_32; data : STRING_32) : SE_RESPONSE require selinum_server_available: is_available local resp: HTTP_CLIENT_RESPONSE do - -- TODO + resp := execute_post (cmd_session_execute (a_session_id), data) + Result := new_response (a_session_id, resp) end - execute_async + execute_async (a_session_id : STRING_32; data : STRING_32) : SE_RESPONSE require selinum_server_available: is_available local resp: HTTP_CLIENT_RESPONSE do - -- TODO + resp := execute_post (cmd_session_execute_async (a_session_id),data) + Result := new_response (a_session_id, resp) end screenshot (session_id: STRING_32): SE_RESPONSE @@ -280,6 +282,17 @@ feature -- Commands Result := new_response (a_session_id, resp) end + + frame (a_session_id: STRING_32; a_data: STRING_32): SE_RESPONSE + require + selinum_server_available: is_available + local + resp: HTTP_CLIENT_RESPONSE + do + resp := execute_post (cmd_session_frame (a_session_id), a_data) + Result := new_response (a_session_id, resp) + end + change_focus_window (a_session_id: STRING_32; a_data: STRING_32): SE_RESPONSE require selinum_server_available: is_available diff --git a/library/test/selenium/src/protocol/se_json_wire_protocol.e b/library/test/selenium/src/protocol/se_json_wire_protocol.e index 4c92864c..2d60960f 100644 --- a/library/test/selenium/src/protocol/se_json_wire_protocol.e +++ b/library/test/selenium/src/protocol/se_json_wire_protocol.e @@ -576,7 +576,7 @@ feature -- Commands end end - frame (a_session_id: STRING_32) + frame (a_session_id: STRING_32; arg : detachable STRING_32) -- POST /session/:sessionId/frame -- Change focus to another frame on the page. If the frame id is null, the server should switch to the page's default content. -- URL Parameters: @@ -586,7 +586,23 @@ feature -- Commands -- Potential Errors: -- NoSuchWindow - If the currently selected window has been closed. -- NoSuchFrame - If the frame specified by id cannot be found. + local + l_json: STRING_32 + resp: SE_RESPONSE do + l_json := "[ + { "id": $id } + ]" + if attached arg as l_arg then + l_json.replace_substring_all ("$id", l_arg) + else + l_json.replace_substring_all ("$id", "null") + end + + if commnad_executor.is_available then + resp := commnad_executor.frame (a_session_id, l_json) + check_response (resp) + end end change_focus_window (a_session_id: STRING_32; a_name: STRING_32) @@ -653,7 +669,7 @@ feature -- Commands end end - size_window (a_session_id: STRING_32; a_window_handle: STRING_32): SE_WINDOW + size_window (a_session_id: STRING_32; a_window_handle: STRING_32): SE_DIMENSION -- GET /session/:sessionId/window/:windowHandle/size -- Get the size of the specified window. If the :windowHandle URL parameter is "current", the size of the currently active window will be returned. -- URL Parameters: @@ -709,7 +725,7 @@ feature -- Commands end end - window_position (a_session_id: STRING_32; a_window_handle: STRING_32): SE_WINDOW + window_position (a_session_id: STRING_32; a_window_handle: STRING_32): SE_POINT -- GET /session/:sessionId/window/:windowHandle/position -- Get the position of the specified window. If the :windowHandle URL parameter is "current", the position of the currently active window will be returned. -- URL Parameters: @@ -931,8 +947,8 @@ feature -- Commands resp := commnad_executor.search_element (a_session_id, strategy) check_response (resp) if not has_error then - if attached {JSON_OBJECT} resp.value as l_value and then attached l_value.item ("ELEMENT") as l_elem then - create Result.make (l_elem.representation) + if attached resp.value as l_value and then attached {JSON_OBJECT} string_to_json (l_value) as ll_value and then attached {JSON_STRING} ll_value.item ("ELEMENT") as l_elem then + create Result.make (l_elem.item) end end end @@ -1437,7 +1453,7 @@ feature -- Commands end end - element_location (a_session_id: STRING_32; an_id: STRING_32): SE_WINDOW + element_location (a_session_id: STRING_32; an_id: STRING_32): SE_POINT -- GET /session/:sessionId/element/:id/location -- Determine an element's location on the page. The point (0, 0) refers to the upper-left corner of the page. -- The element's coordinates are returned as a JSON object with x and y properties. @@ -1469,7 +1485,7 @@ feature -- Commands end end - location_in_view (a_session_id: STRING_32; an_id: STRING_32): SE_WINDOW + location_in_view (a_session_id: STRING_32; an_id: STRING_32): SE_POINT -- GET /session/:sessionId/element/:id/location_in_view -- Determine an element's location on the screen once it has been scrolled into view. -- Note: This is considered an internal command and should only be used to determine an element's @@ -1502,7 +1518,7 @@ feature -- Commands end end - element_size (a_session_id: STRING_32; an_id: STRING_32): SE_WINDOW + element_size (a_session_id: STRING_32; an_id: STRING_32): SE_DIMENSION -- GET /session/:sessionId/element/:id/size -- Determine an element's size in pixels. The size will be returned as a JSON object with width and height properties. -- URL Parameters: @@ -1632,7 +1648,7 @@ feature -- Commands end end - send_alert_text (a_session_id: STRING_32) + send_alert_text (a_session_id: STRING_32; text : STRING_32) -- POST /session/:sessionId/alert_text -- Sends keystrokes to a JavaScript prompt() dialog. -- URL Parameters: @@ -1641,7 +1657,19 @@ feature -- Commands -- text - {string} Keystrokes to send to the prompt() dialog. -- Potential Errors: -- NoAlertPresent - If there is no alert displayed. + local + resp : SE_RESPONSE + l_json : STRING_32 do + l_json := "[ + { "text":"$text" } + ]" + + if commnad_executor.is_available then + l_json.replace_substring_all ("$text", text) + resp := commnad_executor.send_alert_text (a_session_id, l_json) + check_response (resp) + end end accept_alert (a_session_id: STRING_32) @@ -1651,7 +1679,13 @@ feature -- Commands -- :sessionId - ID of the session to route the command to. -- Potential Errors: -- NoAlertPresent - If there is no alert displayed. + local + resp : SE_RESPONSE do + if commnad_executor.is_available then + resp := commnad_executor.accept_alert (a_session_id) + check_response (resp) + end end dismiss_alert (a_session_id: STRING_32) @@ -1661,57 +1695,131 @@ feature -- Commands -- :sessionId - ID of the session to route the command to. -- Potential Errors: -- NoAlertPresent - If there is no alert displayed. + local + resp : SE_RESPONSE do + if commnad_executor.is_available then + resp := commnad_executor.dismiss_alert (a_session_id) + check_response (resp) + end end - move_to (a_session_id: STRING_32) + move_to (a_session_id: STRING_32; web_element : WEB_ELEMENT; xoffset : NATURAL; yoffset:NATURAL) -- POST /session/:sessionId/moveto - -- Move the mouse by an offset of the specificed element. If no element is specified, the move is relative to the current mouse cursor. If an element is provided but no offset, the mouse will be moved to the center of the element. If the element is not visible, it will be scrolled into view. + -- Move the mouse by an offset of the specificed element. + -- If no element is specified, the move is relative to the current mouse cursor. + -- If an element is provided but no offset, the mouse will be moved to the center of the element. + -- If the element is not visible, it will be scrolled into view. -- URL Parameters: -- :sessionId - ID of the session to route the command to. -- JSON Parameters: -- element - {string} Opaque ID assigned to the element to move to, as described in the WebElement JSON Object. If not specified or is null, the offset is relative to current position of the mouse. -- xoffset - {number} X offset to move to, relative to the top-left corner of the element. If not specified, the mouse will move to the middle of the element. -- yoffset - {number} Y offset to move to, relative to the top-left corner of the element. If not specified, the mouse will move to the middle of the element. + local + resp : SE_RESPONSE + l_json : STRING_32 + do + l_json := "[ + { "element" : "$element", + "yoffset" : $yoffset, + "xoffset" : $xoffset + } + ]" + if commnad_executor.is_available then + l_json.replace_substring_all ("$element", web_element.element) + l_json.replace_substring_all ("$yoffset", yoffset.out) + l_json.replace_substring_all ("$xoffset", xoffset.out) + resp := commnad_executor.move_to (a_session_id, l_json) + check_response (resp) + end end - click (a_session_id: STRING_32) + click (a_session_id: STRING_32; button : SE_BUTTON ) -- POST /session/:sessionId/click -- Click any mouse button (at the coordinates set by the last moveto command). Note that calling this command after calling buttondown and before calling button up (or any out-of-order interactions sequence) will yield undefined behaviour). -- URL Parameters: -- :sessionId - ID of the session to route the command to. -- JSON Parameters: -- button - {number} Which button, enum: {LEFT = 0, MIDDLE = 1 , RIGHT = 2}. Defaults to the left mouse button if not specified. + local + resp : SE_RESPONSE + l_json : STRING_32 do + l_json := "[ + { + "button" : $number + } + ]" + if commnad_executor.is_available then + l_json.replace_substring_all ("$number", button.value.out) + resp := commnad_executor.click (a_session_id, l_json) + check_response (resp) + end end - button_down (a_session_id: STRING_32) + button_down (a_session_id: STRING_32; button : SE_BUTTON) -- POST /session/:sessionId/buttondown - -- Click and hold the left mouse button (at the coordinates set by the last moveto command). Note that the next mouse-related command that should follow is buttonup . Any other mouse command (such as click or another call to buttondown) will yield undefined behaviour. + -- Click and hold the left mouse button (at the coordinates set by the last moveto command). + -- Note that the next mouse-related command that should follow is buttonup . + -- Any other mouse command (such as click or another call to buttondown) will yield undefined behaviour. -- URL Parameters: -- :sessionId - ID of the session to route the command to. -- JSON Parameters: - -- button - {number} Which button, enum: {LEFT = 0, MIDDLE = 1 , RIGHT = 2}. Defaults to the left mouse button if not specified. + -- button - {number} Which button, enum: {LEFT = 0, MIDDLE = 1 , RIGHT = 2}. + -- Defaults to the left mouse button if not specified. + local + resp : SE_RESPONSE + l_json : STRING_32 do + l_json := "[ + { + "button" : $number + } + ]" + if commnad_executor.is_available then + l_json.replace_substring_all ("$number", button.value.out) + resp := commnad_executor.button_down (a_session_id, l_json) + check_response (resp) + end end - button_up (a_session_id: STRING_32) + button_up (a_session_id: STRING_32; button : SE_BUTTON) -- POST /session/:sessionId/buttonup -- Releases the mouse button previously held (where the mouse is currently at). Must be called once for every buttondown command issued. See the note in click and buttondown about implications of out-of-order commands. -- URL Parameters: -- :sessionId - ID of the session to route the command to. -- JSON Parameters: - -- button - {number} Which button, enum: {LEFT = 0, MIDDLE = 1 , RIGHT = 2}. Defaults to the left mouse button if not specified. + -- button - {number} Which button, enum: {LEFT = 0, MIDDLE = 1 , RIGHT = 2}. + -- Defaults to the left mouse button if not specified. + local + resp : SE_RESPONSE + l_json : STRING_32 do + l_json := "[ + { + "button" : $number + } + ]" + if commnad_executor.is_available then + l_json.replace_substring_all ("$number", button.value.out) + resp := commnad_executor.button_up (a_session_id, l_json) + check_response (resp) + end end - double_click (a_session_id: STRING_32) -- POST /session/:sessionId/doubleclick -- Double-clicks at the current mouse coordinates (set by moveto). -- URL Parameters: -- :sessionId - ID of the session to route the command to. + local + resp : SE_RESPONSE do + if commnad_executor.is_available then + resp := commnad_executor.double_click (a_session_id) + check_response (resp) + end end touch_click (a_session_id: STRING_32) diff --git a/library/test/selenium/src/protocol/se_json_wire_protocol_commands.e b/library/test/selenium/src/protocol/se_json_wire_protocol_commands.e index 4eba93dc..a1ba2bd7 100644 --- a/library/test/selenium/src/protocol/se_json_wire_protocol_commands.e +++ b/library/test/selenium/src/protocol/se_json_wire_protocol_commands.e @@ -103,8 +103,21 @@ feature Result.replace_substring_all ("$id", id) end - --POST /session/:sessionId/execute Inject a snippet of JavaScript into the page for execution in the context of the currently selected frame. - --POST /session/:sessionId/execute_async Inject a snippet of JavaScript into the page for execution in the context of the currently selected frame. + cmd_session_execute_tmpl: STRING = "session/$id/execute" + + cmd_session_execute (id: STRING_32): STRING_32 + do + create Result.make_from_string (cmd_session_execute_tmpl) + Result.replace_substring_all ("$id", id) + end + + cmd_session_execute_async_tmpl: STRING = "session/$id/execute_async" + + cmd_session_execute_async (id: STRING_32): STRING_32 + do + create Result.make_from_string (cmd_session_execute_async_tmpl) + Result.replace_substring_all ("$id", id) + end cmd_session_screenshot_tmpl: STRING = "session/$id/screenshot" @@ -156,6 +169,15 @@ feature --POST /session/:sessionId/frame Change focus to another frame on the page. + cmd_session_frame_tmpl: STRING = "session/$id/frame" + + cmd_session_frame (id: STRING_32): STRING_32 + do + create Result.make_from_string (cmd_session_frame_tmpl) + Result.replace_substring_all ("$id", id) + end + + cmd_session_window_tmpl: STRING = "session/$id/window" cmd_session_window (id: STRING_32): STRING_32 @@ -220,7 +242,7 @@ feature cmd_session_title (id: STRING_32): STRING_32 do - create Result.make_from_string (cmd_session_source_tmpl) + create Result.make_from_string (cmd_session_title_tmpl) Result.replace_substring_all ("$id", id) end @@ -611,7 +633,7 @@ feature cmd_session_storage_size_tmpl: STRING = "session/$sessionId/session_storage/size" - cmd_session_storage_size (sessionId: STRING_32; key : STRING_32): STRING_32 + cmd_session_storage_size (sessionId: STRING_32): STRING_32 do create Result.make_from_string (cmd_session_storage_size_tmpl) Result.replace_substring_all ("$sessionId", sessionId) diff --git a/library/test/selenium/src/se_button.e b/library/test/selenium/src/se_button.e new file mode 100644 index 00000000..51bb8d38 --- /dev/null +++ b/library/test/selenium/src/se_button.e @@ -0,0 +1,95 @@ +note + description: "Summary description for {SE_BUTTON}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + SE_BUTTON +inherit {NONE} + ENUM + + +create + make_left, + make_middle, + make_right + + +feature -- Initialization + + make_left + do + set_left + end + + make_middle + do + set_middle + end + + make_right + do + set_right + end + + +feature -- Access + + is_valid_value (a_value: INTEGER): BOOLEAN + -- Can `a_value' be used in a `set_value' feature call? + do + Result := (a_value = left_value) or else + (a_value = middle_value) or else + (a_value = right_value) + end + +feature -- Element Change + + set_left + do + value := left_value + end + + set_middle + do + value := middle_value + end + + set_right + do + value := right_value + end + + +feature -- Query + + is_left : BOOLEAN + -- is the current value left? + do + Result := (value = left_value) + end + + is_middle : BOOLEAN + -- is the current value middle? + do + Result := (value = middle_value) + end + + + is_right : BOOLEAN + -- is the current value right? + do + Result := (value = right_value) + end + + +feature {NONE} -- Implementation +-- {LEFT = 0, MIDDLE = 1 , RIGHT = 2} + left_value :INTEGER = 0 + middle_value : INTEGER = 1 + right_value : INTEGER = 2 +end + + + diff --git a/library/test/selenium/src/se_by.e b/library/test/selenium/src/se_by.e index ea4f37ec..84c6b63d 100644 --- a/library/test/selenium/src/se_by.e +++ b/library/test/selenium/src/se_by.e @@ -13,7 +13,7 @@ inherit create default_create feature -- Access - id (an_id : STRING_32; value : STRING_32 ) : STRING_32 + id ( value : STRING_32 ) : STRING_32 -- return a STRING representing a JSON -- with strategy by `id' and value `value' -- { "using" : "id", "value":value } @@ -25,7 +25,7 @@ feature -- Access has_id_strategy : has_correct_stategy (Result, se_id) end - name (an_id : STRING_32; value : STRING_32 ) : STRING_32 + name ( value : STRING_32 ) : STRING_32 -- return a STRING representing a JSON -- with strategy by `name' and value `value' -- { "using" : "name", "value":value } @@ -37,7 +37,7 @@ feature -- Access has_name_strategy : has_correct_stategy (Result, se_name) end - class_name (an_id : STRING_32; value : STRING_32 ) : STRING_32 + class_name ( value : STRING_32 ) : STRING_32 -- return a STRING representing a JSON -- with strategy by `class name' and value `value' -- { "using" : "class name", "value":value } @@ -50,7 +50,7 @@ feature -- Access end - css_selector (an_id : STRING_32; value : STRING_32 ) : STRING_32 + css_selector ( value : STRING_32 ) : STRING_32 -- return a STRING representing a JSON -- with strategy by `css selector' and value `value' -- { "using" : "css selector", "value":value } @@ -62,7 +62,7 @@ feature -- Access has_css_selector_strategy : has_correct_stategy (Result, se_css_selector) end - link_text (an_id : STRING_32; value : STRING_32 ) : STRING_32 + link_text ( value : STRING_32 ) : STRING_32 -- return a STRING representing a JSON -- with strategy by `link text' and value `value' -- { "using" : "link text", "value":value } @@ -75,7 +75,7 @@ feature -- Access end - partial_link_text (an_id : STRING_32; value : STRING_32 ) : STRING_32 + partial_link_text ( value : STRING_32 ) : STRING_32 -- return a STRING representing a JSON -- with strategy by `partial link text' and value `value' -- { "using" : "partial link text", "value":value } @@ -87,7 +87,7 @@ feature -- Access has_partial_link_text_strategy : has_correct_stategy (Result, se_partial_link_text) end - tag_name (an_id : STRING_32; value : STRING_32 ) : STRING_32 + tag_name ( value : STRING_32 ) : STRING_32 -- return a STRING representing a JSON -- with strategy by `tag name' and value `value' -- { "using" : "tag name", "value":value } @@ -100,7 +100,7 @@ feature -- Access end - xpath (an_id : STRING_32; value : STRING_32 ) : STRING_32 + xpath ( value : STRING_32 ) : STRING_32 -- return a STRING representing a JSON -- with strategy by `xpath' and value `value' -- { "using" : "xpath", "value":value } diff --git a/library/test/selenium/src/se_cookie.e b/library/test/selenium/src/se_cookie.e index 6731afdb..f15402f3 100644 --- a/library/test/selenium/src/se_cookie.e +++ b/library/test/selenium/src/se_cookie.e @@ -1,5 +1,5 @@ note - description: "bject that describe a cookie. When returning Cookie objects, the server should only omit an optional field if it is incapable of providing the information." + description: "Objects that describe a cookie. When returning Cookie objects, the server should only omit an optional field if it is incapable of providing the information." author: "" date: "$Date$" revision: "$Revision$" diff --git a/library/test/selenium/src/se_window.e b/library/test/selenium/src/se_dimension.e similarity index 74% rename from library/test/selenium/src/se_window.e rename to library/test/selenium/src/se_dimension.e index 49ea5477..216105af 100644 --- a/library/test/selenium/src/se_window.e +++ b/library/test/selenium/src/se_dimension.e @@ -1,11 +1,11 @@ note - description: "Summary description for {SE_WINDOW}." + description: "Summary description for {SE_DIMENSION}." author: "" date: "$Date$" revision: "$Revision$" class - SE_WINDOW + SE_DIMENSION create default_create, make_with_values @@ -24,8 +24,6 @@ feature -- Access height : NATURAL_32 -- The width and height of the element, in pixels. - x,y : INTEGER_32 - -- The X and Y coordinates for the element. feature -- Change Element set_width (a_width : NATURAL_32) @@ -41,14 +39,6 @@ feature -- Change Element height := a_height end - set_x (an_x : INTEGER_32) - do - x := an_x - end - set_y (an_y : INTEGER_32) - do - y := an_y - end end diff --git a/library/test/selenium/src/se_point.e b/library/test/selenium/src/se_point.e new file mode 100644 index 00000000..fc360760 --- /dev/null +++ b/library/test/selenium/src/se_point.e @@ -0,0 +1,41 @@ +note + description: "Summary description for {SE_POINT}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + SE_POINT + +create + default_create, + make_with_values + +feature -- Initialization + + make_with_values (new_x : INTEGER_32; new_y : INTEGER_32) + do + set_x (new_x) + set_y (new_y) + end + +feature -- Access + + x : INTEGER_32 + y : INTEGER_32 + + -- The X and Y coordinates for the element. + +feature -- Change Element + + set_x (an_x : INTEGER_32) + do + x := an_x + end + + set_y (an_y : INTEGER_32) + do + y := an_y + end + +end diff --git a/library/test/selenium/src/web_driver.e b/library/test/selenium/src/web_driver.e new file mode 100644 index 00000000..5144541f --- /dev/null +++ b/library/test/selenium/src/web_driver.e @@ -0,0 +1,444 @@ +note + description: "Objects that represent a Web Browser" + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WEB_DRIVER + +inherit {NONE} + + SE_JSON_WIRE_PROTOCOL + rename + back as se_back, + forward as se_forward, + refresh as se_refresh, + window_position as se_window_position, + window_maximize as se_window_maximize + export + {NONE} all + end + +create {SE_JSON_WIRE_PROTOCOL} + make, make_with_host + +feature -- Initialize Session + + start_session_firefox + local + l_capabilities: SE_CAPABILITIES + do + create l_capabilities.make + l_capabilities.set_browser_name ("firefox") + session := create_session_with_desired_capabilities (l_capabilities) + end + + start_session_firefox_with_desired_capabilities (a_desired_capabilities: SE_CAPABILITIES) + require + browser_name_firefox: attached a_desired_capabilities.browser_name as l_browser_name and then l_browser_name ~ "firefox" + do + session := create_session_with_desired_capabilities (a_desired_capabilities) + end + + start_session_chrome + local + l_capabilities: SE_CAPABILITIES + do + create l_capabilities.make + l_capabilities.set_browser_name ("chrome") + session := create_session_with_desired_capabilities (l_capabilities) + end + + start_session_chrome_with_desired_capabilities (a_desired_capabilities: SE_CAPABILITIES) + require + browser_name_chrome: attached a_desired_capabilities.browser_name as l_browser_name and then l_browser_name ~ "chrome" + do + session := create_session_with_desired_capabilities (a_desired_capabilities) + end + + start_session_ie + local + l_capabilities: SE_CAPABILITIES + do + create l_capabilities.make + l_capabilities.set_browser_name ("internet explorer") + session := create_session_with_desired_capabilities (l_capabilities) + end + + start_session_ie_with_desired_capabilities (a_desired_capabilities: SE_CAPABILITIES) + require + browser_name_chrome: attached a_desired_capabilities.browser_name as l_browser_name and then l_browser_name ~ "internet explorer" + do + session := create_session_with_desired_capabilities (a_desired_capabilities) + end + + --|TODO add create session with desired and required capabilities + --| add other drivers. + --| think about pre and postconditions + +feature -- Query + + is_session_active: BOOLEAN + -- exist a valid session? + do + Result := attached session + end + +feature -- Ime Handler + + activate_engine (engine: STRING_32) + -- Make an engines that is available (appears on the list returned by getAvailableEngines) active. + require + exist_session: is_session_active + do + if attached session as l_session then + ime_activate (l_session.session_id, engine) + end + end + + deactivate + -- De-activates the currently-active IME engine. + require + exist_session: is_session_active + do + if attached session as l_session then + ime_deactivate (l_session.session_id) + end + end + + available_engines: detachable LIST [STRING_32] + -- List all available engines on the machine. To use an engine, it has to be present in this list. + require + exist_session: is_session_active + do + if attached session as l_session then + Result := ime_available_engines (l_session.session_id) + end + end + + is_activated: BOOLEAN + require + exist_session: is_session_active + do + if attached session as l_session then + Result := ime_activated (l_session.session_id) + end + end + +feature -- Navigation + + back + -- Navigate backwards in the browser history, if possible. + require + exist_session: is_session_active + do + if attached session as l_session then + se_back (l_session.session_id) + end + end + + forward + -- Navigate forwards in the browser history, if possible. + require + exist_session: is_session_active + do + if attached session as l_session then + se_forward (l_session.session_id) + end + end + + refresh + -- + require + exist_session: is_session_active + do + if attached session as l_session then + se_refresh (l_session.session_id) + end + end + + to_url (an_url: STRING_32) + -- Navigate to a new URL. + require + exist_session: is_session_active + do + if attached session as l_session then + navigate_to_url (l_session.session_id, an_url) + end + end + +feature -- Options + -- Stuff you would do in a browser menu + + add_cookie (cookie: SE_COOKIE) + -- Set a cookie. If the cookie path is not specified, it should be set to "/". + -- Likewise, if the domain is omitted, it should default to the current page's domain. + require + exist_session: is_session_active + do + if attached session as l_session then + set_cookie (l_session.session_id, cookie) + end + end + + delete_all_cookies + -- Delete all cookies visible to the current page. + require + exist_session: is_session_active + do + if attached session as l_session then + delete_cookies (l_session.session_id) + end + end + + delete_cookie (cookie: SE_COOKIE) + -- Delete the cookie with the given name. + -- This command should be a no-op if there is no such cookie visible to the current page. + require + exist_session: is_session_active + do + if attached session as l_session and then attached cookie.name as l_name then + delete_cookie_by_name (l_session.session_id, l_name) + end + end + + get_cookies: detachable LIST [SE_COOKIE] + -- Retrieve all cookies visible to the current page. + require + exist_session: is_session_active + do + if attached session as l_session then + Result := retrieve_cookies (l_session.session_id) + end + end + + get_cookie (name: STRING_32): detachable SE_COOKIE + -- Get a cookie with a given name + require + exist_session: is_session_active + local + found: BOOLEAN + do + if attached session as l_session then + if attached retrieve_cookies (l_session.session_id) as l_list then + from + l_list.start + until + l_list.after or found + loop + if attached l_list.item.name as l_name and then l_name.is_case_insensitive_equal (name) then + found := true + Result := l_list.item + end + l_list.forth + end + end + end + end + +feature -- Target Locator + + active_element: detachable WEB_ELEMENT + require + exist_session: is_session_active + do + if attached session as l_session then + Result := element_active (l_session.session_id) + end + end + + default_content + -- The server switch to the page's default content. + require + exist_session: is_session_active + do + if attached session as l_session then + frame (l_session.session_id, Void) + end + end + + frame_by_index (index: INTEGER) + -- Select a frame by index `index' + require + exist_session: is_session_active + do + if attached session as l_session then + frame (l_session.session_id, index.out) + end + end + + frame_by_name (name: STRING_32) + -- Select a frame by name `name' + require + exist_session: is_session_active + do + if attached session as l_session then + frame (l_session.session_id, name) + end + end + + frame_by_web_element (element: WEB_ELEMENT) + -- Select a frame by name `name' + require + exist_session: is_session_active + do + if attached session as l_session then + frame (l_session.session_id, element.element) + end + end + + window (name: STRING_32) + -- Change focus to another window. + -- The window to change focus to may be specified by its server assigned window handle, or by the value of its name attribute. + require + exist_session: is_session_active + do + if attached session as l_session then + change_focus_window (l_session.session_id, name) + end + end + +feature -- Window + + window_position: SE_POINT + -- Get the position of the current window. + require + exist_session: is_session_active + do + create Result + if attached session as l_session then + Result := se_window_position (l_session.session_id, "current") + end + end + + window_size: SE_DIMENSION + --Get the size of the current window. + require + exist_session: is_session_active + do + create Result + if attached session as l_session then + Result := size_window (l_session.session_id, "current") + end + end + + window_maximize + --Maximizes the current window if it is not already maximized + require + exist_session: is_session_active + do + if attached session as l_session then + se_window_maximize (l_session.session_id, "current") + end + end + + set_window_position (target_position: SE_POINT) + -- Set the position of the current window. + require + exist_session: is_session_active + do + if attached session as l_session then + change_window_position (l_session.session_id, "current", target_position.x, target_position.y) + end + end + + set_window_size (target_size: SE_DIMENSION) + --Set the size of the current window. + require + exist_session: is_session_active + do + if attached session as l_session then + change_size_window (l_session.session_id, "current", target_size.width, target_size.height) + end + end + +feature -- Common + + window_close + --Close the current window, quitting the browser if it's the last window currently open. + require + exist_session: is_session_active + do + if attached session as l_session then + close_window (l_session.session_id) + end + end + + find_element (by: SE_BY) : detachable WEB_ELEMENT + -- Find the first WebElement using the given strategy. + require + exist_session : is_session_active + do + if attached session as l_session then + + end + end + + find_elements (by: SE_BY) : detachable LIST[WEB_ELEMENT] + -- Find all elements within the current page using the given mechanism.. + require + exist_session : is_session_active + do + if attached session as l_session then + + end + end + + + get_current_url : detachable STRING_32 + -- Retrieve the URL of the current page. + require + exist_session : is_session_active + do + if attached session as l_session then + Result := retrieve_url (l_session.session_id) + end + end + + get_page_source : detachable STRING_32 + -- Get the current page source. + require + exist_session : is_session_active + do + if attached session as l_session then + Result := page_source (l_session.session_id) + end + end + + get_page_tile : detachable STRING_32 + --Get the current page title + require + exist_session : is_session_active + do + if attached session as l_session then + Result := page_title (l_session.session_id) + end + end + + + + get_window_handle : detachable STRING_32 + require + exist_session : is_session_active + do + if attached session as l_session then + Result := retrieve_window_handle (l_session.session_id) + end + end + + get_window_handles : detachable LIST[STRING_32] + require + exist_session : is_session_active + do + if attached session as l_session then + Result := retrieve_window_handles (l_session.session_id) + end + end + + +feature {NONE} -- Implementation + + session: detachable SE_SESSION + +end diff --git a/library/test/selenium/src/web_element.e b/library/test/selenium/src/web_element.e index d0fd67f0..4ae9c1eb 100644 --- a/library/test/selenium/src/web_element.e +++ b/library/test/selenium/src/web_element.e @@ -7,11 +7,20 @@ note class WEB_ELEMENT create - make + make, + make2 feature + make2 ( an_element : STRING_32 ; an_api : like api; a_session_id : STRING_32) + do + set_element (an_element) + api := an_api + session_id := a_session_id + end make ( an_element : STRING_32) do set_element (an_element) + create api.make + session_id := "" end feature -- Access element : STRING_32 @@ -23,4 +32,102 @@ feature -- Change Element do element := an_element end + +feature -- Web Element API + clear + -- Clear a TEXTAREA or text INPUT element's value. + do + api.clear_element (session_id, element) + end + + click + -- Click on an element. + do + api.element_click (session_id, element) + end + + find_element (by : SE_BY) : detachable WEB_ELEMENT + -- Find the first WebElement using the given method. + do + Result := api.search_element (session_id,"") + end + + find_elementS (by : SE_BY) : detachable LIST[WEB_ELEMENT] + -- Find all elements within the current context using the given mechanism. + do + Result := api.search_elements (session_id,"") + end + + get_attribute (name : STRING_32) : detachable STRING_32 + -- Get the value of an element's attribute. + do + Result := api.element_value (session_id, element, name) + end + + get_css_value (name : STRING_32) : detachable STRING_32 + -- Get the value of an element's attribute. + do + Result := api.element_css_value (session_id, element, name) + end + + get_location : SE_POINT + -- Determine an element's location on the page. The point (0, 0) refers to the upper-left corner of the page. + do + Result := api.element_location (session_id, element) + end + + + get_size : SE_DIMENSION + -- Determine an element's size in pixels. The size will be returned as a JSON object with width and height properties. + do + Result := api.element_size (session_id, element) + end + + get_tag_name : detachable STRING_32 + -- The element's tag name, as a lowercase string. + do + Result := api.query_by_tag_name (session_id, element) + end + + + get_text : detachable STRING_32 + -- Returns the visible text for the element. + do + Result := api.element_text (session_id, element) + end + + is_displayed : BOOLEAN + -- Determine if an element is currently displayed. + do + Result := api.is_displayed (session_id, element) + end + + is_enabled : BOOLEAN + -- Determine if an element is currently enabled. + do + Result := api.is_enabled (session_id, element) + end + + is_selected : BOOLEAN + -- Determine if an OPTION element, or an INPUT element of type checkbox or radiobutton is currently selected. + do + Result := api.is_selected (session_id, element) + end + + send_keys (keys : ARRAY[STRING_32]) + -- Send a sequence of key strokes to an element. + do + api.send_event (session_id, element, keys) + end + + submit + -- Submit a FORM element. The submit command may also be applied to any element that is a descendant of a FORM element. + do + api.element_submit (session_id, element) + end + +feature {NONE} -- Implementation + + api : SE_JSON_WIRE_PROTOCOL + session_id : STRING_32 end diff --git a/library/test/selenium/test/application.e b/library/test/selenium/test/application.e index 3787b649..0c15522a 100644 --- a/library/test/selenium/test/application.e +++ b/library/test/selenium/test/application.e @@ -115,6 +115,7 @@ feature {NONE} -- Initialization print ("The selenium server is not accesible") end end + test_back_forward_refesh local web_driver: SE_JSON_WIRE_PROTOCOL @@ -184,6 +185,8 @@ feature {NONE} -- Initialization end end end + + test_session local h: LIBCURL_HTTP_CLIENT