how to test Router.push options with Jest / React - jestjs

I'm new to testing with routing and was wondering how I would go about testing this
const handleFilter = (items: ParsedUrlQueryInput) => {
push({ pathname: '/games', query: items }, undefined, { scroll: false });
return;
};
<S.ShowMoreButton role="button" onClick={handleShowMore}
I made some mocks and the following test worked without the options, but when I add options, it's impossible to test
mock
const useRouter = jest.spyOn(require('next/router'), 'useRouter');
const push = jest.fn();
useRouter.mockImplementation(() => ({
push,
query: '',
asPath: '',
route: '/',
}));
test
expect(push).toHaveBeenCalledWith({
pathname: '/games',
query: { platforms: ['windows', 'linux'], sort_by: 'low-to-high' },
});
error in test
Expected: {"pathname": "/games", "query": {"platforms": ["windows", "linux"], "sort_by": "low-to-high"}}
Received
1
Object {
"pathname": "/games",
- "query": Object {
- "platforms": Array [
- "windows",
- "linux",
- ],
- "sort_by": "low-to-high",
- },
+ "query": Object {},
},
+ undefined,
+ {"scroll": false}

Related

Can a push notification be send from the server without a client call?

I have a javascript file on my NodeJS server that runs at 00:00:00 and updates some fields in the database, if that happens I want to send out a push notification to some users. I've set this up in my Javascript file:
https://dev.to/devsmranjan/web-push-notification-with-web-push-angular-node-js-36de
const subscription = {
endpoint: '',
expirationTime: null,
keys: {
auth: '',
p256dh: '',
},
};
const payload = {
notification: {
title: 'Title',
body: 'This is my body',
icon: 'assets/icons/icon-384x384.png',
actions: [
{action: 'bar', title: 'Focus last'},
{action: 'baz', title: 'Navigate last'},
],
data: {
onActionClick: {
default: {operation: 'openWindow'},
bar: {
operation: 'focusLastFocusedOrOpen',
url: '/signin',
},
baz: {
operation: 'navigateLastFocusedOrOpen',
url: '/signin',
},
},
},
},
};
const options = {
vapidDetails: {
subject: 'mailto:example_email#example.com',
publicKey: process.env.REACT_APP_PUBLIC_VAPID_KEY,
privateKey: process.env.REACT_APP_PRIVATE_VAPID_KEY,
},
TTL: 60,
};
webpush.sendNotification(subscription, JSON.stringify(payload), options)
.then((_) => {
console.log(subscription);
console.log('SENT!!!');
console.log(_);
})
.catch((_) => {
console.log(subscription);
console.log(_);
});
But when I run the file I get the message:
{ endpoint: '', expirationTime: null, keys: { auth: '', p256dh: '' } } Error: You must pass in a subscription with at least an endpoint.
Which makes sense since the server has no idea about service workers etc. Any suggestions on how to proceed?

Next JS advanced feature Content Security policy format

I am adding security Policy headers to my application using Security headers advanced feature of next.js
Reference :https://nextjs.org/docs/advanced-features/security-headers
I am quiet clear of how to add the security policies to the next application except the Content Security policy,It does not show any format of the policy in the Documentation :
Taking help of next and developer.mozilla org I have some code in place,that I am attaching herewith. Can anybody help me with the correct format to define content-security policy in Next.JS
Code in Next.config.js
const cspPolicy = "default-src 'self';connect-src 'self','preview.contentful.com','*.flippenterprise.net', 'aq.flippenterprise.net','https://www.google-analytics.com','dpm.demdex.net','stats.g.doubleclick.net','lcljoefresh.sc.omtrdc.net','sfml.flippback.com','p.flipp.com','https://sentry.io/',";
const securityHeaders = [
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload'
},
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN'
},
{
key: 'Content-Security-Policy',
value: cspPolicy
}
];
const headers = {
async headers() {
return [
{
// Apply these headers to all routes in your application.
source: '/(.*)',
headers: securityHeaders,
},
]
},
}
const nextConfig = {
env: {
search_key: process.env.search_key,
appDynamicsKey: process.env.appDynamicsKey,
ENVIRONMENT: process.env.ENVIRONMENT,
},
webpack5:false,
// https://nextjs.org/docs#customizing-webpack-config
webpack: (webpackConfig) => {
const { module = {} } = webpackConfig;
return {
...webpackConfig,
module: {
...module,
rules: [
...(module.rules || []),
{
test: /\.(txt|png|woff|woff2|eot|ttf|gif|jpg|ico|svg)$/,
use: {
loader: 'file-loader',
options: {
name: '[name]_[hash].[ext]',
publicPath: '/_next/static/files',
outputPath: 'static/files',
},
},
},
{
test: /\.spec.jsx$/,
loader: 'ignore-loader',
},
],
},
};
},
};
const sassOptions = {
sassLoaderOptions: {
outputStyle: 'compressed',
},
};
module.exports = withPlugins(
[[withSass, sassOptions], [withFonts], [withCSS], [withBundleAnalyzer]],
nextConfig,
headers,
);

