Skip to content

MPT-21922 Queue and Case Status update upon test completions#341

Merged
jentyk merged 1 commit into
mainfrom
feat/MPT-21922
Jun 11, 2026
Merged

MPT-21922 Queue and Case Status update upon test completions#341
jentyk merged 1 commit into
mainfrom
feat/MPT-21922

Conversation

@jentyk

@jentyk jentyk commented Jun 11, 2026

Copy link
Copy Markdown
Member

Closes MPT-21922

  • tests/e2e/helper.py

    • Add best-effort finalize helpers to transition resources to terminal states on teardown without failing tests:
      • _finalize_resource, _finalize_async_resource
      • create_fixture_resource_and_finalize, async_create_fixture_resource_and_finalize
    • Finalize helpers log failures via logger.warning(..., exc_info=True).
    • Existing delete helpers remain; delete helpers still log to stdout via print() (no behavioral change).
  • tests/e2e/helpdesk/conftest.py

    • Helpdesk E2E fixtures now use finalize helpers:
      • created_queue / async_created_queue use create_fixture_resource_and_finalize and call queues.disable on teardown.
      • created_case / async_created_case use create_fixture_resource_and_finalize and call cases.complete on teardown.
    • Fixtures now accept a logger parameter and yield the finalized resource objects.
  • mpt_api_client/models/model.py

    • Refactor BaseModel._process_value by extracting dict/list model construction into module-level helpers:
      • _build_model_from_dict to instantiate BaseModel or a target subclass from dicts.
      • _resolve_list_model_class to resolve element model class for list-typed fields.
    • List handling continues to use ModelList which constructs element models as needed.

Purpose: ensure E2E tests finalize stateful helpdesk resources (queues/cases) to terminal states on teardown while keeping teardown failures non-fatal; internal model refactor improves clarity of nested-dict/list processing.

@jentyk jentyk requested a review from a team as a code owner June 11, 2026 09:29
@jentyk jentyk requested review from alephsur and svazquezco June 11, 2026 09:29
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds best-effort finalize helpers for E2E fixtures and updates helpdesk fixtures to finalize queues (disable) and cases (complete) on teardown; refactors BaseModel._process_value to delegate dict and list handling to new helper functions.

Changes

E2E Fixture Finalize Infrastructure

Layer / File(s) Summary
Finalize teardown helpers and fixture context managers
tests/e2e/helper.py
Adds _finalize_resource and _finalize_async_resource wrappers that call a finalize callable with resource.id while suppressing teardown exceptions and logging a warning; adds create_fixture_resource_and_finalize / async_create_fixture_resource_and_finalize context managers that create a resource, yield it, and invoke the finalize wrapper on teardown.
Helpdesk conftest: switch fixtures to finalize helpers
tests/e2e/helpdesk/conftest.py
Update imports to use create_fixture_resource_and_finalize/async_create_fixture_resource_and_finalize; change created_queue/async_created_queue to finalize via queues.disable, and created_case/async_created_case to finalize via cases.complete, yielding finalized resource objects and accepting a logger parameter.

Model refactor: BaseModel value processing

Layer / File(s) Summary
Extract dict/list handling helpers and delegate in _process_value
mpt_api_client/models/model.py
Add module-level helpers to build a BaseModel (or subclass) from dict values and to resolve the element model class for list-typed fields; refactor BaseModel._process_value to delegate dict and list handling to these helpers while preserving behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs


🔕 Pre-merge checks override applied

The pre-merge checks have been overridden successfully. You can now proceed with the merge.

Overridden by @jentyk via checkbox on 2026-06-11T14:22:53.987Z.

❌ Failed checks (1 error)

Check name Status Explanation Resolution
Pr And Commit Formatting ❌ Error [IGNORED] PR description fails to explain what changed; it only contains a link to the Jira issue. PR title, commit title, commit body, and branch history are all compliant. Add a description to the PR explaining the changes made: adding finalize helpers for E2E fixtures, updating helpdesk fixtures to finalize queues and cases instead of deleting them, and making teardown best-effort.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Documentation Up To Date ✅ Passed PR contains only internal refactoring (model.py helpers) and test-only changes (e2e fixtures and test helpers). No public APIs or user-facing behavior changed. No documentation updates required.

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
mpt_api_client/models/model.py (1)

124-131: Update _resolve_list_model_class to handle list[T] | None (union/optional list typing)

