Jest-expo all tests fail after update to SDK 47 - react-native

Before update my expo project to SDK 47, all test suites worked as a charm. But now I'm getting these kind of errors that I don't know how to solve it.
I've noticed those packages are written now with TS. Maybe the error is going around this. Do I need to change something in order to make packages with TS work?
Here are the versions that I'm using:
"devDependencies": {
"#babel/core": "^7.19.3",
"#babel/plugin-proposal-optional-chaining": "^7.16.7",
"#types/react-native": "~0.70.6",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"babel-plugin-module-resolver": "^4.1.0",
"babel-preset-expo": "~9.2.1",
"concurrently": "^7.2.2",
"deprecated-react-native-prop-types": "^2.3.0",
"eslint": "^7.32.0",
"eslint-plugin-jest": "^24.7.0",
"eslint-plugin-react": "^7.29.4",
"husky": "^6.0.0",
"jest-expo": "^47.0.1",
"jest-json": "^1.1.1",
"postcss": "^8.4.14",
"react-native-jest-mocks": "^1.5.0",
"tailwindcss": "^3.1.4"
}
My jest config
"jest": {
"preset": "jest-expo",
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|unimodules-permissions-interface|react-clone-referenced-element|#react-native(-community)?|expo(nent)?|#expo(nent)?/.*|react-navigation|#react-navigation/.*|#unimodules/.*|sentry-expo|native-base|#codler/react-native-keyboard-aware-scroll-view|react-native-paper|react-native-paper/.*|expo-modules-core|expo-modules-core/.*|)"
],
"setupFiles": [
"./jest-setup.js"
],
"setupFilesAfterEnv": [
"jest-json"
]
}
Any idea? I'd aprreciate your help.
UPDATE
This is an example test.
import Home from './Home';
import React from 'react';
import {
cleanup,
render,
} from '#testing-library/react-native';
import axios from 'axios';
import { Alert } from 'react-native';
import { MockedNavigator, waitFor } from '../../../helpers/testing';
jest.mock('axios');
jest.mock('./Home', () => './Home');
const mockedNavigate = jest.fn();
jest.mock("#react-navigation/native", () => {
const actualNav = jest.requireActual("#react-navigation/native");
return {
...actualNav,
useNavigation: () => ({
navigate: mockedNavigate,
dispatch: jest.fn(),
addListener: jest.fn(),
removeListener: jest.fn(),
}),
};
});
beforeAll(() => {
// Home uses fetch to reload the user, so mock fetch to return a
// fake user
global.fetch = jest.fn().mockResolvedValue({
status: 200,
ok: true,
json: () => Promise.resolve({ data: { user: {} } }),
});
});
afterEach(cleanup);
const setup = async () => {
return render(
<MockedNavigator
routes={[
{ name: 'Home', component: Home },
]}
/>
);
};
describe('API', () => {
test('Shows error when the request can not be completed', async () => {
axios.get.mockRejectedValue({
response: { data: undefined, status: 500 },
});
// Mock alert
Alert.alert = jest.fn();
await setup();
await waitFor(() => {
expect(Alert.alert).toHaveBeenCalledWith('Error', expect.any(String));
});
});
});
I've already have react-native-paper as a Provider, in my MockedNavigator as follows:
export const MockedNavigator = ({ routes }) => {
const { Screen, Navigator } = createStackNavigator();
return (
<NavigationContainer>
<Providers>
<ReservationProvider>
<Navigator>
{routes.map((props, index) => (
<Screen
key={index}
{...props}
/>
))}
</Navigator>
</ReservationProvider>
</Providers>
</NavigationContainer>
);
};
export const Providers = ({ children }) => (
<NotificationProvider>
<GeolocationProvider>
<SettingsProvider>
<OAuthProvider>
<TailwindProvider>
<ThemeProvider>
<PortalProvider>
<CalendarProvider>
<ForegroundNotification />
{children}
</CalendarProvider>
</PortalProvider>
</ThemeProvider>
</TailwindProvider>
</OAuthProvider>
</SettingsProvider>
</GeolocationProvider>
</NotificationProvider>
);
export const ThemeProvider = ({ children }) => {
const [themeWithFont, setThemeWithFont] = useState(theme);
useEffect(() => {
const loadFonts = async () => {
setThemeWithFont({
...theme,
fonts: {
...theme.fonts,
medium: { fontFamily: C.fontFamilyDefault },
}
});
};
loadFonts();
}, []);
return <PaperProvider theme={themeWithFont}>{children}</PaperProvider>;
};
import { Provider as PaperProvider } from 'react-native-paper';

