aUtil.js
module.exports = {
successTrue: function(data) {
return { data: data, success: true };
},
isLoggedin: async (req, res) {
//decoded token in req header
//if decoded token success,
res.json(this.successTrue(req.decoded));
}
}
that function call in test.js
router.get('/check', aUtil.isLoggedin, async (req, res) => { ... })
I want to use the function above in that function.
But I keep getting errors.
ReferenceError: successTrue is not defined
I tried many ways.
insert 'const aUtil = require('./aUtil')`
change to 'res.json(successTrue( ... )'
Use this:
module.exports = {
successTrue: function() {
return { foo: 'bar' }
},
isLoggedin: function() {
console.log(this.successTrue())
}
}
You're exporting an object, so this refers to itself.
Also make sure you're binding aUtils if you're using it as middleware like so:
router.get('/check', aUtil.isLoggedin.bind(aUtil), async (req, res) => { ... })
Try this :
const aUtil = {
successTrue: function() { //return json obj },
isLoggedin: function() {
res.json(aUtil.successTrue( ... ));
}
}
module.exports = aUtil;
Related
On a dynamically generated page, I want to redirect if the user is not logged in. I would do it with getServerSideProps like this:
export async function getServerSideProps({ req, res }) {
if (req.headers['x-user-id']) {
return {
props: {
//...
}
}
} else {
return {
redirect: {
destination: '/'
}
}
}
}
However, in my dynamically generated next.js page, I need to use getStaticPaths and getStaticProps together, and you can't use getStaticProps and getServerSideProps together. Therefore, for my page [username].js, I tried doing this:
export async function getStaticProps({ params, req, res }) {
const results = await Get('https://example.com/api/getUsers')
const i = results.findIndex(e => e.username === params.username)
if (req.headers['x-user-id']) {
return {
props: {
user: results[i]
}
}
} else {
return {
redirect: {
destination: '/'
}
}
}
}
This however gives me the error:
TypeError: Cannot read properties of undefined (reading 'headers')
How can I fix this?
I'm having a hard time finding info on how to test this function:
const MyService = {
async stringify (entry, cb) {
try {
const response = await axios.post('localhost:3005/stringify', {
entry
})
cb(null, response.data)
} catch (minificationError) {
if (minificationError.response.status === 500) {
cb('error 1', null)
} else {
cb('error 2', null)
}
}
}
}
I understand I can import axios and mock the .post like this:
axios.post.mockResolvedValue({
data: { some: 'value' }
})
That'd work great if I the MyService was returning the promise... but how do I deal with the callback? Is this a bad practice and should the service be returning the promise and then handle errors in the component functions instead?
Additionally, how would I mock a status code with jest (to test the failed states?)
First, you have to set up mock axios after that you have to call your mockapi's in your test case
const axios = {
post: jest.fn(() => {
return Promise.resolve({
data: {},
});
}),
create: () => axios,
request: {},
defaults: {
adapter: {},
headers: {},
},
interceptors: {
request: {
use() {},
},
response: {
use() {},
},
},
};
Once you setup mock axios then you can access in your test case and return whatever mock response and status code you want.
mockAxios.post.mockImplementation((url) => {
if (url.includes("something")) {
return Promise.resolve({ data:{"response":""}, status: 200 });
}
return Promise.reject(new Error("not found"));
});
I'm trying to access a function that I'm later going to use for changing some database values. However whenever I try to build the project I get:
Error: Route.post() requires callback functions but got a [object Promise]
My initial function is:
import fetch from '../../../../core/fetch';
import history from '../../../../core/history';
export const BOXOFFICE_CHECKING_IN = 'BOXOFFICE_CHECKING_IN';
export const BOXOFFICE_CHECKED_IN = 'BOXOFFICE_CHECKED_IN';
export const BOXOFFICE_CHECKED_IN_ERROR = 'BOXOFFICE_CHECKED_IN_ERROR';
export default function checkIn() {
return async (dispatch, getState) => {
try {
dispatch({ type: BOXOFFICE_CHECKING_IN });
const state = getState();
const {
order: {
id: orderId,
},
} = state;
const response = await fetch(
`/api/event/orders/${orderId}/checkIn`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
order: orderId,
checkedIn: true,
}),
}
);
if (response.status === 200) {
dispatch({ type: BOOKING_CHECKED_IN });
} else {
const errorResponse = await response.json();
if (errorResponse.code === 'card_error') {
dispatch({ type: BOXOFFICE_CHECKED_IN_ERROR });
}
}
} catch (err) {
throw err;
}
};
}
Which then feeds to the api:
import checkIn from '../handlers/api/orders/checkInCustomer';
...
export default (resources) => {
const router = new Router();
...
router.post('/orders/:orderId/checkIn', checkIn(resources));
Which then reaches the final function I wish to use:
export default async function checkIn(req, res) {
console.log('this is working fully');
return true;
}
Any help is appreciated.
The problem is, you want to be passing the function checkIn, but when you call it using checkIn(resources) you're actually passing the return value (A promise that resolves to true).
You should be using:
router.post('/orders/:orderId/checkIn', checkIn);
Now, I'm assuming you want to do this because you want to pass resources into the router.post function, correct? What happens to the request and response objects?
Where does resources go?
v
export default async function checkIn(req, res) {
console.log('this is working fully');
return true;
}
You have a few ways of accomplishing what you're looking for.
Create a resources file, and import it. This is the ideal solution:
const db = mysql.connect(...);
const lang = lang.init();
console.log('This file is only called once!');
export default {
db,
lang,
};
And then in your code (/routes/checkIn.js):
import { db } from '../resources';
export default async function checkIn(req, res) {
//Access db here
//db.query...
}
Wrap your code in an intermediate function:
router.post('/orders/:orderId/checkIn', (req, res) => checkIn(req, res, resources));
Bind() resources to your checkIn function:
const db = mysql.connect(...);
const lang = lang.init();
const resources = {db, lang};
router.post('/orders/:orderId/checkIn', checkIn.bind(resources));
And then in your code (/routes/checkIn.js):
export default async function checkIn(req, res) {
//Access this.db here
//this.db.query...
}
I am trying to get my head around the move to await/async in Hapi 17.
Mainly I am trying to work out how to rewrite an abstracted route to one that will work with async/await
The following is an extract from my routes\dogs.js file
const DogController = require('../controllers/dog')
exports.plugin = {
name: 'dogs',
register: async (server, options) => {
server.route({
method: 'GET',
path: '/api/dogs',
handler: DogController.list
})
With the relevant extract from ../controllers/dog
exports.list = (req, h) => {
return Dog.find({}).exec().then((dog) => {
return { dogs: dog }
}).catch((err) => {
return { err: err }
})
}
Which currently returns a list of dogs from a MongoDB database at the moment. I'd like to rewrite the route so that the handler becomes something like
handler: async (request, h) => {
return DogController.list
}
But I'm assuming that the Controller itself is what needs to change.
There is an options property in Route that you can change the behavior of Route in request lifecycle. That means you can create an object and tie it up to your route definition.
Here is your dogs.js route plugin.
exports.plugin = {
async register(server, options) {
const DogController = require('../controllers/dogs');
server.route([
{
method: 'GET',
path: '/dogs',
options: DogController.view
},
]);
},
name: 'dogs-route'
};
And here, your dog controller.
exports.view = {
description: 'list all the good dogs',
handler: async (request, h) => {
return h.view('index', {'title': 'Home Page Title'});
try {
const dogs = await Dog.find({}).exec();
return {dogs};
}
catch(e){
// or something you want
return Boom.badRequest(e.message, e);
}
}
};
Here is a full example that you can check both routes and controllers respectively.
Before Node.js 7.0 was released my Sails.js controllers looked something similar to:
const _async = require('asyncawait/async');
const _await = require('asyncawait/await');
...
get: _async (function (req, res) {
try {
let item = _await (Items.find({
id: req.params.id
}));
if (!item.length) {
return res.notFound("The item does not exist");
}
return res.ok(item[0]);
} catch (error) {
return res.serverError(error);
}
}),
Everything used to run perfectly. After the release of Node.js 7.0, I changed it to:
get: async function (req, res) {
try {
let item = await Items.find({
id: req.params.id
});
if (!item.length) {
return res.notFound("The item does not exist");
}
return res.ok(item[0]);
} catch (error) {
return res.serverError(error);
}
},
But it logs error:
error: In items.get, ignored invalid attempt to bind route to a
non-function controller: { [Function: get] _middlewareType: 'ACTION:
items/get' } for path: /v1/items/:id and verb: get
Edit:
Looks like a bug in underscore lib used by sails:
if ( !_.isFunction(originalFn) ) {
sails.after('lifted', function () {
sails.log.error(
'In '+controllerId + '.' + actionId+', ignored invalid attempt to bind route to a non-function controller:',
originalFn, 'for path: ', path, verb ? ('and verb: ' + verb) : '');
});
return;
}
Logged an issue: https://github.com/balderdashy/sails/issues/3863