Serverless offline child process - spawn serverless ENOENT - node.js

I am using GitLab's serverless framework template and trying to run tests locally first, by creating a child serverless offline process. I am getting the error 'spawn serverless ENOENT' when executing the jest tests. Any idea why?
let useLocalService = true
...
let serverlessProcess = {
serverless_process: null,
start: async () => {
if(useLocalService) {
this.serverless_process = spawn('serverless', ['offline', '--port', 3000])
}
},
stop: () => {
if(useLocalService) {
this.serverless_process.kill('SIGINT')
}
}
}
describe('hello', () => {
beforeAll(async () => {
// serverlessProcess.start starts serverless offline in a child process
// unless the test is pointed at a deployed service
await serverlessProcess.start()
})
afterAll(() => {
// serverlessProcess.stop kills the child process at the end of the test
// unless the test is pointed at a deployed service
serverlessProcess.stop()
})
it(...
The only error message I recieve:
● Test suite failed to run
spawn serverless ENOENT

Are your trying to initiate any AWS service locally?
If you are trying to use any AWS plugins that is causing the error.
Make sure Java is installed
setup AWS service which you are trying locally eg: if dynamodb then
sls dynamodb install
If you still face issue then check serverless local issue by enabling DEBUG
export SLS_DEBUG=true

Related

Jest test fail: "● default root route"

I'm trying to write Jest tests for a Fastify project. But I'm stuck with the example code failing with an ambiguous error: "● default root route".
// root.test.ts
import { build } from '../helper'
const app = build()
test('default root route', async () => {
const res = await app.inject({
url: '/'
})
expect(res.json()).toEqual({ root: true })
})
// helper.ts
import Fastify from "fastify"
import fp from "fastify-plugin"
import App from "../src/app"
export function build() {
const app = Fastify()
beforeAll(async () => {
void app.register(fp(App))
await app.ready()
})
afterAll(() => app.close())
return app
}
// console error:
FAIL test/routes/root.test.ts (8.547 s)
● default root route
A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown. Try running with --detectOpenHandles to find leaks. Active timers can also cause this, ensure that .unref() was called on them.
What am I doing wrong?
After running --detectOpenHandles, Jest reported that open ioredis connections were timing out.
I hooked up ioredis instances to Fastify lifecycle with fastify-redis and the test passed.

debug library not working in conjunction with amqplib (rabbitmq)

We run our app in two "modes":
Our REST API (express js)
Our background processor (amqplib)
Our REST API that starts using nodemon runs completely fine with debug, however our background processor does not work with debug.
We declare DEBUG=app:* in our .env file and yes, we do see it when we console log but for some reason when we do the following, nothing reports when running our background processor.
We do see that one of amqp's dependencies called bitsyntax uses debug. I am wondering if it does anything to turn off debug but cannot find anything in their code that does that.
Is there anything I can do to resolve this problem?
import amqp from 'amqplib/callback_api'
import dotenv from 'dotenv'
import debug from 'debug'
const testLog = debug('app:worker')
const rabbitmq = `amqp://${process.env.RABBITMQ_USER}:${process.env.RABBITMQ_PASS}#${process.env.RABBITMQ_HOST}`
console.log(process.env.DEBUG) // app:*
const worker = () => {
try {
amqp.connect(rabbitmq, (err, conn) => {
// ...
testLog('this does not show up')
console.log('this does show up')
// ...
})
} catch (err) {
// ...
}
}
worker()
We run our background processor using the following command:
NODE_ENV=development nodemon ./src/workers/index.ts
As per the following github issue response,
on workers the following code needs to be enabled:
debug.enable(process.env.DEBUG)

How to test nodejs chaincode using ChainCodeMockStub

I am trying to test nodejs chaincode without deploying it to a hyperledger fabic network. There is a popular nodejs library called #theledger/fabric-mock-stub. Below is my unit test
const Chaincode = require('./index.js');
// import { ChaincodeMockStub, Transform } from "#theledger/fabric-mock-stub";
const ChaincodeMockStub = require("#theledger/fabric-mock-stub")
// You always need your chaincode so it knows which chaincode to invoke on
const chaincode = new Chaincode();
describe('Test MyChaincode', () => {
it("Should init without issues", async () => {
const mockStub = new ChaincodeMockStub("MyMockStub", chaincode);
const response = await mockStub.mockInit("tx1", []);
expect(response.status).to.eql(200)
});
});
When this test is run the following error is received
2019-04-08T18:34:55.530Z ERROR [lib/chaincode.js] uncaughtException: Missing required argument peer.address
Does anyone know how to use this testing library? https://github.com/wearetheledger/fabric-mock-stub
Any help would be greatly appreciated thanks.
I had the same issue and what I noticed is that at the bottom of my chaincode js file I had
shim.start(new Chaincode())
If you move this line to another file or comment it out before doing tests, tests should work just fine.

Is it okay to make API requests to set up tests in Cypress when testing serverless applications?

I'm writing a serverless React app using AWS Amplify. I do my E2E tests using Cypress.
Before each test, I log the user in via the AWS Amplify CLI. Afterwards, I clear all data on the development server and create some new data using fixtures. This way I always have controlled state for each test (see code below).
My question is: Is this a good practice? Or is it bad to make that many requests against the server in before each test? If it is bad, how would you do that if you do not have direct access to the server (again serverless) to run commands like cy.exec('npm run db:reset && npm run db:seed')? Cypress does warn me in the console about the use of promises:
Cypress detected that you returned a promise in a test, but also invoked one or more cy commands inside of that promise.
Here is the code I use:
import API, { graphqlOperation } from '#aws-amplify/api';
import Auth from '#aws-amplify/auth';
import Amplify from 'aws-amplify';
import * as R from 'ramda';
import config from '../../src/aws-exports';
import { contacts } from '../../src/contacts/fixtures';
import { replaceEmptyStringsWithNull } from '../../src/contacts/helpers';
import {
createContact as addMutation,
deleteContact as deleteMutation
} from '../../src/graphql/mutations';
import { listContacts } from '../../src/graphql/queries';
Amplify.configure(config);
const deleteContact = input =>
API.graphql(graphqlOperation(deleteMutation, { input }));
const createContact = input =>
API.graphql(graphqlOperation(addMutation, { input }));
describe('Contactlist', () => {
beforeEach(async () => {
await Auth.signIn(Cypress.env('email'), Cypress.env('password'));
const allContacts = await API.graphql(graphqlOperation(listContacts));
await Promise.all(
R.map(
R.pipe(
R.prop('id'),
id => ({ id }),
deleteContact
)
)(allContacts.data.listContacts.items)
);
await Promise.all(
R.map(
R.pipe(
R.dissoc('id'),
replaceEmptyStringsWithNull,
createContact
)
)(contacts)
);
});
// ... my tests
It would be exactly the way I would perform the test. I love to start with a fully controlled state, even if that means having multiple API-calls as a before()

Error:"Failed to get the current sub/segment from the context" when use AWS X-ray in Lambda with node.js

I am trying to use implement the AWS X-ray into my current project (using Node.js and Serverless framework). I am trying to wire the X-ray to one of my lambda function, I got the problem of
Error: Failed to get the current sub/segment from the context.
at Object.contextMissingRuntimeError [as contextMissing] (/.../node_modules/aws-xray-sdk-core/lib/context_utils.js:21:15)
at Object.getSegment (/.../node_modules/aws-xray-sdk-core/lib/context_utils.js:92:45)
at Object.resolveSegment (/.../node_modules/aws-xray-sdk-core/lib/context_utils.js:73:19).....
code below:
import { DynamoDB } from "aws-sdk";
import AWSXRay from 'aws-xray-sdk';
export const handler = async (event, context, callback) => {
const dynamo = new DynamoDB.DocumentClient({
service: new DynamoDB({ region })
});
AWSXRay.captureAWSClient(dynamo.service);
try {
// call dynamoDB function
} catch(err) {
//...
}
}
for this problem, I use the solution from
https://forums.aws.amazon.com/thread.jspa?messageID=821510&#821510
the other solution I tried is from https://forums.aws.amazon.com/thread.jspa?messageID=829923&#829923
code is like
import AWSXRay from 'aws-xray-sdk';
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
export const handler = async (event, context, callback) => {
const dynamo = new AWS.DynamoDB.DocumentClient({region});
//....
}
Still not working...
Appreciated to the help of any kind.
As you mention, that happened because you're running locally (using serverless-offline plugin) and the serverless-offline plugin doesn't provide a valid XRAY context.
One possible way to pass this error and still be able to call your function locally is setting AWS_XRAY_CONTEXT_MISSING environment variable to LOG_ERROR instead of RUNTIME_ERROR (default).
Something like:
serverless invoke local -f functionName -e AWS_XRAY_CONTEXT_MISSING=LOG_ERROR
I didn't test this using serverless framework but it worked when the same error occurred calling an amplify function locally:
amplify function invoke <function-name>
I encountered this error also. To fix it, I disabled XRay when running locally. XRay isn't needed when running locally because I can just set up debug log statements at that time.
This is what the code would look like
let AWS = require('aws-sdk');
if (!process.env.IS_OFFLINE) {
const AWSXRay = require('aws-xray-sdk');
AWS = AWSXRay.captureAWS(require('aws-sdk'));
}
If you don't like this approach, you can set up a contextStrategy to not error out when the context is missing.
Link here
AWSXRay.setContextMissingStrategy("LOG_ERROR");
If you don't want the error clogging up your output you can add a helper that ignores only that error.
// Removes noisy Error: Failed to get the current sub/segment from the context due to Xray
export async function disableXrayError() {
console.error = jest.fn((err) => {
if (err.message.includes("Failed to get the current sub/segment from the context")) {
return;
} else {
console.error(err);
}
});
}

Resources