Testcafe: Run testcafe with https protocol

Created on 6 Dec 2017  路  26Comments  路  Source: DevExpress/testcafe

Are you requesting a feature or reporting a bug?

Requesting a feature (maybe)

What is the current behavior?

I am unable to start testcafe using https protocol

What is the expected behavior?

Testcafe should run with ssl certificate (if provided)

Specify your

  • operating system: MacOS 10.13.1
  • testcafe version: 0.18.3
  • node.js version: 8.7.0
Auto-locked enhancement

All 26 comments

Hello @edoardocavazza!

It's a useful feature, because some browser API's (e.g. Apple Pay) are available only on HTTPS pages, and TestCafe HTTP end-point prevents access to them.

Right now, you can configure stunnel to encrypt traffic from TestCafe to browser. You can check "TLS front-end to a web server" on https://www.stunnel.org/config_windows.html for an example configuration.

Requires Safari on macOS or iOS.
Example page: https://andreybelym.github.io/test-pages/gh-1985.html
Test:

fixture `ApplePay`.page`https://andreybelym.github.io/test-pages/gh-1985.html`;

test(`test`, t => t.wait(10000));

Reproduced in Safari 11.0.2.
With TestCafe browser is raised an error:

InvalidAccessError (DOM Exception 15): Trying to call an ApplePaySession API from an insecure document.

+1

+1

We use crypto.subtle that is unavailable in Chrome without SSL.
And ServiceWorker too.

+1

I'm really struggling with the value of an end-to-end testing framework that doesn't support https. This essentially limits it to running on localhost, which is not end-to-end.

@AndreyBelym, could you please review the pull requests and help me with tests and documentation. Thank you.

https://github.com/DevExpress/testcafe/pull/2359
https://github.com/DevExpress/testcafe-hammerhead/pull/1590
https://github.com/DevExpress/testcafe-live/pull/19

This changes works properly for me. Tests and documentation are needed to be designed.

Hi @intermike, thanks for contributing. Let's focus first on testcafe-hammerhead part, then when it's merged, we will discuss end-user API and CLI switches in TestCafe. I need some time to look at your work, but at first glance it's mostly fine, except a one strange expression at https://github.com/DevExpress/testcafe-hammerhead/pull/1590/files#diff-f17475e116c70c73c37dd369b8d12b6bR30 and absence of tests.

@AndreyBelym

According strange expression

const originalProtocol  = opts && opts.proxyProtocol || location['proto' + 'col'];

lint throws an error for location.protocol or even location['protocol'] and I need to figure it out.

About tests.

I actually do not know how to design tests in this case. I don't mean easy checks (like https,wss protocols in all urls).
First of all it needs to generate certificates on that IP where environment will run the test.
Next, it needs to check that particular certificates are used in HTTPS handshaking properly.
And there is the blocker for me how to make tests properly and make them fast to execute.

I'm not sure I 100% understand this issue, or the proposed changes. Will these changes allow TestCafe to run locally against a remote https endpoint? This use case was the one I was struggling with: to enable smoke testing from our build server against our Integration and UAT environments. Thanks for the progress.

Hi @AndreyBelym

Lint error

/testcafe-hammerhead/src/client/utils/url.js
30:61 error 'protocol' is restricted from being used. Please use getters and setters for anchor element from native methods instead no-restricted-properties

Lint rule

Rule is described in https://github.com/LavrovArtem/eslint-plugin-hammerhead/blob/master/lib/index.js

Please advise what should I do with location.protocol.

@awithy, what do you mean by

run locally against a remote https endpoint*?

You can test websites served over HTTPS as easy as websites served over HTTP, since our proxy accepts both HTTPS and HTTP as input. However all websites regardless their original protocol are served over HTTP in testing session, because our proxy supports only HTTP output. The proposed changes enable HTTPS output for proxy, so connection during testsing session will be encrypted.

