Coder Social home page Coder Social logo

seneca-cdot / plumadriver Goto Github PK

View Code? Open in Web Editor NEW
9.0 8.0 7.0 71.87 MB

A standalone server implementing the W3C WebDriver standard using jsdom

License: MIT License

JavaScript 41.46% HTML 3.50% TypeScript 55.04%
selenium jsdom webdriver w3c typescript javascript nodejs

plumadriver's People

Contributors

c3ho avatar dependabot[bot] avatar humphd avatar manekenpix avatar meisterred avatar miggs125 avatar poftadeh avatar tienpv222 avatar zthaver avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

plumadriver's Issues

Create "has" utility reference for property checks

What would you like to be added:

Object.prototype.hasOwnProperty is used many times throughout the codebase. It is more efficient to cache the lookup (i.e. const has = Object.prototype.hasOwnProperty) in a place like utils/, and import it where it is needed.

Why is this needed:

It is more efficient. See Airbnb's style guide section on this topic.

Replace constructor name checks

What would you like to be added:
Type checking is done in several places with constructor checks, e.g. this.valid = capability.constructor === Object;. Suggest replacing with instanceof/typeof, i.e. this.valid = capability instanceof Object and/or using Typescript guards.

Why is this needed:
The constructor property can be mutated, and may be less reliable in some cases.

Additional context

Cannot access window or document objects when executing a synchronous script

What happened:
Error executing a synchronous script referencing window and document objects.

What you expected to happen:
The ability to use the above objects using the endpoint

How to reproduce it (as minimally and precisely as possible):
In Selenium:

JavascriptExecutor js = (JavascriptExecutor) driver;
String output = (String) js.executeScript("return document.title");

Implement Session Actions

What would you like to be added:
The selenium client provides users with an actions object which allows users to send the driver a list of actions to be performed synchronously or asynchronously. This includes, keyUp, keyDown, mouseMove, click, etc. More info on this can be found here

The following seem the most critical and should be implemented first:

  • click
  • moveToElement
  • contextClick
  • doubleClick
  • sendKeys (this is not the same as the Element Send Keys endpoint)
  • keyUp
  • keyDown
  • moveByOffset
  • dragAndDrop

Why is this needed:
This is a very powerful feature of selenium and plumadriver would be missing a lot of functionality if this fails to be implemented

Additional context

Remove unneeded folders

What changes would you like to see:
The legacy folder can be removed (these files are still accessible in older commits), and perhaps the test_docs folder as well (need to confirm).

Why is this needed:
Master branch should only contain essential files and folders used for development/production.

executeScript: issues returning WebElements

Description
Exceptions when attempting to return a WebElement as a result of executeScript. The first test should just pass an element in and retrieve that same element. The second test should try to retrieve that same element directly.

Steps/Code to Reproduce
public static void test(WebDriver driver)
{
driver.get("http://captive.apple.com");
WebElement element = driver.findElement(By.tagName("body"));

  WebElement e1 = (WebElement)((JavascriptExecutor)driver).executeScript("return arguments[0];", element);
  Assert.assertEquals(e1, element);
        
  WebElement e2 = (WebElement)((JavascriptExecutor)driver).executeScript("return document.getElementsByTagName('body')[0];");
  Assert.assertEquals(e2, element);

}

Expected Results
Both asserts should pass in Pluma, as they do in Chrome.

Actual Results
Chrome passes. The first test fails with an exception; an error log is generated, but completely empty.
Exception in thread "main" java.lang.ClassCastException: com.google.common.collect.Maps$TransformedEntriesMap cannot be cast to org.openqa.selenium.WebElement
at nexj.core.testing.ui.application.Test.test(Test.java:99)
at nexj.core.testing.ui.application.Test.main(Test.java:31)

The second test throws a very familiar console error, and 'document is not defined' is in the error log.
pluma_error_log_2.txt
output_2.txt

Versions
Against this version: 21e5022

Execute script: returns null on falsy values

What happened:
Attempting to return false, '', 0 or other falsy values that are not null or undefined instead returns null.

How to reproduce it (as minimally and precisely as possible):
executeScript("return false")

Anything else we need to know?:
Likely caused by the default endpoint logic handler converting falsy values to null.

Pkg scripts fail to create executables

What happened:
Build process reports many warnings, e.g. Warning Failed to make bytecode latest-x64 for file /snapshot/plumadriver/node_modules/express/index.js

What you expected to happen:
pkg commands to run without any problems.

