Karma/Jasmin Test Promise error inside of regular function - promise

First my Setup. I try to test some of my Ionic Pages etc.
And I have a login page where I want to test the Login.
This is my Login method:
doLogin() {
let authHelper = this.injector.get(AuthHelper);
authHelper.sendSignInLink(this.email).then(()=> {
window.localStorage.setItem("userMail", this.email);
let loginToast = this.toast.create({
message: "Link to email succesfully send. In order to finish the login, it is necessary to click the send link.",
duration: 3000,
position: "bottom",
});
loginToast.present();
}).catch(() => {
throw new EmailSignInLinkError("invalid Mail");
});
}
As we can see the method sendSignInLink is returning a promise and if the promise is rejected it should throw a custom error.
For my unit test I mocked the authHelperClass to a very simple mock:
export class AuthHelperMock {
public auth(): Promise<any> {
return new Promise((resolve, reject) => {
resolve(2);
});
}
public sendSignInLink(email: String): Promise<any> {
return new Promise((resolve, reject) => {
if (email != undefined || email != "")
resolve(1);
else
reject("Invalid email");
});
}
}
Now is the Problem that I try to check on this thrown error from my promise.
My it case is:
it('should not do the login', () => {
component.email = "";
expect(() => {
component.doLogin();
}).toThrowError(EmailSignInLinkError)
I know that this will not work because the promise is async and the case will fail before it throws the error. But I don't find any suitable solution beside changing my doLogin to a promise as well.
How can I check on this Promise within a regular function?

Related

How to fail cypress test from inside the Promise.prototype.catch() block?

I'm using a node library to execute api calls for test data setup and teardown. The library works as follows:
someApiServiceObject
.executeApiCall({... parameters})
.then(doSomethingWithResults())
.catch(() => {
// Here I would like to fail the test as something has gone wrong
})
If the request fails for some reason, I only learn about it by the Promise returning from executeApiCall function being rejected - hence the catch block.
But if I put throw new Error(); into the catch block or remove the catch block, I can see the (uncaught exception) Error: in the cypress console, but the test still passes.
Can someone advise me on how this case should be handled correctly?
The test:
it('List projects', () => {
projectsApi.projectsList({})
.then(() => {
cy.log('Success');
}).catch(() => {
throw new Error();
});
});
If you call someApiServiceObject.executeApiCall({...parameters}) in a task (since it's a node library), you should just be able to return the promise and Cypress handles failing the test. Don't catch() within the task.
module.exports = (on, config) => {
on('task', {
api(parameters) {
return someApiServiceObject
.executeApiCall({... parameters})
.then(doSomethingWithResults())
},
})
}
If that fails, follow this pattern Return number of files in the folder
module.exports = (on, config) => {
on('task', {
countFiles(folderName) {
return new Promise((resolve, reject) => {
someApiServiceObject
.executeApiCall({... parameters})
.then(doSomethingWithResults())
.then((results) => resolve(results))
.catch((err) => reject(err))
})
})
},
})
}
From comments, I think there's a assumption being made that .executeApiCall() must be returning a promise, but that may not be the case.
For example cy.get(...) has a .then(...) method, but it does not return a promise, it just has a .then() method.
If .executeApiCall() does actually return a promise, the first example is all you need. If it does not, you need to wrap the code.
Cypress will recognise a promise returned from a task, and use resolve or reject accordingly.

error Policy in Apollo Client React does'nt work

I have aproblem when test Apollo.When I try query with apollo and graphql, i want response return error and partical data, so I set property errorPolicy:'all'. But its not work. I don't no why? Help please!
Here my code:
query { animal {
name
age }, school {
name
numberfd } } `
const { loading,data,error} = useQuery(GET_DASHBOARD_DATA, {
errorPolicy:'all',
onCompleted: (res) => {console.log("complete",res)},
onError : (res,data) => {console.log("ERRRR",res,data)},
})
and i want to receive:
{
error:[...], data:[animal:[...]] }
but its only response error.Here is Apollo's doc: https://www.apollographql.com/docs/react/data/error-handling/
onError type is onError?: (error: ApolloError) => void;. You don't have data inside onError callback.
After useQuery you can add:
console.log('data', data)
console.log('error', error)
I faced the same issue with errorPolicy: 'all', I only received the partial result inside onCompleted callback of useQuery, but no errors.
I created an ErrorLink like this:
private createErrorLink = () => {
return new ApolloLink((operation, forward) => {
return forward(operation).map((response) => {
// filter out errors you don't want to display
const errors = filterSomeErrors(response.errors);
if (errors && response?.data) {
response.data.errors = errors;
}
return response;
});
});
};
Now inside my onCompleted callback I get my data as well as errors. You will have to tweak your types a bit, because seems there is no errors field on response.data by default.
Mind that if you use onError from Apollo and return something from the link, it will retry your request containing errors!

Nuxt.js and Laravel Api - 422 Displaying Error instead of Forms

[Error][1]
Hi Team,
Whenever I am receiving the error return from laravel the nuxt.js project displays the error on the page instead the HTML/Forms. How can i handle this.
Here is my php code
return response()->json([
'errors' => [
'email' => ['Sorry we cant find you with those details.'],
],
], 422);
Javascript
async submit() {
await this.$auth.loginWith("local", {
data: this.form
})
In your JavaScript you need to wrap your await promise inside a try catch block. Here's a fix for your JS.
try {
await this.$auth.loginWith("local", {
data: this.form
})
} catch (e) {
return;
}
This is an old question at this point, but I thought I'd post the full code since I was pretty stumped and didn't find many great answers out there:
async handleSubmit() {
try {
const authResponse = await this.$auth.loginWith('local', {
data: this.formData
});
const { status, data } = authResponse;
if (status === 200)
this.createFlashAlert({ 'success': 'Login successful' });
} catch (error) {
if (error.response.status === 422)
this.createFlashAlert(error.response.data);
}
}
So the checklist:
Wrap the login call in a try/catch if you're using async await syntax (be sure to make it an async function i.e. async handleSubmit.
in the catch block, use the error.response object, this is an axios thing. With this you'll be able to access the response status and data.
If you log just the error object, it's not obvious that you can access the response within that error which is what had me stumped.

How to pass a parameter in Koa middleware?

So I have this function in Koa, that basically checks if a user can access a specific route.
exports.requireRole = async role =>
async (ctx, next) => {
const { user } = ctx.state.user;
try {
const foundUser = await User.findById(user.id);
// If the user couldn't be found, return an error
if (!foundUser) {
ctx.status = 404;
ctx.body = { errors: [{ error: ERRORS.USER_NOT_FOUND }] };
} else {
// Otherwise, continue checking role
if (getRole(user.role) >= getRole(role)) {
await next();
}
ctx.status = 403;
ctx.body = { errors: [{ error: ERRORS.NO_PERMISSION }] };
}
} catch (err) {
ctx.throw(500, err);
}
};
And I want to use it as a middleware:
router.delete('/:id', combine([jwtAuth, requireRole(ROLES.ADMIN)]), deleteUser);
But then I get an error saying:
middleware must be a function not object
This happens only when I try to pass an argument into it.
What am I doing wrong here?
The issue you are having is due to the fact that Promises are objects, and async functions return Promises. You need to change your initial function to be as follows:
exports.requireRole = role =>
instead of
exports.requireRole = async role =>
I was going over middleware myself, and ran into this issue as well.
Your middleware looks fine, what is combine?
Also, since you are using koa-router you don't need it.
router.delete('/:id', jwtAuth, requireRole(ROLES.ADMIN), deleteUser);

custom async validation not working when returning a promise

I'm calling the web api to check if an urlalias is available, for this task I'm using a httpservice in my async validator.
The issue is that when the validator is called, all the correct code path is performed (all the console.log() run and behave as expected).
Whether the promise from the validation returns/resolves to null or an { 'isUrlAliasActivityMainAvailable': true }, the controller always shows an error object as following, thus keeping the form state as invalid, why (bloody hell!)?
I'm using: angular:2.1.0 and rxjs:5.0.0-beta.12
This is my formbuilder:
this.formBuilder.group({
//...
"urlAliasActivityMain":[null,[ ValidatorsZr.isUrlAliasActivityMainAvailableAsyncValidator(this.httpActivityService)]],
});
This is my validator:
public static isUrlAliasActivityMainAvailableAsyncValidator(httpActivityService: HttpActivityService) {
return function (control: FormControl): Promise<any> | Observable<any> {
const promise = new Promise<any>(
(resolve, reject) => {
httpActivityService.isUrlAliasActivityMainAvailable(control.value)
.subscribe(
(data: any) => {
console.log("isUrlAliasActivityMainAvailableAsyncValidator");
console.log(data);
if (data == false) {
console.log("data == false");
resolve({ 'isUrlAliasActivityMainAvailable': true });
}
else {
console.log("data == true");
resolve(null);
}
},
)
});
return promise;
}
}
Your async validator is listed in the synchronous validators location in the array and is being incorrectly evaluated.
[objectValue, synchronous validators, asynchronous validators]
control(formState: Object, validator?: ValidatorFn|ValidatorFn[],
asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]) : FormControl
Construct a new FormControl with the given formState,validator, and
asyncValidator.
formState can either be a standalone value for the form control or an
object that contains both a value and a disabled status.
To correct it, move your validator to the appropriate array location:
this.formBuilder.group({
//...
"urlAliasActivityMain":[null, null, ValidatorsZr.isUrlAliasActivityMainAvailableAsyncValidator(this.httpActivityService)],
});

Resources