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

I have a scenario where i am trying to utilize a function defined in different js file.
tried to implement above options but when i used export instead of import its saying ** its not defined in my js file.**
Can you please suggest on this?

Solution tried:

Main File:

export { getAPI } from “./ComponentPerf_GET.js”;

export default function(){
getapi();
}

ComponentGET.js:

export const getAPI = function () {
group(“GET_API”, function () {
response = http.get(getUrl.trim(), requestheaders);
}};

Error:
=“ReferenceError: getAPI is not defined\n\tat file:./main.js:90:11(54)\n” executor=ramping-vus scenario=default source=stacktrace

Hi @Komal,

There are some inconcientances in your naming so I would expect that you just wrote getAPI when you imported it as getapi (you do the reverse in the example here ;)) . If you aren’t using k6 v0.36.0, please do - it will give you (hopefully) better error lines as there is definitely not line 90 in your current example.

Please also open a new thread instead of ressurecting 8 months old ones ;).

@mstoykov
hey that is a typo I tried to change and use it. It isn’t working.
Will be opening a new thread for discussion.
Thanks