Trouble connecting express api to nuxt app and mongodb

It's been seriously 10 days since i'm trying to deploy my web app online. i've gone back and forth between heroku and digital ocean. nothing solved. i've asked questions here all i get is a long post with technical terms i' not able to understand. Here's my problem :
i have a nuxt app with express.js in the backend and mongodb as the database. At first i had trouble with configuring host and port for my nuxt app. once i fixed it, anoither problem appeared : i'm not receiving data from the database. i don't if it's something related to database connection or with the express api configuration.
here's my nuxt config
export default {
ssr: false,
head: {
titleTemplate: 'Lokazz',
title: 'Lokazz',
meta: [
{ charset: 'utf-8' },
{
name: 'viewport',
content: 'width=device-width, initial-scale=1'
},
{
hid: 'description',
name: 'description',
content:
'Lokazz'
}
],
link: [
{
rel: 'stylesheet',
href:
'https://fonts.googleapis.com/css?family=Work+Sans:300,400,500,600,700&amp;subset=latin-ext'
}
]
},
css: [
'swiper/dist/css/swiper.css',
'~/static/fonts/Linearicons/Font/demo-files/demo.css',
'~/static/fonts/font-awesome/css/font-awesome.css',
'~/static/css/bootstrap.min.css',
'~/assets/scss/style.scss'
],
plugins: [
{ src: '~plugins/vueliate.js', ssr: false },
{ src: '~/plugins/swiper-plugin.js', ssr: false },
{ src: '~/plugins/vue-notification.js', ssr: false },
{ src: '~/plugins/axios.js'},
{ src: '~/plugins/lazyLoad.js', ssr: false },
{ src: '~/plugins/mask.js', ssr: false },
{ src: '~/plugins/toastr.js', ssr: false },
],
buildModules: [
'#nuxtjs/vuetify',
'#nuxtjs/style-resources',
'cookie-universal-nuxt'
],
styleResources: {
scss: './assets/scss/env.scss'
},
modules: ['#nuxtjs/axios', 'nuxt-i18n','vue-sweetalert2/nuxt', '#nuxtjs/auth-next', "bootstrap-vue/nuxt"],
bootstrapVue: {
bootstrapCSS: false, // here you can disable automatic bootstrapCSS in case you are loading it yourself using sass
bootstrapVueCSS: false, // CSS that is specific to bootstrapVue components can also be disabled. That way you won't load css for modules that you don't use
},
i18n: {
locales: [
{ code: 'en', file: 'en.json' },
],
strategy: 'no_prefix',
fallbackLocale: 'en',
lazy: true,
defaultLocale: 'en',
langDir: 'lang/locales/'
},
router: {
linkActiveClass: '',
linkExactActiveClass: 'active',
},
server: {
port: 8080, // default: 3000
host: '0.0.0.0' // default: localhost
},
auth: {
strategies: {
local: {
token: {
property: "token",
global: true,
},
redirect: {
"login": "/account/login",
"logout": "/",
"home": "/page/ajouter-produit",
"callback": false
},
endpoints: {
login: { url: "/login", method: "post" },
logout: false, // we don't have an endpoint for our logout in our API and we just remove the token from localstorage
user:false
}
}
}
},
};
here's my package.json
{
"name": "martfury_vue",
"version": "1.3.0",
"description": "Martfury - Multi-purpose Ecomerce template with vuejs",
"author": "nouthemes",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
},
"config": {
"nuxt": {
"host": "0.0.0.0",
"port": "8080"
}
},
}
here's my repository.js file
import Cookies from 'js-cookie';
import axios from 'axios';
const token = Cookies.get('id_token');
const baseDomain = 'https://lokazzfullapp-8t7ec.ondigitalocean.app';
export const customHeaders = {
'Content-Type': 'application/json',
Accept: 'application/json'
};
export const baseUrl = `${baseDomain}`;
export default axios.create({
baseUrl,
headers: customHeaders
});
export const serializeQuery = query => {
return Object.keys(query)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`)
.join('&');
};
an example of an api call i make locally that works without a problem :
import Repository, { serializeQuery } from '~/repositories/Repository.js';
import { baseUrl } from '~/repositories/Repository';
import axios from 'axios'
const url = baseUrl;
export const actions = {
async getProducts({ commit }, payload) {
const reponse = await axios.get(url)
.then(response => {
commit('setProducts', response.data);
return response.data;
})
.catch(error => ({ error: JSON.stringify(error) }));
return reponse;
},
}
here's my index.js (express file)
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose')
const cors = require('cors');
//const url = 'mongodb://localhost:27017/lokazz'
const url = 'mongodb+srv://lokazz:zaki123456#cluster0.hsd8d.mongodb.net/lokazz?retryWrites=true&w=majority'
const jwt = require('jsonwebtoken')
const con = mongoose.connection
mongoose.connect(url, {useNewUrlParser:true}).then(()=>{
const app = express();
// middlleware
app.use(express.json())
app.use(cors());
//products routes
const products = require('./product/product.router');
app.use('/', products)
//users routes
const users = require('./user/user.router');
app.use('/', users)
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server started on port ${port}`));
}).catch(error => console.log(error.reason));
con.on('open', () => {
console.log('connected...')
})
My directory structure
the error i get after the api request, meaning it's not receving any data.
ebd1ecd.js:2 TypeError: Cannot read properties of undefined (reading 'username')
at f.<anonymous> (c88240c.js:1)
at f.t._render (ebd1ecd.js:2)
at f.r (ebd1ecd.js:2)
at wn.get (ebd1ecd.js:2)
at new wn (ebd1ecd.js:2)
at t (ebd1ecd.js:2)
at f.In.$mount (ebd1ecd.js:2)
at init (ebd1ecd.js:2)
at ebd1ecd.js:2
at v (ebd1ecd.js:2)
idk if it's a problem with mongodb connection cluster or the api call.