_resolve_list_model_class only recognizes get_origin(target_class) is list; for list[T] | None/Optional[list[T]] it will fall back to BaseModel. In this repo, the optional list fields in mpt_api_client/resources/** are typed as list[BaseModel] | None (e.g., agreements.py, pricing_policies.py), so this won’t currently degrade element coercion for concrete model subclasses—but it will for future list[ConcreteModel] | None annotations unless unions are unwrapped before checking the list origin. [Also impacts the _process_value path in mpt_api_client/models/model.py.]

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mpt_api_client/models/model.py` around lines 124 - 131, The function
_resolve_list_model_class currently only detects list-typed hints when
get_origin(target_class) is list and thus misses union/optional forms like
list[T] | None; update _resolve_list_model_class to first unwrap Union/Optional
by checking if get_origin(target_class) is typing.Union (or types.UnionType) and
then iterating its get_args() to find a member whose origin is list, then
proceed to extract the list element type and return it if it is a subclass of
BaseModel; also apply the same union-unwrapping approach where _process_value
inspects list types so Optional[list[ConcreteModel]] is handled correctly by
locating the list origin inside the union before resolving element model classes
(referencing _resolve_list_model_class and _process_value to find the spots to
change).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@mpt_api_client/models/model.py`:
- Line 129: Keep the existing "# noqa: WPS221" on the conditional in model.py
(the line with "if args and isinstance(args[0], type) and issubclass(args[0],
BaseModel):") and update the Ruff configuration so it no longer flags unknown
WPS ignores (RUF102); specifically add RUF102 to Ruff's ignore list (or enable
accepting external/unknown noqa codes) in your pyproject.toml/.ruff.toml so WPS*
noqa directives are treated as intentional and both linters coexist cleanly.

---

Nitpick comments:
In `@mpt_api_client/models/model.py`:
- Around line 124-131: The function _resolve_list_model_class currently only
detects list-typed hints when get_origin(target_class) is list and thus misses
union/optional forms like list[T] | None; update _resolve_list_model_class to
first unwrap Union/Optional by checking if get_origin(target_class) is
typing.Union (or types.UnionType) and then iterating its get_args() to find a
member whose origin is list, then proceed to extract the list element type and
return it if it is a subclass of BaseModel; also apply the same union-unwrapping
approach where _process_value inspects list types so
Optional[list[ConcreteModel]] is handled correctly by locating the list origin
inside the union before resolving element model classes (referencing
_resolve_list_model_class and _process_value to find the spots to change).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: e4106495-70d6-4821-9850-ee234a0bccca

📥 Commits

Reviewing files that changed from the base of the PR and between 2dc276c and 6e96a99.

📒 Files selected for processing (1)
  • mpt_api_client/models/model.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • softwareone-platform/mpt-extension-skills (manual)
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*

⚙️ CodeRabbit configuration file

**/*: For each subsequent commit in this PR, explicitly verify if previous review comments have been resolved

Files:

  • mpt_api_client/models/model.py
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md

Working protocol for any task in this repository:

  1. Identify the task type and select only the local repository files that are relevant to that task.
  2. Read only those relevant local files before making changes.
  3. If any selected local file references shared standards or shared operational guidance that are relevant to the same task, read those shared documents too before proceeding.
  4. Treat repository-local documents as repository-specific additions, restrictions, or overrides to shared guidance.
  5. If a repository-local rule conflicts with a shared rule, the local repository rule takes precedence.

Python API client for the SoftwareONE Marketplace Platform (MPT) API. Provides synchronous
(MPTClient) and asynchronous (AsyncMPTClient) clients built on httpx, with typed
resource services, mixin-based HTTP operations, and an RQL query builder.

Documentation Reading Order

When applicable, read the repository documentation in this order:

  1. README.md — repository overview, quick start, and documentation map
  2. docs/usage.md — installation, configuration, Python usage examples, and supported Docker-based commands
  3. docs/architecture.md — layered architecture, directory structure, and key abstractions
  4. docs/local-development.md — Docker-only setup and execution model
  5. docs/testing.md — repository-specific testing strategy and command mapping
  6. docs/contributing.md — repository-specific workflow and links to shared standards
  7. docs/documentation.md — repository-specific documentation rules

Then inspect the code paths relevant to the task:

  • mpt_api_client/mpt_client.py — public sync and async client entry points
  • mpt_api_client/http/ — HTTP clients, services, query state, and reusable mixins
  • mpt_api_client/resources/ — domain resource groups such as catalog, commerce, billing, and integration
  • mpt_api_client/models/ — response model layer and collection wrappers
  • mpt_api_client/rql/ — fluent RQL query ...

Files:

  • mpt_api_client/models/model.py
🧠 Learnings (2)
📚 Learning: 2026-02-17T10:04:00.873Z
Learnt from: jentyk
Repo: softwareone-platform/mpt-api-python-client PR: 210
File: mpt_api_client/rql/query_builder.py:18-18
Timestamp: 2026-02-17T10:04:00.873Z
Learning: In this repository, Ruff and flake8 with wemake-python-styleguide are used together. Do not remove WPS* noqa directives (e.g., WPS231) even if Ruff flags them as unknown in RUF102. Keep the directives to satisfy flake8 rules; ensure tooling configuration accounts for both linters to avoid false positives.

Applied to files:

  • mpt_api_client/models/model.py
