minitest-cli 0.27.2__tar.gz → 0.28.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/PKG-INFO +1 -1
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/pyproject.toml +1 -1
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/api/client.py +11 -4
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/draft_feature.py +7 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/run_display.py +5 -1
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/test_profile.py +22 -0
- minitest_cli-0.28.1/src/minitest_cli/commands/test_profile_card.py +52 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/test_profile_update.py +38 -2
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/core/config.py +8 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/story_run.py +3 -1
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_run_commands.py +63 -0
- minitest_cli-0.28.1/tests/test_suite_change_provenance.py +108 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_test_profile_commands.py +61 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/uv.lock +1 -1
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/.env.example +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/.github/workflows/ci.yml +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/.github/workflows/install-scripts.yml +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/.github/workflows/release.yml +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/.gitignore +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/.opencode/skill/release/SKILL.md +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/AGENTS.md +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/README.md +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/RELEASE.md +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/install.ps1 +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/install.sh +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/pyrightconfig.json +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/renovate.json +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/__init__.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/api/__init__.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/api/apps_manager_client.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/api/errors.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/assets/__init__.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/assets/callback.html +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/__init__.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/_response_errors.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/app_knowledge.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/app_knowledge_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/apps.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/apps_dependencies.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/apps_get.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/apps_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/auth.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/auth_api_key.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/batch.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/batch_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/build.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/build_commit.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/build_fix_prompts.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/build_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/capabilities.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/commit_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/draft_feature_apply.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/draft_feature_conflicts.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/draft_feature_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/draft_feature_show.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/env.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/env_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/flow_types.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/flow_types_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/flow_types_write.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/init.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/init_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/init_playbook.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/issues.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/issues_fix.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/issues_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/issues_projection.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/issues_service.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/maintenance.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/maintenance_callbacks.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/maintenance_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/maintenance_state.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/run.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/run_commit.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/run_commit_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/run_feedback.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/run_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/run_targets.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/screens.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/screens_detail.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/screens_format.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/screens_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/screens_tree.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/skill.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/test_file.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/test_file_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/test_file_list.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/test_profile_default.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/test_profile_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/test_profile_list.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/upgrade.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_bindings.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_camera.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_create.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_criteria.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_criterion_edits.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_delete.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_device_count.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_modify.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_overrides.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_profiles.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_update.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/verdicts.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/verdicts_helpers.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/verdicts_projection.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/core/__init__.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/core/app_context.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/core/auth.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/core/credentials.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/core/oauth.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/core/tenants.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/core/token_exchange.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/main.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/__init__.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/app.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/app_env_vars.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/app_failure.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/app_screen.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/base.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/batch.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/build.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/commit_build.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/draft_feature.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/flow_type.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/issues.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/targets.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/models/user_story.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/utils/__init__.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/utils/confirm.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/utils/dependency_sim.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/utils/mermaid.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/utils/output.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/utils/skill_refresh.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/utils/update_check.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/__init__.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/_commit_transport.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_app_knowledge_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_apps_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_apps_dependencies.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_auth.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_auth_api_key.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_auth_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_batch_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_build_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_build_fix_prompts.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_capabilities_command.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_channel_header.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_code_quality.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_commit_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_draft_feature_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_env.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_flow_types_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_init_command.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_issues.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_issues_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_mermaid.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_network_errors.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_response_errors.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_screens_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_skill_command.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_test_file_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_upgrade_command.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_user_story_bindings_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_user_story_commands.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_verdicts.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_verdicts_actionable.py +0 -0
- {minitest_cli-0.27.2 → minitest_cli-0.28.1}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: minitest-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.28.1
|
|
4
4
|
Summary: Minitest CLI – command-line interface for the Minitest testing platform
|
|
5
5
|
Project-URL: Homepage, https://minitap.ai/
|
|
6
6
|
Project-URL: Source, https://github.com/minitap-ai/minitest-cli
|
|
@@ -8,6 +8,8 @@ from minitest_cli.core.auth import load_token
|
|
|
8
8
|
from minitest_cli.core.config import Settings
|
|
9
9
|
|
|
10
10
|
CHANNEL_HEADER = "X-Minitest-Channel"
|
|
11
|
+
CONVERSATION_ID_HEADER = "X-Minitest-Conversation-Id"
|
|
12
|
+
CAUSE_HEADER = "X-Minitest-Cause"
|
|
11
13
|
DEFAULT_TIMEOUT = 30.0
|
|
12
14
|
UPLOAD_TIMEOUT = 300.0 # 5 minutes for large file uploads
|
|
13
15
|
# Creating a batch can block on server-side maintenance before it answers, and the
|
|
@@ -31,12 +33,17 @@ class ApiClient:
|
|
|
31
33
|
|
|
32
34
|
async def __aenter__(self) -> "ApiClient":
|
|
33
35
|
token = self._token_override or load_token(self._settings)
|
|
36
|
+
headers: dict[str, str] = {
|
|
37
|
+
"Authorization": f"Bearer {token}",
|
|
38
|
+
CHANNEL_HEADER: self._settings.channel,
|
|
39
|
+
}
|
|
40
|
+
if self._settings.conversation_id is not None:
|
|
41
|
+
headers[CONVERSATION_ID_HEADER] = self._settings.conversation_id
|
|
42
|
+
if self._settings.cause is not None:
|
|
43
|
+
headers[CAUSE_HEADER] = self._settings.cause
|
|
34
44
|
self._client = httpx.AsyncClient(
|
|
35
45
|
base_url=self._settings.api_url,
|
|
36
|
-
headers=
|
|
37
|
-
"Authorization": f"Bearer {token}",
|
|
38
|
-
CHANNEL_HEADER: self._settings.channel,
|
|
39
|
-
},
|
|
46
|
+
headers=headers,
|
|
40
47
|
timeout=DEFAULT_TIMEOUT,
|
|
41
48
|
)
|
|
42
49
|
return self
|
|
@@ -4,6 +4,7 @@ A draft feature is a branch of the app's test suite — it holds a delta against
|
|
|
4
4
|
main rather than a copy of it, so `show` is the only way to see what it changes.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
import json
|
|
7
8
|
from typing import Annotated
|
|
8
9
|
|
|
9
10
|
import typer
|
|
@@ -66,12 +67,18 @@ def create_draft_feature(
|
|
|
66
67
|
str | None,
|
|
67
68
|
typer.Option("--description", help="What product change the branch describes."),
|
|
68
69
|
] = None,
|
|
70
|
+
source_refs: Annotated[
|
|
71
|
+
str | None,
|
|
72
|
+
typer.Option("--source-refs", help="JSON array of provenance refs (passed as sourceRefs)."),
|
|
73
|
+
] = None,
|
|
69
74
|
) -> None:
|
|
70
75
|
"""Open a branch off the app's main suite."""
|
|
71
76
|
settings, app_id, json_mode = resolve_app()
|
|
72
77
|
body: dict[str, object] = {"title": title}
|
|
73
78
|
if description is not None:
|
|
74
79
|
body["description"] = description
|
|
80
|
+
if source_refs is not None:
|
|
81
|
+
body["sourceRefs"] = json.loads(source_refs)
|
|
75
82
|
|
|
76
83
|
async def _create() -> DraftFeatureResponse:
|
|
77
84
|
async with ApiClient(settings) as client:
|
|
@@ -27,7 +27,9 @@ def _derive_run_status(run: StoryRunResponse) -> str:
|
|
|
27
27
|
Mirrors the heuristic used by the cockpit / webapp: any platform
|
|
28
28
|
with a stamped ``cancellation_requested_at`` short-circuits to
|
|
29
29
|
``cancelled``; otherwise we pick the worst platform state in
|
|
30
|
-
lifecycle order (running > pending/blocked > failed >
|
|
30
|
+
lifecycle order (running > pending/blocked > evaluating > failed >
|
|
31
|
+
completed). ``evaluating`` is a platform that finished executing and
|
|
32
|
+
is waiting for its verdict, so it outranks every terminal state.
|
|
31
33
|
"""
|
|
32
34
|
if any(p.cancellation_requested_at is not None for p in run.platforms):
|
|
33
35
|
return "cancelled"
|
|
@@ -38,6 +40,8 @@ def _derive_run_status(run: StoryRunResponse) -> str:
|
|
|
38
40
|
return "running"
|
|
39
41
|
if "pending" in states or "blocked" in states:
|
|
40
42
|
return "pending"
|
|
43
|
+
if "evaluating" in states:
|
|
44
|
+
return "evaluating"
|
|
41
45
|
if "failed" in states:
|
|
42
46
|
return "failed"
|
|
43
47
|
if all(s in _TERMINAL_EXEC_STATES for s in states) and any(s == "completed" for s in states):
|
|
@@ -4,6 +4,14 @@ import typer
|
|
|
4
4
|
|
|
5
5
|
from minitest_cli.api.client import ApiClient
|
|
6
6
|
from minitest_cli.commands import test_profile_default, test_profile_list, test_profile_update
|
|
7
|
+
from minitest_cli.commands.test_profile_card import (
|
|
8
|
+
CardCvcOption,
|
|
9
|
+
CardExpiryOption,
|
|
10
|
+
CardHolderNameOption,
|
|
11
|
+
CardNumberOption,
|
|
12
|
+
CardPostalCodeOption,
|
|
13
|
+
card_fields,
|
|
14
|
+
)
|
|
7
15
|
from minitest_cli.commands.test_profile_helpers import (
|
|
8
16
|
app_base_path,
|
|
9
17
|
get_app_flag,
|
|
@@ -65,6 +73,11 @@ def create_profile(
|
|
|
65
73
|
about: Annotated[
|
|
66
74
|
str | None, typer.Option("--about", help="Free-text notes about the account.")
|
|
67
75
|
] = None,
|
|
76
|
+
test_card_number: CardNumberOption = None,
|
|
77
|
+
test_card_expiry: CardExpiryOption = None,
|
|
78
|
+
test_card_cvc: CardCvcOption = None,
|
|
79
|
+
test_card_holder_name: CardHolderNameOption = None,
|
|
80
|
+
test_card_postal_code: CardPostalCodeOption = None,
|
|
68
81
|
) -> None:
|
|
69
82
|
settings = get_settings()
|
|
70
83
|
json_mode = is_json_mode()
|
|
@@ -91,6 +104,15 @@ def create_profile(
|
|
|
91
104
|
body["static_otp_code"] = otp
|
|
92
105
|
if about is not None:
|
|
93
106
|
body["about"] = about
|
|
107
|
+
card = card_fields(
|
|
108
|
+
test_card_number,
|
|
109
|
+
test_card_expiry,
|
|
110
|
+
test_card_cvc,
|
|
111
|
+
test_card_holder_name,
|
|
112
|
+
test_card_postal_code,
|
|
113
|
+
)
|
|
114
|
+
if card:
|
|
115
|
+
body["test_card"] = card
|
|
94
116
|
|
|
95
117
|
async def _run() -> dict[str, Any]:
|
|
96
118
|
async with ApiClient(settings) as client:
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from typing import Annotated, Any
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
CardNumberOption = Annotated[
|
|
6
|
+
str | None,
|
|
7
|
+
typer.Option(
|
|
8
|
+
"--test-card-number",
|
|
9
|
+
help="Sandbox payment card number the persona pays with (e.g. 4242 4242 4242 4242).",
|
|
10
|
+
),
|
|
11
|
+
]
|
|
12
|
+
CardExpiryOption = Annotated[
|
|
13
|
+
str | None,
|
|
14
|
+
typer.Option("--test-card-expiry", help="Test card expiry, exactly as the app expects it."),
|
|
15
|
+
]
|
|
16
|
+
CardCvcOption = Annotated[
|
|
17
|
+
str | None,
|
|
18
|
+
typer.Option("--test-card-cvc", help="Test card security code, exactly as the app expects it."),
|
|
19
|
+
]
|
|
20
|
+
CardHolderNameOption = Annotated[
|
|
21
|
+
str | None, typer.Option("--test-card-holder-name", help="Name on the test card.")
|
|
22
|
+
]
|
|
23
|
+
CardPostalCodeOption = Annotated[
|
|
24
|
+
str | None, typer.Option("--test-card-postal-code", help="Test card billing postal code.")
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
_API_KEYS: dict[str, str] = {"holderName": "holder_name", "postalCode": "postal_code"}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def card_fields(
|
|
31
|
+
number: str | None,
|
|
32
|
+
expiry: str | None,
|
|
33
|
+
cvc: str | None,
|
|
34
|
+
holder_name: str | None,
|
|
35
|
+
postal_code: str | None,
|
|
36
|
+
) -> dict[str, str]:
|
|
37
|
+
"""The card fields the command was given, in the API's shape."""
|
|
38
|
+
given = {
|
|
39
|
+
"number": number,
|
|
40
|
+
"expiry": expiry,
|
|
41
|
+
"cvc": cvc,
|
|
42
|
+
"holder_name": holder_name,
|
|
43
|
+
"postal_code": postal_code,
|
|
44
|
+
}
|
|
45
|
+
return {key: value for key, value in given.items() if value is not None}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def merged_card(stored: dict[str, Any] | None, changes: dict[str, str]) -> dict[str, str]:
|
|
49
|
+
"""The stored card with ``changes`` applied, since the API replaces a card whole."""
|
|
50
|
+
items: dict[str, Any] = stored or {}
|
|
51
|
+
current = {_API_KEYS.get(key, key): str(value) for key, value in items.items() if value}
|
|
52
|
+
return {**current, **changes}
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/test_profile_update.py
RENAMED
|
@@ -3,6 +3,15 @@ from typing import Annotated, Any
|
|
|
3
3
|
import typer
|
|
4
4
|
|
|
5
5
|
from minitest_cli.api.client import ApiClient
|
|
6
|
+
from minitest_cli.commands.test_profile_card import (
|
|
7
|
+
CardCvcOption,
|
|
8
|
+
CardExpiryOption,
|
|
9
|
+
CardHolderNameOption,
|
|
10
|
+
CardNumberOption,
|
|
11
|
+
CardPostalCodeOption,
|
|
12
|
+
card_fields,
|
|
13
|
+
merged_card,
|
|
14
|
+
)
|
|
6
15
|
from minitest_cli.commands.test_profile_helpers import (
|
|
7
16
|
app_base_path,
|
|
8
17
|
get_app_flag,
|
|
@@ -66,6 +75,15 @@ def register(app: typer.Typer) -> None:
|
|
|
66
75
|
bool,
|
|
67
76
|
typer.Option("--clear-about", help="Remove the stored about text."),
|
|
68
77
|
] = False,
|
|
78
|
+
test_card_number: CardNumberOption = None,
|
|
79
|
+
test_card_expiry: CardExpiryOption = None,
|
|
80
|
+
test_card_cvc: CardCvcOption = None,
|
|
81
|
+
test_card_holder_name: CardHolderNameOption = None,
|
|
82
|
+
test_card_postal_code: CardPostalCodeOption = None,
|
|
83
|
+
clear_test_card: Annotated[
|
|
84
|
+
bool,
|
|
85
|
+
typer.Option("--clear-test-card", help="Remove the stored test card."),
|
|
86
|
+
] = False,
|
|
69
87
|
) -> None:
|
|
70
88
|
settings = get_settings()
|
|
71
89
|
json_mode = is_json_mode()
|
|
@@ -107,13 +125,31 @@ def register(app: typer.Typer) -> None:
|
|
|
107
125
|
elif clear:
|
|
108
126
|
body[key] = None
|
|
109
127
|
|
|
110
|
-
|
|
128
|
+
card = card_fields(
|
|
129
|
+
test_card_number,
|
|
130
|
+
test_card_expiry,
|
|
131
|
+
test_card_cvc,
|
|
132
|
+
test_card_holder_name,
|
|
133
|
+
test_card_postal_code,
|
|
134
|
+
)
|
|
135
|
+
if card and clear_test_card:
|
|
136
|
+
print_error("Use either --test-card-* options or --clear-test-card, not both.")
|
|
137
|
+
raise typer.Exit(code=1)
|
|
138
|
+
if clear_test_card:
|
|
139
|
+
body["test_card"] = None
|
|
140
|
+
|
|
141
|
+
if not body and not card:
|
|
111
142
|
print_error("Provide at least one field to update.")
|
|
112
143
|
raise typer.Exit(code=1)
|
|
113
144
|
|
|
114
145
|
async def _run() -> dict[str, Any]:
|
|
115
146
|
async with ApiClient(settings) as client:
|
|
116
|
-
|
|
147
|
+
path = f"{app_base_path(app_id)}/{profile_id}"
|
|
148
|
+
if card:
|
|
149
|
+
current = await client.get(path)
|
|
150
|
+
handle_profile_response(current)
|
|
151
|
+
body["test_card"] = merged_card(current.json().get("testCard"), card)
|
|
152
|
+
resp = await client.patch(path, json=body)
|
|
117
153
|
handle_profile_response(resp)
|
|
118
154
|
return resp.json()
|
|
119
155
|
|
|
@@ -48,6 +48,14 @@ class Settings(BaseSettings):
|
|
|
48
48
|
default="cli",
|
|
49
49
|
description="X-Minitest-Channel header value sent on every API call (MINITEST_CHANNEL)",
|
|
50
50
|
)
|
|
51
|
+
conversation_id: str | None = Field(
|
|
52
|
+
default=None,
|
|
53
|
+
description="X-Minitest-Conversation-Id header value (MINITEST_CONVERSATION_ID)",
|
|
54
|
+
)
|
|
55
|
+
cause: str | None = Field(
|
|
56
|
+
default=None,
|
|
57
|
+
description="X-Minitest-Cause header value sent on every API call (MINITEST_CAUSE)",
|
|
58
|
+
)
|
|
51
59
|
token: str | None = Field(
|
|
52
60
|
default=None,
|
|
53
61
|
description="API authentication token (MINITEST_TOKEN)",
|
|
@@ -33,7 +33,9 @@ class PlatformRun(CamelModel):
|
|
|
33
33
|
Every previously-flat ``ios_*`` / ``android_*`` field on
|
|
34
34
|
:class:`StoryRunResponse` now lives here, one row per platform that
|
|
35
35
|
was in scope for the run. ``execution_state`` is the lifecycle axis
|
|
36
|
-
(pending/running/completed/failed/blocked/skipped);
|
|
36
|
+
(pending/running/evaluating/completed/failed/blocked/skipped);
|
|
37
|
+
``evaluating`` is a platform that finished executing and is waiting
|
|
38
|
+
for its verdict. ``verdict`` is
|
|
37
39
|
the criticality-aware outcome populated once the platform reaches a
|
|
38
40
|
non-skipped terminal state. ``cancellation_requested_at`` is
|
|
39
41
|
stamped when a user requested cancellation on this platform; UI
|
|
@@ -11,6 +11,7 @@ from click.exceptions import Exit
|
|
|
11
11
|
from typer.testing import CliRunner
|
|
12
12
|
|
|
13
13
|
from minitest_cli.commands.run import app as run_app
|
|
14
|
+
from minitest_cli.commands.run_display import _derive_run_status
|
|
14
15
|
from minitest_cli.commands.run_helpers import (
|
|
15
16
|
display_run_result,
|
|
16
17
|
extract_detail,
|
|
@@ -1273,3 +1274,65 @@ class TestRunFeedback:
|
|
|
1273
1274
|
tmp_path, ["feedback", "0e4a4b4f-6f0e-4a3b-9e0a-000000000042", "text"], resp=resp
|
|
1274
1275
|
)
|
|
1275
1276
|
assert result.exit_code == 4
|
|
1277
|
+
|
|
1278
|
+
|
|
1279
|
+
_EVALUATING_RUN = {
|
|
1280
|
+
**_PENDING_RUN,
|
|
1281
|
+
"platforms": [
|
|
1282
|
+
{**p, "executionState": "evaluating", "finishedAt": "2025-06-01T10:05:00Z"}
|
|
1283
|
+
for p in _PENDING_RUN["platforms"]
|
|
1284
|
+
],
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
|
|
1288
|
+
class TestEvaluatingRunStatus:
|
|
1289
|
+
def test_evaluating_lane_derives_evaluating(self) -> None:
|
|
1290
|
+
run = StoryRunResponse.model_validate(_EVALUATING_RUN)
|
|
1291
|
+
assert _derive_run_status(run) == "evaluating"
|
|
1292
|
+
|
|
1293
|
+
def test_evaluating_outranks_a_failed_sibling(self) -> None:
|
|
1294
|
+
run = StoryRunResponse.model_validate(
|
|
1295
|
+
{
|
|
1296
|
+
**_EVALUATING_RUN,
|
|
1297
|
+
"platforms": [
|
|
1298
|
+
_EVALUATING_RUN["platforms"][0],
|
|
1299
|
+
{**_EVALUATING_RUN["platforms"][1], "executionState": "failed"},
|
|
1300
|
+
],
|
|
1301
|
+
}
|
|
1302
|
+
)
|
|
1303
|
+
assert _derive_run_status(run) == "evaluating"
|
|
1304
|
+
|
|
1305
|
+
def test_pending_sibling_still_wins(self) -> None:
|
|
1306
|
+
run = StoryRunResponse.model_validate(
|
|
1307
|
+
{
|
|
1308
|
+
**_EVALUATING_RUN,
|
|
1309
|
+
"platforms": [
|
|
1310
|
+
_EVALUATING_RUN["platforms"][0],
|
|
1311
|
+
_PENDING_RUN["platforms"][1],
|
|
1312
|
+
],
|
|
1313
|
+
}
|
|
1314
|
+
)
|
|
1315
|
+
assert _derive_run_status(run) == "pending"
|
|
1316
|
+
|
|
1317
|
+
def test_status_with_watch_polls_through_evaluating(self, tmp_path) -> None:
|
|
1318
|
+
settings = _make_settings(tmp_path)
|
|
1319
|
+
client = _mock_client()
|
|
1320
|
+
client.get = AsyncMock(
|
|
1321
|
+
side_effect=[
|
|
1322
|
+
_mock_response(200, _EVALUATING_RUN),
|
|
1323
|
+
_mock_response(200, _EVALUATING_RUN),
|
|
1324
|
+
_mock_response(200, _COMPLETED_RUN),
|
|
1325
|
+
]
|
|
1326
|
+
)
|
|
1327
|
+
|
|
1328
|
+
with (
|
|
1329
|
+
patch("minitest_cli.commands.run.ApiClient", return_value=client),
|
|
1330
|
+
patch("minitest_cli.commands.run_helpers.asyncio.sleep", new_callable=AsyncMock),
|
|
1331
|
+
patch("minitest_cli.commands.run_helpers.err_console"),
|
|
1332
|
+
):
|
|
1333
|
+
result = _run_with_context(["status", _RUN_UUID, "--watch"], settings, json_mode=True)
|
|
1334
|
+
|
|
1335
|
+
assert result.exit_code == 0
|
|
1336
|
+
assert client.get.call_count == 3
|
|
1337
|
+
data = json.loads(result.output)
|
|
1338
|
+
assert all(p["executionState"] == "completed" for p in data["platforms"])
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Tests for suite-change provenance contract (section 3).
|
|
2
|
+
|
|
3
|
+
Uses real httpx request cycles via MockTransport so headers are proven at
|
|
4
|
+
the HTTP wire level rather than by inspecting mock call args.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
|
|
9
|
+
import httpx
|
|
10
|
+
from typer.testing import CliRunner
|
|
11
|
+
|
|
12
|
+
from minitest_cli.commands.draft_feature import app as df_app
|
|
13
|
+
from tests._commit_transport import cli_context, make_settings, routed
|
|
14
|
+
|
|
15
|
+
runner = CliRunner()
|
|
16
|
+
|
|
17
|
+
_APP_ID = "a0d9820f-5136-4f70-b46b-e5966f56bfb5"
|
|
18
|
+
_FEATURE_PAYLOAD = {
|
|
19
|
+
"id": "b1",
|
|
20
|
+
"tenantId": "t1",
|
|
21
|
+
"appId": _APP_ID,
|
|
22
|
+
"title": "Checkout",
|
|
23
|
+
"description": "test branch",
|
|
24
|
+
"status": "open",
|
|
25
|
+
"rebaseState": "in_sync",
|
|
26
|
+
"rebasedToMainRev": 1,
|
|
27
|
+
"sourceRefs": [],
|
|
28
|
+
"createdAt": "2026-01-01T00:00:00Z",
|
|
29
|
+
"updatedAt": "2026-01-01T00:00:00Z",
|
|
30
|
+
"mergedAt": None,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class TestProvenanceHeaders:
|
|
35
|
+
"""X-Minitest-Conversation-Id and X-Minitest-Cause are sent on every request."""
|
|
36
|
+
|
|
37
|
+
def test_headers_present_when_env_vars_set(self, tmp_path):
|
|
38
|
+
"""Both provenance headers appear when their env vars are set."""
|
|
39
|
+
received: dict[str, str] = {}
|
|
40
|
+
|
|
41
|
+
def handler(request: httpx.Request) -> httpx.Response:
|
|
42
|
+
received["conversation_id"] = request.headers.get("x-minitest-conversation-id", "")
|
|
43
|
+
received["cause"] = request.headers.get("x-minitest-cause", "")
|
|
44
|
+
return httpx.Response(201, json=_FEATURE_PAYLOAD)
|
|
45
|
+
|
|
46
|
+
settings = make_settings(
|
|
47
|
+
tmp_path,
|
|
48
|
+
conversation_id="conv-abc-123",
|
|
49
|
+
cause="ci/pipeline",
|
|
50
|
+
)
|
|
51
|
+
with routed(handler), cli_context(settings, json_mode=True):
|
|
52
|
+
result = runner.invoke(df_app, ["create", "--title", "Checkout"])
|
|
53
|
+
|
|
54
|
+
assert result.exit_code == 0, result.output
|
|
55
|
+
assert received["conversation_id"] == "conv-abc-123"
|
|
56
|
+
assert received["cause"] == "ci/pipeline"
|
|
57
|
+
|
|
58
|
+
def test_headers_absent_when_env_vars_not_set(self, tmp_path):
|
|
59
|
+
"""Neither header is sent when the env vars are absent."""
|
|
60
|
+
received_keys: list[str] = []
|
|
61
|
+
|
|
62
|
+
def handler(request: httpx.Request) -> httpx.Response:
|
|
63
|
+
received_keys.extend(request.headers.keys())
|
|
64
|
+
return httpx.Response(201, json=_FEATURE_PAYLOAD)
|
|
65
|
+
|
|
66
|
+
settings = make_settings(tmp_path)
|
|
67
|
+
with routed(handler), cli_context(settings, json_mode=True):
|
|
68
|
+
result = runner.invoke(df_app, ["create", "--title", "Checkout"])
|
|
69
|
+
|
|
70
|
+
assert result.exit_code == 0, result.output
|
|
71
|
+
assert "x-minitest-conversation-id" not in received_keys
|
|
72
|
+
assert "x-minitest-cause" not in received_keys
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class TestDfCreateSourceRefs:
|
|
76
|
+
"""--source-refs flag is passed as sourceRefs in the POST body."""
|
|
77
|
+
|
|
78
|
+
def test_source_refs_included_in_post_body(self, tmp_path):
|
|
79
|
+
received_body: dict = {}
|
|
80
|
+
|
|
81
|
+
def handler(request: httpx.Request) -> httpx.Response:
|
|
82
|
+
received_body.update(json.loads(request.content))
|
|
83
|
+
return httpx.Response(201, json=_FEATURE_PAYLOAD)
|
|
84
|
+
|
|
85
|
+
source_refs = [{"type": "github_pr", "ref": "https://github.com/org/repo/pull/42"}]
|
|
86
|
+
settings = make_settings(tmp_path)
|
|
87
|
+
with routed(handler), cli_context(settings, json_mode=True):
|
|
88
|
+
result = runner.invoke(
|
|
89
|
+
df_app,
|
|
90
|
+
["create", "--title", "Checkout", "--source-refs", json.dumps(source_refs)],
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
assert result.exit_code == 0, result.output
|
|
94
|
+
assert received_body["sourceRefs"] == source_refs
|
|
95
|
+
|
|
96
|
+
def test_source_refs_absent_when_flag_not_given(self, tmp_path):
|
|
97
|
+
received_body: dict = {}
|
|
98
|
+
|
|
99
|
+
def handler(request: httpx.Request) -> httpx.Response:
|
|
100
|
+
received_body.update(json.loads(request.content))
|
|
101
|
+
return httpx.Response(201, json=_FEATURE_PAYLOAD)
|
|
102
|
+
|
|
103
|
+
settings = make_settings(tmp_path)
|
|
104
|
+
with routed(handler), cli_context(settings, json_mode=True):
|
|
105
|
+
result = runner.invoke(df_app, ["create", "--title", "Checkout"])
|
|
106
|
+
|
|
107
|
+
assert result.exit_code == 0, result.output
|
|
108
|
+
assert "sourceRefs" not in received_body
|
|
@@ -177,6 +177,67 @@ class TestCreate:
|
|
|
177
177
|
assert result.exit_code == 1
|
|
178
178
|
|
|
179
179
|
|
|
180
|
+
class TestTestCard:
|
|
181
|
+
def test_create_sends_only_the_card_fields_given(self, tmp_path):
|
|
182
|
+
settings = _make_settings(tmp_path)
|
|
183
|
+
client = _mock_client(post=_mock_response(201, _PROFILE))
|
|
184
|
+
with patch("minitest_cli.commands.test_profile.ApiClient", return_value=client):
|
|
185
|
+
result = _run(
|
|
186
|
+
[
|
|
187
|
+
"create",
|
|
188
|
+
"--name",
|
|
189
|
+
"Shopper",
|
|
190
|
+
"--test-card-number",
|
|
191
|
+
"4242 4242 4242 4242",
|
|
192
|
+
"--test-card-expiry",
|
|
193
|
+
"12/34",
|
|
194
|
+
],
|
|
195
|
+
settings,
|
|
196
|
+
json_mode=True,
|
|
197
|
+
)
|
|
198
|
+
assert result.exit_code == 0
|
|
199
|
+
body = client.post.await_args.kwargs["json"]
|
|
200
|
+
assert body["test_card"] == {"number": "4242 4242 4242 4242", "expiry": "12/34"}
|
|
201
|
+
|
|
202
|
+
def test_update_changes_one_card_field_and_keeps_the_rest(self, tmp_path):
|
|
203
|
+
settings = _make_settings(tmp_path)
|
|
204
|
+
stored = {
|
|
205
|
+
**_PROFILE,
|
|
206
|
+
"testCard": {"number": "4242 4242 4242 4242", "cvc": "123", "holderName": "Ada"},
|
|
207
|
+
}
|
|
208
|
+
client = _mock_client(get=_mock_response(200, stored), patch_=_mock_response(200, stored))
|
|
209
|
+
with patch("minitest_cli.commands.test_profile_update.ApiClient", return_value=client):
|
|
210
|
+
result = _run(
|
|
211
|
+
["update", "p-111", "--test-card-cvc", "999"],
|
|
212
|
+
settings,
|
|
213
|
+
json_mode=True,
|
|
214
|
+
)
|
|
215
|
+
assert result.exit_code == 0
|
|
216
|
+
body = client.patch.await_args.kwargs["json"]
|
|
217
|
+
assert body == {
|
|
218
|
+
"test_card": {"number": "4242 4242 4242 4242", "cvc": "999", "holder_name": "Ada"}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
def test_update_clear_test_card(self, tmp_path):
|
|
222
|
+
settings = _make_settings(tmp_path)
|
|
223
|
+
client = _mock_client(patch_=_mock_response(200, _PROFILE))
|
|
224
|
+
with patch("minitest_cli.commands.test_profile_update.ApiClient", return_value=client):
|
|
225
|
+
result = _run(["update", "p-111", "--clear-test-card"], settings, json_mode=True)
|
|
226
|
+
assert result.exit_code == 0
|
|
227
|
+
assert client.patch.await_args.kwargs["json"] == {"test_card": None}
|
|
228
|
+
client.get.assert_not_awaited()
|
|
229
|
+
|
|
230
|
+
def test_update_card_field_and_clear_rejected(self, tmp_path):
|
|
231
|
+
settings = _make_settings(tmp_path)
|
|
232
|
+
client = _mock_client()
|
|
233
|
+
with patch("minitest_cli.commands.test_profile_update.ApiClient", return_value=client):
|
|
234
|
+
result = _run(
|
|
235
|
+
["update", "p-111", "--test-card-cvc", "999", "--clear-test-card"], settings
|
|
236
|
+
)
|
|
237
|
+
assert result.exit_code == 1
|
|
238
|
+
client.patch.assert_not_awaited()
|
|
239
|
+
|
|
240
|
+
|
|
180
241
|
class TestUpdate:
|
|
181
242
|
def test_update_clear_password(self, tmp_path):
|
|
182
243
|
settings = _make_settings(tmp_path)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/app_knowledge_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/draft_feature_apply.py
RENAMED
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/draft_feature_conflicts.py
RENAMED
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/draft_feature_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/maintenance_callbacks.py
RENAMED
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/maintenance_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/test_profile_default.py
RENAMED
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/test_profile_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_bindings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_criteria.py
RENAMED
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_criterion_edits.py
RENAMED
|
File without changes
|
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_device_count.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_overrides.py
RENAMED
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/user_story_profiles.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{minitest_cli-0.27.2 → minitest_cli-0.28.1}/src/minitest_cli/commands/verdicts_projection.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|