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

[Cypress version 4.3.0]TypeError: Cannot read property 'key' of undefined #6890

Closed
natkrish opened this issue Mar 31, 2020 · 9 comments · Fixed by #6948 or m87h/site#83
Closed

[Cypress version 4.3.0]TypeError: Cannot read property 'key' of undefined #6890

natkrish opened this issue Mar 31, 2020 · 9 comments · Fixed by #6948 or m87h/site#83
Assignees

Comments

@natkrish
Copy link

@flotwig

Current behavior:

So when I load our live site using cy.visit('https://onlinedoctor.lloydspharmacy.com') using cypress version 4.3.0 - I get the below error.
image
image

Desired behavior:

I expect to be able to load our public site without any issues.

Test code to reproduce

I think to repproduce this issue just simply access our live site using cy.visit('https://onlinedoctor.lloydspharmacy.com');
Please try and replicate with the version set up

Versions

Cypress version - 4.3.0
Chrome - 80
Windows 10 - 64 bit
Node 12.16.1

I was expecting for it to work after the bug fix for this ticket - #5602

image

@CypressCecelia
Copy link
Contributor

I was not able to replicate. I am able to visit the URL in my test runner on 4.3.0. Are you possible logged in on your version of Chrome? The error says the URL it is trying to visit is followed by /logout, so I'm thinking you are being redirected in some way. You may have better luck setting the baseURL in your cypress.config file.

Screen Shot 2020-03-31 at 4 51 37 PM

@CypressCecelia CypressCecelia added the stage: needs information Not enough info to reproduce the issue label Mar 31, 2020
@abasau-incomm
Copy link

abasau-incomm commented Apr 1, 2020

@CypressCecelia I am also having the same issue. It appears that both my web site and https://onlinedoctor.lloydspharmacy.com/ are protected by Incapsula (https://www.imperva.com/imperva-incapsula-faq/). Incapsula generates cookies that Cypress fails to parse. Here is code from %AppData%\Local\Cypress\Cache\4.3.0\Cypress\resources\app\packages\server\lib\request.js which is failing:

