mailgun-js: how to get stats on a tag? - mailgun

I want to get statistics on a Mailgun tag and I follow the docs: https://bojand.github.io/mailgun-js/#/api/tags
This works fine:
const info = await mailgun.tags('my-tag').info()
(it returns { tag, description, 'first-seen', 'last-seen' })
This also works:
const info = await mailgun.tags('my-tag').stats().aggregates().countries().list()
However, this:
const info = await mailgun.tags('my-tag').stats().info()
gives me:
Error: Missing parameters.
at constructor.impl (my-app/node_modules/mailgun-js/lib/build.js:55:17)
at callback (my-app/node_modules/promisify-call/index.js:32:8)
at my-app/node_modules/with-callback/index.js:39:7
at new Promise (<anonymous>)
at withCallback (my-app/node_modules/with-callback/index.js:5:10)
at promisifyCall (my-app/node_modules/promisify-call/index.js:28:10)
at constructor.promisifed [as info] (my-app/node_modules/mailgun-js/lib/build.js:105:14)
at routeGetEmailStats (my-app/server/routes/email.js:192:59)
at process._tickCallback (internal/process/next_tick.js:68:7)
Any tips?

It turns out you need to to pass event as a parameter:
const info = await mailgun.tags('my-tag').stats().info({ event: ['delivered', 'opened', 'clicked', 'failed'] })
First I got it to work with mailgun.get:
const info = await mailgun.get(`/MY-MAILGUN-DOMAIN/tags/my-tag/stats`, { event: ['delivered', 'opened', 'clicked', 'failed'] })
Also, mailgun.get provided a better error message which helped me.

Related

How to form pm.test assertions in Postman

Given the following transaction reply how would I form a pm.test assertion for it?
{
"data": {
"clearEmployerClaim": true
}
}
This isn't working for me:
pm.test("clear employer claim status returned", () => {
const response = pm.response.json();
pm.expect(response.clearEmployerClaim).to.be.true;
});
I would normally do it like this but I'm getting type errors when running this via Jenkins/Newman. It works fine run via Postman.
tests["C536773447 clear employer claim status returned"] = body.data.clearEmployerClaim === true;
Any help is appreciated.
You missed one level here.
pm.expect(response.clearEmployerClaim).to.be.true; --> pm.expect(response.data.clearEmployerClaim).to.be.true;

show failed test results instead of generic message

I am running a test and if it fails the result is
Status code is 200 | AssertionError: expected response to have status
code 200 but got 404
It would be useful to see the result failed message. I am printing it to the console, but not sure how to get it show up on the test results as well.
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
const response = pm.response.json();
console.log(response);
You could add it to the test name, like this:
const response = pm.response.json();
pm.test(`Test something - ${response}`, () => {...})
Depending on the data returned, this would look awful for larger responses.
Not sure what this is giving you though...the console is the best place to print that type of debugging information.

Log all response cookies in Postman

I know I'm able to log a single response cookie using Postman, but is it possible to log ALL the response cookies in one go?
I'm trying to troubleshoot a test and would like to know what cookies are coming back, and I can't seem to get this solution to work:
const jar = pm.cookies.jar();
jar.clear(env, function (error) {
jar.getAll(env, function (error, cookies) {
console.log("cookies: " + cookies);
});
});
In the console "cookies" just remains undefined, and that's after adding the above code to the 'Tests' tab...
Thanks.
I resolved this issue by replacing the following line
const env = "integration-api.yyyy.xxx.xxxx.net";
with the full endpoint URL:
const env = "integration-api.yyyy.xxx.xxxx.net/api/v1/etc/etc";
Full code now looks like this:
const env = "integration-api.yyyy.xxx.xxxx.net/api/v1/etc/etc";
const jar = pm.cookies.jar();
jar.getAll(env, function (error, cookies) {
console.log("cookies: " + cookies);
});
Thanks to #DannyDainton for the pointers.

Validating JSON schema in Postman

When using Postman I validate the JSON response like so:
tv4.addSchema(globalSchema);
const valResult = tv4.validate(data, schema);
// schema is an object, which is a subschema from the larger globalSchema
which works fine, except for the error reporting. The error object I get is missing dataPath and schemaPath, making it hard for my user to find out where the actual problem is. Is there a way to get those properties? (tried validateResult and validateMultiple to no avail)
As an alternative I tried ajv, but as I am in draft-04, it gives me errors. The advice from their site
var ajv = new Ajv({schemaId: 'id'});
// If you want to use both draft-04 and draft-06/07 schemas:
// var ajv = new Ajv({schemaId: 'auto'});
ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'));
does not work because the Postman sandbox does not allow me to require that… any thoughts?
See also: https://community.getpostman.com/t/json-schema-validation-troubles/5024
Here's how I validate schema's with postman to get more detailed errors:
const schema = {
};
var jsonData = JSON.parse(responseBody);
pm.test('Checking Response Against Schema Validation', function() {
var result=tv4.validateMultiple(jsonData, schema);
console.log(result);
pm.expect(result.valid).to.be.true;
});

