Can we import js files in another k6 js file with scenarios in it?

When I am executing scenarios.js using below command, I am getting this error:
ERRO[0002] json: unsupported type: func(goja.FunctionCall) goja.Value

I have attached scenarios,js and other file orderListDownload.js which I have imported in scenarios.js below.
I have been able to execute orderListDownload.js directly using k6 run command easily without any issues. But as we have multiple such files, want to create a separate js file with just scenarios and want to import the different functions(exec value from different files).

Please suggest how can we achieve this.
Fyi, we have more than 100 js files already in place and we do not use scenarios instead use bash to run performance test load. But to simplify things and get rid of bash file want to make use of scenarios and executors. Please suggest how can we import the different files in scenarios.js and run entire suite. Also we should be able to run the different files(to be imported in scenarios.js, example orderListDownload.js below) separately using k6 run command.

scenarios.js:

import http from 'k6/http';
import { orderListDownload } from './orderListDownload.js';

export let options = {
  discardResponseBodies: true,
  scenarios: {
    contacts: {
      executor: 'shared-iterations',
      vus: 5,
      iterations: 3,
      maxDuration: '30s',
      exec: orderListDownload,
    },
  },
};

orderListDownload.js

import http from "k6/http";
import { Trend } from "k6/metrics";
import * as common from "../../commonUtils/common.js";
import { getorderListDownload } from "../../scripts/pgp/orderListDownload.js";

//headers for http request
let headers = { headers: { "Content-Type": "application/json" }, tags: { name: "I02_01_orderListDownload" } };
//Opening config files
const commonConfig = common.commonConfigObj();
const datafilesConfig = common.datafilesConfigObj();
const endPoints = common.endPointsObj();
var dataSet, url, MID, MIDs,endTime,startTime;
let payload, response;
var accessUrl = common.getAccessUrl();

if (__ENV.testEnv == "perf") {
    dataSet = common.perfDataObj();
}
else if (__ENV.testEnv == "shadow") {
    dataSet = common.shadowDataObj();
}
else if (__ENV.testEnv == "mock") {
    dataSet = common.mockDataObj();
}
//To get api stats for two metric separately.
let myTrend = new Trend("I02_01_orderListDownload");

export function orderListDownload() {

    //MIDs = common.getFromCacheDuplicateValuesAllowed(__ENV.domain + "_" + __ENV.testEnv + "_" + datafilesConfig.MIDs);
    //MID = MIDs.split(",")[0];

    //MID = "216820000271071338410"; //IRCTC
    //MID = "216820000262640130669"; //Normal

    //endTime = "2020-05-22T20:50:00+05:30";
    //startTime = "2020-04-23T00:00:00+05:30";

    //http request for getGVtemplateSummaryList
    payload = getorderListDownload(MID,endTime,startTime);
    payload = common.appendSHA256_Signature(payload);
    url = accessUrl + endPoints.pgp_orderListDownload;
    response = http.post(url, payload, headers);
    myTrend.add(response.timings.duration, { name: "I02_01_orderListDownload" });
    common.responseCheck(url, payload, response, "SUCCESS", "orderListDownload");

}

I think what you might need to do in order for this to work is to export the function in your scenarios.js file, rather than import it.

export { orderListDownload } from './orderListDownload.js';

While this example isn’t the exact same as what you are trying to do, I think it follows the same pattern. I implemented the handleSummary() function introduced in k6 v0.30.0 as a separate module in order to reuse the code, rather than copying and pasting that function into dozens of script files. In order for k6 to recognize it and execute the function, I had to export it within the main script file. When I simply imported it, k6 did not execute the function at all.

Example:
main-script.js

export { handleSummary } from './handle-summary.js';

//rest of script follows

handle-summary.js

import { jUnit, textSummary } from 'https://jslib.k6.io/k6-summary/0.0.1/index.js';

export function handleSummary(data) {
    console.log('Preparing the end-of-test summary...');

    return {
        'stdout': textSummary(data, { indent: ' ', enableColors: true}), // Show the text summary to stdout...
        '../path/to/junit.xml': jUnit(data), // but also transform it and save it as a JUnit XML...
        'other/path/to/summary.json': JSON.stringify(data), // and a JSON with all the details...
    }
}
1 Like

@dan_nm is correct, use export instead of import.

Another example using options:

main.js:

export { script1main } from './script1.js';
export { script2main } from './script2.js';
export { script3main } from './script3.js';

export const options = {
  scenarios: {
    script1: {
      exec: 'script1main',
      executor: 'constant-vus',
      vus: 5,
      duration: '10s'
    },
    script2: {
      exec: 'script2main',
      executor: 'constant-vus',
      vus: 5,
      duration: '10s'
    },
    script3: {
      exec: 'script3main',
      executor: 'constant-vus',
      vus: 5,
      duration: '10s'
    }
  }
};
import { sleep } from "k6";

export function script1main() {
  console.log("script1main()");
  sleep(Math.random() * 10);
}

etc.

2 Likes