Importing mp3 asset in Vuetify App break Jest tests - vuejs2

I saw similar topic connected to React but the highest rated solution doesn't work for me, so I decided to add question by myself. I have a Vuetify project that is testing with vue-test-utils. I wanted to add an audio asset using import in errorHandler.ts file that I am using to handle errors accross whole app:
import { AxiosError } from 'axios';
import store from '#/store';
import errorSound from '#/assets/sounds/errorSound.mp3';
const ErrorHandler = {
handler(error: AxiosError): void {
if (error.response) {
const { status, data } = error.response;
const apiMessage = data['hydra:description'] || data.message;
const { errors } = data;
const message = this.createErrorMessage(status, apiMessage, errors);
const audio = new Audio(errorSound);
store.commit('globals/SET_ALERT_TITLE', 'errors.title');
store.commit('globals/SET_ALERT_TEXT', message);
store.commit('globals/SET_ALERT_DIALOG');
store.commit('globals/SET_ALERT_TWO_BUTTONS', false);
audio.play();
}
},
createErrorMessage(status: number, message: string, errors: any): string {
switch (status) {
case 0:
return 'No connection to the network can be established, please check your network settings';
case 400:
return 'errors.400';
case 401:
return 'errors.401';
case 403:
return 'errors.403';
case 404:
return 'errors.404';
case 405:
return 'errors.405';
case 406:
return 'errors.406';
case 408:
return 'errors.408';
case 412:
return message;
case 422:
if (errors) {
const err = [] as any;
Object.entries(errors).forEach(([key, value]) => {
err.push(`${key}: ${value}`);
});
let showErrors = '';
err.forEach((item: any) => {
showErrors += `${item} `;
});
return showErrors;
}
return message;
case 500:
return 'errors.500';
case 502:
return 'errors.502';
case 503:
return 'errors.503';
default:
return `${status}`;
}
},
};
export default ErrorHandler;
In development mode everything is working correctly, the app is building and sound is playing when it should but I cannot build for production cause of failing tests. I added moduleNameMapper to jest.config.ts and file is looking like this:
process.env.VUE_CLI_BABEL_TARGET_NODE = true;
process.env.VUE_CLI_BABEL_TRANSPILE_MODULES = true;
module.exports = {
preset: 'ts-jest',
testMatch: ['**/__tests__/**/*.(js|ts|tsx)', '**/?(*.)+(spec|test).(js|ts|tsx)'],
moduleFileExtensions: ['ts', 'js', 'json', 'vue', '*'],
transform: {
'.*\\.(vue)$': 'vue-jest',
'^.+\\.tsx?$': 'ts-jest',
'^.+\\.[jt]s$': 'ts-jest',
'^.+\\.svg$': '<rootDir>/svgTransform.js',
},
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/src/__mock__/fileMock.js',
'\\.(css|less)$': '<rootDir>/src/__mock__/styleMock.js',
},
transformIgnorePatterns: [
'/node_modules/(?!register-service-worker|vuetify/lib|vee-validate/dist/rules|jwt-decode)',
],
setupFiles: ['./tests/setup.ts'],
};
Unfortunately this is not working for my errorSound.mp3 file. I also tried to move this moduleNameMapper from config.jest.ts right into package.json but also didn't work out.
Error:
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){ID3
^
SyntaxError: Invalid or unexpected token
3 | import errorSound from '#/assets/sounds/errorSound.mp3';
4 |
> 5 | const ErrorHandler = {
| ^
6 | handler(error: AxiosError): void {
7 | if (error.response) {
8 | const { status, data } = error.response;
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14)
at Object.<anonymous> (src/services/ErrorHandler.ts:5:50)

Related

next-i18next, next export & 404 on non-generated pages (with fallback true/blocking)

Having followed the documentation on i18next/next-i18next to configure i18n and then the instructions on this locize blog post on how to export static sites with next export, I am able to export localised versions of each page.
The problem is that pages that have not been statically generated return a 404, despite setting fallback: true in the getStaticPaths return object. The page works on my localhost but not when deployed with Vercel.
Code:
const ArticlePage: NextPageWithLayout<Props> = ({ article }: Props) => {
const { i18n, t } = useTranslation('page/news/article')
const router = useRouter()
if (router.isFallback) return <div>Loading...</div>
return <div>Article</div>
}
export const getStaticPaths: GetStaticPaths = async () => {
let paths: { params: { aid: string; locale: TLocale } }[] = []
try {
const response = await api.get(`/articles?per_page=9999`)
const articles = response.data.data as IArticle[]
articles.forEach((a) => {
getI18nPaths().forEach((p) => {
paths.push({
params: {
aid: a.base_64_id,
locale: p.params.locale,
},
})
})
})
return {
paths,
fallback: true,
}
} catch (error) {
return {
paths,
fallback: true,
}
}
}
export const getStaticProps: GetStaticProps = async ({ locale, params }) => {
try {
const article = await api.get(`/articles/${params?.aid}`)
return {
props: {
...(await serverSideTranslations(locale || 'en', [
'footer',
'header',
'misc',
'page/news/index',
'page/news/article',
])),
article: article.data as IArticle,
},
}
} catch (error) {
return {
notFound: true,
}
}
}
ArticlePage.getLayout = function getLayout(page: ReactElement) {
return <Layout>{page}</Layout>
}
export default ArticlePage
"i18next": "22.4.9",
"next-i18next": "^13.1.5",
"react-i18next": "^12.1.5",
There is a warning in the console react-i18next:: You will need to pass in an i18next instance by using initReactI18next when entering an non-generated page (alongside the not-found error of course). An issue raised about this warning is interesting but I could not find an answer to my issue within: https://github.com/i18next/next-i18next/issues/1917.
Attempts to fix:
adding revalidate: 10 to the return object of getStaticProps
using fallback: 'blocking'
trying a few different variants of localePath in next-i18next.config including the recommendation featured here: https://github.com/i18next/next-i18next#vercel-and-netlify
adding react: { useSuspense: false } to next-i18next.config
combinations of the above

Vercel: This Serverless Function (FUNCTION_INVOCATION_FAILED)

I have an error that appears when I try to access my link
This Serverless Function has crashed.
Your connection is working correctly.
Vercel is working correctly.
500: INTERNAL_SERVER_ERROR
Code: FUNCTION_INVOCATION_FAILED
ID: cdg1:cdg1::bgdnz-1676557396498-149041f4043b
[GET] /6OzxT
15:07:51:26
2023-02-16T14:07:51.324Z 020abb04-a238-441a-8a1d-5a4fb96d66c3 ERROR Unhandled Promise Rejection {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"TypeError: fetch failed","reason":{"errorType":"TypeError","errorMessage":"fetch failed","cause":{"errorType":"ConnectTimeoutError","errorMessage":"Connect Timeout Error","code":"UND_ERR_CONNECT_TIMEOUT","name":"ConnectTimeoutError","message":"Connect Timeout Error","stack":["ConnectTimeoutError: Connect Timeout Error"," at onConnectTimeout (/var/task/vercel/path0/node_modules/undici/lib/core/connect.js:182:24)"," at /var/task/vercel/path0/node_modules/undici/lib/core/connect.js:129:46"," at Immediate._onImmediate (/var/task/vercel/path0/node_modules/undici/lib/core/connect.js:170:9)"," at process.processImmediate (node:internal/timers:471:21)"]},"stack":["TypeError: fetch failed"," at fetch (/var/task/vercel/path0/node_modules/undici/index.js:113:13)"," at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: TypeError: fetch failed"," at process.<anonymous> (file:///var/runtime/index.mjs:1194:17)"," at process.emit (node:events:525:35)"," at emit (node:internal/process/promises:149:20)"," at processPromiseRejections (node:internal/process/promises:283:27)"," at process.processTicksAndRejections (node:internal/process/task_queues:96:32)"]}
Unknown application error occurred
Runtime.Unknown
I tried to add a try/catch, and normally it should be redirected to the URL (here steellgold.fr)
+page.server.ts (Redirect page) (https://preview.linkfy.fr/6OzxT)
import { PUBLIC_URL, PUBLIC_API_URL } from "$env/static/public";
import type { Link } from "$lib/types/link.type";
import { restRequest } from "$lib/utils/request/request";
import { error, redirect } from "#sveltejs/kit";
import type { PageServerLoad } from "./$types";
// eslint-disable-next-line
export const load = (async({ params }) => {
if (!params.slug) throw redirect(303, PUBLIC_URL);
const data = await restRequest<Link>("get", PUBLIC_URL + "api/link", {
query: {
slug: params.slug
}
}, [], true);
if (!data.success) {
throw error(404, { message: "This link not exist or has been disabled", code: 404 });
}
try {
fetch(PUBLIC_API_URL + "link/" + params.slug);
} catch (e) {
console.error(e);
}
if (!data.data.status) throw error(423, { message: "This link has been disabled", code: 423 });
throw redirect(303, data.data.url);
}) satisfies PageServerLoad;
increment.ts (Fastify route fort increment links)
import { FastifyReply, FastifyRequest } from "fastify";
import { app } from "../..";
import { Link } from "../../types/link";
import { error, success, warn } from "../../utils/logger";
import prisma from "../../utils/prisma";
app.get("/link/:slug", {
handler: async(request: FastifyRequest<{ Params: Link }>, reply: FastifyReply) => {
reply.status(200).send({ message: "Correctly routed received request." });
warn(`[GET] incrementing link with slug /${request.params.slug}.`);
const link = await prisma.link.findUnique({
where: { slug: request.params.slug }
});
if (!link) {
reply.status(404).send({ error: "Link not found" });
error(`[404] Link with slug /${request.params.slug} not found.`);
return;
}
await prisma.link.update({
where: { slug: request.params.slug },
data: { clicks: link.clicks + 1 }
});
success(`[200] Link with slug /${request.params.slug} incremented by 1.`);
return reply.status(200).send({
message: "Link incremented successfully."
});
}
});```
All codes is open-source: https://github.com/Steellgold/Linkfy or https://github.com/Steellgold/LinkfyAPI if you want

vue3 testing library - How to use globalProperties in tests

I am new to Vue and followed the recommendation to use vue testing library. The only issue is I can't seem to find a way to inject my code into globalProperties in render function.
Does anyone know of an example where I can inject or mock it out?
main.js
app.config.globalProperties.$globals = globalMethods
...
const app = createApp(App)
app.config.globalProperties.$globals = globalMethods
app.config.globalProperties.$globalVars = globalVars
app.component("font-awesome-icon", fontawesome)
app.use(applicationStore);
app.use (Hotjar, hotjarConfig)
app.use(i18n)
app.use(router)
app.mount('#app')
From my vue component in create I am able to call
Component.vue
let formatedObj = this.$globals.maskValues(this.inputValue, this.inputType, this);
...
,
created() {
let formatedObj = this.$globals.maskValues(this.inputValue, this.inputType, this);
this.myInputValue = formatedObj.formatedString;
this.formatedCharacterCount = formatedObj.formatedCharacterCount;
this.prevValue = this.myInputValue;
},
...
tesst.spec.js
import { render } from '#testing-library/vue'
import FormatedNumericInput from '#/components/Component.vue'
import {globalMethods} from'#/config/global-methods'
const label = 'Price'
const initSettings = {
props: {
inputId: 'testInputId1',
labelTxt: label
}
};
beforeEach(() => {
});
test('a simple string that defines your test', () => {
const { getByLabelText } = render(FormatedNumericInput, initSettings)
const input = getByLabelText(label)
// testing logic
expect(input != null).toBe(true)
expect(FormatedNumericInput != null).toBe(true)
})
** ERROR **
TypeError: Cannot read property 'maskValues' of undefined
85 | },
86 | created() {
> 87 | let formatedObj = this.$globals.maskValues(this.inputValue, this.inputType, this);
| ^
88 | this.myInputValue = formatedObj.formatedString;
89 | this.formatedCharacterCount = formatedObj.formatedCharacterCount;
90 | this.prevValue = this.myInputValue;
at Proxy.created (src/components/FormatedNumericInput.vue:87:37)
The second argument of render() is passed to #vue/test-utils mount(), so you could include the global.mocks mounting option to mock $globals.maskValues:
const { getByLabelText } = render(FormatedNumericInput, {
...initSettings,
global: {
mocks: {
$globals: {
maskValues: (inputValue, inputType) => {
const formatedString = globalFormatValue(inputValue) // declared elsewhere
return {
formatedString,
formatedCharacterCount: formatedString.length,
}
}
}
}
}
})
This is my solution in actual Vue3/Vite/Vitest environment, I set some mocks globally, so I don't need to in every test suite.
// vitest.config.ts
import { mergeConfig } from 'vite';
import { defineConfig } from 'vitest/config';
import viteConfig from './vite.config';
export default defineConfig(
mergeConfig(viteConfig, { // extending app vite config
test: {
setupFiles: ['tests/unit.setup.ts'],
environment: 'jsdom',
}
})
);
// tests/unit.setup.ts
import { config } from "#vue/test-utils"
config.global.mocks = {
$t: tKey => tKey; // just return translation key
};
so for you it will be something like
config.global.mocks = {
$globals: {
maskValues: (inputValue, inputType) => {
// ...implementation
return {
formatedString,
formatedCharacterCount,
}
}
}
}

Getting 401 when using nuxt/apollo with github API

I am trying to pull some data from my pinned repos using the github v4 API within Nuxt.js I have set up the following as per the docs:
buildModules: [
'#nuxtjs/eslint-module',
'#nuxtjs/tailwindcss',
'#nuxtjs/color-mode',
'#nuxtjs/apollo',
],
apollo: {
clientConfigs: {
default: {
httpEndpoint: 'https://api.github.com/graphql',
authenticationType: 'Bearer',
tokenName: process.env.GITHUB_TOKEN,
},
},
},
My query in another component is:
export default {
apollo: {
opensource: gql`
query github {
user(login: "mrpbennett") {
pinnedItems(first: 6, types: REPOSITORY) {
edges {
node {
... on GitHub_Repository {
name
description
url
primaryLanguage {
name
color
}
}
}
}
}
}
}
`,
},
But I am getting the following Network error: Response not successful: Received status code 401 which presents me with
function ApolloError(_a) {
var graphQLErrors = _a.graphQLErrors,
networkError = _a.networkError,
errorMessage = _a.errorMessage,
extraInfo = _a.extraInfo;
var _this = _super.call(this, errorMessage) || this;
_this.graphQLErrors = graphQLErrors || [];
_this.networkError = networkError || null;
if (!errorMessage) {
_this.message = generateErrorMessage(_this);
} else {
_this.message = errorMessage;
}
_this.extraInfo = extraInfo;
_this.__proto__ = ApolloError.prototype;
return _this;
}
Within file bundle.umd.js
I know the query works as I have used the same one within Gatsby. Any ideas where I am going wrong with the authentication?

relay subscription onNext not triggered on react-native

I am a subscription setup but onNext is not getting triggered I am not sure why since this is my first time implementing subscription and docs was not much help with the issue.
Here are the code implementations:
import {
graphql,
requestSubscription
} from 'react-relay'
import environment from '../network';
const subscription = graphql`
subscription chatCreatedSubscription{
chatCreated{
id
initiate_time
update_time
support_id
category_id
email
name
}
}
`;
function chatCreated(callback) {
const variables = {};
requestSubscription(environment, {
subscription,
variables,
onNext: () => {
console.log("onNext");
callback()
},
updater: () => {
console.log("updater");
}
});
}
module.exports = chatCreated;
and here is my network for the subscription
import { Environment, Network, RecordSource, Store } from "relay-runtime";
import Expo from "expo";
import { SubscriptionClient } from "subscriptions-transport-ws";
import { WebSocketLink } from 'apollo-link-ws';
import { execute } from 'apollo-link';
import accessHelper from "../helper/accessToken";
const networkSubscriptions = async (operation, variables) => {
let token = await accessHelper();
if (token != null || token != undefined) {
const subscriptionClient = new SubscriptionClient("ws://localhost:3000/graphql",
{
reconnect: true,
connectionParams: {
Authorization: token,
},
});
execute(new WebSocketLink(subscriptionClient), {
query: operation.text,
variables,
});
}
}
const network = Network.create(fetchQuery, networkSubscriptions);
const store = new Store(new RecordSource());
const environment = new Environment({
network,
store
});
export default environment;
the subscription is called in a componentDidMount method on a component it executes but the onNext method inside the subscription is never triggered when new information is added to what the subscription is listening to.
so i figured out that my issue was the network js not being setup properly and the version of subscription-transport-ws. i added version 0.8.3 of the package and made the following changes to my network file:
const networkSubscriptions = async (config, variables, cacheConfig, observer) => {
const query = config.text;
let token = await accessHelper();
if (token != null || token != undefined) {
const subscriptionClient = new SubscriptionClient(`ws://${api}/graphql`,
{
reconnect: true,
connectionParams: {
Authorization: token,
},
});
subscriptionClient.subscribe({ query, variables }, (error, result) => {
observer.onNext({ data: result })
})
return {
dispose: subscriptionClient.unsubscribe
};
}
}
i hope this helps you if you get stuck with the same issue as mine.