Apollo GraphQL Server - Access query params from cache plugin

I have an Apollo GraphQL server using the apollo-server-plugin-response-cache plugin and I need to determine whether or not I'm going to write to the cache based on incoming parameters. I have the plugin set up and I'm using the shouldWriteToCache hook. I can print out the GraphQLRequestContext object that gets passed into the hook, and I can see the full request source, but request.variables is empty. Other than parsing the query itself, how can I access the actual params for the resolver in this hook? (In the example below, I need the value of param2.)
Apollo Server:
new ApolloServer({
introspection: true,
playground: true,
subscriptions: false,
typeDefs,
resolvers,
cacheControl: {
defaultMaxAge: 60
},
plugins: [
apolloServerPluginResponseCache({
cache, // This is a "apollo-server-cache-redis" instance
shouldWriteToCache: (requestContext) => {
// I get a lot of info here, including the source query, but not the
// parsed out query variables
console.log(requestContext.request);
// What I want to do here is:
return !context.request.variables.param2
// but `variables` is empty, and I can't see that value parsed anywhere else
}
})
]
})
Here is my resolver:
export async function exapi(variables, context) {
// in here I use context.param1 and context.param2
// ...
}
I have also tried:
export async function exapi(variables, { param1, param2 }) {
// ...
}
Here is what I get logged out from the code above:
{
query: '{\n' +
' exapi(param1: "value1", param2: true) {\n' +
' records\n' +
' }\n' +
'}\n',
operationName: null,
variables: {}, // <-- this is empty?! How can I get param2's value??
extensions: undefined,
http: Request {
size: 0,
timeout: 0,
follow: 20,
compress: true,
counter: 0,
agent: undefined,
[Symbol(Body internals)]: { body: null, disturbed: false, error: null },
[Symbol(Request internals)]: {
method: 'POST',
redirect: 'follow',
headers: [Headers],
parsedURL: [Url],
signal: null
}
}
}
If you didn't provide variables for GraphQL query, you could get the arguments from the GraphQL query string via ArgumentNode of AST
If you provide variables for GraphQL query, you will get them from requestContext.request.variables.
E.g.
server.js:
import apolloServerPluginResponseCache from 'apollo-server-plugin-response-cache';
import { ApolloServer, gql } from 'apollo-server';
import { RedisCache } from 'apollo-server-cache-redis';
const typeDefs = gql`
type Query {
exapi(param1: String, param2: Boolean): String
}
`;
const resolvers = {
Query: {
exapi: (_, { param1, param2 }) => 'teresa teng',
},
};
const cache = new RedisCache({ host: 'localhost', port: 6379 });
const server = new ApolloServer({
introspection: true,
playground: true,
subscriptions: false,
typeDefs,
resolvers,
cacheControl: {
defaultMaxAge: 60,
},
plugins: [
apolloServerPluginResponseCache({
cache,
shouldWriteToCache: (requestContext) => {
console.log(requestContext.document.definitions[0].selectionSet.selections[0].arguments);
return true;
},
}),
],
});
server.listen().then(({ url }) => console.log(`🚀 Server ready at ${url}`));
GraphQL query:
query{
exapi(param1: "value1", param2: true)
}
Server logs print param1 and param2 arguments:
🚀 Server ready at http://localhost:4000/
[]
[ { kind: 'Argument',
name: { kind: 'Name', value: 'param1', loc: [Object] },
value:
{ kind: 'StringValue',
value: 'value1',
block: false,
loc: [Object] },
loc: { start: 15, end: 31 } },
{ kind: 'Argument',
name: { kind: 'Name', value: 'param2', loc: [Object] },
value: { kind: 'BooleanValue', value: true, loc: [Object] },
loc: { start: 33, end: 45 } } ]

