Skip to content

ConfigModule

Bootstrap configuration submodule mounted at /_test/config. Carries the per-process session state and exposes the two endpoints the runner uses to acquire/release the session token.

ConfigModule

Bases: Module

Bootstrap configuration module mounted under /_test/config.

Holds the per-process session state as class attributes and exposes two endpoints:

  • POST /json/_test/config/status — verify the runtime is consistent (dev server + correct datastore database), then read or create the session token entity in the test database and return it. POST-only to block drive-by GETs from another browser tab on the same machine (CORS preflight stops the cross-origin call).
  • POST /json/_test/config/finish — verify the runtime, delete the token entity, clear the in-process token.
Source code in src/viur/testing/_test/config.py
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
class ConfigModule(Module):
    """Bootstrap configuration module mounted under ``/_test/config``.

    Holds the per-process session state as class attributes and exposes
    two endpoints:

    - ``POST /json/_test/config/status`` — verify the runtime is consistent
      (dev server + correct datastore database), then read or create
      the session token entity in the test database and return it.
      POST-only to block drive-by GETs from another browser tab on
      the same machine (CORS preflight stops the cross-origin call).
    - ``POST /json/_test/config/finish`` — verify the runtime, delete the
      token entity, clear the in-process token.
    """

    handler = "config"
    accessRights = None

    # ----- mount guards -----------------------------------------------------

    def __init__(
        self,
        moduleName: str = "config",
        modulePath: str = "_test/config",
        *args: t.Any,
        **kwargs: t.Any,
    ) -> None:
        """Refuse to instantiate unless the runtime is in test mode.

        Defense in depth: :class:`~viur.testing._test.TestModule` already
        checks both conditions before constructing the container, but a
        host project might bypass the container and mount ConfigModule
        directly. The same two guards are repeated here so that a direct
        mount cannot accidentally end up in production or run before
        :func:`viur.testing.activate` has wired the datastore client.
        """
        from viur.core.config import conf  # noqa: PLC0415 — fresh lookup on each instantiation

        if not getattr(conf.instance, "is_dev_server", False):
            raise RuntimeError(
                "viur-testing: ConfigModule refuses to instantiate outside a local "
                "dev server. conf.instance.is_dev_server is False."
            )
        if type(self)._database is None:
            raise RuntimeError(
                "viur-testing: ConfigModule cannot mount because viur.testing.activate() "
                "has not been called yet. Move the activate() call to the very top "
                "of main.py, before the modules package is imported."
            )
        super().__init__(moduleName, modulePath, *args, **kwargs)

    # ----- per-process state ------------------------------------------------

    _database: t.ClassVar[str | None] = None
    _namespace: t.ClassVar[str | None] = None
    _project_id: t.ClassVar[str | None] = None
    _token: t.ClassVar[str | None] = None

    # Project-supplied hooks. Each hook returns an optional dict whose
    # entries get merged into the JSON response of /_test/config/status
    # or /_test/config/finish. See :meth:`register_status_hook` and
    # :meth:`register_finish_hook`.
    _status_hooks: t.ClassVar[list[t.Callable[[], dict | None]]] = []
    _finish_hooks: t.ClassVar[list[t.Callable[[], dict | None]]] = []

    @classmethod
    def is_active(cls) -> bool:
        """Whether :func:`viur.testing.activate` has wired the process."""
        return cls._database is not None

    @classmethod
    def has_token(cls) -> bool:
        """Whether a session is currently established (a token is issued)."""
        return cls._token is not None

    @classmethod
    def current_database(cls) -> str | None:
        return cls._database

    @classmethod
    def current_project_id(cls) -> str | None:
        return cls._project_id

    @classmethod
    def current_namespace(cls) -> str | None:
        """Datastore namespace this process is scoped to, or ``None`` for
        the default namespace.
        """
        return cls._namespace

    @classmethod
    def current_token(cls) -> str | None:
        return cls._token

    @classmethod
    def current_token_hash(cls) -> str | None:
        if cls._token is None:
            return None
        return hashlib.sha256(cls._token.encode("utf-8")).hexdigest()

    @classmethod
    def set_active(
        cls, *, database: str, project_id: str, namespace: str | None = None,
    ) -> None:
        """Mark the process as test-mode active.

        Idempotent for matching ``(database, project_id, namespace)``;
        refuses to silently overwrite a mismatching prior activation.

        ``namespace=""`` is normalised to ``None`` — same convention as
        :func:`viur.testing.activate` and the ``VIUR_TESTING`` namespace
        part. Without this normalisation a direct call with the
        empty string followed by an :func:`activate`-driven call with
        ``None`` (or vice-versa) would falsely report a mismatch.
        """
        if namespace == "":
            namespace = None
        if cls._database is None:
            cls._database = database
            cls._project_id = project_id
            cls._namespace = namespace
            return
        if (
            cls._database != database
            or cls._project_id != project_id
            or cls._namespace != namespace
        ):
            raise RuntimeError(
                f"ConfigModule is already active for "
                f"(database={cls._database!r}, namespace={cls._namespace!r}, "
                f"project_id={cls._project_id!r}); refusing to switch to "
                f"(database={database!r}, namespace={namespace!r}, "
                f"project_id={project_id!r})."
            )

    @classmethod
    def set_token(cls, token: str) -> None:
        """Record the current session token. Requires prior :meth:`set_active`."""
        if cls._database is None:
            raise RuntimeError("ConfigModule is not active; cannot set token.")
        cls._token = token

    @classmethod
    def clear_token(cls) -> None:
        """Drop the session token. Test-mode itself stays active."""
        cls._token = None

    @classmethod
    def register_status_hook(cls, hook: t.Callable[[], dict | None]) -> None:
        """Register a project-side callback that fires inside ``/_test/config/status``.

        The hook is invoked after the token has been issued and the
        in-process state primed, but **before** the JSON response is
        serialised. If it returns a dict, the entries are merged into
        the response payload (later hooks win on conflicting keys).
        Side effects on ``viur.core.conf`` are allowed — useful for
        seeding project-specific config that every test relies on.

        Registrations survive across calls to :meth:`reset` only if
        the host re-runs the registration; ``reset()`` clears the
        hook list along with the rest of the state.

        :param hook: A zero-argument callable returning ``dict | None``.
        """
        cls._status_hooks.append(hook)

    @classmethod
    def register_finish_hook(cls, hook: t.Callable[[], dict | None]) -> None:
        """Register a project-side callback that fires inside ``/_test/config/finish``.

        Same shape as :meth:`register_status_hook`: optional dict
        return value is merged into the ``finish`` response.
        """
        cls._finish_hooks.append(hook)

    @classmethod
    def reset(cls) -> None:
        """Clear all state. Intended for tests only."""
        cls._database = None
        cls._namespace = None
        cls._project_id = None
        cls._token = None
        cls._status_hooks = []
        cls._finish_hooks = []

    # ----- private helpers --------------------------------------------------

    @classmethod
    def _require_runtime_consistency(cls) -> None:
        """Re-verify dev-server + datastore database before any DB op.

        Defense in depth: the endpoints are reachable without the token
        header (whitelisted in the validator), so they must re-check
        the environment themselves. A mismatch means the host has been
        misconfigured or the activation step never ran.
        """
        from viur.core.config import conf  # noqa: PLC0415

        if not getattr(conf.instance, "is_dev_server", False):
            raise Forbidden("viur-test: server is not in dev mode")

        if cls._database is None:
            raise Forbidden("viur-test: activate() has not been called")

        from viur.core.db import transport  # noqa: PLC0415

        actual_db = getattr(transport.__client__, "database", None)
        if actual_db != cls._database:
            raise Forbidden(
                f"viur-test: datastore client is on database={actual_db!r}, "
                f"expected {cls._database!r}"
            )

    @classmethod
    def _token_key(cls):
        from viur.core.db import transport  # noqa: PLC0415
        return transport.__client__.key(TOKEN_KIND, TOKEN_ENTITY_NAME)

    @classmethod
    def _current_day(cls) -> str:
        """UTC calendar day as ``YYYY-MM-DD``. Isolated so tests can pin it."""
        return datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d")

    @classmethod
    def _compute_daily_token(cls) -> str:
        """Deterministic per-day session token.

        Identical for the whole UTC day and stable across server restarts,
        :meth:`finish` calls and re-issues — so a cookie armed once via
        ``/_test/config/enter`` keeps working all day; it rotates at UTC
        midnight. Derived from the session identity (database, namespace,
        project id) plus the day, so distinct slices and distinct days never
        share a token.

        Not a secret: ``/_test/config/status`` already hands the token to any
        local caller, and the production guard + dev-server gate remain the
        real protection. Determinism is the point — see :meth:`_read_or_create_token`.
        """
        material = "\0".join([
            "viur-testing-daily-token-v1",
            cls._database or "",
            cls._namespace or "",
            cls._project_id or "",
            cls._current_day(),
        ])
        digest = hashlib.sha256(material.encode("utf-8")).digest()
        return base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii")

    @classmethod
    def _read_or_create_token(cls) -> str:
        """Return today's deterministic token, persisting it in the test DB.

        The stored entity is (re)written whenever it is missing or holds a
        different value — e.g. on the first call of a new day, or after a
        stale entity from a previous day — so the DB always mirrors the
        active token and :meth:`finish` can report ``had_token`` correctly.
        """
        from google.cloud import datastore as gcds  # noqa: PLC0415
        from viur.core.db import transport  # noqa: PLC0415

        token = cls._compute_daily_token()
        key = cls._token_key()
        existing = transport.__client__.get(key)
        if existing is None or existing.get(TOKEN_PROPERTY) != token:
            entity = gcds.Entity(key=key)
            entity[TOKEN_PROPERTY] = token
            transport.__client__.put(entity)
        return token

    @classmethod
    def _delete_token(cls) -> bool:
        """Delete the token entity from the DB. ``True`` if one was present."""
        from viur.core.db import transport  # noqa: PLC0415

        key = cls._token_key()
        existed = transport.__client__.get(key) is not None
        transport.__client__.delete(key)
        return existed

    # ----- HTTP endpoints ---------------------------------------------------

    @staticmethod
    def _json_response(payload: dict) -> str:
        """Serialise ``payload`` to JSON and set the response Content-Type.

        viur-core endpoints return the response body as a *string* — a raw
        ``dict`` would be coerced to ``str(payload)`` which is Python repr,
        not JSON. Mirroring what
        :class:`viur.core.render.json.default.DefaultRender` does: dump
        explicitly and announce ``application/json``.
        """
        current.request.get().response.headers["Content-Type"] = "application/json"
        return json.dumps(payload)

    @staticmethod
    def _set_token_cookie(token: str) -> None:
        """Set the session token as a ``viur-test-token`` cookie.

        ``SameSite=Strict; HttpOnly; Path=/`` — ``Secure`` only on HTTPS so
        it still works on a plain-HTTP ``http://localhost`` dev server. The
        cookie is the canonical transport: once set, the browser attaches it
        to every request, including hard navigations.
        """
        handler = current.request.get()
        secure = getattr(handler.request, "scheme", "http") == "https"
        handler.response.set_cookie(
            TOKEN_COOKIE,
            token,
            path="/",
            secure=secure,
            httponly=True,
            samesite="Strict",
        )

    @staticmethod
    def _clear_token_cookie() -> None:
        """Expire the ``viur-test-token`` cookie (used by ``finish``)."""
        handler = current.request.get()
        handler.response.delete_cookie(TOKEN_COOKIE, path="/")

    @staticmethod
    def _enter_confirmation_html() -> str:
        """Minimal HTML body for the ``enter`` GET navigation."""
        current.request.get().response.headers["Content-Type"] = "text/html; charset=utf-8"
        return (
            "<!doctype html><meta charset=utf-8><title>viur-testing</title>"
            "<p>Test session armed — the <code>viur-test-token</code> cookie is set. "
            "You can now browse the test instance directly.</p>"
        )

    @exposed
    @force_post
    def status(self) -> str:
        """Begin (or resume) a test session.

        Reads the token entity from the test database; creates it on
        first call. Updates the in-process state so the request
        validator starts accepting the token. Returns the full session
        info, including the token, to the runner.

        POST-only on purpose: a third-party browser tab on the same
        machine cannot issue a cross-origin POST without CORS preflight,
        so it cannot drive-by trigger a session through this endpoint.
        """
        cls = type(self)
        cls._require_runtime_consistency()
        token = cls._read_or_create_token()
        cls.set_token(token)

        from viur.testing import __version__  # noqa: PLC0415

        payload: dict = {
            "test_mode": True,
            "is_dev_server": True,
            "database": cls._database,
            "namespace": cls._namespace,
            "project_id": cls._project_id,
            "token": token,
            "token_hash": cls.current_token_hash(),
            "version": __version__,
        }
        for hook in cls._status_hooks:
            extra = hook()
            if extra:
                payload.update(extra)
        return self._json_response(payload)

    @exposed
    def enter(self) -> str:
        """Arm a manual browsing session by setting the token cookie.

        Reached by a plain **GET** navigation (address bar, link, reload)
        before any cookie exists — hence a bootstrap path. Reads/creates the
        session token, primes the in-process state, and sets the
        ``viur-test-token`` cookie. Afterwards every request the browser makes
        — including hard navigations and server-rendered pages — carries the
        cookie, so the developer can browse the test instance directly without
        a header-injecting proxy or browser extension.

        GET (not POST) on purpose: you navigate to it. A cross-site drive-by
        could trigger it, but the resulting cookie is ``SameSite=Strict`` and
        scoped to this (dev-only, localhost) host, so it cannot be used from
        another site — see the security note in the README.
        """
        cls = type(self)
        cls._require_runtime_consistency()
        token = cls._read_or_create_token()
        cls.set_token(token)
        cls._set_token_cookie(token)
        return self._enter_confirmation_html()

    @exposed
    @force_post
    def finish(self) -> str:
        """End the current test session.

        Deletes the token entity from the test database, clears the
        in-process token and expires the cookie. Test-mode itself stays
        armed — the next call to :meth:`status`/:meth:`enter` will provision
        a fresh token.
        """
        cls = type(self)
        cls._require_runtime_consistency()
        existed = cls._delete_token()
        cls.clear_token()
        cls._clear_token_cookie()

        payload: dict = {"finished": True, "had_token": existed}
        for hook in cls._finish_hooks:
            extra = hook()
            if extra:
                payload.update(extra)
        return self._json_response(payload)

