Issues invoking Newman (Postman) collection from C# using Edge.js

My objective is to reuse the collections developed in Postman in a program using Newman. This is going to be part part of Unit Testing or Deployment Script in CI/CD Jenkins Pipeline. I decided to use C# and Selenium, but I can change my mind if you believe there is a better option. This means I can develop the Unit Testing component using C#+NodeJS+Edge.js, also develop the deployment script in C# by invoking Postman Collections, and then integrate all such components using Jenkins Pipeline.

I figured out you can use NodeJS to Invoke Postman Collections using Newman Library. I also found out you can use NuGet Edge.js to script NodeJS from C#. I can use Command Line from C# but I was afraid to find difficulties to capture the response for the request invocations from the Newman command line. That us why I was looking for a more reliable way to integrate Newman with C#.

I successfully used vs code to write the sample program to script Node.js from C#. I use the following code block directly from https://github.com/tjanczuk/edge:

using System;
using System.Threading.Tasks;
using EdgeJs;

class Program
{
    public static async Task Start()
    {
        var func = Edge.Func(@"
            return function (data, callback) {
                callback(null, 'Node.js welcomes ' + data);
            }
        ");

        Console.WriteLine(await func(".NET"));
    }

    static void Main(string[] args)
    {
        Start().Wait();
    }
}

The above is working successfully with .NET Framework 4.5.2 and 4.8.0

Also, I successfully wrote a program in Node.js to invoke a GET request using Newman:

const newman = require('newman'); // require newman in your project
const theCollec = '.\\collections\\vs code test.postman_collection.json';
//call newman.run to pass `options` object and wait for callback
newman.run({
   collection: require(theCollec),
   reporters: 'cli'
}, function (err) {
   if (err) { throw err; }
   console.log('collection run complete!');
});

Now, I am trying to include the Newman code block in the C# program, but it is not working. I am getting the following errors when I run the program using dotnet run:

using System;
using System.Threading.Tasks;
using EdgeJs;

namespace TestNodeJSNET
{

