I try to make some unit tests on a login funtion in flutter and I have an error that I can't fix.
This is the test:
test('Register (success)', () async {
var auth = AuthService();
var result = await auth.login("test", "123456");
var json = jsonDecode(result.toString());
expect(json['success'], true);
});
This is the function called by the test:
login(name, password) async {
if (name.toString().isEmpty || password.toString().isEmpty) {
return "Error: empty field";
}
return await dio.post('https://itsmilife.herokuapp.com/authenticate',
data: {"name": name, "password": password},
options: Options(contentType: Headers.formUrlEncodedContentType))
}
This is the function that sent the informations:
authenticate: function(req, res) {
User.findOne({
name: req.body.name
}, function (err, user) {
if (err) throw err
if (!user) {
res.status(403).send({success: false, msg: 'Authentication Failed, User not found'})
} else {
user.comparePassword(req.body.password, function (err, isMatch) {
if (isMatch && !err) {
var token = jwt.encode(user, config.secret)
res.json({success: true, token: token, user: user})
}
else {
return res.status(403).send({success: false, msg: 'Authentication failed wrong password'})
}
})
}
})
},
I have the error when I launch the test:
NoSuchMethodError: The method '[]' was called on null.
Receiver: null
Tried calling: []("success")
dart:core Object.noSuchMethod
test\widget_test.dart 24:16 main.<fn>
I don't understand how to fix the probleme.
Try something like this:
Future<bool> login(name, password) async {
if (name.toString().isEmpty || password.toString().isEmpty) {
return false;
}
var responseFromServer = await dio.post(
'https://itsmilife.herokuapp.com/authenticate',
data: {"name": name, "password": password},
options: Options(contentType: Headers.formUrlEncodedContentType));
if (responseFromServer == null || responseFromServer.statusCode != 200) {
return false;
}
return true;
}
Also, make your test like:
test('Register (success)', () async {
var auth = AuthService();
var result = await auth.login("test", "123456");
expect(result, true);
});
Related
The following works fine, but I have noticed that it is really slow login in a client. How can I make it faster?
import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"
import { ObjectId } from 'mongodb'
import { MongoDBAdapter } from "#next-auth/mongodb-adapter"
import clientPromise from "../../../lib/mongodb";
import { v4 as uuidv4 } from 'uuid';
var CryptoJS = require("crypto-js");
const sFinder = async (task, token) => {
try{
const client = await clientPromise;
const database = client.db('DRN1');
const ses = await database.collection('sessions');
switch (task) {
case 1:
const result = await ses.find({
"userId": ObjectId(token.uuid)
}).sort({"_id":-1}).limit(1).toArray();
if (!result) {
return 202;
}
else{
return result[0].sessionToken
}
break;
case 2:
const insertResult = await ses.insertOne({"userId":token.uuid, "sessionToken":token.accessToken});
if (!insertResult) {
return 203;
}
else{
return insertResult
}
break;
case 3:
var expdate = new Date(token.exp * 1000);
const UpdateResult = await ses.updateOne({"userId":ObjectId(token.uuid), "sessionToken":token.accessToken},
{ $set: {"expires": expdate}}, { upsert: true });
if (!UpdateResult) {
return 203;
}
else{
return UpdateResult
}
break;
default:
break;
}
} catch(e){
console.error(e);
}
}
export default NextAuth({
adapter: MongoDBAdapter(clientPromise),
session: {
strategy: 'jwt',
jwt: true,
},
providers: [
CredentialsProvider({
name: 'DRN1',
credentials: {
username: { label: "Username", type: "text"},
password: { label: "Password", type: "password" }
},
async authorize(credentials, req) {
try{
const client = await clientPromise;
const database = client.db('DRN1');
const users = await database.collection('users');
const result = await users.findOne({
username: credentials.username,
});
if (!result) {
throw new Error('No user found with the username');
}
var bytes = CryptoJS.AES.decrypt(result.password, process.env.PASS_ENC);
var decryptedData = bytes.toString(CryptoJS.enc.Utf8);
//Check hased password with DB password
if(decryptedData != credentials.password){
throw new Error('Password doesnt match');
}
return {uuid:result._id, username: result.username, email: result.email, type:result.type, "sessionID":uuidv4()};
} catch(e){
console.error(e)
}
}
})
],
callbacks: {
signIn: async ({ user, account, profile, email, credentials }) => {
account.accessToken = user.sessionID
account.uuid = user.uuid
const test = await sFinder(2,account)
return true
},
jwt: async ({ token, account }) => {
if (account) {
token.uuid = account.uuid
token.accessToken = account.accessToken
}
const lastUsedToken = await sFinder(1,token)
const updateTokenExpire = await sFinder(3,token)
if(lastUsedToken != token.accessToken){
// console.log("I have made it an error")
token.error = 555;
}
return token
},
session: async ({ session, token, user }) => {
session.uuid = token.uuid
if(!token.accessToken){
//OAUTH Accounts
session.accessToken = uuidv4()
}else{
session.accessToken = token.accessToken
}
if(token.error == 555){
session.error = 555
}
return session
}
},
pages:{
error: 'signin'
},
theme: {
colorScheme: "dark", // "auto" | "dark" | "light"
brandColor: "", // Hex color code
logo: "https://storage.googleapis.com/radiomedia-images/station_logos/v2/DRN1_small.png" // Absolute URL to image
}
});
I believe what is slowing it down is the following
callbacks: {
signIn: async ({ user, account, profile, email, credentials }) => {
account.accessToken = user.sessionID
account.uuid = user.uuid
const test = await sFinder(2,account)
return true
},
jwt: async ({ token, account }) => {
if (account) {
token.uuid = account.uuid
token.accessToken = account.accessToken
}
const lastUsedToken = await sFinder(1,token)
const updateTokenExpire = await sFinder(3,token)
if(lastUsedToken != token.accessToken){
// console.log("I have made it an error")
token.error = 555;
}
return token
},
session: async ({ session, token, user }) => {
session.uuid = token.uuid
if(!token.accessToken){
//OAUTH Accounts
session.accessToken = uuidv4()
}else{
session.accessToken = token.accessToken
}
if(token.error == 555){
session.error = 555
}
return session
}
},
Mainly all the awaits, but the await functions are to make sure the user is not login on another device. As we log the old devices out automatically.
below is a code snippet from https://www.mongodb.com/blog/post/quick-start-nodejs--mongodb--how-to-implement-transactions
It works perfectly but here is what I don't understand:
This function didn't call session.commitTransaction(), how does it commit the transaction?
it aborts the transaction by determining if isListingReservedResults is null or not null, but my implementation is to throw an error in the if block and catches the error then calling the session.abortTransaction() (which result in a "MongoError: Cannot call abortTransaction twice"), I wonder Why would this happen since i only call it onece.
async function createReservation(client, userEmail, nameOfListing, reservationDates, reservationDetails) {
const usersCollection = client.db("sample_airbnb").collection("users");
const listingsAndReviewsCollection = client.db("sample_airbnb").collection("listingsAndReviews");
const reservation = createReservationDocument(nameOfListing, reservationDates, reservationDetails);
const session = client.startSession();
try {
const transactionResults = await session.withTransaction(async () => {
const usersUpdateResults = await usersCollection.updateOne(
{ email: userEmail },
{ $addToSet: { reservations: reservation } },
{ session });
const isListingReservedResults = await listingsAndReviewsCollection.findOne(
{ name: nameOfListing, datesReserved: { $in: reservationDates } },
{ session });
if (isListingReservedResults) {
await session.abortTransaction();
return;
// throw new Error('message'); myi mplementaion, throw error here then abort the transaction in catch block
}
const listingsAndReviewsUpdateResults = await listingsAndReviewsCollection.updateOne(
{ name: nameOfListing },
{ $addToSet: { datesReserved: { $each: reservationDates } } },
{ session });
});
if (transactionResults) {
console.log("The reservation was successfully created.");
} else {
console.log("The transaction was intentionally aborted.");
}
} catch(e){
console.log("The transaction was aborted due to an unexpected error: " + e);
// await session.abortTransaction(); result in a "MongoError: Cannot call abortTransaction twice"
} finally {
await session.endSession();
}
}
I'm trying to send GET request and I also want to fetch the data using the search input. So I have used Params but it is not working ,
here's my code :
// setFetching(true)
let url = `${TEST_API_URL}/teammember/getAll`
try {
const posts: any = await axios.get(`${url}`, {
withCredentials: true,
headers: {
Authorization: `${localStorage.getItem('access_token')}`,
},
params: {
search
},
})
console.log(posts.data.Data)
setPosts(posts.data.Data)
} catch (error: any) {
toast.error('Something went wrong')
}
// setFetching(false)
}, [search])
useEffect(() => {
async function fetchData() {
await fetchFunction()
}
void fetchData()
}, [fetchFunction])```
I recommend you to do like this.
// setFetching(true)
let url = `${TEST_API_URL}/teammember/getAll`
try {
const posts: any = await axios.get(`${url}?search=${search}`, {
withCredentials: true,
headers: {
Authorization: `${localStorage.getItem('access_token')}`,
}
})
console.log(posts.data.Data)
setPosts(posts.data.Data)
} catch (error: any) {
toast.error('Something went wrong')
}
// setFetching(false)
}, [search])
useEffect(() => {
async function fetchData() {
await fetchFunction()
}
void fetchData()
}, [fetchFunction])```
I'm trying to use flutter_stripe for a stripe connect account, But I always get the
same error: The client_secret provided doesn't match the client_secret associated with the PaymentIntend.
I've completed all steps according to flutter_stripe but I still face this error.
Below is my code Please check this and help me.
inde.js
const functions = require("firebase-functions");
const stripe = require("stripe")("secret_key");
exports.stripePaymentIntentRequest = functions.https.onRequest(async (req, res) => {
try {
let customerId;
//Gets the customer who's email id matches the one sent by the client
const customerList = await stripe.customers.list({
email: req.body.email,
limit: 1
});
//Checks the if the customer exists, if not creates a new customer
if (customerList.data.length !== 0) {
customerId = customerList.data[0].id;
}
else {
const customer = await stripe.customers.create({
email: req.body.email
});
customerId = customer.data.id;
}
//Creates a temporary secret key linked with the customer
const ephemeralKey = await stripe.ephemeralKeys.create(
{ customer: customerId },
{ apiVersion: '2020-08-27' }
);
//Creates a new payment intent with amount passed in from the client
const paymentIntent = await stripe.paymentIntents.create({
amount: parseInt(req.body.amount),
currency: 'usd',
customer: customerId,
})
res.status(200).send({
clientSecret: paymentIntent.client_secret,
paymentIntent: paymentIntent,
ephemeralKey: ephemeralKey.secret,
customer: customerId,
success: true,
})
} catch (error) {
res.status(404).send({ success: false, error: error.message })
}
});
PaymentService.dart
Future<void> initPaymentSheet(
{required BuildContext context, required String email, required int amount}) async {
try {
// 1. create payment intent on the server
final response = await http.post(
Uri.parse(
'Firebase api link of Functions'),
body: {
'email': email,
'amount': amount.toString(),
});
Map<String, dynamic> paymentIntentBody = jsonDecode(response.body);
log(paymentIntentBody.toString());
//2. initialize the payment sheet
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: paymentIntentBody["clientSecret"],
merchantDisplayName: 'Flutter Stripe Store Demo',
customerId: paymentIntentBody['customer'],
customerEphemeralKeySecret: paymentIntentBody['ephemeralKey'],
style: ThemeMode.light,
testEnv: true,
merchantCountryCode: 'US',
),
);
await Stripe.instance.presentPaymentSheet();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Payment completed!')),
);
} catch (e) {
if (e is StripeException) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error from Stripe: ${e.error.localizedMessage}'),
),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error the Stripe of : $e')),
);
}
}
}
The log error print on my console is :
> [log] {paymentIntent:
> pi_3LI2acCTAUDjRNFV1Ra3dahz_secret_Fcqw73pWrE4avKRyuDVzRBitG,
> ephemeralKey:
> ek_test_YWNjdF8xSlQ3amtDVEFVRGpSTkZWLDl1OE5Vdm1jTGY4T1RpaVhHOTB3NTRVSkQ5UGl4azA_00j32OYG9n,
> customer: cus_LHG2YpQP9Cgwuy, success: true}
The following code is from a previous Stripe evaluation stage. But it worked. Slim it down to your needs.
Remember to publish your secret key to the server, so the server can talk to Stripe.
code.dart
Future<bool> payWithPaymentSheet(
ProductModel productModel, PriceModel priceModel,
{String merchantCountryCode = 'DE'}) async {
if (kIsWeb) {
throw 'Implementation not availabe on Flutter-WEB!';
}
String uid = AuthService.instance.currentUser().uid;
String email = AuthService.instance.currentUser().email ?? '';
HttpsCallableResult response;
try {
response = await FirebaseFunctions
.httpsCallable('createPaymentIntent')
.call(<String, dynamic>{
'amount': priceModel.unitAmount,
'currency': priceModel.currency,
'receipt_email': email,
'metadata': {
'product_id': productModel.id,
'user_id': uid,
"valid_until": productModel.getUntilDateTime().toIso8601String(),
'product_name': productModel.name.tr,
},
'testEnv': kDebugMode,
});
} on FirebaseFunctionsException catch (error) {
log(error.code);
log(error.details);
log(error.message ?? '(no message)');
Get.snackbar(
error.code,
error.message ?? '(no message)',
icon: const Icon(Icons.error_outline),
);
return false;
}
Map<String, dynamic> paymentIntentBody = response.data;
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: paymentIntentBody["clientSecret"],
currencyCode: priceModel.currency,
applePay: false,
googlePay: false,
merchantCountryCode: merchantCountryCode,
merchantDisplayName: Strings.appName,
testEnv: kDebugMode,
customerId: paymentIntentBody['customer'],
customerEphemeralKeySecret: paymentIntentBody['ephemeralKey'],
));
try {
await Stripe.instance.presentPaymentSheet();
return true;
} on StripeException catch (e) {
log(e.error.code.name);
log(e.error.message ?? '(no message)');
log(e.error.localizedMessage ?? '(no message)');
Get.snackbar(e.error.code.name, e.error.message ?? '',
icon: const Icon(Icons.error_outline));
} catch (e) {
Get.snackbar('An unforseen error occured', e.toString(),
icon: const Icon(Icons.error_outline));
}
return false;
}
index.ts
// SETTING SECRET KEY ON SERVER:
// cd functions
// firebase functions:config:set stripe.secret_key="sk_live_51L...Noe"
// firebase deploy --only functions
let stripe = require("stripe")(functions.config().stripe.secret_key);
exports.createPaymentIntent = functions
.https.onCall((data, context) => {
// if (!context.auth) {
// return { "access": false };
// }
return new Promise(function (resolve, reject) {
stripe.paymentIntents.create({
amount: data.amount,
currency: data.currency,
receipt_email: decodeURIComponent(data.receipt_email),
metadata: data.metadata,
}, function (err, paymentIntent) {
if (err != null) {
functions.logger.error("Error paymentIntent: ", err);
reject(err);
}
else {
resolve({
clientSecret: paymentIntent.client_secret,
paymentIntentData: paymentIntent,
});
}
});
});
});
am trying to do an API call where am getting an error to hangle null safety variable must be assigned.
here is my code
Future<LoginResponseModel> loginCustomer(
String username, String password) async {
LoginResponseModel model;
try {
var response = await Dio().post(Config.tokenURL,
data: {
"username": username,
"password": password,
},
options: Options(headers: {
HttpHeaders.contentTypeHeader: "application/x-www-form-urlencoded",
}));
if (response.statusCode == 200) {
model = LoginResponseModel.fromJson(response.data);
}
} on DioError catch (e) {
print(e.message);
}
return model;
}
exception am getting
The non-nullable local variable 'model' must be assigned before it can
be used. Try giving it an initializer expression, or ensure that it's
assigned on every execution path.dart
(not_assigned_potentially_non_nullable_local_variable)
is there any solution to handle this
tried "?" it's not working.
Screenshot
Future<LoginResponseModel?> loginCustomer(
String username, String password) async {
LoginResponseModel? model;
try {
var response = await Dio().post(Config.tokenURL,
data: {
"username": username,
"password": password,
},
options: Options(headers: {
HttpHeaders.contentTypeHeader: "application/x-www-form-urlencoded",
}));
if (response.statusCode == 200) {
model = LoginResponseModel.fromJson(response.data);
}
} on DioError catch (e) {
print(e.message);
}
return model;
}