Using the notebook's own base class is a great place to start:
It does a number of things to ensure you have a clean setting, like populating HOME. It's harder to not include things that are installed into the environment in which the test is running, but with virtual/conda envs (or something like tox) you can be pretty sure.
Once you have a server: the notebook tests are currently moving away from js-based tests towards python tests with selenium directly
I have been using Robot Framework and it's selenium wrapper a lot recently for testing JupyterLab, but it could certainly test classic:
Here are some (admittedly pretty crazy) tests:
And some of the output, which includes lovely screenshots and timings:
If you want to go the extra meta-mile, a new Robot kernel was released this week: