error detecting global http method from vue test - jestjs

I'm running vue3 and testing a vue component using the vue test utils library and in the component i am making an api call like this:
const api = this.$http.publisher.fetchValidatedWebsites();
I have this global http variable registered
app.config.globalProperties.$http = HttpServiceFactory(HttpClient);
HttpServicefactory returns publisher like so:
const httpServiceFactory = (HttpClient) => ({
publisher: PublisherService(HttpClient),
});
and in the PublisherService i have my fetchValidatedWebsites() method; but when i run the test
expect(wrapper.vm.$http.publisher.fetchValidatedWebsites)
.toHaveBeenCalledTimes(1);
i get this error:
TypeError: Cannot read property 'fetchValidatedWebsites' of undefined
Seems like for some reason the vm doesn't recognise this variable.
In my package.json:
"vue": "^3.2.12",
"#vue/test-utils": "^2.0.0-rc.21"
How do i go about fixing this?

You need to register $http as a global mock in your vue-test-utils config.
Try something like:
import { config } from '#vue/test-utils'
config.global.mocks = {
$http: (HttpClient) => ({
publisher: PublisherService(HttpClient),
})
}

Related

When using (require/import) axios, Cannot seem to use a JS custom function within Angular (.ts) component

I am trying to embed a JS custom function within my Angular (.ts) component.
The proccess i have gone through:
created and added a .js file with a function of my need
added the reference to this file on my angular.json scripts array
defined the function in my .ts component file
When i do this proccess with a .js file without require('axios') etc. it seems to work perfectly. but my .js file has some libraries (axios, express, cheerio) and when i use 'ng serve' i get an error at my console:
"Uncaught ReferenceError: require is not defined" - when using require
"Uncaught SyntaxError: Cannot use import statement outside a module" - when changing it to import
my .js file beginning:
// const axios = require('axios')
// const cheerio = require('cheerio')
// const express = require('express')
import axios from "axios"
import { Cheerio } from "cheerio"
import { Express } from "express"
const app = Express()
const axi = axios()
const cheer = cheerio()
function getScheduleFromUrl() {}
my .ts component references to the function:
declare function getScheduleFromUrl(): void;
constructor(private tvScheduleService: TvScheduleService) {
getScheduleFromUrl()
}
finally the reference in angular.json:
"src/assets/js/web-scrape-tv-schedule.js"]
Couldnt find a working example of this.
again: using .js function within my .ts component, while the .js file contains some exports

Invariant Violation: fetch is not found globally and no fetcher passed, to fix pass a fetch for your environment

