Throwing a string is not a good practice at all. The normal way is to throw a new Error().
And sure you can just check if any error is thrown? There's no need to forcefully make one only throws a specific error unless that's clarity requirements (which you have none of them, your error requirements are nothing but error and they're even strings).
It's a good kata, and I enjoyed tackling it. There are just a couple of things you could change to make things a littler easier to understand and debug:
As it is, the formatting and spacing is kind of an afterthought, but in actuality, this is the main part of the kata. There are other problems making it hard to parse the instructions first time, also. With just a bit of rejigging and moving stuff around, the understandability would really be helped, I think.
The .normalize() method, while nice, does tend to give the coder cryptic errors from time to time. If a returned value is not a string, a test should fail or error should be thrown explicitly stating that problem, rather than an unrelated error arising after the fact, leaving the coder to scratch their heads, print out the inner-workings of .normalize(), re-read the instructions, and so-on until they figure out what's going on.
Messages like "'undefined' is not a valid time" is a bit too sparse--and misleading--to be that helpful. First, you could actually say that a value was returned, and that an error was expected. Test.expectError is perfect for this. Second, the input value is always wrapped in ' characters, when in reality, the value is rarely a string at all. You can use Test.inspect(value) to generate a readable string of the value in question to use in your errors or test failure messages.
But again, good job on the kata so far!
On the 24 > 12 > 24 tests, 24:XX is not a valid 24h format