@intermike, I think it's ok to disable this check here with

/*eslint-disable no-restricted-properties*/
protocol = ...
/*eslint-enable no-restricted-properties*/

@AndreyBelym Thanks for the guide. Pushed into PR.

It's time to discuss API, because testcafe-hammerhead's part of this feature already completed (nearly).
I propose the following API for this feature:

//Programming Interface
createTestCafe (hostname, port1, port2, sslOptions)

sslOptions.key - <Buffer> - private key in PEM format
sslOptions.cert - <Buffer> - cert in PEM format

//Command line
testcafe chrome my-tests --ssl-key test/key/agent2-key.pem --ssl-cert test/key/agent2-cert.pem
--ssl-key - <string> path to key file
--ssl-cert - <string> path to cert file

@kirovboris @AndreyBelym

I believe key and cert are path to files, why should it be <Buffer>? It works this way in nodejs, but it's not quite usable. Why should we choose this approach?

It works this way in nodejs, but it's not quite usable. Why should we choose this approach?

Nodejs api is polymorphically for this option. It takes string, Buffer and Object (see createsecurecontext_options).
Eventually, all of this will transformed to Buffer.

In my opinion, Buffer is the best way to specify ssl keys in programming interface.
Also, in https example from the nodejs documentation used this way.

const https = require('https');
const fs = require('fs');

const options = {
  key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
  cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};

https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('hello world\n');
}).listen(8000);

@miherlosev
I suppose the approach runner.ssl(key, cert) does not fit the initialization order of testcafe

createTestCafe('localhost', 1337, 1338) // We need to pass certificates here
    .then(tc => {
        testcafe     = tc;
        const runner = testcafe.createRunner(); // But runner is created only here

        return runner
            .src(['tests/fixture1.js', 'tests/func/fixture3.js'])
            .browsers(['chrome', 'safari'])
            .run();
    })
    .then(failedCount => {
        console.log('Tests failed: ' + failedCount);
        testcafe.close();
    });

ping @AndreyBelym

@intermike

Yes you are right. sslOptions should be declared in a factory method. I've updated the https://github.com/DevExpress/testcafe/issues/1985#issuecomment-387341594

  1. I think we should also support PFX certificates (because it's more convenient to use) and rejectUnauthorized property to enable self-signed certificates for testing purposes. @miherlosev's proposal for Runner API extension is already fine with this, but for CLI we should use more general approach like:
testcafe --ssl pfx=path/to/some.pfx;rejectUnauthorized=true;...

We already have such options syntax for browser providers' options.

  1. I would argue that we should support only Buffers and threat strings as a kind of Buffer. Yes, Node.js API works this way, but it makes harder switching from CLI to a custom runner. We went a similar way with globs and runner.src, and now this feature is in top 5 of the requested features. IMHO our API must be as convenient as the CLI.

After discussing with @AndreyBelym, we introduce the following API:

Programming interface

createTestCafe (hostname, port1, port2, sslOptions)

sslOptions are nodejs https options

Command-line interface

testcafe --ssl pfx=path/to/some.pfx;rejectUnauthorized=true;...

ssl is a parameter that contains semicolon-separated options in the key-value format.

For the key, cert and pfx properties, the following processing algorithm is used:
if a property has a string type and its length is less that the MAX_PATH limit,
we interpret the value as a file path. Thus, we read the file content and replace the property value with this content.

@kirovboris Take a look please

Hi @intermike

We've updated the testcafe-hammerhead dependency with changes related to the https support feature.
You can continue to develop this feature on the TestCafe side.

See an API description in https://github.com/DevExpress/testcafe/issues/1985#issuecomment-389488983.
Let us know if you need any help about with our development workflow.

Affirmative, @miherlosev.

Working on docs

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs or feature requests. For TestCafe API, usage and configuration inquiries, we recommend asking them on StackOverflow.

Was this page helpful?
0 / 5 - 0 ratings