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

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.

Related

How to do never finishing Futures in Dart/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.

What is the difference between scheduleFinally and scheduleDeferred in GWT Scheduler?

I could not find my answer in this thread:
Using the GWT Scheduler
The GWT Scheduler class has scheduleDeferred API which executes after the browser event loop returns. The scheduleFinally API allows me to execute code before the control returns to the browser event loop.
How do I decide whether I should use scheduleDeferred or scheduleFinally? Is there a code example which shows the difference in behavior?
To understand this, you need to first get the basic idea of an event loop. When you write code to run in the browser, you don't write this loop - it lives in the browser, waiting for the user to do something. When that something happens (mouse event, keyboard event, AJAX call returns, setTimeout goes off), the loop calls into your code, and lets you handle it however you would like to.
So first, we have scheduleDeferred, which is a way to notify the browser that we have some code to run soon, but not in this loop. This is a handy way to let the browser regain control, render some content, and then give you control again. This can be helpful to break up calculations into several chunks to avoid any "long running script" errors, or can be an early attempt at animation (Note: use the actual requestAnimationFrame api from the browser, or AnimationScheduler.get().requestAnimationFrame in GWT instead for this).
Next, there are two interesting places in the loop where you might have code that you would like to run - either right as the browser transfers control to you, or right before you return control back again. Of these two, the end is usually more interesting: scheduleFinally. This lets you run some code inside the current event loop, but not until the very end of it. CssResource uses this strategy in its ensureInjected() method - when you run several different calls to this method, rather than poking the DOM several times, it batches them all up and runs them at the end of the event loop, using scheduleFinally.
The last one, the beginning of each event loop is managed by another method - scheduleEntry. In theory, this could be used in conjunction with finally to reimplement a simple version of AngularJS's binding wiring.
//event comes in to GWT from the $entry method, and follows these steps
try {
// 1. run registered scheduleEntry calls
// 2. run the current event or callback that the browser called us for
} finally {
// 3. run registered scheduleFinally calls
}
Any call to scheduleDeferred during those steps has added a call to the next event loop, to run as part of #2.

CQRS - can EventListener invoke Command?

I want to use elements of CQRS pattern in my project. I wonder if i do it right with Command and Events.
The thing that I'm not sure is if event can invoke command. To better show what i want to do I will use diagram and example.
This is an example:
User invoke TripCreateCommand. TripCreateCommandHandler do his job and after success publish TripCreatedEvent.
Now we have two listener to TripCreatedEvent (the order of listener execution does not matter)
First listener (can be execute after the second listener):
for each user in trip.author.friends invoke two Command (the order of commands is important)
PublishTripOnUserWallCommand
SendNewTripEmailNotificationCommand
SendNewTripPlatformNotification
Second listener (can be execute before the first listener):
PublishTripOnUserSocials
And this is sample diagram:
Is this a good way ? Can EventListener invoke Command, or maybe I should do it in some other way ?
Your question is about Mesage Driven Architecture which works together with but otherwise unrelated to CQRS.
Anyway, your diagram is almost correct. The event subscriber/handler (I prefer this terminology) can send new Commands via the service bus, but it's not a rule that you should always do this. I implement quite a lot of functionality directly in the event handler, although probalby would be more clean and reliable to send a new command. It really depends on what I want to do.
Note that the message handlers (commands or events) should not know about other handlers. They should know about the bus and the bus takes care of handling. This means that in your app, the event handlers would take the bus as dependency, create the command and send it via the bus. The event handler itself doesn't know what command handler generated the event and can 'reply' to it.
Usually the commands would be handled independently and you can't guarantee the order (unless they're handled synchronously) so maybe you want the second command to be issued as a result of the first command's handling. Indeed, it can be the case for a Saga.
AFAIK you are talking only about doing things synchronously, so your approach works in this case but it's probably not scalable. Moving to async handling will break this execution flow. However your application can be fine with it, not everyhting needs to be twitter.
A message driven architecture is not that straightforward and for some cases (like you want an immediate response from the backend) it's quite complicated to implement, at least more complicated than with the 'standard' approach. So maybe for those particular cases you might want to do it the 'old' way.
If you're worried about decoupling and testing, you can still design the services as they were message handlers but use them directly, instead of a service bus.
Not sure why you would need Commands for performing the updating the information on the user's wall. Why would you choose not to use a View Model Updater for that task.
Sending an email can be considered a Command but could also easily be viewed as just another View Model update.
Not clear on what the purpose of the SendNewTripPlatformNotification is, so I cannot give any suggestions there...
Some of this could also be a candidate for a Saga. Secondly I'm missing your Domain in the diagram, that is what should be responsible for publishing any events, or do you consider the CommandHandler to be the Domain?

