Saving jasmine expect() results - javascript

Does expect() have a return type (or a promise it fulfills)? If not, how can I store/access the result of an it('should...')'s expect()?
Edited-Clarification: I want to store and use these results during subsequent tests.
Reason: I'd like to make some tests resilient enough to know if they should be skipped because prior tests failed, without having to make the comparison a second time and wait for nested promises to all resolve again.

Have a look at the http://jasmine.github.io/2.3/custom_reporter.html which allows you to be notified of the suite/specs success/failure as they are executed.
You could then store this information in an object which could then be accessible to your specs.

Related

Configure Jest to await all pending promises before tearing down

Is it possible to configure jest to await any pending promises before exiting, to avoid log noise caused by pending code being called after the last test is finished, at which point jest will have torn down the environment?
I have an application which starts by initializing some services asynchronously. If calls are made to these services, the pending background work will first be awaited, and then the task executed. If no calls are made however, the services will invisibly be running init code in the background that no-one cares about.
The problem arises when my tests finish too quickly; if this happens before this pending init work is done, strange things happen - my log gets full of noise which I at first couldn't at all understand - calls like JSON.stringify would fail with cannot access JSON of object null, which turned out to be because jest had torn down the environment so that the global object, containing symbols like JSON was now null (_environment.global.JSON).
I can add an afterAll() hook that simply waits for a second or so, but this seems ugly, and also adds the question what kind of delay is needed; this might break randomly if initialization sometimes takes 100 ms and sometimes 1100 ms.
I could of course add code to afterAll() that makes dummy service calls simply to guarantee that any pending initialization is awaited.
But I would rather like a general, configuration based approach to this, if there is one?
So, is there a way to tell jest to await all pending promises, either before tests start or after?
Or is there a way to tell jest to add a grace period at the end, after all tests, without having to resort to a manual afterAll() call (which must be placed in a file which all tests import, to still have it working properly if only running some tests etc)?
This question actually asks the same question, but the answer with 177 upvotes doesn't do what the question asked for - it simply awaits any promises that are already fulfilled but not handled by the micro tasks queue yet. It does not await any promises that are still pending.

Cloud Functions and Firestore: Using Promise.all() to track multiple documetn modifications

I use a callable Cloud function for creating a new user. For this user, multiple documents in Cloud Firestore are created.
I do not want to store only parts of the data, if one promise (document creation fails), but completely undo the registration, so I use Promise.all(documentCreationPromisses)
So my question is if it is still possible that some documents are created and others are not, although I use Promise.all() ?
Promise.all() returns a promise that tells you if all of the other promises succeeded, or if any one of them failed. It can certainly resolve with a partial set of successes, and there was a failure, you would have to check each individual promise to find out which ones succeeded or failed.
If you are modifying a bunch of documents in Firestore, and you require that all of the modifications either fully succeed, otherwise nothing happens (a full rollback), then you should use a batch write or transaction. With a batch writes and transactions, everything must succeed, or the entire batch fails. The single returned promise from that batch will tell you what happened.

Why does Promise not have a get() function?

If you know that the Promise has already been resolved why can't you just call get() on it and receive the value? As opposed to using then(..) with a callback function.
So instead of doing:
promise.then(function(value) {
// do something with value
});
I want to be able to do the much simpler:
var value = promise.get();
Java offers this for it's CompletableFuture and I see no reason why JavaScript couldn't offer the same.
Java's get method "Waits if necessary for this future to complete", i.e. it blocks the current thread. We absolutely never want to do that in JavaScript, which has only one "thread".
It would have been possible to integrate methods in the API to determine synchronously whether and with what results the promise completed, but it's a good thing they didn't. Having only one single method, then, to get results when they are available, makes things a lot easier, safer and more consistent. There's no benefit in writing your own if-pending-then-this-else-that logic, it only opens up possibilities for mistakes. Asynchrony is hard.
Of course it not, because the task will run asynchronously so you can't get result immediately.
But you can use a sync/await to write sequential asynchronous code.

When do I have to wait for a promise in Protractor?

I know there is similar questions on here about this, but I cannot make sense of them for the life of me.
Here's an example, where I need to click a button and check the url.
My initial thought is I would write it as
element(by.id('button')).click();
expect(browser.getCurrentUrl()).toContain('asyncisconfusing');
I know the expect handles its promise but what about the .click? Shouldn't I have to write it like this?
element(by.id('button')).click().then(() => {
expect(browser.getCurrentUrl()).toContain('asyncisconfusing')
})
Or is protractor/webdriver auto-magically doing this?
In theory, since Protractor maintains a queue of promises via Control Flow and works in sync with an AngularJS application under test, you should not resolve promises explicitly unless you need a real value for further processing. In other words, this should be the prefferred form:
element(by.id('button')).click();
expect(browser.getCurrentUrl()).toContain('asyncisconfusing');
In practice though, explicitly resolving click() promises, or adding explicit waits via browser.wait() helps to deal with occasional and random timing issues.
http://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/promise.html
The first section talks about how the control flow is used to manage promises without having to chain together every single command.

angularJS $q -- stopping execution to wait for all promises

I've got this problem that I couldn't find a solution for by googling.
I've got a library, that I'm using (and do not want to edit, unless it's really necessary) that allows the user to select an item, then calls my custom callback function to modify the item and then continues working with it.
I need to perform some asynchronous tasks on it, which may take some time. This creates a race condition as my async tasks have not yet finished when the callback function is finished and the library continues its work on the item.
library.onItemSelectionCallback = function (item) {
myService.modifyItem(item).then(
function (modifiedItemProperty) {
item.newProperty = modifiedItemProperty;
});
myService.anotherModifyItem(item).then(
function (modifiedItemProperty) {
item.existingProperty = modifiedItemProperty;
});
}
How do I wait for both of my async tasks to finish, before allowing this callback to finish?
Only thing I could think of is looping with while and sleep every hundred or so milliseconds until both of the promises have been resolved, but that doesn't seem to be a very good solution.
I understand that this makes async requests quite synchronous and might possibly be detrimental for UX, but do not really see another way out.
EDIT: I know that i'm risking with removing the generic nature of the question and thus making it too localized, I will say that I'm trying to use angular-file-upload module, specifically, trying to mount a custom imageService, that would resize the picture before it's upload. I'm mounting it on the onBeforeUploadItem callback. The idea is that creating the resized image may take a while and that is why I need to return a promise from my imageService, that needs to be resolved before upload.
If modifyItem and anotherModifyItem work independently (that is, one does not rely on the other), you can just pipe them both into $q.all, eg
library.onItemSelectionCallback = function(item) {
var promises = {
newProperty: myService.modifyItem(item),
existingProperty: myService.anotherModifyItem(item)
};
return $q.all(promises).then(function(values) {
return angular.extend(item, values);
});
}
This will return a promise that resolves with item.
For the first part of my question -- Yes, I guess the only way to really wait for those two promises to be resolved would be something with a while and sleep, making them synchronous, which would probably work and not even be that bad (except for the site pausing until the requests are fulfilled), but would make me feel very, very bad about myself as a person and how my actions affect this world.
It is not possible to correctly mix callbacks and promises without hacks afaik.
For the second part of my question -- as per comments of #georgeawg, figured that an AngularJS module that implements HTML5 API and callbacks instead of $http service and promises is not how a good AngularJS module should be implemented, and so I moved towards a different module ng-file-upload, which, even though one could argue is less stylish, does the job very well and in an Angular way (ng-file-upload provides a simple $upload service, that returns a promise. If you want to modify files before upload, suggested way is to simply $watch and catch the moment user drag-drops or selects a file.).

Categories