Related

how to mock async PermissionsAndroid.request in jest?

I have this code in react native i want to make a test:
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Device current location permission',
message: 'Allow app to get your current location',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
}
);
i am looking at an answer here but seem not working: How to mock PermissionAndroid from react native
jest.doMock('react-native/Libraries/PermissionsAndroid/PermissionsAndroid', () => ({
...jest.requireActual('react-native/Libraries/PermissionsAndroid/PermissionsAndroid'),
request: () => ({
[PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION]: PermissionsAndroid.RESULTS.GRANTED,
}),
check: () => true,
}));
on ios i am doing it like this which was quick:
jest.spyOn(Geolocation, 'requestAuthorization').mockResolvedValue('granted');
i can't seem to think of a way how to do it in android?
I could recommend you to try with react-native-permissions. It already have a mock file that you can use. You can use Jest + React Testing Library Native.
In my case I used a jest-setup.js file
import {jest} from '#jest/globals';
jest.mock('react-native-permissions', () =>
require('react-native-permissions/mock'),
);
Then configure jest inside you package.json file
"jest": {
"preset": "react-native",
"setupFilesAfterEnv": [
"#testing-library/jest-native/extend-expect"
],
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native-permissions|)"
],
"setupFiles": [
"./jest-setup.js"
]
}
For Geolocation service I created a react-native-geolocation-service inside __mocks__/react-native-geolocation-service.js
export default {
getCurrentPosition: jest.fn().mockImplementation(successCallback => {
const position = {
coords: {
latitude: 57.7,
longitude: 11.93,
},
};
successCallback(position);
}),
};
In your App component you could have this
import React, {useEffect, useState} from 'react';
import { View } from 'react-native';
import {check, request, PERMISSIONS, RESULTS} from 'react-native-permissions';
import Geolocation from 'react-native-geolocation-service';
const App = () => {
const [location, setLocation] = useState(null);
const handleLocationPermission = async () => {
let permissionCheck = '';
if (Platform.OS === 'ios') {
permissionCheck = await check(PERMISSIONS.IOS.LOCATION_WHEN_IN_USE);
if (permissionCheck === RESULTS.DENIED) {
const permissionRequest = await request(
PERMISSIONS.IOS.LOCATION_WHEN_IN_USE,
);
permissionRequest === RESULTS.GRANTED
? console.warn('Location permission granted.')
: console.warn('Location perrmission denied.');
}
}
if (Platform.OS === 'android') {
permissionCheck = await check(PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION);
if (permissionCheck === RESULTS.DENIED) {
const permissionRequest = await request(
PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
);
permissionRequest === RESULTS.GRANTED
? console.warn('Location permission granted.')
: console.warn('Location perrmission denied.');
}
}
};
useEffect(() => {
handleLocationPermission();
}, []);
useEffect(() => {
Geolocation.getCurrentPosition(
position => {
const {latitude, longitude} = position.coords;
setLocation({latitude, longitude});
},
error => {
console.log(error.code, error.message);
},
{enableHighAccuracy: true, timeout: 15000, maximumAge: 10000},
);
}, []);
return (<View></View>)
}
Then in you test file you can test the behaviour using React Testing Library Native.
import React from 'react';
import {render, waitFor} from '#testing-library/react-native';
import App from '../App';
import {check} from 'react-native-permissions';
import Geolocation from 'react-native-geolocation-service';
describe('<UserScreen />', () => {
test('should check for permissions', async () => {
render(<App />);
await waitFor(() => {
expect(check).toHaveBeenCalledTimes(1);
expect(Geolocation.getCurrentPosition).toHaveBeenCalledTimes(1);
});
});
});
I wrote a similar and more detailed Post on my website.