Why a form is needed for a SetWinEventHook callback?

Currently, I'm using the powerful SetWinEventHook() function to catch some user-interface's actions like minimizing and maximizing from other window runned by programs on the computer.
So I inspired myself by using the code provided by BrendanMcK on this post and it does work (I mean: the callback function is called when an event occurs) until the line
MessageBox.Show("Something")
is present. But I don't want to use any form or window for this program..
After some research, I figured out this kind of hook needs a message loop to allow the redirection of messages from other window handles. Apparently, calling the thread using Application.Run() should do the trick, but I would prefer something cleaner, in the C# object itself.
So my question is: is it possible to create a message loop inside an object's method?
http://bytes.com/topic/c-sharp/answers/557342-thread-message-loop-c
No, the function doesn't require a window handle so no "form" is needed. But the MSDN docs for the function is quite explicit:
The client thread that calls SetWinEventHook must have a message loop in order to receive events.
A message loop is universal in any program that want to receive notifications that are generated externally by other processes or threads. It is the common solution to the producer-consumer problem. Clearly any GUI app has a need for such a solution, Windows messages are generated by the operating system. It isn't different for SetWinEventHook(), the accessibility events originate in other programs. There is no clean mechanism to "interrupt" a thread and make it run other code, the re-entrancy problems that causes are extremely difficult to deal with. The thread has to co-operate, it must be idle and ready to receive a notification to safely process it. A message loop solves that problem.
Pumping a message loop (calling Application.Run) in a method is certainly possible. But do keep in mind that the method won't return until you explicitly stop the loop with Application.ExitThread. There is therefore usually only one good place for that call, the Main() method of your program.
Starting your project with a Winforms or WPF project template is a very good way to get this right. You have no need to actually create a window, call Application.Run() without an argument, after pinvoking SetWinEventHook.

How to use a WF DelayActivity in an ASP.Net web based workflow

I have a web application that I am adding workflow functionality to using Windows Workflow Foundation. I have based my solution around K. Scott Allen's Orders Workflow example on OdeToCode. At the start I didn't realise the significance of the caveat "if you use Delay activities with and configure active timers for the manual scheduling service, these events will happen on a background thread that is not associated with an HTTP request". I now need to use Delay activities and it doesn't work as is with his solution architecture. Has anyone come across this and found a good solution to this? The example is linked to from a lot of places but I haven't seen anyone else come across this issue and it seems like a bit of a show stopper to me.
Edit: The problem is that the results from the workflow are returned to the the web application via HttpContext. I am using the ManualWorkflowSchedulerService with the useActiveTimers and this works fine for most situations because workflow events are fired from the web app and HttpContext still exists when the workflow results are returned and the web app can continue processing. When a delay activity is used processing happens on a background thread and when it tries to return results to the web app, there is no valid HttpContext (because there has been no Http Request), so further processing fails. That is, the webapp is trying to process the workflow results but there has been no http request.
I think I need to do all post Delay activity processing within the workflow rather than handing off to the web app.
Cheers.
You didn't describe the problem you are having. But maybe this is of some help.
You can use the ManualWorkflowSchedulerService with the useActiveTimers and the workflow will continue on another thread. Normally this is fine because your HTTP request has already finished and it doesn't really matter.
If however you need full control the workflow runtime will let you get a handle on all loaded workflows using the GetLoadedWorkflows() function. This will return acollection of WorkflowInstance objects. usign these you can can call the GetWorkflowNextTimerExpiration() to check which is expired. If one is you can manually resume it. In this case you want to use the ManualWorkflowSchedulerService with the useActiveTimers=false so you can control the last thread as well. However in most cases using useActiveTimers=true works perfectly well.