__init__

__init__(moduleName: str = 'config', modulePath: str = '_test/config', *args: Any, **kwargs: Any) -> None

Refuse to instantiate unless the runtime is in test mode.

Defense in depth: :class:~viur.testing._test.TestModule already checks both conditions before constructing the container, but a host project might bypass the container and mount ConfigModule directly. The same two guards are repeated here so that a direct mount cannot accidentally end up in production or run before :func:viur.testing.activate has wired the datastore client.

Source code in src/viur/testing/_test/config.py
def __init__(
    self,
    moduleName: str = "config",
    modulePath: str = "_test/config",
    *args: t.Any,
    **kwargs: t.Any,
) -> None:
    """Refuse to instantiate unless the runtime is in test mode.

    Defense in depth: :class:`~viur.testing._test.TestModule` already
    checks both conditions before constructing the container, but a
    host project might bypass the container and mount ConfigModule
    directly. The same two guards are repeated here so that a direct
    mount cannot accidentally end up in production or run before
    :func:`viur.testing.activate` has wired the datastore client.
    """
    from viur.core.config import conf  # noqa: PLC0415 — fresh lookup on each instantiation

    if not getattr(conf.instance, "is_dev_server", False):
        raise RuntimeError(
            "viur-testing: ConfigModule refuses to instantiate outside a local "
            "dev server. conf.instance.is_dev_server is False."
        )
    if type(self)._database is None:
        raise RuntimeError(
            "viur-testing: ConfigModule cannot mount because viur.testing.activate() "
            "has not been called yet. Move the activate() call to the very top "
            "of main.py, before the modules package is imported."
        )
    super().__init__(moduleName, modulePath, *args, **kwargs)

is_active classmethod

is_active() -> bool

Whether :func:viur.testing.activate has wired the process.

Source code in src/viur/testing/_test/config.py
@classmethod
def is_active(cls) -> bool:
    """Whether :func:`viur.testing.activate` has wired the process."""
    return cls._database is not None

has_token classmethod

has_token() -> bool

Whether a session is currently established (a token is issued).

Source code in src/viur/testing/_test/config.py
@classmethod
def has_token(cls) -> bool:
    """Whether a session is currently established (a token is issued)."""
    return cls._token is not None

current_namespace classmethod

current_namespace() -> str | None

Datastore namespace this process is scoped to, or None for the default namespace.

Source code in src/viur/testing/_test/config.py
@classmethod
def current_namespace(cls) -> str | None:
    """Datastore namespace this process is scoped to, or ``None`` for
    the default namespace.
    """
    return cls._namespace

set_active classmethod

set_active(*, database: str, project_id: str, namespace: str | None = None) -> None

Mark the process as test-mode active.

Idempotent for matching (database, project_id, namespace); refuses to silently overwrite a mismatching prior activation.

namespace="" is normalised to None — same convention as :func:viur.testing.activate and the VIUR_TESTING namespace part. Without this normalisation a direct call with the empty string followed by an :func:activate-driven call with None (or vice-versa) would falsely report a mismatch.