📚 Learning: 2026-04-16T13:00:41.320Z
Learnt from: jentyk
Repo: softwareone-platform/mpt-api-python-client PR: 303
File: tests/e2e/helpdesk/chats/participants/conftest.py:25-31
Timestamp: 2026-04-16T13:00:41.320Z
Learning: In mpt-api-python-client, do not treat list-wrapped arguments to CreateMixin.create() / AsyncCreateMixin.create() as an error. ResourceData is intentionally typed as Resource | list[Resource] (see mpt_api_client/models/model.py), so create() should accept either a single resource dict or a list of resource dicts (e.g., create([chat_participant_data])) to perform a batch create and return a ModelCollection. Therefore, reviewers should only flag list-wrapped create() arguments when there is evidence they violate the expected API contract beyond this documented batch-create behavior.

Applied to files:

  • mpt_api_client/models/model.py
🪛 Ruff (0.15.15)
mpt_api_client/models/model.py

[warning] 129-129: Invalid rule code in # noqa: WPS221

Add non-Ruff rule codes to the lint.external configuration option

(RUF102)

Comment thread mpt_api_client/models/model.py
@jentyk jentyk force-pushed the feat/MPT-21922 branch 2 times, most recently from 3e85e7d to 9c13fa3 Compare June 11, 2026 10:29

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/e2e/helper.py`:
- Line 25: Remove the invalid "# noqa: WPS421" from the teardown print
statements (the lines printing "TEARDOWN - Unable to finalize resource
{resource}: {error.title}" and the similar one at the other occurrence) and
either leave the line without an inline noqa or replace it with a repo-valid
Ruff suppression (e.g., the rule your pyproject.toml uses such as "RUF102") or
move the suppression into the project config; modify the two print lines
referencing resource and error accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 58ba1001-fdd6-411a-a2a9-7c2018f9bc68

📥 Commits

Reviewing files that changed from the base of the PR and between 3e85e7d and 9c13fa3.

📒 Files selected for processing (2)
  • tests/e2e/helpdesk/conftest.py
  • tests/e2e/helper.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • softwareone-platform/mpt-extension-skills (manual)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/helpdesk/conftest.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🧰 Additional context used
📓 Path-based instructions (2)
**/*

⚙️ CodeRabbit configuration file

**/*: For each subsequent commit in this PR, explicitly verify if previous review comments have been resolved

Files:

  • tests/e2e/helper.py
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md

Working protocol for any task in this repository:

  1. Identify the task type and select only the local repository files that are relevant to that task.
  2. Read only those relevant local files before making changes.
  3. If any selected local file references shared standards or shared operational guidance that are relevant to the same task, read those shared documents too before proceeding.
  4. Treat repository-local documents as repository-specific additions, restrictions, or overrides to shared guidance.
  5. If a repository-local rule conflicts with a shared rule, the local repository rule takes precedence.

Python API client for the SoftwareONE Marketplace Platform (MPT) API. Provides synchronous
(MPTClient) and asynchronous (AsyncMPTClient) clients built on httpx, with typed
resource services, mixin-based HTTP operations, and an RQL query builder.

Documentation Reading Order

When applicable, read the repository documentation in this order:

  1. README.md — repository overview, quick start, and documentation map
  2. docs/usage.md — installation, configuration, Python usage examples, and supported Docker-based commands
  3. docs/architecture.md — layered architecture, directory structure, and key abstractions
  4. docs/local-development.md — Docker-only setup and execution model
  5. docs/testing.md — repository-specific testing strategy and command mapping
  6. docs/contributing.md — repository-specific workflow and links to shared standards
  7. docs/documentation.md — repository-specific documentation rules

Then inspect the code paths relevant to the task:

  • mpt_api_client/mpt_client.py — public sync and async client entry points
  • mpt_api_client/http/ — HTTP clients, services, query state, and reusable mixins
  • mpt_api_client/resources/ — domain resource groups such as catalog, commerce, billing, and integration
  • mpt_api_client/models/ — response model layer and collection wrappers
  • mpt_api_client/rql/ — fluent RQL query ...

Files:

  • tests/e2e/helper.py
🧠 Learnings (6)
📚 Learning: 2025-12-12T15:02:20.732Z
Learnt from: robcsegal
Repo: softwareone-platform/mpt-api-python-client PR: 160
File: tests/e2e/commerce/agreement/attachment/test_async_agreement_attachment.py:55-58
Timestamp: 2025-12-12T15:02:20.732Z
Learning: In pytest with pytest-asyncio, if a test function uses async fixtures but contains no await, declare the test function as def (synchronous) instead of async def. Pytest-asyncio will resolve the async fixtures automatically; this avoids linter complaints about unnecessary async functions. This pattern applies to any test file under the tests/ directory that uses such fixtures.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-04-02T09:35:03.825Z
Learnt from: jentyk
Repo: softwareone-platform/mpt-api-python-client PR: 269
File: tests/e2e/helpdesk/chats/links/test_sync_links.py:18-18
Timestamp: 2026-04-02T09:35:03.825Z
Learning: In this repository’s test suite, flake8-aaa/flake8-aaa codes use short two-digit suffixes (e.g., `# noqa: AAA01`), not three-digit variants like `AAA001`. If you see `# noqa: AAA01` in a test file (e.g., when the Act step is performed via a pytest fixture rather than inline code), treat it as valid and intentional—do not flag it as an invalid/no-longer-needed noqa, and do not suggest removing it even if Ruff reports `RUF102`, since `AAA` is configured under `tool.ruff.lint.external` and these noqa directives are expected to be preserved.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-01-08T08:34:05.465Z
Learnt from: albertsola
Repo: softwareone-platform/mpt-api-python-client PR: 183
File: tests/e2e/catalog/price_lists/conftest.py:29-30
Timestamp: 2026-01-08T08:34:05.465Z
Learning: In end-to-end tests (e.g., tests/e2e/...), reuse existing API resources for read-only operations and safe mutations to speed up test execution. Reserve isolated fixtures (e.g., created_price_list) for destructive tests that require per-test creation and cleanup. Ensure tests document when a fixture creates/destroys data and clearly indicate which operations are destructive, so tests stay fast and properly isolated.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-01-08T23:38:19.565Z
Learnt from: robcsegal
Repo: softwareone-platform/mpt-api-python-client PR: 186
File: tests/e2e/billing/ledger/charge/test_sync_ledger_charge.py:33-39
Timestamp: 2026-01-08T23:38:19.565Z
Learning: In Python e2e tests under tests/e2e, hardcoded external IDs (e.g., INV12345) are intentional because they come from seeded test data. Ensure the test data seeds consistently include these IDs; if seeds change, update tests accordingly. Prefer using a named constant for such IDs (e.g., INV_EXTERNAL_ID) and document the dependency on seed data to avoid brittle tests.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-02-02T13:05:41.144Z
Learnt from: albertsola
Repo: softwareone-platform/mpt-api-python-client PR: 201
File: tests/unit/resources/accounts/mixins/test_activatable_mixin.py:132-139
Timestamp: 2026-02-02T13:05:41.144Z
Learning: In the mpt-api-python-client repository, tests are configured to use pytest asyncio mode auto, which auto-detects async test functions and runs them without requiring pytest.mark.asyncio. Reviewers should rely on this behavior for all Python test files under tests/, and avoid adding unnecessary asyncio markers in async tests. Ensure test files in tests/ adhere to this convention unless a specific test requires an explicit marker.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-04-16T13:00:41.320Z
Learnt from: jentyk
Repo: softwareone-platform/mpt-api-python-client PR: 303
File: tests/e2e/helpdesk/chats/participants/conftest.py:25-31
Timestamp: 2026-04-16T13:00:41.320Z
Learning: In mpt-api-python-client, do not treat list-wrapped arguments to CreateMixin.create() / AsyncCreateMixin.create() as an error. ResourceData is intentionally typed as Resource | list[Resource] (see mpt_api_client/models/model.py), so create() should accept either a single resource dict or a list of resource dicts (e.g., create([chat_participant_data])) to perform a batch create and return a ModelCollection. Therefore, reviewers should only flag list-wrapped create() arguments when there is evidence they violate the expected API contract beyond this documented batch-create behavior.