How to reproduce it (as minimally and precisely as possible):
Run any one of the four build scripts. (tested not working on both windows and linux)

Anything else we need to know?:
pkg also seems to have problems with node12. Changing target build settings results in errors with this version.

Enforce and automate code standards

What would you like to be added:
Add and configure Eslint rules for the following:

  • typescript
  • prettier

Add automation for linting rules:

  • husky
  • lint-staged

Add linting of commit messages:

  • commitlint

Why is this needed:
Improves the readability of the code, prevents certain bugs, and ensures that consistent standards are being followed during development.

Implement Get Named Cookie endpoint

What would you like to be added:
Get Named Cookie: returns a cookie with a requested name from the Cookie Jar.

Why is this needed:
It is part of the endpoints needed for cookie management

Additional context
Specification.

UnhandledPromptBehaviour property typo

What would you like to be changed:
There is a typo on line 50 of SessionManager.ts. Add the missing letter in unhandledPromtBehaviour.

Why is this needed:
This causes the capability to be improperly reported to the client.

Convert existing Mocha tests to Jest

What would you like to be changed:
Change the existing tests (e.g. validator.js) to work under Jest.

Why is this needed:
Consolidates all tests under one framework.

Additional context:
Jest's migration documentation suggests using npx jest-codemods to assist in the conversion.

Runscripts validator conflicts with RunScripts type

Describe the bug
runScripts validator expects a boolean:

runScripts(value) {
      return value.constructor === Boolean;
},

RunScriptsValues are defined as StringUnion('dangerously', 'outside-only', '')

To Reproduce
Sending a request to /session with the following JSON produces an error:

{    
      "capabilities": {
      "firstMatch": [
        {
          "browserName": "pluma",
          "plm:plumaOptions": { "runScripts": "dangerously" }
        }
      ]
    }
  }

Replacing dangerously with false creates a session successfully, but node reports an unhandled promise rejection warning.

defaultSessionEndpointLogic ignores explicit "value: null" responses

In utils.ts:

    let response = null;
    const result = await req.session.process(req.sessionRequest);
    if (result) {
      response = { value: result };
      res.json(response);
    } else {
      res.send(response);
    }

Sometimes the endpoint must return null (e.g. NAVIGATE_TO), but in some cases it must return explicitly { "value": null } (e.g. ELEMENT_CLICK).

  • Refactor the logic to handle both cases appropriately.

Make issue template

We need a template to log issues, simplify debugging and make the code base more maintainable. This should at the very least include the following:

  • reproduction environment: OS, code that caused the issue/bug
  • expected value vs actual value

any other ideas as to what to include in the template?

Add isDisplayed endpoint

What would you like to be added:
isDisplayed: this endpoint determines whether or not an element is visible to the human eye.

Why is this needed:
According to the spec, this is a feature that is important to many users.

Additional context
Reference algorithm

executeScript: incorrect return value of undefined

Description
executeScript returns an empty map instead of null when executing 'return undefined;' or 'return;'

Steps/Code to Reproduce
public static void test(WebDriver driver)
{
driver.get("http://captive.apple.com");

  Assert.assertEquals(null, ((JavascriptExecutor)driver).executeScript("return null;"));      
  Assert.assertEquals(null, ((JavascriptExecutor)driver).executeScript("return undefined;"));
  Assert.assertEquals(null, ((JavascriptExecutor)driver).executeScript("return;"));     

}

Expected Results
All three asserts should pass in both Chrome and Pluma, since, according to the Selenium Javadoc, "Unless the value is null or there is no return value, in which null is returned"

https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/JavascriptExecutor.html

Actual Results
All three pass in Chrome. The first passes in Pluma, and the next two fail.
Exception in thread "main" junit.framework.AssertionFailedError: expected: but was:<{}>
at junit.framework.Assert.fail(Assert.java:47)

Versions
Against this build: 21e5022

Execute script: global functions are not recognized

What happened:
Attempting to run a global function throws a JavaSciptError: not defined.

How to reproduce it (as minimally and precisely as possible):
Create a global function foo within the page, and attempt to call it from executeScript('foo()')

Anything else we need to know?:
This is likely a problem with contextifying the V8 Virtual Machine.

ExecuteScript endpoint enhancements

What would you like to be added:

  • Add JavaScriptError and ScriptTimeoutError classes
  • fix bug related to missing window and document objects in execute script context.
  • write jest tests for endpoint functions.
  • refactor/optimize old code
  • add missing timeout check (use Promise.race() during script execution)