Source code in src/viur/testing/_test/config.py
@classmethod
def set_active(
    cls, *, database: str, project_id: str, namespace: str | None = None,
) -> None:
    """Mark the process as test-mode active.

    Idempotent for matching ``(database, project_id, namespace)``;
    refuses to silently overwrite a mismatching prior activation.

    ``namespace=""`` is normalised to ``None`` — same convention as
    :func:`viur.testing.activate` and the ``VIUR_TESTING`` namespace
    part. Without this normalisation a direct call with the
    empty string followed by an :func:`activate`-driven call with
    ``None`` (or vice-versa) would falsely report a mismatch.
    """
    if namespace == "":
        namespace = None
    if cls._database is None:
        cls._database = database
        cls._project_id = project_id
        cls._namespace = namespace
        return
    if (
        cls._database != database
        or cls._project_id != project_id
        or cls._namespace != namespace
    ):
        raise RuntimeError(
            f"ConfigModule is already active for "
            f"(database={cls._database!r}, namespace={cls._namespace!r}, "
            f"project_id={cls._project_id!r}); refusing to switch to "
            f"(database={database!r}, namespace={namespace!r}, "
            f"project_id={project_id!r})."
        )

set_token classmethod

set_token(token: str) -> None

Record the current session token. Requires prior :meth:set_active.