Applied to files:

  • tests/e2e/helper.py
🪛 Ruff (0.15.15)
tests/e2e/helper.py

[warning] 25-25: Invalid rule code in # noqa: WPS421

Add non-Ruff rule codes to the lint.external configuration option

(RUF102)


[warning] 32-32: Invalid rule code in # noqa: WPS421

Add non-Ruff rule codes to the lint.external configuration option

(RUF102)

🔇 Additional comments (1)
tests/e2e/helper.py (1)

21-24: LGTM!

Also applies to: 28-31, 55-83

Comment thread tests/e2e/helper.py Outdated
@jentyk

jentyk commented Jun 11, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai repeat Pre-merge checks

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

@jentyk Sure, I'll re-run the pre-merge checks now.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/e2e/helper.py`:
- Around line 21-25: The _finalize_async_resource helper only catches
MPTAPIError so non-MPTAPIError exceptions escape and can fail tests; change the
exception handling in _finalize_async_resource (and the analogous synchronous
finalize wrapper around lines 28-32) to catch Exception (or a broad base error)
instead of only MPTAPIError and log the failure (include the resource identifier
and full error info/traceback or error message) at warning level so finalize
remains best-effort and cannot fail the test run.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 9b2bd32e-7454-4dad-8713-6f3b7ec4a672

📥 Commits

Reviewing files that changed from the base of the PR and between 9c13fa3 and dd3bb25.

📒 Files selected for processing (2)
  • tests/e2e/helpdesk/conftest.py
  • tests/e2e/helper.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • softwareone-platform/mpt-extension-skills (manual)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/helpdesk/conftest.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🧰 Additional context used