Can't upload files with Apollo-client GraphQL in Next.js app: POST body missing

I am trying to implement avatar upload in Next.js blog with Node.js server using Apollo client + apollo-upload-client on client side and apollo-express-server on server side.
I've got the next error:
POST body missing. Did you forget use body-parser middleware?
I am sure that I have body parser on my server.
Server.ts
import "reflect-metadata";
import "dotenv-safe/config";
import 'module-alias/register';
import { __prod__ } from "#/config/config";
import express from "express";
import Redis from "ioredis";
import session from "express-session";
import connectRedis from "connect-redis";
import { createConnection } from "typeorm";
import { User } from "#/entities/User";
import { Project } from "#/entities/Project";
import path from "path";
const server = async () => {
await createConnection({
type: "postgres",
url: process.env.DATABASE_URL,
logging: true,
migrations: [path.join(__dirname, "./migrations/*")],
entities: [User, Project]
});
const app = express();
require("#/start/logger"); // log exceptions
const RedisStore = connectRedis(session); // connect redis store
const redis = new Redis(process.env.REDIS_URL);
require("#/start/apolloServer")(app, redis); // create apollo server
require("#/start/appConfig")(app,redis,RedisStore) // configure app
const PORT = process.env.PORT || 3007;
app.listen(PORT, () => {
console.log(`🚀 Server Started at PORT: ${PORT}`);
});
};
server().catch((err) => {
console.error(err);
});
My Apollo Server
I use apollo-server-express
import { ApolloServer, gql } from "apollo-server-express";
import { buildSchema } from "type-graphql";
import ProfilePictureResolver from "#/resolvers/upload";
import { createUserLoader } from "#/utils/createUserLoader";
import { UserResolver } from "#/resolvers/user";
import { ProjectResolver } from "#/resolvers/project";
import {Express} from "express";
import { Redis } from "ioredis";
const typeDefs = gql`
scalar Upload
type File {
id: ID!
filename: String!
mimetype: String!
path: String!
}
type Mutation {
singleUpload(file: Upload!): File!
}
`;
module.exports = async function(app:Express,redis:Redis){
const apolloServer = new ApolloServer({
typeDefs,
schema: await buildSchema({
resolvers: [UserResolver, ProjectResolver, ProfilePictureResolver],
validate: false,
}),
context: ({ req, res }) => ({
req,
res,
redis,
userLoader: createUserLoader()
}),
uploads: false
});
apolloServer.applyMiddleware({
app,
cors: false,
});
}
Resolver:
import { Resolver, Mutation, Arg } from 'type-graphql'
import { GraphQLUpload, FileUpload } from 'graphql-upload'
import os from 'os'
import { createWriteStream } from 'fs'
import path from 'path'
#Resolver()
export default class SharedResolver {
#Mutation(() => Boolean)
async uploadImage(
#Arg('file', () => GraphQLUpload)
file: FileUpload
): Promise<Boolean> {
const { createReadStream, filename } = await file
const destinationPath = path.join(os.tmpdir(), filename)
const url = await new Promise((res, rej) =>
createReadStream()
.pipe(createWriteStream(destinationPath))
.on('error', rej)
.on('finish', () => {
//stuff to do
})
);
return true;
}
}
Server config
import {Express} from 'express'
import { __prod__, COOKIE_NAME } from "#/config/config";
import cors from "cors";
import session from "express-session";
import { Redis } from 'ioredis';
import { RedisStore } from 'connect-redis';
import { bodyParserGraphQL } from 'body-parser-graphql'
module.exports = function(app:Express, redis:Redis, RedisStore:RedisStore){
app.set("trust proxy", 1);
app.use(bodyParserGraphQL());
app.use(
cors({
origin: process.env.CORS_ORIGIN,
credentials: true,
})
);
app.use(
session({
name: COOKIE_NAME,
store: new RedisStore({
client: redis,
disableTouch: true,
}),
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 365 * 10, // 10 years
httpOnly: true,
sameSite: "lax",
secure: __prod__,
domain: __prod__ ? ".heroku.com" : undefined,
},
saveUninitialized: false,
secret: process.env.SESSION_SECRET,
resave: false,
})
);
}
Client
App client
import { createWithApollo } from "#/utils/createWithApollo";
import { ApolloClient, InMemoryCache } from "#apollo/client";
import { NextPageContext } from "next";
import { createUploadLink } from 'apollo-upload-client';
const createClient = (ctx: NextPageContext) =>
new ApolloClient({
credentials: "include",
headers: {
cookie:
(typeof window === "undefined"
? ctx?.req?.headers.cookie
: undefined) || "",
},
cache: new InMemoryCache({
typePolicies: {
Query: {}
}
}),
link: createUploadLink({uri:'http://localhost:4000/graphql'})
});
// const createClient: ApolloClient<NormalizedCacheObject> = new ApolloClient({
// cache: new InMemoryCache({}),
// uri: 'http://localhost:4000/graphql'
// });
export const withApollo = createWithApollo(createClient);
Query
import { gql } from '#apollo/client';
export const UPLOAD_IMAGE_MUTATION = gql`
mutation uploadImage($file: Upload!) {
uploadImage(file: $file)
}
`;
Page
import React, {useState} from 'react';
import {useSelector} from "react-redux";
import {Box} from "#/components/UI/Box/Box"
import {Header} from "#/components/UI/Text/Header"
import { withApollo } from "#/utils/withApollo";
import withPrivateRoute from "#/HOC/withPrivateRoute";
import { useMutation } from "#apollo/react-hooks";
import { UPLOAD_IMAGE_MUTATION } from "#/graphql/mutations/uploadImage";
interface IProps{};
const Profile:React.FC<IProps> = () => {
const user = useSelector(state => state.user);
const [file, setFileToUpload] = useState(null);
const [uploadImage, {loading}] = useMutation(UPLOAD_IMAGE_MUTATION);
const onAvatarUpload = (e) =>{
setFileToUpload(e.target.files[0]);
}
const onSubmit = async (e) =>{
e.preventDefault();
const response = await uploadImage({
variables: {file}
});
}
return (
<Box mt={20} pl={30} pr={30}>
<Header>
Edit Profile
</Header>
<input onChange={onAvatarUpload} type="file" placeholder="photo" />
<button onClick={(e)=>onSubmit(e)}>Submit</button>
</Box>
)
};
export default withApollo({ ssr: false })(withPrivateRoute(Profile, true));
My Client package:
{
"name": "app",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"#apollo/client": "^3.2.5",
"#apollo/react-hooks": "^4.0.0",
"apollo-upload-client": "^14.1.3",
"graphql": "^15.4.0",
"graphql-tag": "^2.11.0",
"graphql-upload": "^11.0.0",
"isomorphic-unfetch": "^3.1.0",
"next": "^9.5.5",
"next-apollo": "^5.0.3",
"next-redux-wrapper": "^6.0.2",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"react-is": "^16.13.1",
"react-redux": "^7.2.2",
"redux": "^4.0.5",
"styled-components": "^5.2.1",
"urql": "^1.10.3",
"uuid": "^8.3.1"
},
"devDependencies": {
"#testing-library/jest-dom": "^5.11.5",
"#testing-library/react": "^11.1.1",
"#types/graphql": "^14.5.0",
"#types/jest": "^26.0.15",
"#types/next": "^9.0.0",
"#types/node": "^14.0.27",
"#types/react": "^16.9.55",
"#types/react-dom": "^16.9.9",
"#types/styled-components": "^5.1.4",
"#types/uniqid": "^5.2.0",
"#types/uuid": "^8.3.0",
"#welldone-software/why-did-you-render": "^5.0.0",
"babel-plugin-inline-react-svg": "^1.1.2",
"babel-plugin-module-resolver": "^4.0.0",
"babel-plugin-styled-components": "^1.11.1",
"redux-devtools-extension": "^2.13.8",
"typescript": "^4.0.5"
}
}
Server package:
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "server.ts",
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"nodemon": "nodemon dist/server.js",
"dev": "npm-run-all --parallel watch nodemon",
"start": "ts-node src/server.ts",
"client": "cd ../ && npm run dev --prefix client",
"runall": "npm-run-all --parallel client dev",
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js",
"migration:up": "typeorm migration:run",
"migration:down": "typeorm migration:revert",
"migration:generate": "typeorm migration:generate -n 'orm_migrations'"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"apollo-server-express": "^2.16.1",
"argon2": "^0.26.2",
"connect-redis": "^5.0.0",
"cors": "^2.8.5",
"dataloader": "^2.0.0",
"dotenv-safe": "^8.2.0",
"express": "^4.17.1",
"express-async-errors": "^3.1.1",
"express-session": "^1.17.1",
"graphql": "^15.3.0",
"ioredis": "^4.17.3",
"module-alias": "^2.2.2",
"path": "^0.12.7",
"pgtools": "^0.3.0",
"reflect-metadata": "^0.1.13",
"type-graphql": "^1.0.0-rc.3",
"typeorm": "^0.2.25",
"uuid": "^8.3.0",
"winston": "^3.3.3"
},
"devDependencies": {
"#types/connect-redis": "0.0.14",
"#types/cors": "^2.8.8",
"#types/express": "^4.17.8",
"#types/express-session": "^1.17.0",
"#types/graphql": "^14.5.0",
"#types/ioredis": "^4.17.7",
"#types/node": "^8.10.66",
"#types/nodemailer": "^6.4.0",
"#types/pg": "^7.14.6",
"#types/uuid": "^8.3.0",
"gen-env-types": "^1.0.4",
"nodemon": "^2.0.6",
"npm-run-all": "^4.1.5",
"pg": "^8.4.2",
"ts-node": "^8.10.2",
"typescript": "^3.9.7"
},
"_moduleAliases": {
"#": "dist/"
}
}
NOTE!
When I try to remove uploads: false from apolloServer configuration I receive another error:
"Variable "$file" got invalid value {}; Upload value invalid."
And indeed in form data I see
------WebKitFormBoundarybNufV7QLX3EU1SN6 Content-Disposition: form-data; name="operations"
{"operationName":"uploadImage","variables":{"file":null},"query":"mutation
uploadImage($file: Upload!) {\n uploadImage(file: $file)\n}\n"}
------WebKitFormBoundarybNufV7QLX3EU1SN6 Content-Disposition: form-data; name="map"
{"1":["variables.file"]}
------WebKitFormBoundarybNufV7QLX3EU1SN6 Content-Disposition: form-data; name="1"; filename="Screen Shot 2020-11-20 at 17.56.14.png"
Content-Type: image/png
------WebKitFormBoundarybNufV7QLX3EU1SN6--
I am 100% sure that I pass the file.
I faced the same problem in my NextJs project, I found that the resolver of Upload checks if the value is instanceOf Upload, and that is somehow not working.
I fix it by creating my own resolver without using the 'graphql-upload' package like this:
Solution 1 :
export const resolvers: Resolvers = {
Upload: new GraphQLScalarType({
name: 'Upload',
description: 'The `Upload` scalar type represents a file upload.',
parseValue(value) {
return value;
},
parseLiteral(ast) {
throw new GraphQLError('Upload literal unsupported.', ast);
},
serialize() {
throw new GraphQLError('Upload serialization unsupported.');
},
})
};
Solution 2 :
Or you can just don't declare any resolver for this type.
Note:
Be sure that you declared scalar type of Upload in your schema and you need to add the uploads field to your Apollo Server configuration:
const apolloServer = new ApolloServer({
uploads: {
maxFileSize: 10000000, // 10 MB
maxFiles: 20
},
.
.
.

Jest Unit Test: wrapper.vm.$refs.editForm.validate is not a function

When I write test case for form submit, i m getting issue with 1wrapper.vm.$refs.editForm.validate is not a function
I am unable to figure out the problem.. please Help me.
"#vue/cli-plugin-babel": "^3.11.0", "#vue/cli-plugin-eslint": "^3.11.0", "#vue/cli-plugin-pwa": "^3.11.0", "#vue/cli-plugin-unit-jest": "^3.11.0", "#vue/cli-service": "^3.11.0", "#vue/eslint-config-prettier": "^5.0.0", "#vue/test-utils": "^1.0.0-beta.29", "babel-core": "^7.0.0-bridge.0", "babel-eslint": "^10.0.1", "babel-jest": "^23.6.0"
==== EditProperty.vue======
<v-form ref="editForm" lazy-validation>
<v-flex>
<v-text-field label="Label Text" v-model="labelName" :rules="[v => !!v || 'Label Text is required']"
/>
</v-flex>
</v-form>
<script>
export default {
data() {
return {
labelName: ''
}
},
methods: {
save() {
if (this.$refs.editForm.validate()) {
this.$emit('updateLable', this.labelName)
}
}
}
}
</script>
======EditProperty.spec.js =====
import { shallowMount, createLocalVue } from '#vue/test-utils'
import EditProperty from '#/components/EditProperty.vue'
import Vuetify from 'vuetify'
const localVue = createLocalVue()
localVue.use(Vuetify)
let wrapper
describe('EditProperty.vue', () => {
beforeEach(() => {
wrapper = shallowMount(EditProperty, {
localVue,
data() {
return {
labelName: 'Username'
}
}
})
})
it('should save called correctly', () => {
wrapper.vm.save()
})
})
expected => test should be pass
getting => wrapper.vm.$refs.editForm.validate is not a function
When I write test case for form submit, i m getting issue with 1wrapper.vm.$refs.editForm.validate is not a function
I am unable to figure out the problem.. please Help me.
shallowMount does not render the child components. I.E. in your case, v-form won't be rendered in the test. In fact if you call html from your wrapper, you will see a HTML comment in place of the <edit-form>.
The rationale behind that vue test utils feature is that, when you're unit testing a component, you test only the logic of such component in isolation, and don't rely on code from other modules.
Now you could manually pass an object as stub and provide any test double to allow the validate() call, via the stubs option:
import { shallowMount, createLocalVue } from '#vue/test-utils'
import EditProperty from '#/components/EditProperty.vue'
import Vuetify from 'vuetify'
const localVue = createLocalVue()
localVue.use(Vuetify)
let wrapper
describe('EditProperty.vue', () => {
beforeEach(() => {
const EditFormStub = {
render: () => {},
methods: {
validate: () => true,
}
};
wrapper = shallowMount(EditProperty, {
localVue,
stubs: {
'edit-form': EditFormStub,
}
data() {
return {
labelName: 'Username'
}
}
})
})
it('should save called correctly', () => {
wrapper.vm.save()
})
})
So we are passing a fake editForm as a stub, with a fake validate() method which always returns true.
Then you can test your component code. For instance, you could test that your label is emitted as updateLabel (in your original snippet it was 'updateLable', be wary):
it('should save called correctly', () => {
wrapper.vm.save();
expect(wrapper.emitted('updateLabel')[0][0]).toBe(whatever the label should be)
})
if you got in a situation where you don't need to stub. You could easily do this:
import { nextTick } from 'vue'
it('test', async () => {
wrapper.vm.$refs.editForm.validate = jest.fn()
await nextTick()
})

react-native-fbsdk imports are undefined after RN 0.52 upgrade

I just upgraded my RN project to RN 0.52 and the react-native fbsdk was not working correctly so I changed my import structure from:
const FBSDK = require('react-native-fbsdk');
const {
LoginManager,
AccessToken,
GraphRequest,
GraphRequestManager
} = FBSDK;
To
import { LoginManager,
AccessToken,
GraphRequest,
GraphRequestManager } from 'react-native-fbsdk';
full source code:
import React, { Component } from 'react';
import { View, ActivityIndicator, FlatList, Image, TouchableHighlight, StatusBar, Alert} from 'react-native';
import styles from './styles';
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { Container, Header, Content, Button, Text, Spinner, Title } from 'native-base';
import { requestBusiness, receiveBusiness, storeLoginScreenId, receiveAwsId } from '../../actions'
import { withApollo, ApolloClient, graphql } from 'react-apollo';
import gql from 'graphql-tag';
var AWS = require('aws-sdk/dist/aws-sdk-react-native');
import { LoginManager,
AccessToken,
GraphRequest,
GraphRequestManager } from 'react-native-fbsdk';
class Login extends Component {
static propTypes = {
dispatch: PropTypes.func.isRequired,
isLoggedIn: PropTypes.bool.isRequired,
isFetching: PropTypes.bool.isRequired,
client: PropTypes.instanceOf(ApolloClient).isRequired
}
_handleFacebookLogin(navigation, dispatch, client, isFetching) {
//const { navigation } = this.props
//LoginManager.logOut();
LoginManager.logInWithReadPermissions(["business_management","pages_show_list"]).then(
function (result) {
if (result.isCancelled) {
Alert.alert(
'Facebook Permissions issue')
} else {
//alert('Login success with permissions: ' + result.grantedPermissions.toString())
AccessToken.getCurrentAccessToken().then(
(data) => {
AWS.config.region = 'us-east-1';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'xxxxxxxxxxxxxxx',
Logins: {
'graph.facebook.com': data.accessToken.toString()
}
}
);
AWS.config.credentials.clearCachedId();
AWS.config.credentials.get(function(err) {
if (err){ alert("Error" + err);
console.log(err);
}
dispatch(requestBusiness())
client.query({
query: gql`query getCurrentUser($Id: String!) {
User(id: $Id) {
id,
posts {
postId,
postText
}
}
}
}`,
variables: {Id: AWS.config.credentials.identityId},
fetchPolicy: 'network-only'
}).then((result) => {
dispatch(receiveAwsId(AWS.config.credentials.identityId))
dispatch(receiveBusiness())
if(result.data.businessUser != null){
navigation.dispatch({ type: 'LOGGEDIN' });
}
else {
navigation.dispatch({ type: 'ONBOARD' });
}
}).catch((err) => {
console.log('catch', err)
});
});
}
)
//navigation.dispatch({ type: 'LOGIN' });
}
},
function (error) {
alert('Login fail with error: ' + error)
console.log(error)
}
)
}
componentWillReceiveProps(nextProps) {
/*
const { business, navigation, isFetching, dispatch } = this.props
if(nextProps.isFetching == false && isFetching == true){
if(nextProps.business == null && business == undefined){
navigation.dispatch({ type: 'ONBOARD' });
} else {
navigation.dispatch({ type: 'LOGIN' });
}
}*/
}
render() {
const {navigation, dispatch, isFetching, client} = this.props
return (
<Container style={styles.container}>
<Text></Text>
<Title>
<Title style={styles.title}>App</Title>
<Title style={styles.secondaryTitle}>Login</Title>
</Title>
{isFetching ? <Spinner color='#FFFFFF' /> :
<Button bordered rounded light
style={styles.loginButton}
onPress={() => this._handleFacebookLogin(navigation, dispatch, client, isFetching)}>
<Text>Login With Facebook</Text>
</Button>}
</Container>
);
}
}
const LoginComponentWithApollo = withApollo(Login)
const mapStateToProps = state => {
const { business } = state
const {
businessInfo,
lastUpdated,
isFetching
} = business
return {
isLoggedIn : state.isLoggedIn,
dispatch : state.dispatch,
businessInfo,
lastUpdated,
isFetching
}
}
export default connect(mapStateToProps)(LoginComponentWithApollo);
psckage.json:
{
"name": "MyApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"dependencies": {
"aws-sdk": "^2.130.0",
"native-base": "^2.3.9",
"prop-types": "^15.6.0",
"react": "^16.2.0",
"react-apollo": "^1.4.16",
"react-native": "^0.52.1",
"react-native-code-push": "^5.1.2-beta",
"react-native-fbsdk": "^0.7.0",
"react-native-onesignal": "^3.0.6",
"react-native-sentry": "^0.26.0",
"react-native-vector-icons": "^4.4.0",
"react-navigation": "^1.0.0-beta.13",
"react-redux": "^5.0.5",
"redux": "^3.7.2",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.2.0"
},
"devDependencies": {
"babel-jest": "20.0.3",
"babel-preset-react-native": "2.1.0",
"jest": "20.0.4",
"react-test-renderer": "16.0.0-alpha.12"
},
"jest": {
"preset": "react-native"
},
"rnpm": {
"assets": [
"./assets/fonts/"
]
}
}
^^ I am getting the following error:
Cannot read property 'loginWithReadPermissions' of undefined.
Any idea what might be causing this? when I go into the react-native-fbdsk I do see that these functions are defined in there.

