I want to run my test by i'm getting errors related to SharedElement component from react-navigation-shared-element
My mocks are this:
jest.mock('react-native-shared-element', () => {
return () => ({});
});
jest.mock('react-navigation-shared-element', () => {
return () => ({
createSharedElementStackNavigator: jest.fn(),
});
});
When I run my tests:
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Related
effector throws error ".use argument should be a function" at getCurrent (node_modules/effector/effector/region.ts:27:5) on attach method while testing.
I'm trying integration testing with mocking of some initial state.
//babel config
module.exports = (api) => {
if (api.env('test')) {
config.plugins.push([
'module-resolver',
{
root: ['.'],
alias: {
effector-react: 'effector-react/scope',
},
},
]);
}
return config;
};
//store.ts
export const getUsersFx = attach({
effect: getUsersOriginalFx,
source: [$clientId],
mapParams: (_, [clientId]) => ({
clientId
}),
});
//component.tsx
import { render } from '#testing-library/react';
import { Provider } from 'effector-react/scope'
describe('TestableComponent', () => {
test('should increment counter after click', () => {
const scope = fork()
const rendered = render(
<Provider value={scope}>
<TestableComponent />
</Provider>
);
})
})
I think the reason is that Effector mocks Effect and under the hood uses .use for effect callback mock. But then it change it to null or undefined and Effector throws error that fn in .use(fn) must be function
Effector mocks getUsersFx => getUsersFx.use(mockFn <- it's undefined i think).
Effector version: 22
Looks like the reason is multiple passes of effector/babel-plugin which you using for tests - error with attach is similiar:
https://github.com/effector/effector/issues/601
Multiple passes of babel-plugin will be supported in the next minor release of effector - for now you can check your babel configuration for duplicated usage of effector/babel-plugin
I'm mocking expo and the Permissions module, but when calling Permissions.AskAsync Permissions is undefined.
Problem looks like this question. Using Jest to mock named imports
Used the provided answer, but did not work.
I have mocked the axios, which works. Doing the same for the expo module does not work.
The function I want to test:
checkPermission = async () => {
const {statusCamera} = await Permissions.askAsync(Permissions.CAMERA);
// console.log(statusCamera);
this.setState({cameraPermission: statusCamera});
const {statusCameraRoll} = await Permissions.askAsync(Permissions.CAMERA_ROLL);
this.setState({cameraRollPermission: statusCameraRoll});
};
The test:
describe("Test the Permission function", () => {
it('should return rejected permission.', async function () {
const wrapper = shallow(<Photo2/>);
const instance = wrapper.instance();
await instance.checkPermission();
expect(instance.state("cameraPermission")).toBeFalsy();
});
});
The mock I use for expo:
jest.mock('expo', ()=>({
Permissions: {
askAsync: jest.fn()
}
}))
and tried
(In file mocks/expo.js)
export default {
Permissions: {
askAsync: jest.fn(() => {
return "SOMETHING"
})
}
}
and tried
(In file mocks/expo.js)
jest.mock('expo', ()=>({
Permissions: {
askAsync: jest.fn()
}
}));
Error: "TypeError: Cannot read property 'askAsync' of undefined"
This error occures on line where Permissions.askAsyc is called. So Permissions is undefined. (Also checked it with console.log(Permissions)
I expected the instance.state("cameraPermission") to be falsy, but it crashes before it comes to that line.
Since expo change the packages to be import * as Permissions from 'expo-permissions';
You just need to create "mocks/expo-permissions.js" and have it has:
export const getAsync = jest.fn(permissions => Promise.resolve());
export const askAsync = jest.fn(permissions => Promise.resolve());
teerryn's answer is correct and is a good start. To add some more details:
Unless you've configured different roots for Jest, you should place your mock file in __mocks__/expo-permissions.js where __mocks__ is a directory at the same level as your node_modules folder. See Jest docs on mocking node modules.
The permissions argument being passed in will be undefined due to the way we're mocking the module, so you'll need to mock the permission types you want to use. Just need something simple like export const CAMERA_ROLL = 'camera_roll';
If you want to respond differently based on the permission type passed in (for example, allow Permissions.CAMERA but deny Permissions.CAMERA_ROLL and all other types), you can mock the implementation of the askAsync function. For example, your __mocks__/expo-permissions.js file would look like this:
export const CAMERA = 'camera';
export const CAMERA_ROLL = 'camera_roll';
export const askAsync = jest.fn().mockImplementation((permissionType) => {
const responseData = permissionType === CAMERA ? { status: 'granted' } : { status: 'undetermined' }; // you could also pass `denied` instead of `undetermined`
return Promise.resolve(responseData);
});
The problem is that you are handling async tests incorrectly (your checkPermission() function is async). There are several ways you can tell jest that you want to test an async function. Here are a few ways.
Here is a quick solution to your problem:
...
import { Permissions } from 'expo';
...
jest.mock('expo', () => ({
Permissions: {
askAsync: jest.fn(),
}
}));
...
describe("Test the Permission function", () => {
it('should return rejected permission.', () => {
Permissions.askAsync.mockImplementation( permission => { return {status: 'granted'}; } ); // if you want to add some sort of custom functionality
const wrapper = shallow(<Photo2/>);
const instance = wrapper.instance();
return instance.checkPermission().then(data => {
expect(instance.state("cameraPermission")).toBeFalsy();
});
});
});
I am trying to use this techniqe. In short I am trying code splitting with auto-registered dynamically imported Vue components. My file structure is js/utils/vue.js and js/components/***.vue.
This is how my Vue components are loaded:
const files = require.context('../components', true, /\.vue$/i, 'lazy').keys();
files.forEach(file => {
Vue.component(file.split('/').pop().split('.')[0], () => import(`${file}`));
});
But it results in an error:
[Vue warn]: Failed to resolve async component: function () {
return webpack_require("./resources/js/utils lazy recursive ^.*$")("".concat(file));
}
Reason: Error: Cannot find module './MainNavbar.vue'
Manually registering the component, while still using dynamic import works.
Vue.component('main-navbar', () => import('../components/MainNavbar.vue'));
Why am I receiving this error?
edit:
I found something here that works for me:
const files = require.context('./', true, /\.vue$/i, 'lazy').keys();
files.forEach(file => {
Vue.component(file.split('/').pop().split('.')[0], () => import(`${file}`));
});
Judging from the error message, your expression () => import(${file}) needs to prepend the context path, since you're not referencing that like in () => import('../components/MainNavbar.vue')
so maybe something like
const componentName = key.split('/').pop().split('.')[0]
Vue.component(file.split('/').pop().split('.')[0], () => import(`../components/${file}`));
works?
When I run npm test:
➜ mobile git:(develop) ✗ npm test
> jest
FAIL __tests__/index.js
● Test suite failed to run
TypeError: Cannot read property 'fs' of undefined
at Object.<anonymous> (node_modules/react-native-cached-image/utils/fsUtils.js:9:12)
at Object.<anonymous> (node_modules/react-native-cached-image/ImageCacheManager.js:5:13)
at Object.<anonymous> (node_modules/react-native-cached-image/CachedImage.js:13:23)
I see it's related to react-native-cached-image dependency on fs.
Do I have to mock fs somehow? I tried couple of things but wasn't successful.
Mocking components using fs
Instead of mocking fs I would recommend you to mock react-native-image-cache if possible because fs is used by one of the dependencies of that package. You can see the line listed in you're error.
You can just mock react-native-image-cache like the following:
jest.mock('react-native-img-cache', () => {
return {
DocumentDir: () => {},
ImageCache: {
get: {
clear: () => {}
}
}
}
})
In the same matter it should be possible to mock react-native-fetch-blob which is using fs and causing the error. The properties on the return statement depend on the methods and properties that are used by image-cache lib. Probably you don't need as much as listed below but now you know that there could be more than fs.
jest.mock('react-native-fetch-blob', () => {
return {
DocumentDir: () => {},
fetch: () => {},
base64: () => {},
android: () => {},
ios: () => {},
config: () => {},
session: () => {},
fs: {
dirs: {
MainBundleDir: () => {},
CacheDir: () => {},
DocumentDir: () => {},
},
},
wrap: () => {},
polyfill: () => {},
JSONStream: () => {}
}
})
Mocking fs
In case you want/need to mock fs specifically, you could do the following:
Study the tests used by the library react-native-cached-image
Use one of the npm packages for mocking fs: mock-fs, jest-plugin-fs or fake-fs
Do it yourself
Sometimes it's even possible to do something like that:
fs = require("fs")
fs.readFile = function (filename, cb) {
cb(null, new Buffer("fake contents");
};
// etc
But keep in mind that fs is used somewhere in an dependent package. In that case I'm not sure if the code works properly and this is why I put the other options at the top.
I have two async requests, want to write a epic do the job like promise.all()
const fetchData1 = () => (action$: ActionsObservable<any>, store: any) => (
ajax.getJSON('../../mockData/promiseAll/data1.json').map((data: any) => {
return requestData1Success(data);
})
);
const fetchData2 = () => (action$: ActionsObservable<any>, store: any) => (
ajax.getJSON('../../mockData/promiseAll/data2.json').map((data: any) => {
return requestData2Success(data);
})
)
const requestAllDataEpic = (action$: ActionsObservable<any>, store: any) => {
return action$.ofType(t.REQUEST_ALL_DATA)
.map((action) => action.payload)
.switchMap((names: string[]) => {
console.log(names);
return Observable.forkJoin([
fetchData1()(action$, store),
fetchData2()(action$, store)
])
.map((results: any[]) => {
const [action1, action2] = results;
requestData1Success(action1);
requestData2Success(action2);
});
});
};
But when I dispatch the action, the console give me an error:
Uncaught TypeError: Cannot read property 'type' of undefined
I think the reason is I do not give the middleware an action object, but undefined.
How can I do this correctly?
In the provided example, you are not actually returning your two actions, you're returning nothing:
.map((results: any[]) => {
const [action1, action2] = results;
// v----- not returning either of these
requestData1Success(action1);
requestData2Success(action2);
});
map can't used to emit two actions sequentially because it's 1:1 not 1:many (mergeMap, switchMap, concatMap, etc are 1:many). However, in your example you are already converting the responses to the actions inside your fetchData helpers--doing it again would wrap an action inside another action, not what you want. This looks like a bug when you were refactoring.
Other than that, it's actually not clear what you intended to do. If you have further questions you'll need to describe what you want you'd like to achieve.