    class Program
    {
        public static async Task Start()
        {
             var func = Edge.Func(@"
                const newman = require('newman'); // require newman in your project
                return function (data, callback) {

                    const theCollec = '.\\collections\\vs code test.postman_collection.json';
                    // call newman.run to pass `options` object and wait for callback
                    newman.run({
                       collection: require(theCollec),
                       reporters: 'cli'
                    }, function (err) {
                       if (err) { throw err; }
                       console.log('collection run complete!');
                    });
                    callback(null, 'Node.js welcomes ' + data + theCollec);
                }
            ");

            Console.WriteLine(await func(".NET"));
        }
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            Start().Wait();
        }
    }
}

I am getting the following errors:

Unhandled Exception: System.AggregateException: One or more errors occurred. ---> System.Exception: C:\Projects\TestNodeJSNET\node_modules\ws\lib\websocket.js:460
      ...options
      ^^^

SyntaxError: Unexpected token ...
    at createScript (vm.js:74:10)
    at Object.runInThisContext (vm.js:116:10)
    at Module._compile (module.js:533:28)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
    at Module.require (module.js:513:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (C:\Projects\TestNodeJSNET\node_modules\ws\index.js:3:19)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at TestNodeJSNET.Program.<Start>d__0.MoveNext()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at TestNodeJSNET.Program.Main(String[] args)

See the snapshot below of the code that caused the error. Note that the error above is thrown during run-time after I tried using other libraries such as const ws=require("ws"). I will get the same error if I use const newman = require('newman'); but in a different script file.

It is clear that there Newman script is using the new spread operator ... which probably Edge.js didn’t like. I think one solution is to use a version of Newman module that doesn’t use ... operator or transpile such script using Babel to a lower JavaScript version.

I appreciate your help to resolve this issue.

Script causing Unexpected Token Spread Operator

Hi @tarekahf

You clearly know more about JS than I do, but just a thought, could it be a limitation such as;

Only for iterables
Spread syntax (other than in the case of spread properties) can only be applied to iterable objects like Array , or with iterating functions such as map() , reduce() , and assign() .
Many objects are not iterable, including Object :
let obj = {‘key1’: ‘value1’};
let array = […obj]; // TypeError: obj is not iterable

I think the issue is that Newman module has a script file that uses spread operator which is causing issue in Edge.js NuGet library (C# / NodeJS Integration).

I think the problem will be solved if I can use an earlier version of Newman that doesn’t use the spread operator.

Can you help with that?

I confirmed that if I use Newman version 4.6.1, the problem is solved. When I tried a more recent version, I got the error related to the spread operator.

Now, I can live with that solution, but I’d like to do more.

I can transpile the Newman Module and all its dependencies to a lower version using Babel. I did some research, and most probably it will work, but still not clear how to do that. I need to do more research.

However, the only issue with using Babel is how to make it a reliable solution. This means I need to set up my project in such a way that it will install Newman’s latest version using npm install newman then trigger the transpiler to compile the modules to a lower version using minimal manual interventions, and yet, still be able to use the node API require("newman"). I still didn’t figure out how to wrap my head around this issue.

I am looking for help to implement the transpiler option using Babel.

Tarek

Hi tarekahf,
I am trying to do the exact same thing i.e, to invoke newman from C# and node.js. Can you please share elaborate steps do that? or your github project link? The one you have shared here is not found

I’m glad that you need this also. I’ll come back to you soon. We can help each other.

Regards,
Tarek

1 Like

Hi @smkruthika

It’s a relatively long exercise. I’ll try to give you the steps (just google if you get stuck):

  1. Create a Postman account, goto to the Public API Workspace, and find the Postman Echo collection sample. Create a fork from the collection, and from your workspace, export the collection to a local file say “vs code test.postman_collection.json”. Test the collection from your local Postman (click the Send button).

  2. Initialize and create a project folder using VS Code. Create a sample Hello World C# Project using .NET Framework 4.5.x (net452) or equivalent. Don’t use .NET Core 5 or 6. Test it to verify.

  3. Install NodeJS. In the same folder, create a sample Hello World NodeJs project and test it.

  4. Create a sample NodeJS Module and import it to the Hello Word application and test it.

  5. Add Newman 4.6.1 to the NodeJS Modules, and include the sample Newman NodeJS code block to run the Postman Echo Test Collection. Include this code block in the Hello World program. Run the program to verify it.

  6. Go back to the C# Program. Install NuGet Package Manager vscode extension. Add the libraries (ctrl-shift-p / NuGet Add Package) Edge.js and Edge.js.Binaries. Add the simple code block to run NodeJS from C#. Don’t call Newman yet, just add the sample Hello Word NodeJS program inside the C# program, and verify it.

  7. Now include the NodeJS program that imports the sample module you created. Include this in the C# NodeJS part. The purpose here is to make sure the structure you are using to include NodeJS with Modules (NodeJS “require” statement) in C# is correct.

  8. If your module uses the spread operator (…) with Object Variables (not Arrays), then you should get an error if you run NodeJS from inside C#. You should not get an error if you run the sample NodeJS directly. Example of NodeJS spread operator:

var a1 = {b:"x", y:"z"}
var a2 = {w:"r", ...a1}
console.log ("Using spread operator, a2 = ", a2);

Remove the spread operator to convert it to use the old JavaScript style, and test it again. You should not get an error.

  1. Now include the code to run the test collection from NodeJS from inside C#. If you are using Newman 4.6.1, it should work and should give the same output as the Postman application. If you use a newer version, you will get a large number of errors.

I hope this will be of help.

Please let me know if you get stuck.

Tarek

1 Like

Thank you. Will try this and let you know how it goes. Meanwhile, found this in Nuget library if you want to have a glance GitHub - cake-contrib/Cake.Newman at master => I tried using it. Stuck at passing one of the arguments CakeContext for function RunCollection.

Stuck a step 7.
Node JS program called nodeapp in path => C:/Users/abcd/nodeapp
Sample module imported into above program is colors in path => C:/Users/abcd/colors
C# HellowWorld project in location => C:/Users/abcd/source/repos/HelloWorld/HelloWorld
Added nodejs program into c# prgram like this

In this Program.cs, trying to use nodeapp like this. Its failing saying module not found. I am doing something wrong. Can you pls point it out? Not sure whats the issue

I tried this too. Same No module found error. I would really appreciate your help

Also, locally this is ok. But how to package it for deployment? thanks in advance

It seems you are using a sample NodeJS module in a format that I did not use. See below the sample module named “examples.js”

console.log("evaluating example.js");
var invisible = function () {
  console.log("invisible");
}
exports.message = "hi";
exports.arr = [1,2,3,4,5];
exports.obj = {name:"Tarek", subject:"Math"};
exports.say = function () {
  console.log(exports.message);
  console.log("Testing the spread operator for arr: ", ...exports.arr);
  //var obj2 = {...exports.obj};
  var obj2 = {key:"Obj 2", val:"val of obj2"};
  console.log("Testing the spread operator for obj: ", obj2);
  return "Competed log of " + exports.message;
}

Below is the test NodeJS program importing the “examples.js” module:

const example = require("./examples.js");
const newman = require('newman'); // require newman in your project
const theCollec = '.\\collections\\vscodetest.postman_collection.json';
//call newman.run to pass `options` object and wait for callback
newman.run({
   collection: require(theCollec),
   reporters: 'cli'
}, function (err) {
   if (err) { throw err; }
   console.log('collection run complete!');
});
console.log("Test from examples moduel: " + example.say());

Both files above are in the same root folder of the C# program.

In C# Program, you import the module as follows:

                const examples = require('.\\..\\examples.js');

The following is part of the source code of the C# Program:

        public static async Task Start()
        {
            var func = Edge.Func(@"
                console.log(`current __direname`, __dirname);
                console.log(`current module __filename`, __filename);
                var newman = require('newman'); // require newman in your project
                const examples = require('.\\..\\examples.js');
                return function (data, callback) {
                    const theCollec = '.\\..\\collections\\Postman Echo.postman_collection.json';
                    // call newman.run to pass `options` object and wait for callback
                    newman.run({
                       collection: require(theCollec),
                       reporters: 'cli'
                    }, function (err) {
                        console.log('This is the function part of Newman.');
                        console.log(err);
                       if (err) { throw err; }
                       callback(null, 'Node.js welcomes ' + data + ' - ' + theCollec + ' - examples hi :' + examples.say());
                       console.log('collection run complete!');
                    });
                    console.log('This is from NodeJS in .NET');
                    // callback(null, 'Node.js welcomes ' + data + ' - ' + theCollec + ' - examples hi :' + examples.say());
                }
            ");

            Console.WriteLine(await func(".NET"));
        }

When you import or require “newman”, you don’t specify a path. I learned this by trial and error. Maybe because the module “newman” was installed using the npm install [email protected] command. It seems that “require()” is expecting the module to be under the directory “node_modules” so we have to go up one level to access the needed JavaScript file to the .json file. If your module format is similar to “newman” then you specify the name without any folder qualifier.

I think the problem is because you are using the forward-slash “/”. Try to use double backslash “\”, and go up one level as shown in the sample above, and I am not sure why this is working that way. Follow the same approach when you specify the path to the postman collection. If still not working, that is because the folder structure of your project is different. Either specify the absolute path or keep going up one level as such “.\…\…\filename.js”.

You don’t have to make it work with the sample module, you can try to run the collection with the newman module right away.

Tarek