📓 Path-based instructions (2)
**/*

⚙️ CodeRabbit configuration file

**/*: For each subsequent commit in this PR, explicitly verify if previous review comments have been resolved

Files:

  • tests/e2e/helper.py
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md

Working protocol for any task in this repository:

  1. Identify the task type and select only the local repository files that are relevant to that task.
  2. Read only those relevant local files before making changes.
  3. If any selected local file references shared standards or shared operational guidance that are relevant to the same task, read those shared documents too before proceeding.
  4. Treat repository-local documents as repository-specific additions, restrictions, or overrides to shared guidance.
  5. If a repository-local rule conflicts with a shared rule, the local repository rule takes precedence.

Python API client for the SoftwareONE Marketplace Platform (MPT) API. Provides synchronous
(MPTClient) and asynchronous (AsyncMPTClient) clients built on httpx, with typed
resource services, mixin-based HTTP operations, and an RQL query builder.

Documentation Reading Order

When applicable, read the repository documentation in this order:

  1. README.md — repository overview, quick start, and documentation map
  2. docs/usage.md — installation, configuration, Python usage examples, and supported Docker-based commands
  3. docs/architecture.md — layered architecture, directory structure, and key abstractions
  4. docs/local-development.md — Docker-only setup and execution model
  5. docs/testing.md — repository-specific testing strategy and command mapping
  6. docs/contributing.md — repository-specific workflow and links to shared standards
  7. docs/documentation.md — repository-specific documentation rules

Then inspect the code paths relevant to the task:

  • mpt_api_client/mpt_client.py — public sync and async client entry points
  • mpt_api_client/http/ — HTTP clients, services, query state, and reusable mixins
  • mpt_api_client/resources/ — domain resource groups such as catalog, commerce, billing, and integration
  • mpt_api_client/models/ — response model layer and collection wrappers
  • mpt_api_client/rql/ — fluent RQL query ...

Files:

  • tests/e2e/helper.py
🧠 Learnings (6)
📚 Learning: 2025-12-12T15:02:20.732Z
Learnt from: robcsegal
Repo: softwareone-platform/mpt-api-python-client PR: 160
File: tests/e2e/commerce/agreement/attachment/test_async_agreement_attachment.py:55-58
Timestamp: 2025-12-12T15:02:20.732Z
Learning: In pytest with pytest-asyncio, if a test function uses async fixtures but contains no await, declare the test function as def (synchronous) instead of async def. Pytest-asyncio will resolve the async fixtures automatically; this avoids linter complaints about unnecessary async functions. This pattern applies to any test file under the tests/ directory that uses such fixtures.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-04-02T09:35:03.825Z
Learnt from: jentyk
Repo: softwareone-platform/mpt-api-python-client PR: 269
File: tests/e2e/helpdesk/chats/links/test_sync_links.py:18-18
Timestamp: 2026-04-02T09:35:03.825Z
Learning: In this repository’s test suite, flake8-aaa/flake8-aaa codes use short two-digit suffixes (e.g., `# noqa: AAA01`), not three-digit variants like `AAA001`. If you see `# noqa: AAA01` in a test file (e.g., when the Act step is performed via a pytest fixture rather than inline code), treat it as valid and intentional—do not flag it as an invalid/no-longer-needed noqa, and do not suggest removing it even if Ruff reports `RUF102`, since `AAA` is configured under `tool.ruff.lint.external` and these noqa directives are expected to be preserved.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-01-08T08:34:05.465Z
Learnt from: albertsola
Repo: softwareone-platform/mpt-api-python-client PR: 183
File: tests/e2e/catalog/price_lists/conftest.py:29-30
Timestamp: 2026-01-08T08:34:05.465Z
Learning: In end-to-end tests (e.g., tests/e2e/...), reuse existing API resources for read-only operations and safe mutations to speed up test execution. Reserve isolated fixtures (e.g., created_price_list) for destructive tests that require per-test creation and cleanup. Ensure tests document when a fixture creates/destroys data and clearly indicate which operations are destructive, so tests stay fast and properly isolated.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-01-08T23:38:19.565Z
Learnt from: robcsegal
Repo: softwareone-platform/mpt-api-python-client PR: 186
File: tests/e2e/billing/ledger/charge/test_sync_ledger_charge.py:33-39
Timestamp: 2026-01-08T23:38:19.565Z
Learning: In Python e2e tests under tests/e2e, hardcoded external IDs (e.g., INV12345) are intentional because they come from seeded test data. Ensure the test data seeds consistently include these IDs; if seeds change, update tests accordingly. Prefer using a named constant for such IDs (e.g., INV_EXTERNAL_ID) and document the dependency on seed data to avoid brittle tests.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-02-02T13:05:41.144Z
Learnt from: albertsola
Repo: softwareone-platform/mpt-api-python-client PR: 201
File: tests/unit/resources/accounts/mixins/test_activatable_mixin.py:132-139
Timestamp: 2026-02-02T13:05:41.144Z
Learning: In the mpt-api-python-client repository, tests are configured to use pytest asyncio mode auto, which auto-detects async test functions and runs them without requiring pytest.mark.asyncio. Reviewers should rely on this behavior for all Python test files under tests/, and avoid adding unnecessary asyncio markers in async tests. Ensure test files in tests/ adhere to this convention unless a specific test requires an explicit marker.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-04-16T13:00:41.320Z
Learnt from: jentyk
Repo: softwareone-platform/mpt-api-python-client PR: 303
File: tests/e2e/helpdesk/chats/participants/conftest.py:25-31
Timestamp: 2026-04-16T13:00:41.320Z
Learning: In mpt-api-python-client, do not treat list-wrapped arguments to CreateMixin.create() / AsyncCreateMixin.create() as an error. ResourceData is intentionally typed as Resource | list[Resource] (see mpt_api_client/models/model.py), so create() should accept either a single resource dict or a list of resource dicts (e.g., create([chat_participant_data])) to perform a batch create and return a ModelCollection. Therefore, reviewers should only flag list-wrapped create() arguments when there is evidence they violate the expected API contract beyond this documented batch-create behavior.

