Cannot read property 'functionName' of undefined - javascript

I am working on a react native project where I am trying to retrieve an array of json objects. I am currently using the fetch function like so:
//******************* require in root App.js ***********
global.fetch = require('isomorphic-fetch');
//******************* API.js *************************
import fetch from 'isomorphic-fetch';
const api = {
getData() {
const url = 'http://.php?route=users';
return fetch(url).then((res) => res.json());
}
};
export { api };
//****************** dataRetrieval.js *********************
//imports
import api.js form './filepath.js';
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
error: '',
loading: false,
users: []
};
}
componentDidMount() {
api.getData(this).then((res) => {
this.setState({ users: res.getData });
});
}
Project Dependencies:
"dependencies": {
"axios": "^0.18.0",
"eslint-config-rallycoding": "^3.2.0",
"isomorphic-fetch": "^2.2.1",
"node-fetch": "^2.2.0",
"npm": "^6.4.1",
"react": "16.4.1",
"react-native": "0.56.0",
"react-native-fetch": "^2.0.0",
"react-navigation": "^2.12.1",
"unfetch": "^3.1.1"
},
When I try and run the simulator I recieve an error saying that my getData() function is undefined and cannot be read.

You're incorrectly using export/import.
Either use export default api in your API.js file, or use import { api } from './filepath.js' in your dataRetrieval.js file.

Then, Adding the upper answer, you should write the .catch.
it's not relevance your error, but have to get into the habit.
import fetch from 'isomorphic-fetch';
const api = {
getData() {
const url = 'http://.php?route=users';
return fetch(url)
.then((res) => res.json())
.catch(err=> console.log(err)
}
};
You can check for this

Related

ReferenceError: exports is not defined in ES module scope

I am new in typescript, when I compiled code it compiled properly but when I run program using node
I got this error ReferenceError: exports is not defined in ES module scope
ReferenceError: exports is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and 'D:\projects\pro8\package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
at file:///D:/projects/pro8/await.js:40:1
at ModuleJob.run (node:internal/modules/esm/module_job:185:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:281:24)
at async loadESM (node:internal/process/esm_loader:88:5)
at async handleMainPromise (node:internal/modules/run_main:65:12)
typescript code
import fetch from "node-fetch";
const baseApi = "https://reqres.in/api/users?page=1";
const userApi = "https://reqres.in/api/user";
interface Employee {
id: number
employee_name: string
employee_salary: number
employee_age: number
profile_image: string
}
const fetchAllEmployees = async (url: string): Promise<Employee[]> => {
const response = await fetch(url);
const { data }:any = await response.json();
return data;
};
const fetchEmployee = async (url: string, id: number): Promise<Record<string, string>> => {
const response = await fetch(`${url}/${id}`);
const { data }:any = await response.json();
return data;
};
const generateEmail = (name: string): string => {
return `${name.split(" ").join(".")}#company.com`;
};
const runAsyncFunctions = async () => {
try {
const employees = await fetchAllEmployees(baseApi);
Promise.all(
employees.map(async user => {
const userName = await fetchEmployee(userApi, user.id);
const emails = generateEmail(userName.name);
return emails;
})
);
} catch (error) {
console.log(error);
}
};
runAsyncFunctions();
package.json
{
"name": "pro8",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#typescript-eslint/eslint-plugin": "^5.21.0",
"#typescript-eslint/parser": "^5.21.0",
"eslint": "^8.14.0",
"eslint-config-standard": "^17.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-n": "^15.2.0",
"eslint-plugin-promise": "^6.0.0"
},
"dependencies": {
"#types/node-fetch": "^2.6.1",
"node-fetch": "^3.2.4"
}
}
I tried to solve this error ts An async function or method in ES5/ES3 requires the 'Promise' constructor
any answer not working in my case
so please give me solution if any
Try and remove "type": "module" from package.json. I had this issue before and it seemed to do the trick.

Error Mocking Firebase Admin in Jest: "TypeError: admin.firestore is not a function"