I'm trying to run a NodeJS app with an AWS Lambda handler. My package.json is very simple:
...
"dependencies": {
"aws-appsync": "^4.1.7",
"aws-sdk": "^2.1202.0",
"graphql-tag": "^2.12.6"
}
When I try to run anything I get:
Invariant Violation:
fetch is not found globally and no fetcher passed, to fix pass a fetch for
your environment like https://www.npmjs.com/package/node-fetch.
For example:
import fetch from 'node-fetch';
import { createHttpLink } from 'apollo-link-http';
const link = createHttpLink({ uri: '/graphql', fetch: fetch });
at new InvariantError (/Users/jamesdaniels/Code/node_modules/ts-invariant/lib/invariant.js:16:28)
at Object.exports.checkFetcher (/Users/jamesdaniels/Code/node_modules/apollo-link-http-common/lib/index.js:65:15)
at Object.createHttpLink (/Users/jamesdaniels/Code/node_modules/apollo-link-http/lib/bundle.umd.js:47:30)
at Object.exports.createAppSyncLink (/Users/jamesdaniels/Code/node_modules/aws-appsync/lib/client.js:144:201)
at new AWSAppSyncClient (/Users/jamesdaniels/Code/node_modules/aws-appsync/lib/client.js:214:72)
at Object.<anonymous> (/Users/jamesdaniels/Code/utils/appsync.js:16:23)
The error appears to be with the aws-appsync package. The error only occurs when I introduce that to my app:
const AWS = require("aws-sdk") // Works fine
const AUTH_TYPE = require("aws-appsync").AUTH_TYPE;
const AWSAppSyncClient = require("aws-appsync").default;
// GraphQL client config
const appSyncClientConfig = {
url: "https://xxxxxxxxxxxxxxxxx.appsync-api.eu-west-2.amazonaws.com/graphql",
region: "eu-west-2",
auth: {
type: AUTH_TYPE.AWS_IAM,
credentials: AWS.config.credentials,
},
disableOffline: true,
};
// Initialise the AppSync client
const appSyncClient = new AWSAppSyncClient(appSyncClientConfig);
An error is thrown from dependent modules aws-appsync > apollo-link-http > apollo-link-http-common.
Turns out the error message was telling me exactly what I needed to know. aws-appsync isn't designed for a back-end environment. It's intended for front-end environments, where fetch is available globally. In the back-end we need to create our own global variable for our own fetch if we want it to be available for any node packages that we've installed.
The solution is to download node-fetch and then follow the instructions in the "Provide Global Access" section:
Providing global access
To use fetch() without importing it, you can patch the global object in node:
// fetch-polyfill.js
import fetch, {
Blob,
blobFrom,
blobFromSync,
File,
fileFrom,
fileFromSync,
FormData,
Headers,
Request,
Response,
} from 'node-fetch'
if (!globalThis.fetch) {
globalThis.fetch = fetch
globalThis.Headers = Headers
globalThis.Request = Request
globalThis.Response = Response
}
// index.js
import './fetch-polyfill'
// ...

Firebase Cloud functions - Failed to load function definition from source: Restful Endpoints - Failed to add the endpoint defined

I am using firebase cloud functions with typescript in node 16.14.
My index.ts look like this:
import { FunctionParser } from "firebase-backend";
exports = new FunctionParser({rootPath: __dirname, exports,
verbose:true}).exports;
Here is the addEvent.endpoint.ts:
import { Request, Response } from "express";
import { Endpoint, RequestType } from "firebase-backend";
// import * as functions from "firebase-functions";
const fs = require('firebase-admin');
const serviceAccount = require('./key.json');
fs.initializeApp({
credential: fs.credential.cert(serviceAccount)
});
const db = fs.firestore();
export default new Endpoint(
"addEvent",
RequestType.POST,
(request: Request, response: Response) => {
const message = request.body["message"];
db.collection("events").doc("adkakjagjh").set("message", message);
return response.status(201).send({
message: message
});
}
)
I have the following file structure as below.
My cloud functions worked just recently but some change that I am not aware of has made them error out with the following error for just this 1 endpoint "addEvent.endpoint.ts": Error: Failed to load function definition from source: Failed to generate manifest from function source: Error: Restful Endpoints - Failed to add the endpoint defined in C:/Development/EventFeeder/Backend/Firebase/functions/lib/users/restful/addEvent.endpoint.js to the users Api.
How can I fix this issue?
I am not sure what I need to try because the error message is not that specific about the problem's root cause.
I did not find any post about this particular problem.
I try to run the functions with "npm run build && firebase emulators:start --only functions" and "firebase emulators:start"
The issue disappear when I remove the addEvent.endpoint.ts file
I was facing the same problem, and I figured out that you shouldn't initialize the app (initializeApp()) in each endpoint, just write it in the index.ts one time and everything will work as expected.

Firebase getAuth() throws error getProvider of undefined but can access database

