A while back I decided to make a progressive web-app and for the fun of it, learn a new framework (Angular 7 at the time, 9 now), language (TypeScript) and to top it all off, challenge myself by test driving the entire thing.
From the very inception, I decided to test drive my app and to do it only with unit tests and depending on your definition, integration tests. After years of writing, re-writing and maintaining end-2-end tests, I figured one thing only: they are a waste of time and money. So my entire app is test driven by jasmine specs, starting at individual components (or a service) and moving onto a combination of components (how they work together) and culminating with the main component which is mostly in charge of testing navigation through out the app.
Now, to test a component in Angular (to the best of my knowledge and understanding) is to test a template and associate code together as one thing (unit of work). This represents a bit of a challenge, mostly associated with manipulation of UI. Effectively you will be doing a lot of query selections, clicking, and sometimes dealing with async and Angular change detection. Since I get to work on my app few hours per week, I tend to forget (sometimes rather quickly) fine details of writing a component test. Like the saying goes: “if you can’t beat them, join them”, so I gave up on constant rehashing and decided to write my own test helper, which is easy to use and doesn’t need much to remember. For example, find an element with the placeholder value of “name”.
In addition to all of the above, jasmine errors tend to be verbose and not very user friendly. For example if you are trying to query select all elements, which don’t exist (but you assumed they did) and then call a method on a particular one, you will be met with off-putting exception “undefined is not an object”.
TypeError: undefined is not an object (evaluating 'this.findElementsByPlaceholder(placeholder)') in http://localhost:9876/karma_webpack/main.js (line 3909)
I believe we can do better than that. We can wrap “query select all” calls in your own method, check length and if there are no elements then simply throw an error with explanation. For example:
Error: Could not find a placeholder: name in either of tags: placeholder,ng-reflect-placeholder in http://localhost:9876/karma_webpack/main.js (line 3906)
By doing so, you effectively eliminate confusion and save yourself some time (at least I do). So go out there and throw some well-explained exceptions, so you don’t have to guess which object is undefined and why.