Source code in src/viur/testing/_test/config.py
@classmethod
def set_token(cls, token: str) -> None:
    """Record the current session token. Requires prior :meth:`set_active`."""
    if cls._database is None:
        raise RuntimeError("ConfigModule is not active; cannot set token.")
    cls._token = token

clear_token classmethod

clear_token() -> None

Drop the session token. Test-mode itself stays active.

Source code in src/viur/testing/_test/config.py
@classmethod
def clear_token(cls) -> None:
    """Drop the session token. Test-mode itself stays active."""
    cls._token = None

register_status_hook classmethod

register_status_hook(hook: Callable[[], dict | None]) -> None

Register a project-side callback that fires inside /_test/config/status.

The hook is invoked after the token has been issued and the in-process state primed, but before the JSON response is serialised. If it returns a dict, the entries are merged into the response payload (later hooks win on conflicting keys). Side effects on viur.core.conf are allowed — useful for seeding project-specific config that every test relies on.

Registrations survive across calls to :meth:reset only if the host re-runs the registration; reset() clears the hook list along with the rest of the state.

Parameters:

Name Type Description Default
hook Callable[[], dict | None]

A zero-argument callable returning dict | None.

required
Source code in src/viur/testing/_test/config.py
@classmethod
def register_status_hook(cls, hook: t.Callable[[], dict | None]) -> None:
    """Register a project-side callback that fires inside ``/_test/config/status``.

    The hook is invoked after the token has been issued and the
    in-process state primed, but **before** the JSON response is
    serialised. If it returns a dict, the entries are merged into
    the response payload (later hooks win on conflicting keys).
    Side effects on ``viur.core.conf`` are allowed — useful for
    seeding project-specific config that every test relies on.

    Registrations survive across calls to :meth:`reset` only if
    the host re-runs the registration; ``reset()`` clears the
    hook list along with the rest of the state.

    :param hook: A zero-argument callable returning ``dict | None``.
    """
    cls._status_hooks.append(hook)

register_finish_hook classmethod

register_finish_hook(hook: Callable[[], dict | None]) -> None

Register a project-side callback that fires inside /_test/config/finish.

Same shape as :meth:register_status_hook: optional dict return value is merged into the finish response.

Source code in src/viur/testing/_test/config.py
@classmethod
def register_finish_hook(cls, hook: t.Callable[[], dict | None]) -> None:
    """Register a project-side callback that fires inside ``/_test/config/finish``.

    Same shape as :meth:`register_status_hook`: optional dict
    return value is merged into the ``finish`` response.
    """
    cls._finish_hooks.append(hook)

