Skip to content

feat(tests): add e2e test suite#1609

Open
LioriE wants to merge 3 commits into
mainfrom
e2e-clean
Open

feat(tests): add e2e test suite#1609
LioriE wants to merge 3 commits into
mainfrom
e2e-clean

Conversation

@LioriE

@LioriE LioriE commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Related Issues

Fixes: https://github.com/descope/etc/issues/16390

In a Nutshell

  • Add end-to-end test suite for the Python SDK
  • Cover auth methods: OTP, magic link, password, access keys
  • Cover management APIs: user, SSO, project, flow, JWT, mgmt key
  • Wire an e2e job into the CI workflow

Description

Adds an end-to-end test suite under tests/e2e that exercises authentication flows and management APIs against a live project. Includes shared fixtures/config (conftest.py, _unified.py), a CI job to run the suite, and the supporting pyproject.toml/uv.lock dependency updates.

Must

  • Tests
  • Documentation (if applicable)

Add end-to-end tests that exercise the SDK against a real Descope
backend (sync + async via a unified client wrapper), gated behind the
`e2e` pytest marker and a dedicated CI job (with debounce + sandbox
secrets). Unit CI runs with --ignore=tests/e2e so e2e stays opt-in.
@shuni-bot

shuni-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🐕 Review complete — View session on Shuni Portal 🐾

@shuni-bot

shuni-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🐕 Suggested Reviewers

The review assignment focuses on contributors who have made recent commits to critical configuration and workflow files, ensuring thorough coverage of CI integration and project setup for the new end-to-end testing suite.

Reviewer Reason
omercnet oMercnet has contributed multiple commits related to the CI workflow, which is essential to review since the PR involves integrating tests into the CI pipeline.
dorsha Dorsha's commit in pyproject.toml suggests involvement in project configuration, making them a good candidate to review overall project setup and dependencies, especially for running the new end-to-end tests.

Suggested by Shuni based on git history and PR context. Names are not @-mentioned to avoid notifying anyone — request a review from whoever fits best.

assert jwt_response[REFRESH_SESSION_TOKEN_NAME]["jwt"], "Refresh token missing after sign-in"
assert jwt_response.get("firstSeen") is False
assert jwt_response.get("user", {}).get("name") == "Test User"
refresh_token = jwt_response[REFRESH_SESSION_TOKEN_NAME]["jwt"]
finally:
try:
await descope_client.invoke(descope_client.mgmt.user.delete(login_id))
except Exception:
finally:
try:
await descope_client.invoke(descope_client.mgmt.user.delete(login_id))
except Exception:
finally:
try:
await descope_client.invoke(descope_client.mgmt.user.delete(login_id))
except Exception:
for rname in [role1_name, role2_name]:
try:
await descope_client.invoke(descope_client.mgmt.role.delete(rname))
except Exception:
for uid in [invited_login_id, invited1_login_id, invited2_login_id]:
try:
await descope_client.invoke(descope_client.mgmt.user.delete(uid))
except Exception:
Comment thread tests/e2e/management/test_sso.py Fixed
Comment thread tests/e2e/management/test_sso.py Fixed
Comment thread tests/e2e/management/test_sso.py Fixed

@shuni-bot shuni-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐕 Shuni's Review

Adds an e2e test suite for auth flows + management APIs, with a CI e2e job and shared sync/async harness. Solid coverage and clean teardown — good bones!

Sniffed out 5 issues (test/CI only — no production impact):

  • 2 🟡 MEDIUM: skip_debounce CI input is dead code; e2e conftest aborts the whole pytest session when env vars are missing
  • 3 🟢 LOW: substring localhost TLS-skip check, inaccurate "shared base" docstring, fragile magic-link token parsing

See inline comments. Woof!

Comment thread .github/workflows/ci.yml
with:
report_paths: e2e-report.xml
check_name: E2E Test Report

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM: The skip_debounce input can never actually skip the debounce.

This step is guarded by github.event_name == 'pull_request', but skip_debounce can only be set on a workflow_dispatch run — on which this step is already skipped. On real PR events inputs.skip_debounce is null, and null != 'true' is always true, so the debounce always runs regardless. The input is effectively dead. (Separately, line 13's description says "5-minute debounce" but sleep 60 is 1 minute.)

Drop the event guard and evaluate the input directly, e.g. !fromJSON(inputs.skip_debounce || 'false'), so dispatch runs can honor it.

Comment thread tests/e2e/conftest.py
"ERROR: DESCOPE_PROJECT_ID and DESCOPE_MANAGEMENT_KEY must be set to run e2e tests",
file=sys.stderr,
)
pytest.exit("Missing required e2e environment variables", returncode=1)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM: Module-level pytest.exit() aborts the entire pytest session, not just the e2e tests.

tests/e2e/conftest.py is imported at collection time whenever pytest discovers tests/e2e/. CI is safe because the unit job passes --ignore=tests/e2e, but a developer running pytest tests/ locally without DESCOPE_PROJECT_ID/DESCOPE_MANAGEMENT_KEY gets a session-level SystemExit that cancels their unit tests too. Prefer skipping only the e2e tests (e.g. pytest.skip(..., allow_module_level=True) or a session fixture) so unmarked tests still run.

Comment thread tests/e2e/conftest.py
project_id = os.environ["DESCOPE_PROJECT_ID"]
management_key = os.environ["DESCOPE_MANAGEMENT_KEY"]

skip_verify = "localhost" in os.environ.get("DESCOPE_BASE_URI", "")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 LOW: "localhost" in DESCOPE_BASE_URI is a substring match, so a host like https://localhost.example.com would silently disable TLS verification against a real remote endpoint.

Low risk since the value comes from a controlled secret, but a hostname check is safer:

Suggested change
skip_verify = "localhost" in os.environ.get("DESCOPE_BASE_URI", "")
from urllib.parse import urlparse
skip_verify = urlparse(os.environ.get("DESCOPE_BASE_URI", "")).hostname in {"localhost", "127.0.0.1", "::1"}

Comment thread tests/_unified.py
"""
Shared base class for unified sync/async client wrappers.

Both the unit-test UnifiedClient (tests/conftest.py) and the e2e wrapper

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 LOW: This docstring says both UnifiedClient (tests/conftest.py) and the e2e wrapper "inherit from this", but neither actually does — UnifiedClient is a standalone copy of the same three methods, and the e2e fixture instantiates UnifiedClientBase directly. The shared base isn't shared yet. Either make UnifiedClient subclass UnifiedClientBase (and drop the duplicated __init__/__getattr__/invoke) or correct the docstring.

)
)
raw_link = td["link"]
token = raw_link[raw_link.index("=") + 1 :]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 LOK: Token extraction via raw_link.index("=") grabs everything after the first = in the URL. It works for uri="http://test.me" today, but breaks if the link ever carries an earlier query param, and raises ValueError (unhandled) if no = is present. Same at line 73. Consider parsing the t param explicitly: parse_qs(urlparse(raw_link).query)["t"][0].

Avoids CodeQL py/incomplete-url-substring-sanitization on domain
membership assertions and checks the full domain list.
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

Coverage report

The coverage rate went from 98.24% to 98.24% ➡️

None of the new lines are part of the tested code. Therefore, there is no coverage data about them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants