Repository: pyscript/pyscript
File: pyscriptjs/tests/integration/support.py (Python)

Code before:
        check_errors will not raise, unless NEW JS errors have been reported
        in the meantime.
        """
        exc = None
        if len(self._page_errors) == 1:
            # if there is a single error, wrap it
            exc = JsError(self._page_errors[0])
        elif len(self._page_errors) >= 2:
            exc = JsMultipleErrors(self._page_errors)
        self._page_errors = []
        if exc:
            raise exc

    def clear_errors(self):
        """
        Clear all JS errors.
        """
        self._page_errors = []

    def writefile(self, filename, content):
        """
        Very thin helper to write a file in the tmpdir
        """
        file_dir, _ = os.path.split(filename)
        if file_dir:
            os.makedirs(file_dir, exist_ok=True)
        f = self.tmpdir.join(filename)
        f.write(content)

    def goto(self, path):
        self.logger.reset()
        self.logger.log("page.goto", path, color="yellow")
        url = f"{self.fake_server}/{path}"
        self.page.goto(url, timeout=0)

    def wait_for_console(self, text, *, timeout=None, check_errors=True):
        """
        Wait until the given message appear in the console.

        Note: it must be the *exact* string as printed by e.g. console.log.
        If you need more control on the predicate (e.g. if you want to match a
        substring), use self.page.expect_console_message directly.

        timeout is expressed in milliseconds. If it's None, it will use
        playwright's own default value, which is 30 seconds).

        If check_errors is True (the default), it also checks that no JS
        errors were raised during the waiting.
        """
        pred = lambda msg: msg.text == text
        try:

Review comment (suggestion):
[suggestion/fix]
as you have noticed, `self.tmpdir` is an instance of `py.path.local` (which is a predecessor and inspiration for `pathlib`), which makes it very easy to deal with files, paths and directory. It is a standard feature of `pytest` so I strongly suggest to become familiar with it because it's used in many other python projects, and it's also better to keep consistency inside our own code.
[py.path documentation](https://py.readthedocs.io/en/latest/path.html) (it says not to use it for new projects, but `tmpdir` is used *everywhere* in the python world so I guess it will stay there basically forever).

I also suggest you to put a `pdb.set_trace()` there (or better, `pdbpp`) and play around with the various methods on it. Once you get used to it, you don't want to go back.

In this particular case, you could use `.dirpath()` to get "the directory where the file is contained", and other useful properties are `f.basename`, `f.purebasename` (basename without the extension), `f.ext`, etc.
Or even better, your logic can be rewritten as follows:

```python
        f = self.tmpdir.join(filename)
        f.dirpath().ensure(dir=True)
        f.write(content)
```


Code after:
        self._js_errors.append(error)

    def check_js_errors(self, *expected_messages):
        """
        Check whether JS errors were reported.

        expected_messages is a list of strings of errors that you expect they
        were raised in the page.  They are checked using a simple 'in' check,
        equivalent to this:
            if expected_message in actual_error_message:
                ...

        If an error was expected but not found, it raises
        DidNotRaiseJsError().

        If there are MORE errors other than the expected ones, it raises JsErrors.

        Upon return, all the errors are cleared, so a subsequent call to
        check_js_errors will not raise, unless NEW JS errors have been reported
        in the meantime.
        """
        expected_messages = list(expected_messages)
        js_errors = self._js_errors[:]

        for i, msg in enumerate(expected_messages):
            for j, error in enumerate(js_errors):
                if msg is not None and error is not None and msg in error.message:
                    # we matched one expected message with an error, remove both
                    expected_messages[i] = None
                    js_errors[j] = None

        # if everything is find, now expected_messages and js_errors contains
        # only Nones. If they contain non-None elements, it means that we
        # either have messages which are expected-but-not-found or errors
        # which are found-but-not-expected.
        expected_messages = [msg for msg in expected_messages if msg is not None]
        js_errors = [err for err in js_errors if err is not None]
        self.clear_js_errors()

        if expected_messages:
            # expected-but-not-found
            raise JsErrorsDidNotRaise(expected_messages, js_errors)

        if js_errors:
            # found-but-not-expected
            raise JsErrors(js_errors)

    def clear_js_errors(self):
        """
        Clear all JS errors.
        """