Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File Upload with Selenium Grid #890

Open
scrawfor opened this issue Mar 7, 2016 · 24 comments
Open

File Upload with Selenium Grid #890

scrawfor opened this issue Mar 7, 2016 · 24 comments

Comments

@scrawfor
Copy link

scrawfor commented Mar 7, 2016

Is it now possible to implement file uploading using LocalFileDetector?

After some quick googling I found this. But I'm not familiar enough with the selenium project to node if it has any true impact.

This issue provide a method for uploading files and it works locally, but fails when using selenium grid as the remote node is unaware of the local file.

@scrawfor
Copy link
Author

scrawfor commented Mar 8, 2016

I looked through the implementation in the WebDriverJS Bindings.

Based on that, I implemented a custom action in protocol.js which uploads the file and returns the remote path. But it does not provide the other piece of functionality ("Replacing local path with remote path automatically").

    /**
     * Uploads a file to the remote server, returning the path to the remote file.
     * 
     * @param  {[String]} file The path to the file.
     * @param  {Function} [callback] Optional callback function to be called when the command finishes.
     * @return {[String]}  The path to the file on the remote server.
     */
    Actions.uploadFileToSeleniumServer = function( filePath, callback ) {
        //TODO Validate the file.
        var AdmZip = require('adm-zip');

        var zip = new AdmZip();
        zip.addLocalFile(filePath);

        return postRequest( '/file', { file : zip.toBuffer().toString('base64') }, callback );

    };

@straris
Copy link

straris commented Aug 10, 2016

