| 109 | |
| 110 | |
| 111 | class Server: |
| 112 | protocol = "http" |
| 113 | |
| 114 | def __init__(self) -> None: |
| 115 | self.PORT = find_free_port() |
| 116 | self.EMPTY_PAGE = f"{self.protocol}://localhost:{self.PORT}/empty.html" |
| 117 | self.PREFIX = f"{self.protocol}://localhost:{self.PORT}" |
| 118 | self.CROSS_PROCESS_PREFIX = f"{self.protocol}://127.0.0.1:{self.PORT}" |
| 119 | # On Windows, this list can be empty, reporting text/plain for scripts. |
| 120 | mimetypes.add_type("text/html", ".html") |
| 121 | mimetypes.add_type("text/css", ".css") |
| 122 | mimetypes.add_type("application/javascript", ".js") |
| 123 | mimetypes.add_type("image/png", ".png") |
| 124 | mimetypes.add_type("font/woff2", ".woff2") |
| 125 | |
| 126 | def __repr__(self) -> str: |
| 127 | return self.PREFIX |
| 128 | |
| 129 | @abc.abstractmethod |
| 130 | def listen(self, factory: TestServerFactory) -> None: |
| 131 | pass |
| 132 | |
| 133 | def start(self) -> None: |
| 134 | request_subscribers: Dict[str, asyncio.Future] = {} |
| 135 | auth: Dict[str, Tuple[str, str]] = {} |
| 136 | csp: Dict[str, str] = {} |
| 137 | routes: Dict[str, Callable[[TestServerRequest], Any]] = {} |
| 138 | gzip_routes: Set[str] = set() |
| 139 | self.request_subscribers = request_subscribers |
| 140 | self.auth = auth |
| 141 | self.csp = csp |
| 142 | self.routes = routes |
| 143 | self.gzip_routes = gzip_routes |
| 144 | self.static_path = _dirname / "assets" |
| 145 | factory = TestServerFactory() |
| 146 | factory.server_instance = self |
| 147 | self.listen(factory) |
| 148 | |
| 149 | async def wait_for_request(self, path: str) -> TestServerRequest: |
| 150 | if path in self.request_subscribers: |
| 151 | return await self.request_subscribers[path] |
| 152 | future: asyncio.Future["TestServerRequest"] = asyncio.Future() |
| 153 | self.request_subscribers[path] = future |
| 154 | return await future |
| 155 | |
| 156 | @contextlib.contextmanager |
| 157 | def expect_request(self, path: str) -> Generator[ExpectResponse[TestServerRequest], None, None]: |
| 158 | future = asyncio.create_task(self.wait_for_request(path)) |
| 159 | |
| 160 | cb_wrapper: ExpectResponse[TestServerRequest] = ExpectResponse() |
| 161 | |
| 162 | def done_cb(task: asyncio.Task) -> None: |
| 163 | cb_wrapper._value = future.result() |
| 164 | |
| 165 | future.add_done_callback(done_cb) |
| 166 | yield cb_wrapper |
| 167 | |
| 168 | def set_auth(self, path: str, username: str, password: str) -> None: |
nothing calls this directly
no outgoing calls
no test coverage detected