Explorar o código

Add constructor for desired capabilties: new_from_caps

Daniel Gempesaw %!s(int64=11) %!d(string=hai) anos
pai
achega
626cd2cbf9
Modificáronse 2 ficheiros con 96 adicións e 46 borrados
  1. 42 31
      lib/Selenium/Remote/Driver.pm
  2. 54 15
      t/01-driver.t

+ 42 - 31
lib/Selenium/Remote/Driver.pm

@@ -196,56 +196,57 @@ available here.
     or
     my $driver = Selenium::Remote::Driver->new('default_finder' => 'css');
 
-=head2 new (desired_capabilities)
+=head2 new_from_caps
 
  Description:
 
     For experienced users who want complete control over the desired
-    capabilities, use the desired_capabilities hash option. This will
-    IGNORE all other browser-related desiredCapability options; the
-    only options that will be respected are those that are NOT part of
-    the Capabilities JSON Object as described in the Json Wire
-    Protocol. See Inputs below for more details.
+    capabilities, use this alternative constructor along with the
+    C<desired_capabilities> hash key in the init hash. Unlike "new",
+    this constructor will not assume any defaults for your desired
+    capabilities.
 
-    The hashref you pass in as desired_capabilities only gets json
-    encoded before being passed to the Selenium server; no default
-    options of any sort will be added.
+    This alternate constructor IGNORES all other browser-related
+    desiredCapability options; the only options that will be respected
+    are those that are NOT part of the Capabilities JSON Object as
+    described in the Json Wire Protocol.
 
-    Additionally, you must handle normalization of the input options
-    (like C<browser_name> vs C<browserName>) and take care of things
-    like encoding the firefox profile if applicable.
+ Input:
+    The only respected keys in the input hash are:
 
-    More information about the desired capabilities object is
-    available on the Selenium wiki:
+        remote_server_addr   - STRING  - defaults to localhost
+        port                 - INTEGER - defaults to 4444
+        default_finder       - STRING  - defaults to xpath
+        webelement_class     - STRING  - defaults to Selenium::Remote::WebElement
+        auto_close           - BOOLEAN - defaults to 1
+        desired_capabilities - HASHREF - defaults to {}
 
-    https://code.google.com/p/selenium/wiki/JsonWireProtocol#Capabilities_JSON_Object
+    Except for C<desired_capabilities>, these keys perform exactly the
+    same as listed in the regular "new" constructor.
 
- Input:
-    If 'desired_capabilities' is one of your keys, these are the only
-    respected options:
+    The hashref you pass in as desired_capabilities only gets json
+    encoded before being passed to the Selenium server; no default
+    options of any sort will be added.
 
-        'remote_server_addr'
-        'port'
-        'default_finder'
-        'webelement_class'
-        'auto_close'
-        'desired_capabilities'
+    This means you must handle normalization and casing of the input
+    options (like "browser_name" vs "browserName") and take care of
+    things like encoding the firefox profile if applicable. More
+    information about the desired capabilities object is available on
+    the Selenium wiki:
 
-    All other options will be ignored.
+    https://code.google.com/p/selenium/wiki/JsonWireProtocol#Capabilities_JSON_Object
 
  Output:
     Remote Driver object
 
  Usage:
-    my $driver = Selenium::Remote::Driver->new(
-        'desired_capabilities' => {
-            'browserName' => 'firefox'
-        }
+    my $driver = Selenium::Remote::Driver->new_from_caps(
+        'desired_capabilities' => {'browserName' => 'firefox'}
     );
 
     The above would generate a POST to the webdriver server at
-    localhost:4444 with the payload of {"desiredCapabilities":
-    {"browserName": "firefox" }}.
+    localhost:4444 with the exact payload of '{"desiredCapabilities":
+    {"browserName": "firefox" }}'.
 
 =cut
 
@@ -397,6 +398,16 @@ sub BUILD {
     }
 }
 
+sub new_from_caps {
+    my ($self, %args) = @_;
+
+    if (not exists $args{desired_capabilities}) {
+        $args{desired_capabilities} = {};
+    }
+
+    return $self->new(%args);
+}
+
 sub DESTROY {
     my ($self) = @_;
     return if $$ != $self->pid;

+ 54 - 15
t/01-driver.t

@@ -47,21 +47,42 @@ DESIRED_CAPABILITIES: {
         sessionId => '123124123'
     };
 
-    $tua->map_response(qr{status|quit}, HTTP::Response->new(200, 'OK'));
-
-    $tua->map_response(qr{session}, sub {
-                           my $request = shift;
-                           my $caps = from_json($request->decoded_content)->{desiredCapabilities};
-                           my @keys = keys %$caps;
-                           ok(scalar @keys == 2, 'exactly 2 keys passed in if we use desired_capabilities');
-                           ok($keys[0] eq 'browserName', 'and it is the right one');
-                           ok($caps->{superfluous} eq 'thing', 'and we pass through anything else');
-                           ok($caps->{browserName} eq 'firefox', 'and we override the "normal" caps');
-                           ok(!exists $caps->{platform}, 'or ignore them entirely');
-                           HTTP::Response->new(204, 'OK', ['Content-Type' => 'application/json'], to_json($res));
-                       });
-
-    my $driver = Selenium::Remote::Driver->new(
+    $tua->map_response(qr{status}, HTTP::Response->new(200, 'OK'));
+
+    my $requests_count = 0;
+    my $mock_session_handler = sub {
+        my $request = shift;
+        $requests_count++;
+
+        if ($request->method eq 'POST') {
+            my $caps = from_json($request->decoded_content)->{desiredCapabilities};
+
+            my @keys = keys %$caps;
+            if (scalar @keys) {
+                ok(scalar @keys == 2, 'exactly 2 keys passed in if we use desired_capabilities');
+
+                my $grep = grep { 'browserName' eq $_ } @keys;
+                ok($grep, 'and it is the right one');
+                ok($caps->{superfluous} eq 'thing', 'and we pass through anything else');
+                ok($caps->{browserName} eq 'firefox', 'and we override the "normal" caps');
+                ok(!exists $caps->{platform}, 'or ignore them entirely');
+            }
+            else {
+                ok(to_json($caps) eq '{}', 'an empty constructor defaults to an empty hash');
+            }
+
+            return HTTP::Response->new(204, 'OK', ['Content-Type' => 'application/json'], to_json($res));
+        }
+        else {
+            # it's the DELETE when the driver calls
+            # DESTROY. This should be the last call to /session/.
+            return HTTP::Response->new(200, 'OK')
+        }
+    };
+
+    $tua->map_response(qr{session}, $mock_session_handler);
+
+    my $caps_driver = Selenium::Remote::Driver->new_from_caps(
         auto_close => 0,
         browser_name => 'not firefox',
         platform => 'WINDOWS',
@@ -71,6 +92,24 @@ DESIRED_CAPABILITIES: {
         },
         ua => $tua
     );
+
+    ok($caps_driver->auto_close eq 0, 'and other properties are still set');
+
+    $caps_driver = Selenium::Remote::Driver->new(
+        auto_close => 0,
+        browser_name => 'not firefox',
+        platform => 'WINDOWS',
+        desired_capabilities => {
+            'browserName' => 'firefox',
+            'superfluous' => 'thing'
+        },
+        ua => $tua
+    );
+
+    ok($caps_driver->auto_close eq 0, 'and other properties are set if we use the normal constructor');
+
+    $caps_driver = Selenium::Remote::Driver->new_from_caps(ua => $tua);
+    ok($requests_count == 3, 'The new_from_caps section has the correct number of requests to /session/');
 }
 
 CHECK_DRIVER: {