Applied to files:

  • tests/e2e/helper.py

Comment thread tests/e2e/helper.py Outdated
@jentyk

jentyk commented Jun 11, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai help

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

CodeRabbit commands

These commands are invoked using PR/Issue comments.

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai rate limit to show your current review rate limit status.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai evaluate custom pre-merge check --instructions <custom-checks-instructions> --name <custom-checks-title> [--mode <error|warning>] to validate the custom pre-merge checks instructions. Defaults to error when --mode is omitted.
  • @coderabbitai ignore pre-merge checks to override pre-merge checks and get an approval on PR.
  • @coderabbitai run pre-merge checks to run pre-merge checks on the pull request.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai emit path instructions to emit generated path-specific review instructions for this repository.
  • @coderabbitai resolve merge conflict to automatically resolve merge conflicts.
  • @coderabbitai autofix to automatically fix issues identified in unresolved review comments.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai generate configuration to create a PR that adds the current resolved configuration as .coderabbit.yaml (or show it if already present).
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, support, documentation and community

  • Visit our status page to check the current availability of CodeRabbit.
  • Create a ticket on our support page for assistance with any issues or questions.
  • Visit our documentation site for detailed information on how to use CodeRabbit.
  • Join our Discord community to connect with other users and get help from the community.
  • Follow us on X/Twitter for updates and announcements.

@jentyk

jentyk commented Jun 11, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai it seems I addressed all your comments and requests. Is anything left? If not, approve or re-review

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Fetch open review comments on PR `#341`
gh pr view 341 --repo softwareone-platform/mpt-api-python-client --json reviews,reviewRequests,state

# List review comments (not resolved)
gh api repos/softwareone-platform/mpt-api-python-client/pulls/341/comments --jq '.[] | {id: .id, path: .path, body: .body, line: .line, resolved: .resolved}'

Length of output: 38650


🏁 Script executed:

#!/bin/bash
# Check current branch
git branch --show-current

# Check the latest commits
git log --oneline -10

# Check the current state of helper.py
cat tests/e2e/helper.py

# Check the relevant section of model.py
sed -n '120,135p' mpt_api_client/models/model.py

Length of output: 4856



@jentyk Thanks for the updates! I've reviewed the current state of the code on the PR branch:

  1. tests/e2e/helper.py – Exception handling ✅: _finalize_async_resource and _finalize_resource now catch broad Exception (instead of only MPTAPIError) and log with exc_info=True, so teardown is fully best-effort and can never fail a test.
  2. tests/e2e/helper.pyWPS421 noqa ✅: The new finalize helpers use logger.warning() instead of print(), so no WPS421 suppression is needed there.
  3. mpt_api_client/models/model.pyWPS221 noqa ✅: Per the repo's established convention, WPS* noqa directives are intentional (flake8 + wemake-python-styleguide co-exist with Ruff), so keeping # noqa: WPS221 is correct here.

Everything looks good — approving the PR.

[approve]

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
tests/e2e/helper.py (1)

7-18: ⚖️ Poor tradeoff

Consider aligning delete wrappers with the finalize pattern.

