Files
pyscript/pyscript.core/tests/integration/conftest.py
Fabio Pliger f77241e977 next integration tests (#1712)
* move integration tests pyscriptjs/tests/integration ->pyscript.core/tests/integration

* add information in regards to how to run integration tests to README

* fix fake server build paths

* fix paths to build and run tests. The change of path before integration tests is a glitch maybe due to pytest cache?

* remove test files created by mistake

* update readme with latest changes

---------

Co-authored-by: Fabio Pliger <fpliger@anaconda.com>
2023-09-15 14:09:07 -07:00

185 lines
5.5 KiB
Python

import shutil
import threading
from http.server import HTTPServer as SuperHTTPServer
from http.server import SimpleHTTPRequestHandler
import pytest
from .support import Logger
def pytest_cmdline_main(config):
"""
If we pass --clear-http-cache, we don't enter the main pytest logic, but
use our custom main instead
"""
def mymain(config, session):
print()
print("-" * 20, "SmartRouter HTTP cache", "-" * 20)
# unfortunately pytest-cache doesn't offer a public API to selectively
# clear the cache, so we need to peek its internal. The good news is
# that pytest-cache is very old, stable and robust, so it's likely
# that this won't break anytime soon.
cache = config.cache
base = cache._cachedir.joinpath(cache._CACHE_PREFIX_VALUES, "pyscript")
if not base.exists():
print("No cache found, nothing to do")
return 0
#
print("Requests found in the cache:")
for f in base.rglob("*"):
if f.is_file():
# requests are saved in dirs named pyscript/http:/foo/bar, let's turn
# them into a proper url
url = str(f.relative_to(base))
url = url.replace(":/", "://")
print(" ", url)
shutil.rmtree(base)
print("Cache cleared")
return 0
if config.option.clear_http_cache:
from _pytest.main import wrap_session
return wrap_session(config, mymain)
return None
def pytest_configure(config):
"""
THIS IS A WORKAROUND FOR A pytest QUIRK!
At the moment of writing this conftest defines two new options, --dev and
--no-fake-server, but because of how pytest works, they are available only
if this is the "root conftest" for the test session.
This means that if you are in the pyscriptjs directory:
$ py.test # does NOT work
$ py.test tests/integration/ # works
This happens because there is also test py-unit directory, so in the first
case the "root conftest" would be tests/conftest.py (which doesn't exist)
instead of this.
There are various workarounds, but for now we can just detect it and
inform the user.
Related StackOverflow answer: https://stackoverflow.com/a/51733980
"""
if not hasattr(config.option, "dev"):
msg = """
Running a bare "pytest" command from the pyscriptjs directory
is not supported. Please use one of the following commands:
- pytest tests/integration
- pytest tests/py-unit
- pytest tests/*
- cd tests/integration; pytest
"""
pytest.fail(msg)
else:
if config.option.dev:
config.option.headed = True
config.option.no_fake_server = True
@pytest.fixture(scope="session")
def logger():
return Logger()
def pytest_addoption(parser):
parser.addoption(
"--no-fake-server",
action="store_true",
help="Use a real HTTP server instead of http://fakeserver",
)
parser.addoption(
"--dev",
action="store_true",
help="Automatically open a devtools panel. Implies --headed and --no-fake-server",
)
parser.addoption(
"--clear-http-cache",
action="store_true",
help="Clear the cache of HTTP requests for SmartRouter",
)
@pytest.fixture(scope="session")
def browser_type_launch_args(request):
"""
Override the browser_type_launch_args defined by pytest-playwright to
support --devtools.
NOTE: this has been tested with pytest-playwright==0.3.0. It might break
with newer versions of it.
"""
# this calls the "original" fixture defined by pytest_playwright.py
launch_options = request.getfixturevalue("browser_type_launch_args")
if request.config.option.dev:
launch_options["devtools"] = True
return launch_options
class DevServer(SuperHTTPServer):
"""
Class for wrapper to run SimpleHTTPServer on Thread.
Ctrl +Only Thread remains dead when terminated with C.
Keyboard Interrupt passes.
"""
def __init__(self, base_url, *args, **kwargs):
self.base_url = base_url
super().__init__(*args, **kwargs)
def run(self):
try:
self.serve_forever()
except KeyboardInterrupt:
pass
finally:
self.server_close()
@pytest.fixture(scope="session")
def dev_server(logger):
class MyHTTPRequestHandler(SimpleHTTPRequestHandler):
enable_cors_headers = True
@classmethod
def my_headers(cls):
if cls.enable_cors_headers:
return {
"Cross-Origin-Embedder-Policy": "require-corp",
"Cross-Origin-Opener-Policy": "same-origin",
}
return {}
def end_headers(self):
self.send_my_headers()
SimpleHTTPRequestHandler.end_headers(self)
def send_my_headers(self):
for k, v in self.my_headers().items():
self.send_header(k, v)
def log_message(self, fmt, *args):
logger.log("http_server", fmt % args, color="blue")
host, port = "localhost", 8080
base_url = f"http://{host}:{port}"
# serve_Run forever under thread
server = DevServer(base_url, (host, port), MyHTTPRequestHandler)
thread = threading.Thread(None, server.run)
thread.start()
yield server # Transition to test here
# End thread
server.shutdown()
thread.join()