setCookiesOnBrowser: function(res, resUrl, automationFn) {
        ...
  return Promise.map(cookies, function (cyCookie) {
    var cookie, expiry;
    cookie = tough.Cookie.parse(cyCookie, {
      loose: true
    });
    debug('parsing cookie %o', {
      cyCookie: cyCookie,
      toughCookie: cookie
    });
    cookie.name = cookie.key; \\ <<<< This fails because cookie is undefined.

Here is Cypress log (I changed some random values for security reasons):

  cypress:server:request received status code & headers on request { requestId: 'request58', statusCode: 200, headers: { 'content-type': 'text/html; charset=utf-8', 'set-cookie': [ ..., '___utmvaFvuoaRv=ScK\u0001oacs; path=/; Max-Age=900', '___utmvbFvuoaRv=TZI    XasJslrv: TtI; path=/; Max-Age=900' ] } } +138ms
  cypress:server:request setting cookies on browser { url: '<my url>', defaultDomain: '<my domain>', cookies: [ ..., '___utmvaFvuoaRv=ScK\u0001oacs; path=/; Max-Age=900', '___utmvbFvuoaRv=TZI    XasJslrv: TtI; path=/; Max-Age=900' ] } +3ms
  cypress:server:request parsing cookie { cyCookie: '___utmvaFvuoaRv=ScK\u0001oacs; path=/; Max-Age=900', toughCookie: undefined } +0ms

As you can see tough.Cookie.parse() didn't parse the cookie and toughCookie: undefined. I suspect it doesn't like \u0001 in cookie value.

@jennifer-shehane
Copy link
Member

@abasau-incomm @natkrish - Can you downgrade to Cypress 4.2.0 and verify if this fixes the issue?

@natkrish (For my future notes - I had to VPN in to US because their website is blocked in my country).

I'm not able to reproduce the error with the given code - please provide all cypress.json, any plugins/support files, etc that are necessary to encounter the error when running the tests - likely there is some cookies being set when you login - then logout that will reproduce the error. Please provide a fully reproducible example.

@abasau-incomm I don't see an exact change to these lines of code, although I do see that tough-cookie was updated in 4.3.0 here: https://github.com/cypress-io/cypress/pull/6778/files#diff-8c42f42f65d0890e0bba62a07ab08042R108 Please also if you can provide a reproducible example - this would be helpful.

@natkrish
Copy link
Author

natkrish commented Apr 1, 2020

@jennifer-shehane @abasau-incomm @CypressCecelia As per @abasau-incomm said my site is protected by Incapsula. I am not sure why this happens and every time I come across this type of issue on production - I then had to downgrade to 3.4.1 which is the only version that doesn't throw this error.
However on the other hand after @CypressCecelia said she was able to access without any issues, I created a new project from scratch and I was able to access my production site with out any issues. See this
image
But as @jennifer-shehane it will be great if you can infer any thing from these files that might hinder the launch of my site - it will be good to get down to the bottom of the problem.

cypress/plugins/index.js

// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
const cucumber = require('cypress-cucumber-preprocessor').default;

function getCliArgs(args) {
    args = args.filter((arg) => {
        return arg !== "--use-fake-ui-for-media-stream" && arg !== "--use-fake-device-for-media-stream"
    });
    args.push('--allow-file-access-from-files');
    return args
}

module.exports = (on, config) => {
    /** the rest of your plugins... **/
    require('cypress-log-to-output').install(on);
    on('file:preprocessor', cucumber());
    // `on` is used to hook into various events Cypress emits
    // `config` is the resolved Cypress config
    on('before:browser:launch', (browser, args) => {
        if (browser.family === 'chrome') {
            // `args` is a list of all the arguments that will be passed to Chrome when it launchers
            return getCliArgs(args)
        } else if (browser.family === 'electron') {
            // `args` is a `BrowserWindow` options object
            // https://electronjs.org/docs/api/browser-window#new-browserwindowoptions
            if (!args.webPreferences) {
                args.webPreferences = {}
            }
            if (!args.webPreferences.additionalArguments) {
                args.webPreferences.additionalArguments = []
            }
            args.webPreferences.additionalArguments = getCliArgs(args.webPreferences.additionalArguments);
            return args
        }
    })
};

cypress.json

{
  "chromeWebSecurity": false,
  "reporter": "mochawesome",
  "reporterOptions": {
    "overwrite": true,
    "html": false,
    "json": true,
    "timestamp": "mmddyyyy_HHMMss"
  },
  "projectId": "4zqjtd",
  "modifyObstructiveCode": false,
  "pageLoadTimeout": 60000,
  "baseUrl": "https://onlinedoctor.lloydspharmacy.com/",
  "nodeVersion":"system"
}

cypress/support/commands.js

cypress/support/index.js

// Import commands.js using ES2015 syntax:
import '@bahmutov/cy-api/support'
import './commands'
require('cypress-plugin-retries');
const addContext = require('mochawesome/addContext');
Cypress.on('test:after:run', (test, runnable) => {
    if (test.state === 'failed') {
        const screenshotFileName = `${runnable.parent.title} -- ${test.title} (failed).png`;
        addContext({ test }, `assets/${Cypress.spec.name}/${screenshotFileName}`)
    }
});
Cypress.on('uncaught:exception', (err, runnable) => {
    // returning false here prevents Cypress from
    // failing the test
    return false
});

@abasau-incomm
Copy link

abasau-incomm commented Apr 1, 2020

@jennifer-shehane I checked cypress 4.2.0 and a similar issue is reproducible there (#5602) - Cypress fails with Error: Parse Error: Invalid header value char error when it encounters a cookie with Unicode character in its value.

Also I found a stable way to reproduce the issue. You will need to:

  1. Install and open Fiddler.
  2. Uncheck File->"Capture Traffic" (we don't need to capture all traffic).
  3. Go to FiddlerScript tab and modify OnBeforeResponse() so it looks like this:
public static void OnBeforeResponse(Session oSession)
{
	if (m_Hide304s && oSession.responseCode == 304)
	{
		oSession["ui-hide"] = "true";
	}

	oSession.oResponse["Set-Cookie"] = "___utmvaFvuoaRv=TkE\u0001sCvZ; path=/; Max-Age=900";
}

image
4. Click "Save Script" button.
5. Open command line prompt.
6. Configure Cypress to use Fiddler as Proxy:

set HTTP_PROXY=http://localhost:8888
  1. Open Cypress:
npx cypress open
  1. Modify our Cypress test to make a GET request. E.g.:
cy.request({ method: 'GET', url: 'https://onlinedoctor.lloydspharmacy.com/' });
  1. Run the test. =>
    image

@tmonteith
Copy link

tmonteith commented Apr 5, 2020

I can definitely reproduce this within our code base.

Here is the failing step on version 4.3.0:
Screen Shot 2020-04-05 at 3 42 53 AM

And here is the failing step on version 4.2.0
Screen Shot 2020-04-05 at 3 40 28 AM

The same exact step is able to pass on version 3.4.1

Here is our code:

Cypress.Commands.add("login", (email, password) => {
	cy.request({
		url: '/account/login',
		method: 'POST',
		headers: {
			Accept: 'application/json',
			'Content-Type': 'application/json;charset=UTF-8' },
		body: {
			EmailAddress: email, 
			Password: password
		},
		followRedirect: true
	})
})

System info:
MacOS 10.15.2
Node v12.16.0
Chrome - 80

Note: Our entire test site is behind Incapsula and NGINX but every other request/page is able to load just fine on v4.3.0 which contains fix #5988 that addressed #5602 which we originally posted as a parse error issue as well. I would not be surprised if there was some sort of correlation.

P.S. I am not sure if this is caused by the exact same error.. If it is, the previous error message was clearer and I would expect to see that. The new error message had me debugging my VPN, Incapsula, and the actual code to see if one of my changes caused the request to abort prematurely.

Thanks!

Thanks!

@flotwig flotwig self-assigned this Apr 6, 2020
@flotwig
Copy link
Contributor

flotwig commented Apr 6, 2020

This issue occurs when tough-cookie is unable to parse the cookie's value.

tough-cookie expects cookies to follow RFC 6265, which doesn't permit control characters like \u0001 in cookie values.

Even if tough-cookie is patched to allow invalid control characters, further down the line, Chrome DevTools Protocol will fail on the Network.setCookie call:

Network.setCookie failed to set cookie: {"domain":"localhost","path":"/","secure":false,"httpOnly":false,"expires":1586192011.465,"name":"___utmvaFvuoaRv","value":"TkE\u0001sCvZ"}

I was curious about how real browsers react to headers with invalid control characters, so I tried visiting this controller in Firefox and Chrome:

  app.get "/invalidControlCharCookie", (req, res) ->
    ## `http` lib throws an error if we use .setHeader to set this
    res.connection.end("""
    HTTP/1.1 200 OK
    Content-Type: text/html
    Set-Cookie: ___utmvaFvuoaRv=TkE\u0001sCvZ; path=/; Max-Age=900
    Set-Cookie: _valid=true; path=/; Max-Age=900

    foo
    """)

Chrome 80 complains of invalid Set-Cookie headers and only sets the second cookie:
image

image

Firefox 75 appears to receive the cookie, but fails to actually set it in storage:
image

image

In light of this, I think the best way to resolve this issue is to make Cypress ignore invalid cookie values in requests, just like browsers do.

@cypress-bot cypress-bot bot added stage: work in progress stage: needs review The PR code is done & tested, needs review and removed stage: needs information Not enough info to reproduce the issue stage: work in progress labels Apr 6, 2020
flotwig added a commit that referenced this issue Apr 8, 2020
* add invalid header char repro

* ignore tough-cookie/automation failures

see #6890 (comment)

* restore snapshot

* Update packages/server/lib/request.coffee

* Update packages/server/lib/request.coffee

Co-Authored-By: Jennifer Shehane <jennifer@cypress.io>

Co-authored-by: Jennifer Shehane <jennifer@cypress.io>
@cypress-bot
Copy link
Contributor

cypress-bot bot commented Apr 8, 2020

The code for this is done in cypress-io/cypress#6948, but has yet to be released.
We'll update this issue and reference the changelog when it's released.

@cypress-bot cypress-bot bot added stage: pending release and removed stage: needs review The PR code is done & tested, needs review labels Apr 8, 2020
@cypress-bot
Copy link
Contributor

cypress-bot bot commented Apr 13, 2020

Released in 4.4.0.

This comment thread has been locked. If you are still experiencing this issue after upgrading to
Cypress v4.4.0, please open a new issue.

@cypress-bot cypress-bot bot locked as resolved and limited conversation to collaborators Apr 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
6 participants