Cross Domain Cookie Syncing

Hello there!

I’m currently testing an API user journey which traverses two domains (one LegacySystem and a NewSystem). An example test might be:

Req1 - Home page (NewSystem)
Req2 - Login POST (LegacySystem)
Req3 - Third page (NewSystem)

Cookies per VU are carried forward automatically between Req1 and Req3, but the Login has new User ID values and additional cookies for the logged in session.

Right now, in order to keep the cookie jars for the two domains in sync, I’m extracting from LegacySystem and using jar.set() with replace:true flags to overwrite the jar values for the NewSystem domain; but that feels clunky to have to do each request.

Is there a better way to keep the cookies between the two domains in sync?

Hi @pennellbeth

I believe wich you use setup() functions to use the login Cookies for the all request. The setup function runs, setting up the test environment and generating data as the example in the documentation

Thanks for the response! When I have tested this, I don’t see the cookie jars being filled properly.
Example code:

import { group } from 'k6';
import http from 'k6/http';
import config from '../config.js';
import { logCookies } from '../utils/cookies.js';

export function setup() {
  let jar = http.cookieJar();
  let domains = [`${config.legacyDomain}`, `${config.newDomain}`]
  for (const domain in domains) {
    jar.set(`${domain}`, "USERID", "Foo");
    jar.set(`${domain}`, "JSESSIONID", "1234");
  }
  const legacyJar = jar.cookiesForURL(`${config.legacyDomain}`);
  const newJar = jar.cookiesForURL(`${config.newDomain}`);
  // Console logs in this section are not logged out
}

export default function () {
  let jar = http.cookieJar();
  const legacyJar = jar.cookiesForURL(`${config.legacyDomain}`);
  const newJar = jar.cookiesForURL(`${config.newDomain}`);
  let response;

  console.log("Script start Legacy Cookie Jar values: ", legacyJar); // both return empty Objects
  console.log("Script start New Cookie Jar values: ", newJar);

  group('User Journey', () => {
    response1 = http.get(`${config.newDomain}`); // request returns new cookie values
    response2 = http.get(`${config.legacyDomain}`); // request returns different values again
  };

I’ve tried setting the jar and passing this through into the VU function, but the jar is empty between setup and VU execution, so it didn’t change much?

Example using the pass-through of the variables created in setup():

import { group } from 'k6';
import http from 'k6/http';
import config from '../config.js';
import { logCookies } from '../utils/cookies.js';

export function setup() {
  let jar = http.cookieJar();
  let domains = [`${config.legacyDomain}`, `${config.newDomain}`]
  for (const domain in domains) {
    jar.set(`${domain}`, "USERID", "Foo");
    jar.set(`${domain}`, "JSESSIONID", "1234");
  }
  const legacyJar = jar.cookiesForURL(`${config.legacyDomain}`);
  const newJar = jar.cookiesForURL(`${config.newDomain}`);
  // Console logs in this section are not logged out
}

export default function (legacyJar, newJar) {
  let jar = http.cookieJar();
  let response;

  console.log("Script start Legacy Cookie Jar values: ", legacyJar); // returns undefined
  console.log("Script start New Cookie Jar values: ", newJar); // returns undefined

  group('User Journey', () => {
    response1 = http.get(`${config.newDomain}`); // request returns new cookie values
    response2 = http.get(`${config.legacyDomain}`); // request returns different values again
  };

for you get the value from setup function, you need to return the variable in setup() for you get in default function, as example:

import http from 'k6/http';

export function setup() {
  const res = http.get('https://httpbin.test.k6.io/get');
  return { data: res.json() };
}
export function teardown(data) {
  console.log(JSON.stringify(data));
}

export default function (data) {
  console.log(JSON.stringify(data));
}

In your code, maybe you need return legacyJar and newJar in data, try this form

import http from 'k6/http';

const file = open('./path/to/file', 'b');

export function setup() {
  const uploadData = {
    fileUploadFieldName: http.file(file, 'yourfilename'),
  };

  const res = http.post('https://example.com/upload', uploadData);
  return { documentId: res.json('document.id') };
}

export default function (data) {
  const res = http.get(http.url`https://example.com/documents/${data.documentId}`);
  // ...
}

Thank you for clarifying, I tried returning return { data: {legacy: legacyJar, new: newJar} } but it still returns undefined for the jars in the beginning of the VU script.

I’m not sure that the setup() function provides what I’m looking for in this instance.

If my user journey has multiple requests (that may span multiple modularised test files or k6 test groups), then the first request will set cookies, but keeping those cookies synced across multiple domains across this journey is where I’m struggling, and whilst setup() appears great for data files, the progressive application of the cookie Jars that k6 has in built is what I’m wrestling with.

Edit: The only way I’ve been able to guarantee that the same user session is continued across the journey is to manually retrieve the cookie values from the jar I want, and add each individually into the next request. However, this can lead to drift - hence asking about keeping them in sync.

Hi @pennellbeth

In my experience with set Cookies with Jar wasn’t good. Do you try verify if the values set in cookies? Maybe the set Cookies isn’t working.

Try check setCookies using Check k6.

I feel like what I need is a multi-domain example of the Integration test documented here:

If anyone in the K6 team feels like updating that!