I have a Pricing page which has a pricing table and does the following to redirect to a Sign Up page with a route param which determines which price (product) the user picked:
methods: {
subscribe(price) {
this.loading = true;
if (!this.loggedIn) {
this.$router.push({ name: "Sign Up", params: { price: price } });
}
},
},
In the Sign Up component, it will console log the correct price from the route param in mounted , but after the signIn with google happens and it redirects to the Checkout component, the route param price is lost:
mounted: function () {
const googleAuth = new firebase.auth.GoogleAuthProvider();
if (!this.loggedIn) {
firebase.auth().signInWithRedirect(googleAuth);
firebase
.auth()
.getRedirectResult()
.then((result) => {
this.$router.push({ name: "Checkout", params: { price: this.$route.params.price } });
console.log(result);
})
.catch((error) => {
console.log(error);
});
firebase.auth().onAuthStateChanged((user) => {
if (user) {
this.loggedIn = true;
} else {
// Show sign in screen with button above.
}
});
}
},
Related
react-native-push-notification's configure method is not return data. Data is coming null .Here is my code
React.useEffect(() => {
PushNotification.configure({
onNotification(notification) {
if (notification.userInteraction) {
console.log(notification);
console.log('hi');
}
var nottype = notification.data.actionId;
var notid = notification.data.id;
console.log(notid);
AsyncStorage.setItem('actionId', nottype);
AsyncStorage.setItem('orderId', notid);
},
});
}, []);
you are using react-native-push-notification this library is not the best to handle notification. instead you can use #notifee/react-native to configure this for notification. this is very easy to use and do not need native code configuration.
to create a group or single channel
// Create a group
await notifee.createChannelGroup({
id: 'personal',
name: 'Personal',
});
// Assign the group to the channel
await notifee.createChannel({
id: 'comments',
name: 'New Comments',
groupId: 'personal',
});
here is a sample
import notifee, {
AndroidBadgeIconType,
EventType,
TriggerType,
} from '#notifee/react-native';
const onDisplayNotification = async (item, distance, message) => {
try {
await notifee.requestPermission();
const channelId = await notifee.createChannel({
id: 'default',
name: 'Default Channel',
});
await notifee.displayNotification({
title: `You are getting ${message} ${
message == 'Close' ? 'to' : 'from'
} ${item.name}`,
body: `You are ${distance} M away form ${item.name}`,
android: {
channelId,
actions: [
{
title: 'Close',
pressAction: {
id: 'stop',
},
},
],
smallIcon: 'ic_launcher',
pressAction: {
id: 'default',
},
},
});
} catch (e) {
console.error(e, 'ERRORORORORORORO');
}
};
here is the event with which you can interreact with them .
useEffect(() => {
return notifee.onForegroundEvent(({ type, detail }) => {
switch (type) {
case EventType.DISMISSED:
console.log('User dismissed notification', detail.notification);
break;
case EventType.PRESS:
console.log('User pressed notification', detail.notification);
break;
}
});
}, []);
currently Iam trying to mock a session for website project with cypress, so the tests are not actually accessing database cause Iam using only 0Auth 3th party login (google and github). I already succesfuly mocked a session so main page shows as logged user. However when I click on my profile, it says: No profile (expected behavior when there is no UserInfo data).
This is my cypress code:
Command:
Cypress.Commands.add("login", () => {
cy.intercept("/api/auth/session", { fixture: "session.json" }).as("session");
cy.setCookie("next-auth.session-token", "testcookie");
Cypress.Cookies.preserveOnce("next-auth.session-token");
});
Fixture:
{
"user": {
"name": "test",
"email": "test#test.com",
"slug": "test0000",
"id": "strasnedlouhejstring",
"image": "https://avatars.githubusercontent.com/u/112759319?v=4"
},
"userInfo": {
"bio": "Lorem Testum",
"name": "test",
"email": "test#test.com",
"slug": "test0000",
"id": "strasnedlouhejstring",
"isActive": "true"
},
"expires": "3000-01-01T00:00:00.000Z",
"accessToken": "test"
}
First test (success):
describe("Cypress login", () => {
it("should provide a valid session", () => {
cy.login();
cy.visit("/");
cy.wait("#session");
cy.get("#dropdown > div")
.should("exist")
.then(() => {
cy.log("Cypress login successful");
});
});
});
And finally page rendering:
import ProfilePage from "#components/Layout/ProfilePage";
import { User } from "#prisma/client";
import { getUserInfo } from "#scripts/prisma/getUserInfo";
import { GetServerSideProps } from "next";
import { useSession } from "next-auth/react";
const UserProfile = ({ userInfo }: { userInfo: User | null }) => {
const { data: session } = useSession();
if (userInfo) return <ProfilePage userInfo={userInfo} session={session} />;
return <h1>No profile</h1>;
};
export const getServerSideProps: GetServerSideProps = async (context) => {
const slug = context.query.userProfile?.toString();
if (slug) {
const user = await getUserInfo(slug);
if (user) {
return {
props: { userInfo: JSON.parse(JSON.stringify(user)) },
};
}
}
return {
props: { userInfo: null },
};
};
export default UserProfile;
As I said, the condition is always false so i get the message: No Profile.
I spent 2days figuring this out, however not successfuly.
I'm currently creating an authentication feature in Nuxt and Firebase.
The login and logout process itself can be done and the header display changes accordingly, but there is an error in console when I press the login button.
Error content (in console)
Uncaught RangeError: Maximum call stack size exceeded
at Function.keys (<anonymous>)
code
Header.vue(This is the page containing the login button.)↓
googleLogin () {
const provider = new firebase.auth.GoogleAuthProvider()
auth.signInWithPopup(provider)
.then(res => {
this.dialogAuthVisible = false
this.$store.dispatch('auth/setUser',res.user)
}).catch(e => console.log(e))
}
store/auth.js↓
export const strict = false
export const state = () => ({
user: null
})
export const mutations = {
SET_USER (state, payload) {
state.user = payload
}
}
export const actions = {
setUser ({ commit }, user) {
commit('SET_USER',user)
}
}
export const getters = {
isAuthenticated (state) {
return !!state.user
}
}
default.vue↓
mounted () {
auth.onAuthStateChanged(user => {
const { uid, displayName, photoURL} = user
if (user) {
this.$store.dispatch('auth/setUser', { uid, displayName, photoURL})
} else {
this.$store.dispatch('auth/setUser', null)
}
})
}
If there's any information I'm missing, please let me know 🙇️.
Please teach me how to do this 🙇️.
I think the problem is in this code lines :
export const mutations = {
SET_USER (state, payload) {
state.user = payload
}
}
export const actions = {
setUser ({ commit }, user) {
commit('SET_USER',user)
}
}
There is a loop between this mutations and actions
Instead of setting the entire payload into the store object, I just picked the fields I needed, and that resolved the problem for me.
Before:
AUTH_STATUS_CHANGED ({commit}, data: any): any {
if (data && data.authUser) {
commit('SetAuthUser', data.authUser);
} else {
commit('SetAuthUser', null);
}
}
After:
AUTH_STATUS_CHANGED ({commit}, data: any): any {
if (data && data.authUser) {
const user = data.authUser;
commit('SetAuthUser', {
uid: user.uid,
email: user.email,
emailVerified: user.emailVerified,
displayName: user.displayName,
isAnonymous: user.isAnonymous,
photoURL: user.photoURL,
stsTokenManager: user.stsTokenManager,
createdAt: user.createdAt,
lastLoginAt: user.lastLoginAt,
apiKey: user.apiKey,
});
} else {
commit('SetAuthUser', null);
}
}
Inside the mutation, just add the value received from the mutation payload.
I want to call an action in created hook, wait until is done and in same hook to display the result. Is that possible?
I tried to put async / await in actions but doesn't help.
This is the action property with the async function in the store:
actions: {
async FETCH_USER({commit}) {
await firebase.firestore().collection('test').get().then(res => {
commit('FETCH_USER', res.docs[0].data())
})
}
}
created() {
this.FETCH_USER()
console.log(this.GET_USER)
},
methods: {
...mapActions([
'FETCH_USER'
]),
login() {
if(this.$refs.form.validate()) {
console.log('welcome')
}
}
},
computed: {
...mapGetters([
'GET_USER'
])
}
export default new Vuex.Store({
state: {
user: null
},
getters: {
GET_USER: state => state.user
},
mutations: {
FETCH_USER(state, user) {
state.user = user
}
},
actions: {
FETCH_USER({commit}) {
firebase.firestore().collection('test').get().then(res => {
commit('FETCH_USER', res.docs[0].data())
})
}
}
})
async/await version
async FETCH_USER({ commit }) {
const res = await firebase.firestore().collection('test').get()
const user = res.docs[0].data()
commit('FETCH_USER', user)
return user
}
async created() {
// The action returns the user out of convenience
const user = await this.FETCH_USER()
console.log(user)
// -- or --
// Access the user through the getter
await this.FETCH_USER()
console.log(this.GET_USER)
}
You need to await the action call because it is an async function.
Promise version
FETCH_USER({ commit }) {
return firebase.firestore().collection('test').get().then(res => {
const user = res.docs[0].data()
commit('FETCH_USER', user)
return user
})
}
created() {
this.FETCH_USER().then(user => {
console.log(user)
})
// -- or --
this.FETCH_USER().then(() => {
console.log(this.GET_USER)
})
}
I'm trying to test a 'redux observable epic' but the test fail because not all actions are in store.getActions() the strange is the store.dispatch function runs.
Epic and actions
export const VERIFY_SESION = 'auth/VERIFY_SESION';
export const SET_POLICIES_ACCEPTED = 'auth/SET_POLICIES_ACCEPTED';
export const AUTHENTICATE = 'auth/AUTHENTICATE';
export function setPoliciesAccepted(wereAccepted: boolean) {
return {
wereAccepted,
type: SET_POLICIES_ACCEPTED,
};
}
export function verifySesion() {
return {
type: VERIFY_SESION,
};
}
export function authenticate(token) {
return {
token,
type: AUTHENTICATE,
};
}
export function verifySesionEpic(action$, store) {
return action$
.ofType(VERIFY_SESION)
.switchMap(async () => {
try {
store.dispatch(setBlockLoading(true));
const token = await AsyncStorage.getItem('token');
if (token !== null) {
store.dispatch(setBlockLoading(false));
return authenticate(token);
}
const policiesWereAccepted = await AsyncStorage.getItem('policiesWereAccepted');
store.dispatch(setBlockLoading(false));
return setPoliciesAccepted(policiesWereAccepted);
} catch (error) {
return setMessage(error.message);
}
});
}
test
describe('actions/auth', () => {
let store;
const asyncStorageGetStub = stub(AsyncStorage, 'getItem');
beforeEach(() => {
store = mockStore();
});
afterEach(() => {
asyncStorageGetStub.restore();
});
it('Should call authenticate if token', () => {
const token = 'mitoken';
asyncStorageGetStub.withArgs('token').returns(Promise.resolve(token));
store.dispatch(verifySesion());
expect(store.getActions()).toContain({ type: AUTHENTICATE, token });
});
});
Test result
1) "actions/auth Should call epic for verifySesion:
Error: Expected [ { type: 'auth/VERIFY_SESION' } ] to include { token: 'mitoken', type: 'auth/AUTHENTICATE' }"
Note
im sure that the conditional token !== null pass
I was to add a timeout before getAction because the 'AUTHENTICATE' actions is added after.
it('Should call authenticate if token', (done) => {
const token = 'mitoken';
asyncStorageGetStub.withArgs('token').returns(Promise.resolve(token));
store.dispatch(verifySesion());
setTimeout(() => {
expect(store.getActions()).toContain({ type: AUTHENTICATE, token });
done();
}, 1000);
});