0

I perform a performance testing of the application with an endpoint that should have Authorization.

Authorization to this application was done by the AWS Cognito tool.

The tool that I use for performance testing is k6 with Webpack.

But when I try to test the endpoint, I catch an exception from await client.initiateAuth(params) as ReferenceError: URL is not defined . Where client is CognitoIdentityProvider

During debugging I found that AWS await client.config.endpoint() return me the correct URL of Cognito when I run it without Webpack. But with Webpack it is throwing the same error.

Could someone face the same issue? How to resolve it?

Code examples:

index.js

import http from 'k6/http';
import { Rate, Trend } from 'k6/metrics';
import { check } from 'k6';
import { getToken } from "./cognito-service";

var errors = new Rate("errors");
var trends = new Trend("trends");

export const options = {
    vus: 1,
    duration: '10s',
  };
const token = getToken();

const params = {
  headers: {
    'Authorization': 'Bearer ' + token,
  },
};


export default function () {
  const res = http.get('https://myurl.com/api/need/to/test', params);
  check(res, { 'status was 200': (r) => r.status == 200 });
  errors.add(res.error_code);
  trends.add(res.timings.sending + res.timings.receiving);
}

webpack.config.js

const path = require('path');

module.exports = {
  mode: 'production',
  entry: {
    login: './index.js',
  },
  output: {
    path: path.resolve(__dirname, 'build'),
    libraryTarget: 'commonjs',
    filename: '[name].bundle.js',
  },
  module: {
    rules: [
      { test: /\.js$/, use: 'babel-loader' }
    ],
  },
  target: 'web',
  externals: /k6(\/.*)?/,
};

cognito-service.js

import { CognitoIdentityProvider } from "@aws-sdk/client-cognito-identity-provider";

export const getToken = async () => {
    const clientId = "XXXXXXXXXX";
    const params = {
        AuthFlow: "USER_PASSWORD_AUTH",
        ClientId: clientId,
        AuthParameters: { "USERNAME": "xxxxxx@gmail.com", "PASSWORD": "Test123$" }
    };
    const client = new CognitoIdentityProvider({ region: "eu-central-1" });
    try {
        console.log(client.config);
        const response = await client.initiateAuth(params);
        console.log(`Response is -> ${response}`)
        return response;
    } catch(error) {
        console.log(`Err is -> ${error}`);
    }
}

Also attached is the log::

> k6 run build/login.bundle.js


          /\      |‾‾| /‾‾/   /‾‾/
     /\  /  \     |  |/  /   /  /
    /  \/    \    |     (   /   ‾‾\
   /          \   |  |\  \ |  (‾)  |
  / __________ \  |__| \__\ \_____/ .io

INFO[0000] {"apiVersion":"2016-04-18","disableHostPrefix":false,"logger":{},"serviceId":"Cognito Identity Provider","runtime":"browser","requestHandler":{"configProvider":{}},"tls":true,"isCustomEndpoint":false,"systemClockOffset":0,"signingEscapePath":true}  source=console
INFO[0000] Err is -> ReferenceError: URL is not defined  source=console
  execution: local
     script: build/login.bundle.js
     output: -

  scenarios: (100.00%) 1 scenario, 1 max VUs, 40s max duration (incl. graceful stop):
           * default: 1 looping VUs for 10s (gracefulStop: 30s)

INFO[0000] {"apiVersion":"2016-04-18","disableHostPrefix":false,"logger":{},"serviceId":"Cognito Identity Provider","runtime":"browser","requestHandler":{"configProvider":{}},"tls":true,"isCustomEndpoint":false,"systemClockOffset":0,"signingEscapePath":true}  source=console
INFO[0000] Err is -> ReferenceError: URL is not defined  source=console
INFO[0000] {"apiVersion":"2016-04-18","disableHostPrefix":false,"logger":{},"serviceId":"Cognito Identity Provider","runtime":"browser","requestHandler":{"configProvider":{}},"tls":true,"isCustomEndpoint":false,"systemClockOffset":0,"signingEscapePath":true}  source=console
INFO[0000] Err is -> ReferenceError: URL is not defined  source=console
Tomash Gombosh
  • 143
  • 1
  • 3
  • 18

1 Answers1

2

Explanation of the problem

The problem is k6 does not provide node.js runtime or Browser API by design choice. So some functions, classes, etc. are not possible to use in k6.

An example

For example, URL is not included in k6, you can try the below via: k6 run file.js.

import http from "k6/http";

export default function () {
  http.get("https://google.com");
  const url = new URL("https://google.com");
}

And you'll get

ERRO[0000] ReferenceError: URL is not defined
running at file:///tmp/file.js:5:18(8)
default at native  executor=per-vu-iterations scenario=default source=stacktrace

What you can do

Use AWS REST API to get token (recommended)

AFAIK you can make any AWS call via the REST API you can make your calls with http.get http.post etc.

Use xk6-cognito extension

To extend k6 ahead of its javascript capabilities, we can use k6-extensions. There's an already built one work AWS Cognito.

An example script

go install go.k6.io/xk6/cmd/xk6@latest
xk6 build  --with github.com/tmieulet/xk6-cognito
./k6 script.js

Include necessary libraries (not recommended)

You can give necessary polyfills in webpack to handle these problems, but if one depends on anything k6 doesn't support, test won't compile. The most problematic dependency is fs k6 doesn't support fs, and most libraries depend on fs.

Umut Gerçek
  • 630
  • 6
  • 9