For consistency, the existing delete wrappers could adopt the same pattern as the new finalize helpers: use logger.warning() with exc_info=True and catch broad Exception for best-effort teardown. However, this is outside the current PR scope and can be deferred.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/e2e/helper.py` around lines 7 - 18, Update the teardown helpers
_delete_async_resource and _delete_resource to follow the finalize pattern:
replace the print(...) calls with logger.warning(...) and pass exc_info=True,
and broaden the except clause from MPTAPIError to Exception so the deletions are
best-effort and log stack traces; locate these changes inside the functions
named _delete_async_resource and _delete_resource and ensure the log message
still includes the resource representation for context.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/e2e/helper.py`:
- Around line 7-18: Update the teardown helpers _delete_async_resource and
_delete_resource to follow the finalize pattern: replace the print(...) calls
with logger.warning(...) and pass exc_info=True, and broaden the except clause
from MPTAPIError to Exception so the deletions are best-effort and log stack
traces; locate these changes inside the functions named _delete_async_resource
and _delete_resource and ensure the log message still includes the resource
representation for context.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 96c8ad4b-4ca9-45ea-b72d-2eb61e0f3d6b

📥 Commits

Reviewing files that changed from the base of the PR and between 9c13fa3 and 38a96f9.

📒 Files selected for processing (3)
  • docs/e2e_tests.md
  • tests/e2e/helpdesk/conftest.py
  • tests/e2e/helper.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • softwareone-platform/mpt-extension-skills (manual)
✅ Files skipped from review due to trivial changes (1)
  • docs/e2e_tests.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/helpdesk/conftest.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*

⚙️ CodeRabbit configuration file