Why is this needed:
To adhere to W3C recommendation, optimize, and prevent future bugs related to the endpoint.

Support typescript strict mode

What would you like to be added:

Support strict type checking settings, such as disallowing implicit any or missing declarations. Change config properties in tsconfig.json to enable these features (i.e. strict: true). Make the necessary changes to the codebase to pass checks under these settings.

Why is this needed:

Helps further prevent bugs with more thorough type validation throughout the codebase.

Tasks:

  • noImplicitAny @MeisterRed
  • strictNullChecks @zthaver
  • strictPropertyInitialization @zthaver
  • strictBindCallApply @pynnl
  • noImplicitThis @pynnl
  • strictFunctionTypes @pynnl
  • alwaysStrict @pynnl
  • combine strict options in tsconfig (should be done after the aboves) @pynnl
  • add type for jsdom and express, and remove redundancy @pynnl

Split session commands into modules

The Session class is growing rather large and violating the single-responsibility principle. Suggest splitting each command into its own module. This will make the code more maintainable and easier to reason about.

Clean up error logging

The error log produced by plumadriver is somewhat messy. This needs to be cleaned up. A date should also be added everytime an error is logged.

Unable to navigate to a file on the local filesystem

Description
.get fails to navigate to a path on the local filesystem. The use case for this is twofold; one, it would be nice to test small items quickly without standing up a web server, and we also have a large offline demo app which displays examples of each of our control types. The test .html page is very basic but I'll attach it anyways. (as .txt since I can't upload an .html)
test.txt

Steps/Code to Reproduce
public static void test(WebDriver driver)
{
driver.get("file://C:/work/test.html");
}

Expected Results
Both ChromeDriver and the PlumaDriver should navigate properly.

Actual Results
ChromeDriver navigates properly. PlumaDriver fails on the get. Stack trace as follows:
stack.txt

Error log:
pluma_error_log.txt

Versions
latest

Support click navigation

What would you like to be added:
The click endpoint ignores elements that would trigger navigation due to jsdom's limitations. Add a way to support this.

Why is this needed:
Click navigation is part of the W3C spec, and would allow implementing some common user interactions (e.g. clicking anchor tags).

Additional context
May involve refactoring click and clear logic to be handled by the Browser.

Convert namespace imports to default imports

What would you like to be added:

  • Convert all import * as foo from foo to import foo from foo
  • enable esModuleInterop in tsconfig.json
  • set moduleResolution to 'node'

Why is this needed:
This is recommended by Typescript's documentation as it brings imports closer to intended behaviour.

Additional context
See Typescript's notes.

getText returns innerHTML instead of textContent

Description
PlumaDriver .getText() returns the innerHTML of the element instead of the textContent.

Steps/Code to Reproduce

public static void test(WebDriver driver)
{
driver.get("http://captive.apple.com");
WebElement element = driver.findElement(By.tagName("head"));
Assert.assertTrue(element.getText().equals("Success"));
}

Expected Results
Passing in a ChromeDriver instance and a PlumaDriver instance should both pass.

Actual Results
Passing in a ChromeDriver instance passes. Passing in a PlumaDriver instance fails, and the result of the call is <title>Success</title> instead of simply Success.

Versions
Is PlumaDriver versioned yet?

DOM is undefined when a session is created without a url parameter

Describe the bug
If no url is provided when creating a session, the dom object within a Browser class does not get initialized.

To Reproduce
POST to /session/ with the following capabilities:

{    
	"capabilities": {
      "firstMatch": [
        {
          "browserName": "pluma",
          "plm:plumaOptions": { "runScripts": false }
        }
      ]
    }
}

Describe the results you received:
this.dom is undefined.

Describe the results you expected:
this.dom to be set to a default jsdom object.

Additional context
Suspected cause is in Browser.ts:

      this.dom = await new JSDOM(' ', {
        resources: config.resourceLoader,
        runScripts: config.runScripts,
        beforeParse: config.beforeParse,
        pretendToBeVisual: true,
        cookieJar: config.jar
      });

await on a non-promise may be preventing the value from being set.

Exception adding cookie to plumadriver

Our basic strategy was to:

  1. Login to the application directly with Chrome via basic auth.
  2. Use getCookies and store the resultant set of cookies.
  3. Get an instance of PlumaDriver, and navigate to some site on the domain,
  4. Apply those stored cookies via addCookie.
  5. Navigate to the application proper, you're now logged in.