Nestjs with Fastify e2e test with jest mocking is not working

I have Nodejs API that use Fastify. The e2e test is written with jest.
Please find my e2e test. It works and test passes.
Here I find the response is same as the request parameter instead of mocking object.
The actual API respond the request parameter but here I am mocking different object but it is not using it for response.
I am not sure whether passing request body is correct for POST.
Why Jest mocking is not working. The similar mocking works for unit test.
import {
FastifyAdapter,
NestFastifyApplication,
} from '#nestjs/platform-fastify';
import { Test, TestingModule } from '#nestjs/testing';
import request from 'supertest';
import { AppModule } from '../src/app/app.module';
import Axios, { AxiosResponse } from 'axios';
import { HttpService } from '#nestjs/common';
import { Observable, of, observable } from 'rxjs';
import { OracleDBService } from 'synapse.bff.core';
describe('AppController (e2e)', () => {
let app: NestFastifyApplication;
let httpService: HttpService;
let oracleDBService: OracleDBService;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication<NestFastifyApplication>(
new FastifyAdapter(),
);
httpService = moduleFixture.get<HttpService>(HttpService);
oracleDBService = moduleFixture.get<OracleDBService>(OracleDBService);
await app.init();
jest.setTimeout(30000);
});
it('/ (GET)', () => {
const data = [
{ name: 'item1', code: '100', category: 'cat1', price: 1250 },
{ name: 'item2', code: '101', category: 'cat1', price: 1250 },
{ name: 'item3', code: '102', category: 'cat1', price: 1250 },
{ name: 'item4', code: '103', category: 'cat1', price: 1250 },
];
const response: AxiosResponse<any> = {
data,
headers: {},
config: { url: 'http://localhost:3001/item/getitem' },
status: 200,
statusText: 'OK',
};
jest.spyOn(httpService, 'get').mockReturnValue(of(response));
return app
.inject({
method: 'GET',
url: '/item/100',
})
.then(onresponse =>
expect(JSON.parse(onresponse.payload)).toEqual(response.data),
);
});
it('/ (POST)', () => {
const data = {
Name: 'item1Mock',
Code: '500',
Category: 'cat1Mock',
Price: 9250,
};
const response: AxiosResponse<any> = {
data,
headers: {},
config: { url: 'http://localhost:3001/item/getitem' },
status: 200,
statusText: 'OK',
};
jest.spyOn(httpService, 'post').mockReturnValue(of(response));
return app
.inject({
method: 'POST',
url: '/item/create',
payload: {
body: {
Name: 'item1',
Code: '200',
Category: 'cat1',
Price: 1250,
},
},
})
.then(onResponse =>
expect(
JSON.parse(onResponse.payload).message.Detail.message[0].target.body,
).toEqual(response.data),
);
});
I am getting the following error
expect(received).toEqual(expected) // deep equality
- Expected
+ Received
Object {
- "Category": "cat1Mock",
- "Code": "500",
- "Name": "item1Mock",
- "Price": 9250,
+ "Category": "cat1",
+ "Code": "200",
+ "Name": "item1",
+ "Price": 1250,
}
90 | expect(
91 | JSON.parse(onResponse.payload).message.Detail.message[0].target.body,
> 92 | ).toEqual(response.data),
| ^
93 | );
94 | });
95 |
at item.controller.e2e-spec.ts:92:11

Resources