I have a function to handle connecting to Cloud Firestore through the Admin SDK. I know the function works fine, as the app connects and allows writing to the database.
Now I am trying to test this function with Jest. To avoid testing outside the scope of this function, I am mocking the firebase-admin Node module. However, my test is failing with the error "TypeError: admin.firestore is not a function".
My function and tests are both written in TypeScript, run via ts-jest, but I don't think this is a TypeScript error, as VS Code has no complaints. I believe this is an issue with Jest's automatic mocking.
admin.firebase() is a valid call. The TypeScript definition file defines it as function firestore(app?: admin.app.App): admin.firestore.Firestore;
I've read over the Jest docs, but I'm not understanding how to fix this.
This is my function:
// /src/lib/database.ts
import * as admin from "firebase-admin"
/**
* Connect to the database
* #param key - a base64 encoded JSON string of serviceAccountKey.json
* #returns - a Cloud Firestore database connection
*/
export function connectToDatabase(key: string): FirebaseFirestore.Firestore {
// irrelevant code to convert the key
try {
admin.initializeApp({
credential: admin.credential.cert(key),
})
} catch (error) {
throw new Error(`Firebase initialization failed. ${error.message}`)
}
return admin.firestore() // this is where it throws the error
}
Here is my test code:
// /tests/lib/database.spec.ts
jest.mock("firebase-admin")
import * as admin from "firebase-admin"
import { connectToDatabase } from "#/lib/database"
describe("database connector", () => {
it("should connect to Firebase when given valid credentials", () => {
const key = "ewogICJkdW1teSI6ICJUaGlzIGlzIGp1c3QgYSBkdW1teSBKU09OIG9iamVjdCIKfQo=" // dummy key
connectToDatabase(key) // test fails here
expect(admin.initializeApp).toHaveBeenCalledTimes(1)
expect(admin.credential.cert).toHaveBeenCalledTimes(1)
expect(admin.firestore()).toHaveBeenCalledTimes(1)
})
})
Here are my relevant (or possibly relevant) package.json (installed with Yarn v1):
{
"dependencies": {
"#firebase/app-types": "^0.6.0",
"#types/node": "^13.13.5",
"firebase-admin": "^8.12.0",
"typescript": "^3.8.3"
},
"devDependencies": {
"#types/jest": "^25.2.1",
"expect-more-jest": "^4.0.2",
"jest": "^25.5.4",
"jest-chain": "^1.1.5",
"jest-extended": "^0.11.5",
"jest-junit": "^10.0.0",
"ts-jest": "^25.5.0"
}
}
And my jest config:
// /jest.config.js
module.exports = {
setupFilesAfterEnv: ["jest-extended", "expect-more-jest", "jest-chain"],
preset: "ts-jest",
errorOnDeprecated: true,
testEnvironment: "node",
moduleNameMapper: {
"^#/(.*)$": "<rootDir>/src/$1",
},
moduleFileExtensions: ["ts", "js", "json"],
testMatch: ["<rootDir>/tests/**/*.(test|spec).(ts|js)"],
clearMocks: true,
}
Your code looks good. jest.mock mocks all the methods of the library and, by default, all of them will return undefined when called.
Explanation
The problem you are seeing is related to how the firebase-admin module methods are being defined.
In the source code for firebase-admin package, the initializeApp method is being defined as a method in the FirebaseNamespace.prototype:
FirebaseNamespace.prototype.initializeApp = function (options, appName) {
return this.INTERNAL.initializeApp(options, appName);
};
However, the firestore method is being defined as a property:
Object.defineProperty(FirebaseNamespace.prototype, "firestore", {
get: function () {
[...]
return fn;
},
enumerable: true,
configurable: true
});
It seems that jest.mock is able to mock the methods declared directly in the prototype (that's the reason why your call to admin.initializeApp does not throw an error) but not the ones defined as properties.
Solution
To overcome this problem you can add a mock for the firestore property before running your test:
// /tests/lib/database.spec.ts
import * as admin from "firebase-admin"
import { connectToDatabase } from "#/lib/database"
jest.mock("firebase-admin")
describe("database connector", () => {
beforeEach(() => {
// Complete firebase-admin mocks
admin.firestore = jest.fn()
})
it("should connect to Firebase when given valid credentials", () => {
const key = "ewogICJkdW1teSI6ICJUaGlzIGlzIGp1c3QgYSBkdW1teSBKU09OIG9iamVjdCIKfQo=" // dummy key
connectToDatabase(key) // test fails here
expect(admin.initializeApp).toHaveBeenCalledTimes(1)
expect(admin.credential.cert).toHaveBeenCalledTimes(1)
expect(admin.firestore).toHaveBeenCalledTimes(1)
})
})
Alternative solution
Since the previous solution did not work for you, I'll suggest an alternative solution. Instead of assigning the value of the firestore method you can define the property so that it returns a mocked function.
To simplify the mock, I would create a little helper mockFirestoreProperty in your test file:
// /tests/lib/database.spec.ts
import * as admin from "firebase-admin"
import { connectToDatabase } from "#/lib/database"
jest.mock("firebase-admin")
describe("database connector", () => {
// This is the helper. It creates a mock function and returns it
// when the firestore property is accessed.
const mockFirestoreProperty = admin => {
const firestore = jest.fn();
Object.defineProperty(admin, 'firestore', {
get: jest.fn(() => firestore),
configurable: true
});
};
beforeEach(() => {
// Complete firebase-admin mocks
mockFirestoreProperty(admin);
})
it("should connect to Firebase when given valid credentials", () => {
const key = "ewogICJkdW1teSI6ICJUaGlzIGlzIGp1c3QgYSBkdW1teSBKU09OIG9iamVjdCIKfQo=" // dummy key
connectToDatabase(key) // test fails here
expect(admin.initializeApp).toHaveBeenCalledTimes(1)
expect(admin.credential.cert).toHaveBeenCalledTimes(1)
expect(admin.firestore).toHaveBeenCalledTimes(1)
})
})
It works properly to combine your own mocks with its auto-mocks when you initially mock it, i.e.:
jest.mock('firebase-admin', () => ({
...jest.mock('firebase-admin'),
credential: {
cert: jest.fn(),
},
initializeApp: jest.fn(),
firestore: jest.fn(),
}));

I am trying to run my test script using mocha but there is an error of "Reference Error: beforeEach is not defined"

Mocha test Suite gives a reference error and it says "beforeEach is not defined"
I am trying to run my test script for my todo app in node.js using mocha. But there is a reference error and it says "beforeEach is not defined"
const {app} = require('./../server');
const {Todo} = require('./../models/todo');
beforeEach((done) => {
Todo.remove({}).then(() => done());
});
describe('POST /todos', () => {
it('should create a new todo', (done) => {
var text = 'Test todo text';
request(app)
.post('/todos')
.send({text})
.expect(200)
.expect((res) => {
expect(res.body.text).toBe(text);
})
.end((err, res) => {
if (err) {
return done(err);
}
Todo.find().then((todos) => {
expect(todos.length).toBe(1);
expect(todos[0].text).toBe(text);
done();
}).catch((e) => done(e));
});
});
it('should not create todo with invalid body data', (done) => {
request(app)
.post('/todos')
.send({})
.expect(400)
.end((err, res) => {
if (err) {
return done(err);
}
Todo.find().then((todos) => {
expect(todos.length).toBe(0);
done();
}).catch((e) => done(e));
});
});
});
Also, I have included all the necessary packages for my package.json file.
My Package.json file is given below
{
"name": "todo-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "mocha server/**/*.test.js",
"test-watch": "nodemon --exec 'npm test' "
},
"author": "",
"license": "ISC",
"dependencies": {
"bluebird": "^3.5.3",
"body-parser": "^1.15.2",
"express": "^4.14.0",
"mongodb": "^2.2.5",
"mongoose": "^4.5.9"
},
"devDependencies": {
"expect": "^1.20.2",
"mocha": "^3.0.2",
"nodemon": "^1.10.2",
"supertest": "^2.0.0"
}
}
It looks to me like you are trying to clear out your data in your MongoDB database before each new test of your todo app. So you want to find your collection of todo and drop everything in there before your next test, if so
beforeEach(() => {
mongoose.connection.collections.todo
});
With the above you are directly referencing the collection of todo sitting inside your database and you call the drop() function on your collection of todo.
beforeEach(() => {
mongoose.connection.collections.todo.drop();
});
Please let me know if I am correct in fulfilling your requirement. Keep in mind this is an asynchronous operation, so you need to ensure you pause the entire testing environment until the operation is complete, but you already know this, because you have already attempted to implement the done callback.
Also, drop() will accept a callback function like so:
beforeEach((done) => {
mongoose.connection.collections.todo.drop(() => {});
});
The function will only be executed once you are done with the collection. So you also have to pass the done() callback after defining it like so:
beforeEach((done) => {
mongoose.connection.collections.todo.drop(() => {
done();
});
});
Also, when you run a Mocha test, you do npm run test.
I've just tried to replicate your issue with the test with simple repository using your package.json file. My test file
const expect = require('expect');
beforeEach((done) => {
done();
});
describe('just a test', function() {
it('test', function() {
expect(true).toBe(true);
})
});
Then, when running npm t, the test was executed successfully.
Perhaps there is a misconfiguration in your project.