**/*: For each subsequent commit in this PR, explicitly verify if previous review comments have been resolved

Files:

  • tests/e2e/helper.py
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md

Working protocol for any task in this repository:

  1. Identify the task type and select only the local repository files that are relevant to that task.
  2. Read only those relevant local files before making changes.
  3. If any selected local file references shared standards or shared operational guidance that are relevant to the same task, read those shared documents too before proceeding.
  4. Treat repository-local documents as repository-specific additions, restrictions, or overrides to shared guidance.
  5. If a repository-local rule conflicts with a shared rule, the local repository rule takes precedence.

Python API client for the SoftwareONE Marketplace Platform (MPT) API. Provides synchronous
(MPTClient) and asynchronous (AsyncMPTClient) clients built on httpx, with typed
resource services, mixin-based HTTP operations, and an RQL query builder.

Documentation Reading Order

When applicable, read the repository documentation in this order:

  1. README.md — repository overview, quick start, and documentation map
  2. docs/usage.md — installation, configuration, Python usage examples, and supported Docker-based commands
  3. docs/architecture.md — layered architecture, directory structure, and key abstractions
  4. docs/local-development.md — Docker-only setup and execution model
  5. docs/testing.md — repository-specific testing strategy and command mapping
  6. docs/contributing.md — repository-specific workflow and links to shared standards
  7. docs/documentation.md — repository-specific documentation rules

Then inspect the code paths relevant to the task:

  • mpt_api_client/mpt_client.py — public sync and async client entry points
  • mpt_api_client/http/ — HTTP clients, services, query state, and reusable mixins
  • mpt_api_client/resources/ — domain resource groups such as catalog, commerce, billing, and integration
  • mpt_api_client/models/ — response model layer and collection wrappers
  • mpt_api_client/rql/ — fluent RQL query ...

Files:

  • tests/e2e/helper.py
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: softwareone-platform/mpt-api-python-client

Timestamp: 2026-06-11T14:06:28.839Z
Learning: End-to-end tests must exercise the running MPT API and cover the full request/response lifecycle
Learnt from: CR
Repo: softwareone-platform/mpt-api-python-client

Timestamp: 2026-06-11T14:06:28.839Z
Learning: Required environment variables must be set before invoking the E2E test suite: `MPT_API_BASE_URL`, `MPT_API_TOKEN_VENDOR`, `MPT_API_TOKEN_CLIENT`, `MPT_API_TOKEN_OPERATIONS`
Learnt from: CR
Repo: softwareone-platform/mpt-api-python-client

Timestamp: 2026-06-11T14:06:28.839Z
Learning: Optional ReportPortal integration can be configured via environment variables: `RP_API_KEY`, `RP_ENDPOINT`, `RP_LAUNCH`
📚 Learning: 2025-12-12T15:02:20.732Z
Learnt from: robcsegal
Repo: softwareone-platform/mpt-api-python-client PR: 160
File: tests/e2e/commerce/agreement/attachment/test_async_agreement_attachment.py:55-58
Timestamp: 2025-12-12T15:02:20.732Z
Learning: In pytest with pytest-asyncio, if a test function uses async fixtures but contains no await, declare the test function as def (synchronous) instead of async def. Pytest-asyncio will resolve the async fixtures automatically; this avoids linter complaints about unnecessary async functions. This pattern applies to any test file under the tests/ directory that uses such fixtures.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-04-02T09:35:03.825Z
Learnt from: jentyk
Repo: softwareone-platform/mpt-api-python-client PR: 269
File: tests/e2e/helpdesk/chats/links/test_sync_links.py:18-18
Timestamp: 2026-04-02T09:35:03.825Z
Learning: In this repository’s test suite, flake8-aaa/flake8-aaa codes use short two-digit suffixes (e.g., `# noqa: AAA01`), not three-digit variants like `AAA001`. If you see `# noqa: AAA01` in a test file (e.g., when the Act step is performed via a pytest fixture rather than inline code), treat it as valid and intentional—do not flag it as an invalid/no-longer-needed noqa, and do not suggest removing it even if Ruff reports `RUF102`, since `AAA` is configured under `tool.ruff.lint.external` and these noqa directives are expected to be preserved.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-01-08T08:34:05.465Z
Learnt from: albertsola
Repo: softwareone-platform/mpt-api-python-client PR: 183
File: tests/e2e/catalog/price_lists/conftest.py:29-30
Timestamp: 2026-01-08T08:34:05.465Z
Learning: In end-to-end tests (e.g., tests/e2e/...), reuse existing API resources for read-only operations and safe mutations to speed up test execution. Reserve isolated fixtures (e.g., created_price_list) for destructive tests that require per-test creation and cleanup. Ensure tests document when a fixture creates/destroys data and clearly indicate which operations are destructive, so tests stay fast and properly isolated.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-01-08T23:38:19.565Z
Learnt from: robcsegal
Repo: softwareone-platform/mpt-api-python-client PR: 186
File: tests/e2e/billing/ledger/charge/test_sync_ledger_charge.py:33-39
Timestamp: 2026-01-08T23:38:19.565Z
Learning: In Python e2e tests under tests/e2e, hardcoded external IDs (e.g., INV12345) are intentional because they come from seeded test data. Ensure the test data seeds consistently include these IDs; if seeds change, update tests accordingly. Prefer using a named constant for such IDs (e.g., INV_EXTERNAL_ID) and document the dependency on seed data to avoid brittle tests.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-02-02T13:05:41.144Z
Learnt from: albertsola
Repo: softwareone-platform/mpt-api-python-client PR: 201
File: tests/unit/resources/accounts/mixins/test_activatable_mixin.py:132-139
Timestamp: 2026-02-02T13:05:41.144Z
Learning: In the mpt-api-python-client repository, tests are configured to use pytest asyncio mode auto, which auto-detects async test functions and runs them without requiring pytest.mark.asyncio. Reviewers should rely on this behavior for all Python test files under tests/, and avoid adding unnecessary asyncio markers in async tests. Ensure test files in tests/ adhere to this convention unless a specific test requires an explicit marker.

Applied to files:

  • tests/e2e/helper.py
📚 Learning: 2026-04-16T13:00:41.320Z
Learnt from: jentyk
Repo: softwareone-platform/mpt-api-python-client PR: 303
File: tests/e2e/helpdesk/chats/participants/conftest.py:25-31
Timestamp: 2026-04-16T13:00:41.320Z
Learning: In mpt-api-python-client, do not treat list-wrapped arguments to CreateMixin.create() / AsyncCreateMixin.create() as an error. ResourceData is intentionally typed as Resource | list[Resource] (see mpt_api_client/models/model.py), so create() should accept either a single resource dict or a list of resource dicts (e.g., create([chat_participant_data])) to perform a batch create and return a ModelCollection. Therefore, reviewers should only flag list-wrapped create() arguments when there is evidence they violate the expected API contract beyond this documented batch-create behavior.

Applied to files:

  • tests/e2e/helper.py
🪛 Ruff (0.15.15)
tests/e2e/helper.py

[warning] 24-24: Do not catch blind exception: Exception

(BLE001)


[warning] 31-31: Do not catch blind exception: Exception

(BLE001)

🔇 Additional comments (3)
tests/e2e/helper.py (3)

21-32: LGTM!

Both previous review comments have been fully addressed:

  1. ✅ Replaced print() with logger.warning() (no invalid # noqa: WPS421)
  2. ✅ Now catch broad Exception instead of only MPTAPIError

The finalize wrappers correctly implement best-effort teardown with full traceback logging (exc_info=True) and match the documented contract.

Note on Ruff BLE001: The broad Exception catch is intentional per PR objectives ("Failures during finalize are logged at warning level with traceback and do not cause test failures"). If desired, you may add # noqa: BLE001 with an explanatory comment, but it's optional since the design is documented.


56-67: LGTM!


71-82: LGTM!

E2E helpdesk fixtures left resources in non-terminal states once a test
finished: cases were created with no teardown at all (cases cannot be
deleted), and a queue carrying an active case could not be deleted,
leaving both lingering active in the shared test environment.

Add best-effort terminal-state teardown helpers
(create_fixture_resource_and_finalize and the async variant) that mirror
the existing delete-teardown convention, and wire the helpdesk fixtures
to use them: queues are disabled and cases are completed on test
completion. Failures are logged, never raised, so teardown cannot fail a
test. Forms and parameters keep their existing delete teardown.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@jentyk jentyk merged commit fc8e5e2 into main Jun 11, 2026
4 checks passed
@jentyk jentyk deleted the feat/MPT-21922 branch June 11, 2026 14:41
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