reset classmethod

reset() -> None

Clear all state. Intended for tests only.

Source code in src/viur/testing/_test/config.py
@classmethod
def reset(cls) -> None:
    """Clear all state. Intended for tests only."""
    cls._database = None
    cls._namespace = None
    cls._project_id = None
    cls._token = None
    cls._status_hooks = []
    cls._finish_hooks = []

status

status() -> str

Begin (or resume) a test session.

Reads the token entity from the test database; creates it on first call. Updates the in-process state so the request validator starts accepting the token. Returns the full session info, including the token, to the runner.

POST-only on purpose: a third-party browser tab on the same machine cannot issue a cross-origin POST without CORS preflight, so it cannot drive-by trigger a session through this endpoint.

Source code in src/viur/testing/_test/config.py
@exposed
@force_post
def status(self) -> str:
    """Begin (or resume) a test session.

    Reads the token entity from the test database; creates it on
    first call. Updates the in-process state so the request
    validator starts accepting the token. Returns the full session
    info, including the token, to the runner.

    POST-only on purpose: a third-party browser tab on the same
    machine cannot issue a cross-origin POST without CORS preflight,
    so it cannot drive-by trigger a session through this endpoint.
    """
    cls = type(self)
    cls._require_runtime_consistency()
    token = cls._read_or_create_token()
    cls.set_token(token)

    from viur.testing import __version__  # noqa: PLC0415

    payload: dict = {
        "test_mode": True,
        "is_dev_server": True,
        "database": cls._database,
        "namespace": cls._namespace,
        "project_id": cls._project_id,
        "token": token,
        "token_hash": cls.current_token_hash(),
        "version": __version__,
    }
    for hook in cls._status_hooks:
        extra = hook()
        if extra:
            payload.update(extra)
    return self._json_response(payload)

enter

enter() -> str

Arm a manual browsing session by setting the token cookie.

Reached by a plain GET navigation (address bar, link, reload) before any cookie exists — hence a bootstrap path. Reads/creates the session token, primes the in-process state, and sets the viur-test-token cookie. Afterwards every request the browser makes — including hard navigations and server-rendered pages — carries the cookie, so the developer can browse the test instance directly without a header-injecting proxy or browser extension.

GET (not POST) on purpose: you navigate to it. A cross-site drive-by could trigger it, but the resulting cookie is SameSite=Strict and scoped to this (dev-only, localhost) host, so it cannot be used from another site — see the security note in the README.

Source code in src/viur/testing/_test/config.py
@exposed
def enter(self) -> str:
    """Arm a manual browsing session by setting the token cookie.

    Reached by a plain **GET** navigation (address bar, link, reload)
    before any cookie exists — hence a bootstrap path. Reads/creates the
    session token, primes the in-process state, and sets the
    ``viur-test-token`` cookie. Afterwards every request the browser makes
    — including hard navigations and server-rendered pages — carries the
    cookie, so the developer can browse the test instance directly without
    a header-injecting proxy or browser extension.

    GET (not POST) on purpose: you navigate to it. A cross-site drive-by
    could trigger it, but the resulting cookie is ``SameSite=Strict`` and
    scoped to this (dev-only, localhost) host, so it cannot be used from
    another site — see the security note in the README.
    """
    cls = type(self)
    cls._require_runtime_consistency()
    token = cls._read_or_create_token()
    cls.set_token(token)
    cls._set_token_cookie(token)
    return self._enter_confirmation_html()

finish

finish() -> str

End the current test session.

Deletes the token entity from the test database, clears the in-process token and expires the cookie. Test-mode itself stays armed — the next call to :meth:status/:meth:enter will provision a fresh token.

Source code in src/viur/testing/_test/config.py
@exposed
@force_post
def finish(self) -> str:
    """End the current test session.

    Deletes the token entity from the test database, clears the
    in-process token and expires the cookie. Test-mode itself stays
    armed — the next call to :meth:`status`/:meth:`enter` will provision
    a fresh token.
    """
    cls = type(self)
    cls._require_runtime_consistency()
    existed = cls._delete_token()
    cls.clear_token()
    cls._clear_token_cookie()

    payload: dict = {"finished": True, "had_token": existed}
    for hook in cls._finish_hooks:
        extra = hook()
        if extra:
            payload.update(extra)
    return self._json_response(payload)