React-Native app doesn't work if i use await

This is the first time I'm using react-native to develop an Android app.
I'm trying to use async/await when I retrieve some data from firestore, but when I add the word await the app crashes and it won't start anymore.
I use react-native-firebase library as you can see in my package.json file.
This is the part of my component that doesn't work:
componentDidMount() {
this.getAccountFromFirestore(this.props.user);
}
getAccountFromFirestore = async user => {
const accounts = await firebase
.firestore()
.collection('accounts')
.get();
this.setState({ loading: false });
};
This is my package.json, if it's usefull
{
"name": "myapp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest",
"ios": "react-native run-ios",
"android": "react-native run-android"
},
"dependencies": {
"native-base": "^2.8.1",
"react": "16.6.1",
"react-native": "0.57.6",
"react-native-firebase": "^5.1.1",
"react-native-navigation": "^1.1.493",
"react-native-vector-icons": "^6.1.0",
"react-redux": "^5.1.1",
"redux": "^4.0.1"
},
"devDependencies": {
"babel-jest": "23.6.0",
"jest": "23.6.0",
"metro-react-native-babel-preset": "0.49.2",
"react-test-renderer": "16.6.1"
},
"jest": {
"preset": "react-native"
}
}
You can implement with Promise like :
firebase
.firestore()
.collection('accounts')
.get()
.then(accounts => {
console.log ('Use accounts variable as per your requirement,'accounts)
})
.catch(error => {console.error(error)})
I don't know whether it's your React Native or if you're using Node 6. But for what I know, async/await is only supported on Node 8 or above. So, your best bet is still using Promises with this problem. For example:
componentDidMount() {
this.getAccountFromFirestore(this.props.user);
}
getAccountFromFirestore = user => {
firebase
.firestore()
.collection('accounts')
.get()
.then(accounts => {
let data = accounts.docs.map(account => account.data());
console.log(data);
this.setState({ loading: false });
})
.catch(err => console.log(err));
};
Also when using async/await, don't forget the try-catch blocks:
componentDidMount() {
this.getAccountFromFirestore(this.props.user);
}
getAccountFromFirestore = async user => {
try {
const accounts = await firebase
.firestore()
.collection('accounts')
.get();
const data = accounts.docs.map(a => a.data());
console.log(data);
this.setState({ loading: false });
} catch (err) {
console.error(err);
}
};
Option a) keep using promises
Option b) Migrate that RN, if you can use async/await your code is prob too old to go in the stores anyway.
Option c) Babel...