Import vue package in laravel

What is the corect way to import vue packages in laravel 5.6? It comes with vue and bootstrap preinstall. I see they are all compile in app.js from public directory but I can figure out how to import https://github.com/moreta/vue-search-select and use it. After I tried to import it on my own:
Error:
ncaught TypeError: Vue.component is not a function
At line:
Vue.component('search-user', __webpack_require__(42));
Until now I tried this:
assets/js/bootstrap.js:
import { BasicSelect } from 'vue-search-select';
window.BasicSelect = BasicSelect;
assets/js/app.js:
require('./bootstrap');
window.Vue = require('vue');
window.Vue = require('vue-search-select');
Vue.component('search-user', require('./components/SearchUser.vue'));
var app = new Vue({
el: '#app'
})
components
<template>
<basic-select :options="options"
:selected-option="item"
placeholder="select item"
#select="onSelect">
</basic-select>
</template>
<script>
export default {
data() {
return {
keywords: null,
options: []
};
},
watch: {
keywords(after, before) {
if (this.keywords.length > 0)
this.fetch();
}
},
methods: {
fetch() {
axios.get('/api/search', {params: {keywords: this.keywords}})
.then(response => this.options = response.data)
.catch(error => {
});
},
onSelect (item) {
this.item = item
},
reset () {
this.item = {}
},
selectOption () {
// select option from parent component
this.item = this.options[0]
},
components: {
BasicSelect
}
}
}
</script>
I ran: npm install and npm run watch:
"devDependencies": {
"ajv": "^6.0.0",
"bootstrap": "^4.0.0",
"cross-env": "^5.1",
"laravel-mix": "^2.0",
"lodash": "^4.17.4",
"popper.js": "^1.12",
"uikit": "^3.0.0-beta.35",
"vue": "^2.5.7",
"vue-search-select": "^2.5.0"
},
"dependencies": {
"axios": "^0.17.1",
"jquery": "^3.3.1"
}
I think that the simple will do
window.Vue = require('vue');
require('vue-search-select');
Then in your components you can import what you need on top:
import { BasicSelect } from 'vue-search-select';
export default {
data() {
return {
keywords: null,
options: [],
item: null
};
},
...
One missing detail that tricked me with this one, you need to register the components like this, otherwise it won't be found:
components: {
ModelSelect,
BasicSelect
},