Starting a StepFunction and exiting doesn't trigger execution

I have Lambda function tranportKickoff which receives an input and then sends/proxies that input forward into a Step Function. The code below does run and I am getting no errors but at the same time the step function is NOT executing.
Also critical to the design, I do not want the transportKickoff function to wait around for the step function to complete as it can be quite long running. I was, however, expecting that any errors in the calling of the Step Function would be reported back synchronously. Maybe this thought is at fault and I'm somehow missing out on an error that is thrown somewhere. If that's the case, however, I'd like to find a way which is able to achieve the goal of having the kickoff lambda function exit as soon as the Step Function has started execution.
note: I can execute the step function independently and I know that it works correctly
const stepFn = new StepFunctions({ apiVersion: "2016-11-23" });
const stage = process.env.AWS_STAGE;
const name = `transport-steps ${message.command} for "${stage}" environment at ${Date.now()}`;
const params: StepFunctions.StartExecutionInput = {
stateMachineArn: `arn:aws:states:us-east-1:999999999:stateMachine:transportion-${stage}-steps`,
input: JSON.stringify(message),
name
};
const request = stepFn.startExecution(params);
request.send();
console.info(
`startExecution request for step function was sent, context sent was:\n`,
JSON.stringify(params, null, 2)
);
callback(null, {
statusCode: 200
});
I have also checked from the console that I have what I believe to be the right permissions to start the execution of a step function:
I've now added more permissions (see below) but still experiencing the same problem:
'states:ListStateMachines'
'states:CreateActivity'
'states:StartExecution'
'states:ListExecutions'
'states:DescribeExecution'
'states:DescribeStateMachineForExecution'
'states:GetExecutionHistory'
Ok I have figured this one out myself, hopefully this answer will be helpful for others:
First of all, the send() method is not a synchronous call but it does not return a promise either. Instead you must setup listeners on the Request object before sending so that you can appropriate respond to success/failure states.
I've done this with the following code:
const stepFn = new StepFunctions({ apiVersion: "2016-11-23" });
const stage = process.env.AWS_STAGE;
const name = `${message.command}-${message.upc}-${message.accountName}-${stage}-${Date.now()}`;
const params: StepFunctions.StartExecutionInput = {
stateMachineArn: `arn:aws:states:us-east-1:837955377040:stateMachine:transportation-${stage}-steps`,
input: JSON.stringify(message),
name
};
const request = stepFn.startExecution(params);
// listen for success
request.on("extractData", req => {
console.info(
`startExecution request for step function was sent and validated, context sent was:\n`,
JSON.stringify(params, null, 2)
);
callback(null, {
statusCode: 200
});
});
// listen for error
request.on("error", (err, response) => {
console.warn(
`There was an error -- ${err.message} [${err.code}, ${
err.statusCode
}] -- that blocked the kickoff of the ${message.command} ITMS command for ${
message.upc
} UPC, ${message.accountName} account.`
);
callback(err.statusCode, {
message: err.message,
errors: [err]
});
});
// send request
request.send();
Now please bear in mind there is a "success" event but I used "extractData" to capture success as I wanted to get a response as quickly as possible. It's possible that success would have worked equally as well but looking at the language in the Typescript typings it wasn't entirely clear and in my testing I'm certain that the "extractData" method does work as expected.
As for why I was not getting any execution on my step functions ... it had to the way I was naming the function ... you're limited to a subset of characters in the name and I'd stepped over that restriction but didn't realize until I was able to capture the error with the code above.
For anyone encountering issues executing state machines from Lambda's make sure the permission 'states:StartExecution' is added to the Lambda permissions and the regions match up.
Promise based version:
import { StepFunctions } from 'aws-sdk';
const clients = {
stepFunctions: new StepFunctions();
}
const createExecutor = ({ clients }) => async (event) => {
console.log('Executing media pipeline job');
const params = {
stateMachineArn: '<state-machine-arn>',
input: JSON.stringify({}),
name: 'new-job',
};
const result = await stepFunctions.startExecution(params).promise();
// { executionArn: "string", startDate: number }
return result;
};
const startExecution = createExecutor({ clients });
// Pass in the event from the Lambda e.g S3 Put, SQS Message
await startExecution(event);
Result should contain the execution ARN and start date (read more)