It looks like we're failing on step 4. Replacing PlumaDriver with the Firefox GeckoDriver works properly. I thought maybe this method of getting the cookies was a bit janky, so I replaced it with the 'proper' method; using OkHttp to create a request with the authentication, and parsing out the cookies from the response headers. This gives me the same error. Firefox continues to work.

I've attached a partial stack trace below; if there's any more information you need, please let me know.

org.openqa.selenium.InvalidArgumentException: The arguments passed to undefined are either invalid or malformed
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:25:48'
System info: host: 'TOR-DT-AJORDAN1', ip: '192.168.61.28', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_121'
Driver info: org.openqa.selenium.chrome.PlumaDriver
Capabilities {acceptInsecureCerts: true, browserName: pluma, browserVersion: v1.0, javascriptEnabled: true, pageLoadStrategy: normal, platform: UNIX, platformName: UNIX, plm:plumaOptions: {}, proxy: Proxy(), setWindowRect: false, timeouts: {implicit: 0, pageLoad: 30000, script: 30000}}
Session ID: 0c9d37b1-82f1-11e9-907f-c1ce7518a251
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeConstructorAccessorImpl.java)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
at org.openqa.selenium.remote.RemoteWebDriver$RemoteWebDriverOptions.addCookie(RemoteWebDriver.java:682)
at nexj.core.testing.ui.application.Application.login(Application.java:604)
at nexj.core.testing.ui.application.AFLApplication.login(AFLApplication.java:174)
at nexj.core.testing.ui.application.AFLApplication.login(AFLApplication.java:145)

Remove copy command in build scripts

What would you like to be added:
The command cp -r ./src/jsdom_extensions/ ./build/ found in the build scripts is no longer necessary since typescript has been configured to include this folder on compile (see #38).

Why is this needed:
Reduces build times since the tsc command already compiles this folder.

Remove explicit Promise return in Session process function

What would you like to be changed:

In Session.ts:

async process({
    command,
    parameters,
    urlVariables,
  }: Pluma.Request): Promise<string> {
    let response = null;

    return new Promise(
      async (resolve, reject): Promise<void> => ...

Async functions wrap return values in Promises, so this can be omitted.

Remove unused packages

What would you like to be added:
Uninstall packages that are not used in the project. Remove these dependencies from package.json.

Why is this needed:
Doing so will reduce the application's overhead.

Additional context
npx depcheck gives the following output. This is not comprehensive or entirely accurate (i.e. some of these are actual dependencies), but it's a starting point.

Unused dependencies
* encodeurl
* express_logger
* os
* request
* validator-js
Unused devDependencies
* @typescript-eslint/eslint-plugin
* @typescript-eslint/parser
* fs
* http-post
* jsdoc
* should
* tslint-eslint-rules
Missing dependencies
* underscore

Elements are not sent to the client in the expected JSON format

What happened:
Received the following response when using findElement to find an h1 element:

value: {
          element: {},
          'element-6066-11e4-a52e-4f735466cecf': '23ad8680-07f8-11ea-a7f8-c5a5f09ee86f'
        }

What you expected to happen:
To receive the response:

 value: {
          'element-6066-11e4-a52e-4f735466cecf': '23ad8680-07f8-11ea-a7f8-c5a5f09ee86f'
        }

How to reproduce it (as minimally and precisely as possible):
make a request to the Find Element endpoint and check the pluma request logs.

Anything else we need to know?:
This breaks the Execute Script Sync endpoint on certain requests. HTMLElements will need to be serialized in the proper format.

Add element clear endpoint

What would you like to be added:
The Element Clear endpoint should be added to PlumaDriver's list of supported endpoints.

Why is this needed:
It is a useful feature that will allow clearing text content from editable or resettable elements.

Additional context
Specification

Execute script sync endpoint does not throw errors according to spec

What happened:
Execute Script Sync endpoint does not throw JavascriptError and ScriptTimeout when appropriate.

How to reproduce it (as minimally and precisely as possible):

  • for missing JavaScriptError: executeScript("return null.foo");
  • for missing ScriptTimeout: executeScript("while (true) {}");

GET element attribute endpoint is never called by getAttribute method in Selenium

the GET element attribute endpoint is never called by getAttribute method in Selenium as expected. Instead, the execute script endpoint is called with a function in the request body that handles the logic for getting element attributes. Execute script endpoint must be implemented in order to obtain functionality for this endpoint

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.