fix(cdk/testing): simulate focusin/focusout events
This is a resubmit of https://github.com/angular/components/pull/23768.
Fixes that our fake fallback focus events weren't dispatching focusin and focusout events as well.
Fixes #23757.
Caretaking Note: spent a couple of hours looking into this, but it turned out to be trickier than expected. The extra events trigger a "changed after checked" error in some apps. Tried to simulate browser events even closer by only emitting the events when elements have focus, but that broke even more apps.
Caretaker note: this change previously caused a few failures in g3.
Ran presubmit recently and got 39 failures. I briefly looked at the test failures and many of them are because the autocomplete element cannot be found. Needs more investigation, but I'm noticing tests that are manually invoking the focusin and focusout event. Perhaps the tests do not need to do that anymore with this change.
@crisbeto it looks like a bunch of tests call .blur() in order to mark form controls as touched and cause error messages to appear, etc. I see the original PR did not have the logic to prevent calling blur if the element was already blurred, so I assume it was added in this re-submit to fix some issue that came up last time.
I wonder could we still fire the focus/blur and just skip the focusin/focusout depending on the current state? I started going through all of the tests to change them to focus and then blur, but the more tests I change the more I feel that this isn't really a desirable change, I think its just going to confuse people about why their blur logic isn't working
When I first submitted the PR, it didn't have all the extra checks around focus and blur, but the new focusin and focusout events ended up causing some "Changed after checked" errors internally. The current state of the PR is me trying to reduce the amount of breakages, but it didn't help much. Ideally we wouldn't have those checks. I can revert it to the initial state if you want to see what failures it was causing.
I figured it was something like that. That's why I'm asking can we always fire the focus/blur events and just guard the focusin/focusout events with the extra hasFocus logic?
Looking at my CL from when I tried to land this (cl/433124526), that's what I tried doing as well but there were still a handful of failures. I can change it here if you want to give it a shot.