Why is my Mocha/Chai test giving a false positive?

As a pre-cursor to this question, I am a novice at Node, JS, Mocha and Chai!
I have a set of tests which I run using npm run start, in which 'start' defines a script within my Package.json file:
"devDependencies": {
"chai": "^3.5.0",
"chai-as-promised": "^7.1.1",
"cli-color": "^1.1.0",
"concurrently": "^3.1.0",
"mocha": "^5.2.0"
},
"dependencies": {
"body-parser": "^1.16.1",
"cors": "^2.8.1",
"express": "^4.14.0",
"moment": "^2.18.1",
"superagent": "^3.3.2"
}
Here is my test:
const expect = require('chai').expect;
const screenshotFolder = 'puppeteer/test/screenshots';
module.exports = async(page) => {
const frame = page.frames().find(frame => frame.name() === 'iframe');
const allChoicesButton = await frame.$('.statement a.all-choices');
await allChoicesButton.click({});
const saveYourChoicesButton = await frame.$('.button.permissions-block__submit');
await saveYourChoicesButton.click({});
try {
const confirmationMessageText = await frame.$eval('.submission-response__copy > p', e => e.textContent);
describe('User can choose all', function() {
it('Click choose all and display a confirmation message', function(done) {
expect(confirmationMessageText).to.equal('Thank you. Your choices have been updatedx.').
notify(done)
});
});
} catch (err) {
await page.screenshot({
path: screenshotFolder + '/confirmationMessageText.png',
fullPage: true
});
}
};
I have purposefully added an 'x' to 'updatedx' so it fails....only it passes. So, I'm sure this has been asked 100 times but I'm unclear as to why it is passing and also why the screenshot is printed, given that an error is not thrown.
Thanks in advance.
I've realised the error now, swapped frame.$eval with frame.$ and this has resolved the issue.

Categories

Resources