How to do never finishing Futures in Dart/Flutter? - flutter

Imagine the following scenario: A widget shows a "Loading" screen until an async callback completes, then it switches to a different widget.
I'm trying to test it, specifically the part that shows the "Loading" screen. So what I tried to do was mock the async callback and set it to something like Future.delayed(Duration(days: 1)) so that I can be sure that it will never finish within that specific test.
That seems to work, but then flutter gets angry at me and reports issues about pending timers. For some reason all timers have to finish for a test to finish successfully.
So how do I write this test case the correct way? How can I create a future that will never finish and not run into issues with timers?

Another solution would be to use Completer.
future: Completer().future,
will do the trick. However, reading your description, I get the feeling that you might want to rethink your approach since having the need for a never completing future sounds like your code in itself might be the issue.

As I was about to give up, I found out from Dart docs that Future.any([]) essentially achieves this.
If [futures] is empty, or if none of its futures complete, the returned future never completes.

Related

Flutter: Will callback supplied to Timer get fired when application goes to background

In Flutter if I create a Timer, will the supplied callback get executed if the application is in background?
I think documentation is not clear on this or I might have missed it (please supply a link if you find it anywhere).
I just tried doing this with a timer set up to 10 seconds and it works fine.
I assume that is approach is not very reliable and other methods* should be used instead. I think if the app is paused/terminated by operating system to preserve battery or due to low memory, nothing will be executed. But for me this situation could be an ok approach.
* I know there are isolates so I guess I could spawn the timer inside one of these. Downside is that the isolate must be regular function (or static method) so no access to application data in my scenario. Then there are different scheduling packages etc but I'm trying to avoid these for now. I know about background tasks but I'm really looking for an answer on code execution using timers.

Is there any way to get Documents Directory synchroniously?

I need to load a small settings file before showing the first screen.
I'm curently using the PathProvider plugin, but all the functions in it are async.
Is there any way to find the application documents directory synchroniously and then use dart:io sync functions on it? Instead of showing a placeholder for infinite decimal of a second.
EDIT: considering the first 2 answers, probably my explaination was really bad. The answers suggested me to still use async code. Problem is, I need the directory before runApp(), and I dont want my void main() to be async, because this ruins any splash animation for sure.
And the PathProvider API is async, as far as I can see, only because it utilizes MethodChannel, which is async, but functions behind it in PathProvider are pretty much synchronious.
What I'm asking is - is there a way, on Android or IOS, to know ApplicationDocumentsDirectory in sync code? Maybe without using platform-specific code at all?
You can use FutureBuilder for the same purpose without having to worry about execution.
It will allow you to do your process in the background and allows you to show a splash screen UI until your specified process is complete and data is ready to use.
Note: Any plugin or code which needs access to the device's native method channel will be async by default, since access of the method channel itself is supposed to be async.

How should I test functionality accessible only during the lifetime of an async method using #testing-library/react?

I have a React component which allows users to submit potentially long-running queries to a remote service. While the query is running, the component shows a cancel button. I want to test that this button shows up when expected, that its click handler cancels the previous API request, and so on.
Since the button is only present while the async API call is active, the tests I wrote for this purpose make their assertions about the button in the mock implementation of the async API itself. They're not super elegant but I confirmed that they do go red as I expect when I remove parts of the production code.
On upgrading #testing-library/react from 8.0.1 to 9.3.2, although the tests still pass, I now get the following warning several times:
console.error node_modules/#testing-library/react/dist/act-compat.js:52
Warning: You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one.
I have reproduced the issue in the following CodeSandbox (be sure to selected the "Tests" tab on the right-hand side and then view the "Console" messages at the bottom right).
The final comment on this GitHub issue says that I shouldn't need to worry about act() as long as I'm using the React Testing Library helpers and functions (which I am). What am I missing?
Raising an issue (here) against react-testing-library has helped me reach the conclusion that the best approach seems to be not to worry about it too much. The library's author was kind enough to propose a simpler test pattern of just making assertions directly after the action that causes the component to enter the transient state that you're trying to test. For example:
fireEvent.click(getByText("Submit")); // <-- action which triggers an async API call
expect(getByText("Fetching answers")).toBeInTheDocument();
Previously, I had the same expect statement in my mock implementation of the API call triggered by the click. My reasoning was that this was the only way I could be certain that the assertions would run while the component was in the transient state I was trying to test.
AFAICT, these tests are not strictly correct with respect to asynchronous actions because the promise returned by the mock implementation could resolve before the expectation was checked. In practice though, I have observed that the tests rewritten to the simpler approach:
do not provoke the warning about overlapping act() calls in the OP
can be made to fail as expected if I change the non-test code to break the behaviour under test
have not so far shown any intermittent failures
are far easier to read and understand
This question has never attracted much attention but I hope recording the answer I eventually arrived at myself might help others out in future.

E2E Best Practices - Waiting for Elements on the Page

Recently, our team has adopted blue-harvest for E2E testing which seems to be a wrapper around Protractor.
I noticed that our tests are flimsy in that sometimes they pass and sometimes they don't. Even if nothing changes, and you just run them again, the results are intermittent.
I feel like one of the reasons is because we have so many timeouts littered across our tests to wait for things to be clickable, visible, etc.
In terms of best practices, is it common to always have to wait for things to be on the page before clicking on them or interacting with them to test them?
I feel like using slow (in the case of blue-harvest), or even agonizinglySlow doesn't look good and is the effect of flimsy tests.
If I do choose to continue going down this route, is it better to make everything always wait? Instead of having some tests written as:
await slow.see('My Element');
await click('My Element');
await click('Another Element');
await slow.see('Another Element');
Should I just be consistent and make everything slow?
Thanks
To be honest I don't know blue-harvest at all but I know protractor very well.
Because protractor is a wrapper on Selenium with the support for Angular, we generally don't need to wait after each operation on page. The protractor know when Angular application works and stops the test execution until Angular finish their work.
However we should still wait manually for more complex operations.
I would recommend to reduce the number of waits to minimum and use it only in special cases. However much better are ExpectedConditions from protractor https://www.protractortest.org/#/api?view=ProtractorExpectedConditions.prototype.elementToBeClickable

Waiting for a Future to complete before making assertions

I have a Scala Play application and one of the controllers fires a Future which does some logging. I have a simple call back function which executes when the Future completes.
I have written a test to check whether this logging happens. The rough logic is as follows:
feature{
scenario{
Given()
// set up the call
When()
// make a FakeRequest via reverse routing - logging will done in a separate thread via a Future
Then()
Thread.sleep(50) // sleep to allow logging to finish
// check if the logging has been done
The issue is the Thread.sleep. I have added that call in to block the main testing thread in order to give enough time to elapse for the Future which does the logging in a separate thread to complete before actually doing the checks to see if the logging has been done.
My question is whether there is a better way to do this? In reality if my application is running and the logging is taking an inordinate amount of time, then the main thread which governs the application will not terminate until the Future that does the logging in a separate thread finishes. So I don't see a problem of putting in the Thread call above to simulate that. But I just want to confirm if this is correct.
For me, there is absolutely no other way than to do this. If I try to replicate how the app behaves in reality with my test, then the main thread for the test should complete and terminate even though the future for the logging is still going on; there is no call back in the test and neither should there be.
Assuming you're using ScalaTest ; you can use whenReady construct ; which periodically inspects the passed future, until it is either ready or the configured timeout has been surpassed;
see
http://www.artima.com/docs-scalatest-2.0.M5/org/scalatest/concurrent/Futures.html
http://doc.scalatest.org/2.0/index.html#org.scalatest.concurrent.ScalaFutures