* Add get_child_by_id and get_widget_by_id
* Remove redundant code
* Add unit tests for app-level get_child_by_id and get_widget_by_id
* Remove redundant test fixture injection
* Update CHANGELOG
* Enforce uniqueness of ID amongst widget children
* Enforce unique widget IDs amongst widgets mounted together
* Update CHANGELOG.md
* Ensuring unique IDs in a more logical place
* Add docstring to NodeList._get_by_id
* Dont use duplicate IDs in tests, dont mount 2000 widgets
* Mounting less widgets in a unit test
* Reword error message
* Use lower-level depth first search in get_widget_by_id to break out early
These tests are designed to give 100% coverage to the App._on_remove method,
which is the heart of the widget removal system. This is done in
anticipation to some reworking as part of #1094.
Note that, for the moment, there's a bit of a hack in here. These tests need
the pilot. The pilot would need that we await changes to the DOM. Removing
things from the DOM changes the DOM. Remove can't be awaited (see above
change that's coming). So... until such a time as we can await a remove, we
go with a simple await of asyncio.sleep to get things started.
Once #1094 has been done these tests should all still work fine *and* we
should be able to await the removes rather than use the sleeps.