protractor implemented setFileDetector :(

@scrawfor
Copy link
Author

@straris The custom action I posted seems to work pretty well. We are running a private forked version of nightwatch with this change and haven't had any failures.

@straris
Copy link

straris commented Aug 10, 2016

Thank you @scrawfor
How do you actually use your custom command?
I am getting postRequest is not defined

@scrawfor
Copy link
Author

scrawfor commented Aug 10, 2016

You would need to fork the repository and add the command to protocol.js.

You could then use it like any standard nightwatch action. Personally I defined a custom command which looks something like this:

exports.command = function (localFilepath, callback) {
    var browser = this;

    // First upload the file to the selenium server. This allows our code to work with selenium grid.
    browser.uploadFileToSeleniumServer(localFilepath, function (result) {

        if (result.status === -1) {
            console.error(result);
            return;
        }

        // Extract the new remote path of the file
        var remotePath = result.value || "";

        // Now, begin uploading the file to the website being tested.
        browser.setValue("#someInput", remotePath, function () {

          // Upload started, continue code.  Wait for upload complete if necessary.
          callback();

        });

    });

    return this; // allows the command to be chained.
};

I should create a PR for this but I haven't had the chance yet.

@straris
Copy link

straris commented Aug 11, 2016

Thank you for that @scrawfor
Next error would be:
{ status: -1, value: { localizedMessage: 'invalid code lengths set', cause: null, suppressed: [], message: 'invalid code lengths set', hCode: 1876464331, class: 'java.util.zip.ZipException', screen: null }, errorStatus: 13, error: 'An unknown server-side error occurred while processing the command.' }

@scrawfor
Copy link
Author

I don't think I have run into that issue. Seems like the zip file you are sending is corrupt in some way.

  1. How are you calling the custom command? Are you sure the file exists on the machine you are running nightwatch on?
  2. Try to zip the same file in some scratch code, but just save the zip file to the disk. Then try to unzip it.

@straris
Copy link

straris commented Aug 11, 2016

ok, this helped me out:
SeleniumHQ/selenium#640

It seems to be a problem with adm-zip, I replaced it with archiver and it worked

@straris
Copy link

straris commented Aug 19, 2016

@scrawfor How would you send a file without compressing it?

@scrawfor
Copy link
Author

As far as I know you have to zip the file since that is expected by the server. Is that causing issues for you?

@straris
Copy link

straris commented Sep 5, 2016

@scrawfor problem is that the file is being uploaded as a zip and in my case the test fails because the website expects an image file, should the server unzip it?

@scrawfor
Copy link
Author

scrawfor commented Sep 7, 2016

Yeah the server should unzip it. My guess is the file isn't being properly zipped, or you've got some other issues going on. Maybe try running the job locally or on another server?

@straris
Copy link

straris commented Sep 8, 2016

thank you for the explanation! will give it a try

@nareng
Copy link

nareng commented Feb 9, 2017

@scrawfor thanks this works for me are these changes merged to the master?

@mdharamadas
Copy link

+1 we are blocked on this.

@jakejuby
Copy link

jakejuby commented May 2, 2017

+1 as well, would be great to have this.

@MHenley
Copy link

MHenley commented May 11, 2017

I've had to fork nightwatch and pull in the the above protocal.js changes and usage example, but this is working for us as well.

scottymo pushed a commit to scottymo/nightwatch that referenced this issue Jul 25, 2017
Forgot to mention in my last commit: this solution is based on a suggestion found on this issue thread: nightwatchjs#890
@Bunk
Copy link

Bunk commented Nov 21, 2017

I created a custom command that will perform the upload without having to clone the repo if anyone else is interested: https://gist.github.com/Bunk/6c384fbe15556f7702d32aa8aa7a7521

@ConnorStroomberg
Copy link

The custom command work great for running the tests on sauselabs, i only have a problem when i try to run the test using the safari browser ( both locally and via sauslabs).

I posted the error message below, any ideas on how i should go about fixing this ?

`Error processing the server response:

<title>Error 500 Server Error</title>

HTTP ERROR 500

Problem accessing /wd/hub/session/undefined/file. Reason:

    Server Error

Caused by:

org.openqa.selenium.injector.UnableToInstaniateInstanceException: Unable to find required matches for constructor of: class org.openqa.selenium.remote.server.commandhandler.UploadFile
        at org.openqa.selenium.injector.Injector.newInstance(Injector.java:81)
        at org.openqa.selenium.remote.server.AllHandlers.lambda$handler$3(AllHandlers.java:139)
        at org.openqa.selenium.remote.server.AllHandlers.lambda$match$0(AllHandlers.java:87)
        at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
        at java.util.Spliterators$ArraySpliterator.tryAdvance(Spliterators.java:958)
        at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
        at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
        at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464)
        at org.openqa.selenium.remote.server.AllHandlers.match(AllHandlers.java:89)
        at org.openqa.selenium.remote.server.WebDriverServlet.handle(WebDriverServlet.java:210)
        at org.openqa.selenium.remote.server.WebDriverServlet.doPost(WebDriverServlet.java:169)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
        at org.openqa.selenium.remote.server.WebDriverServlet.service(WebDriverServlet.java:129)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
        at org.seleniumhq.jetty9.servlet.ServletHolder.handle(ServletHolder.java:860)
        at org.seleniumhq.jetty9.servlet.ServletHandler.doHandle(ServletHandler.java:535)
        at org.seleniumhq.jetty9.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
        at org.seleniumhq.jetty9.security.SecurityHandler.handle(SecurityHandler.java:548)
        at org.seleniumhq.jetty9.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
        at org.seleniumhq.jetty9.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
        at org.seleniumhq.jetty9.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
        at org.seleniumhq.jetty9.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
        at org.seleniumhq.jetty9.servlet.ServletHandler.doScope(ServletHandler.java:473)
        at org.seleniumhq.jetty9.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
        at org.seleniumhq.jetty9.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
        at org.seleniumhq.jetty9.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at org.seleniumhq.jetty9.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
        at org.seleniumhq.jetty9.server.Server.handle(Server.java:530)
        at org.seleniumhq.jetty9.server.HttpChannel.handle(HttpChannel.java:347)
        at org.seleniumhq.jetty9.server.HttpConnection.onFillable(HttpConnection.java:256)
        at org.seleniumhq.jetty9.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
        at org.seleniumhq.jetty9.io.FillInterest.fillable(FillInterest.java:102)
        at org.seleniumhq.jetty9.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
        at org.seleniumhq.jetty9.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
        at org.seleniumhq.jetty9.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
        at org.seleniumhq.jetty9.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
        at org.seleniumhq.jetty9.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:382)
        at org.seleniumhq.jetty9.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:708)
        at org.seleniumhq.jetty9.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:626)
        at java.lang.Thread.run(Thread.java:748)

`

@drussell13
Copy link

@ConnorStroomberg did you end up solving what caused this issue? I am having a similar problem

@DylanLacey
Copy link

@ConnorStroomberg What version of Safari? I wonder if this is a problem with the new WebDriver implementation... Or the Older one, which didn't support remote file uploads at all.

@benjy
Copy link

benjy commented Sep 18, 2019

@Bunk Do you have an updated version of that gist, it no longer seems to work.

@RohanImmanuel
Copy link

Created a custom command for v1.4
https://github.com/RohanImmanuel/NightwatchJS-Remote-File-Upload

@beatfactor beatfactor added this to To do in Nightwatch v2 Apr 16, 2021
@beatfactor beatfactor moved this from To do to In progress in Nightwatch v2 Jun 22, 2021
@beatfactor beatfactor moved this from In progress to Done in Nightwatch v2 Aug 23, 2021
@beatfactor beatfactor moved this from Done to Shipped in Nightwatch v2 Sep 13, 2021
@tim-yao
Copy link
Contributor

tim-yao commented Dec 8, 2021

For anyone before V2 has this issue. Maybe this will help you to bypass the issue:
https://www.browserstack.com/docs/automate/selenium/test-file-upload#uploading-pre-loaded-files

BTW, none of above custom commands work for me. I guess the API has changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.