I have the following code running on a Node server.
import admin from 'firebase-admin';
import {getAuth} from 'firebase/auth';
class MyFirebase {
constructor() {
console.log("MyFirebase Constructor");
this.firebaseApp = admin.initializeApp({
credential: admin.credential.cert("PATH_TO_CERT/cert.json"),
databaseURL: "https://DATABASE_URL",
});
console.log("App name="+firebaseApp.name);
this.defaultAuth = getAuth(firebaseApp);
this.database = this.firebaseApp.database();
// database ref code here...
}
}
and it throws the following error:
return app.container.getProvider(name);
TypeError: Cannot read property 'getProvider' of undefined
If I remove "firebaseApp" from the getAuth(..) call I get this error:
No Firebase app '[DEFAULT'] has been created - call Firebase
App.initializeApp() (app/no-app)
However the "console.log("App Name...")" line produces:
App name=[DEFAULT]
So clearly a DEFAULT app has been created. Additionally if I remove the "getAuth..." call the database calls pulling data from the realtime database below it work just fine, which seem to imply the authentication worked properly because I can access data from the database.
What the heck is going on?
You are confusing Firebase Admin SDK (Node.js) with Firebase Javascript SDK. The former is for the back-end, while the latter is for the front-end. I understand your confusion because the front-end package/s are installable via NPM, although they are meant to be bundled with front-end code.
You can't do this:
import admin from 'firebase-admin' // back-end code
import { getAuth } from 'firebase/auth' // front-end code !!!
const adminApp = admin.initializeApp(...)
getAuth(adminApp) // TypeScript actually catches this error
/*
Argument of type 'App' is not assignable to parameter of type 'FirebaseApp'.
Property 'automaticDataCollectionEnabled' is missing in type 'App' but required in type 'FirebaseApp'.ts(2345)
app-public.d.ts(92, 5): 'automaticDataCollectionEnabled' is declared here.
const adminApp: admin.app.App
*/
If you are on the back-end, just use adminApp.auth() to get the Auth instance. If on the front-end, you need to call getAuth with the front-end Firebase App instance:
import { initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'
const app = initializeApp(...)
const auth = getAuth(app)
The new modular apis have a slightly different syntax. The following should still work if you wrap it in a class, but as long as you only do this once at the top of your express? server you shouldn't need to use a class.
Also, I'm using the require syntax but imports should work too depending on your setup.
//Import each function from the correct module.
const { initializeApp, applicationDefault } = require("firebase-admin/app");
const { getAuth } = require("firebase-admin/auth");
const { getDatabase } = require("firebase-admin/database");
const app = initializeApp({
credential: applicationDefault(), //Don't forget to export your configuration json https://firebase.google.com/docs/admin/setup
databaseURL: "https://DATABASE_URL",
});
const auth = getAuth(app)
const database = getDatabase(app)
It's not super well documented but you can find hints in the Admin SDK reference: https://firebase.google.com/docs/reference/admin/node/firebase-admin.auth
One tip: In VSCode you should see the a description of each function when you hover over them, if you have the import path formatted correctly.

How do I fix "unexpected token 'export'" error when I try to use uuid package?

I'm working in a vue.js application with node.js in the backend. We've installed the npm package uuid in the backend but it's not working.
Our package.json file in the backend contains this:
"uuid": "^8.2.0",
In our controller, in the constructor, we have this:
this.uuid = require("uuid");
And we use it like this:
const id = this.uuid.v1();
The problem is, when we call the endpoint on the backend, we get this error:
C:\...\backend\node_modules\uuid\dist\esm-browser\index.js:1
export { default as v1 } from './v1.js';
^^^^^^
SyntaxError: Unexpected token 'export'
Googling this issue, the only solutions I've found involve importing v1 specifically, such as this:
import {v1 as uuid} from "uuid";
But since we're using node.js on the backend, we get this error:
SyntaxError: Cannot use import statement outside a module
How can I solve this problem?
I have been there. Used this approach:
const uuid = require('uuid');
const newUuid = uuid.v4();
You may use .v1() instead of .v4().
You should first export your functions (that you need in other modules) in v1.js like below-
function xyz() {
}
module.exports = xyz;
You can then use this in the respective files as-
const xyz = require(‘../pathname’);

Resources