The thing that I am testing is kinda OK. It is a map of the text contents of <div> elements. I could do without the map(), but it's not horrible. The toList() is bothersome. It can be omitted, but it is useful to have around. For instance, if I cause an intentional failure by naming the menu "Saved Code" instead of "Saved Projects", I get a nice error message that gives me an idea of what went wrong:

So I leave toList() as a bit of test code ugliness so that I get nicer test code output. I can live with that.

The expected value is not quite as nice. Dart provides a nice matcher for lists: contains(). So in this case I am expecting a list that contains something. That something is anything that matches the string 'Saved Projects'. It works, but it is hard to read.

But hard to read matchers are what custom matchers are for. For this expectation, I may not even need to write an entirely new matcher. Instead, I start by inheriting from CustomMatcher. These nifty little things set a description ("List of elements") and a feature name ("Element list content") in the constructor:

I then pick a value to extract from the actual value. If the actual value is a list of elements, then the above extracts the text contents in List form. That is just what I had to do by hand in my test, but all of the ugliness of mapping and converting from an iterable to a list is done in the custom matcher.

I then create a top-level helper that uses this matcher to check the extracted/featured list to see if it contains a match:

That is even more expressive than what I had when I manually extracted a list to test and the test content is easier to read. The use of the helpers prefix from last night is the only remaining noise (and I still think it worth keeping about). All in all, these test matchers are pretty powerful.