In my Saga test for my react native application (that does work correctly) I have added the following test that calls a function that perform a POST http call (doScan).
describe('Scan the product and register the scanning action', () => {
const it = sagaHelper(scanProductSaga(scanProductAction(item)));
it('logscan via ASL', (result) => {
expect(result).toEqual(cps(ASLogger.logScan, xxx));
return logScanResult;
});
it('should register the product', (result) => {
expect(result).toEqual(call(doScan, logScanResult));
});
});
Separate file:
const doScan = scanObj =>
toJSON(fetch('https://xxxx.xxxxxx.com/logger/scans', {
method: 'POST',
headers: new Headers(CONTENT_TYPE_HEADERS),
body: JSON.stringify(scanObj),
}));
Note: the fetch function is from 'react-native-interfaces.js' within the react-native library. The test fails and the error is caused by the following exception :
ReferenceError: fetch is not defined
at doScan (/Users/andy/WebstormProjects/ASAP/api/index.js:81:11)....
What can cause such issue? What the solution may be?
react-native has fetch default, but test environment on node.js does not have fetch.
You can import fetch like following at the top of test code.
const fetch = require('node-fetch')
The file react-native-interface.js only declare the type of fetch.
declare var fetch: any;
For some cases, in a universal application for both, client and server the maintainers have to use isomorphic-fetch module to their Node project because of Node does not contain Fetch API yet. For more information read this question and answer
But in this special case, hence, React Native, it is some different, Because, in the mobile device area, there is no V8, SpiderMonkey or Node. There is JavaScriptCore. So, for this new situation should be used react-native-fetch.
It is a little different, install it with below code:
npm install react-native-fetch
And then, use it like a JSX component:
import Fetch from 'react-native-fetch'
...
<Fetch
url="https://jsonplaceholder.typicode.com/posts/1"
retries={3}
timeout={3000}
onResponse={async (res) => {
const json = await res.json()
console.log(json)
}}
onError={console.error}
/>
It's so new, but lovely.
Related
I'm trying to add existing backend to a new react frontend. Every time I call the API from react i get,
Uncaught (in promise) API api3ceaf69c does not exist
Client side code
function getData() {
const apiName = "api3ceaf69c";
const path = "/users";
const myInit = {
headers: {},
};
return API.get(apiName, path, myInit);
}
(async function () {
const response = await getData();
console.log(JSON.stringify(response));
})();
index.js
import { Amplify, API } from "aws-amplify";
import awsExports from "./aws-exports";
Amplify.configure(awsExports);
API.configure(awsExports);
aws-exports.json
{
"aws_cloud_logic_custom": [
{
"name": "api3ceaf69c",
"endpoint": "https://xxxxxxx.execute-api.ap-south-1.amazonaws.com/dev",
"region": "ap-south-1"
}
]
}
"aws-amplify": "^4.3.27"
Error
Error screenshot
I went through multiple answers around the same issue but none of them are working for me.
Interestingly this exact same code was working a few days back until I had to rebuild my backend due to some changes.
I thought client code used aws-exports.js to decide if the API exists. Looks like you may have checked it already. Does the xxxxxxx API from your exports file show up in the API Gateway in AWS Console? Can you invoke it from the console?
I figured out the problem finally! Issue was at the place where I'm calling Amplify.configure(aws_exports).
For some reason aws exports was not getting initialized in index.js file so I moved it closer to where I am actually calling the api, i.e. getData() function. It started working post that.
I learning redux right now, and i was making a project where i was doing a google oAuth authentication. so when i tried to use optional chaining operator i get this error.
You may need an appropriate loader to handle this file type.
| switch (_context.prev = _context.next) {
| case 0:
> result = res?.profileObj;
| token = res.tokenId;
and here is the code that is giving me the error
const googleSuccess = async (res) => {
const result = res?.profileObj;
const token = res?.tokenId;
try {
dispatch({ type: AUTH, data: { result, token } });
history.push('/');
} catch (error) {
console.log(error);
}
};
however if i remove the ? the error goes away and it works fine.
i am using react-google-login npm package and the googleSuccess function is passed as a props to the GoogleLogin component.
if someone could clarify it to me. its just that sometimes, the value am assigning might not always be there and it may crash my app, and for that since optional chaining operator wasn't working i am using ternary operator(if the value to be assigned isn't present i am just assigning null using ternary operator. (and am not sure if that is okie)).
apologies if this question is a newbie, i just wanted to clarify myself on why i cannot use ?. operator because i couldn't find answers anywhere else. ps: today was the first time i was using ?. operator
This is because webpack is not able to parse the file correctly because of the new syntax. If you have done the react-app setup from scratch using webpack . Then i suggest you to upgrade webpack . If you are using create-react-app , then you should upgrade to the latest version of CRA .
Webpack Optional Chaining Issue
I am trying to run a face detection process in the background of my React app using a web worker. I am using a library called face-api.js to do the face detection. But I'm unsure as to how to import this library to use in my worker.js file.
worker.js
import * as faceapi from 'face-api.js';
this.onmessage = (e) => {
console.log("Message from worker.js");
this.postMessage('Hello Main')
};
TestComponent.js
import React, {useEffect} from 'react'
function TestComponent() {
useEffect(() => {
const worker = new Worker('./workers/worker.js')
worker.postMessage('Hello Worker')
worker.onmessage = e => {
console.log('Message received from worker:', e.data)
}
}
);
return (
<div>
<h1> Test Component </h1>
</div>
)
}
export default TestComponent
I run this test code and I get the following error on chrome:
/workers/worker.js:1 Uncaught SyntaxError: Cannot use import statement outside a module
I have tried using require to import the library which didn't work. I also tried declaring the worker as a module
const worker = new Worker('./workers/worker.js', type: "module")
This makes the error go away but then nothing works: the worker does not do what it is intended to do.
Please point me in the right direction. Thanks in advance!
I guess you should use importScript() in your service worker file
you need to use {type:"module"} in the options of worker constructor for use "import" features in the worker file.
https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker
options Optional
An object containing option properties that can be set when creating the object instance. Available properties are as follows:
type: A DOMString specifying the type of worker to create. The value can be classic or module. If not specified, the default used is classic.
credentials: A DOMString specifying the type of credentials to use for the worker. The value can be omit, same-origin, or include. If not specified, or if type is classic, the default used is omit (no credentials required).
name: A DOMString specifying an identifying name for the DedicatedWorkerGlobalScope representing the scope of the worker, which is mainly useful for debugging purposes.
I've got some client-side code that I'd like to test with Jest. Let's narrow it down to this reproducible bit:
// fetch-example.js
const fetchExample = () => fetch('http://example.org/');
module.exports = fetchExample
Since Jest runs tests via Node and Node doesn't support fetch, the following test script
// fetch-example.test.js
const fetchExample = require('./fetch-example')
test('fetch resolves to something', () => {
expect.assertions(1);
return fetchExample().then(() => expect(true).toBe(true));
});
fails with ReferenceError: fetch is not defined. No surprises, but... fetchExample works fine in a browser and I'd like Jest to take this into account and mark the test as passed.
Is there any way to make this work? Is there any parameter I can pass to Jest to include browser functions like fetch?
NB: Jest's browser configuration entry does not make it work.
I have the following example test:
import { assert } from 'chai'
function starWarsMovies () {
fetch('http://swapi.co/api/films/')
.then((res) => {
return res.json()
})
.then((res) => res.count)
}
describe('Get star war movies', () => {
it('should get 7', () =>{
assert.equal(starWarsMovies(), 7)
})
})
But I getting
ReferenceError: fetch is not defined
What do I have to use in order to test a fetch request.
UPDATE
I also tried:
import { polyfill } from 'es6-promise'
import fetch from 'isomorphic-fetch'
but then I get:
AssertionError: expected undefined to equal 7
and I don't understand why.
You are probably testing your code server-side with node.js.
fetch is not a part of node, but is a web-API, you get with newer browsers and can use from JavaScript running in a browser.
You need to import node-fetch as sketched below, and it will work:
npm install node-fetch --save
and in your code:
const fetch = require("node-fetch")
...
If you are running in (an older browser not supporting fetch) and is not using a tool like webpack, you must include the polyfills from your html the old "traditional way".
Even if you use node-fetch or isomorphic-fetch the issue here is that you're checking for equality between a number and the result of a function that doesn't return anything. I was able to make this work!
describe('Get star war movies', () => {
it('should get 7', async () => {
await fetch('http://swapi.co/api/films/')
.then((res) => {
return res.json()
})
.then((res) => {
console.log(res);
assert.equal(res.count, 7)
})
})
})
Note that I'm using async await syntax here. There are lots of different ways we could do this (callbacks, promises, async/await), but the key is that in making a call out to an API we have to wait for the result. Also, the response you get from the star wars API seems to be a huge object, so I took the liberty of assuming that you were just checking for the count!