pyplaykit 1.19.2__tar.gz → 1.20.0__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.
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/CHANGELOG.md +16 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/MANIFEST.in +1 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/PKG-INFO +1 -1
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/config/projects/customs_modernization.yaml +7 -5
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/config/projects/dispatcho.yaml +7 -5
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/config/projects/timelyquote.yaml +7 -5
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pages/orangehrm_login_page.py +17 -8
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit/cli.py +192 -0
- pyplaykit-1.20.0/pyplaykit/config/projects/customs_modernization.yaml +78 -0
- pyplaykit-1.20.0/pyplaykit/config/projects/dispatcho.yaml +71 -0
- pyplaykit-1.20.0/pyplaykit/config/projects/timelyquote.yaml +66 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit/plugin.py +62 -2
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit.egg-info/PKG-INFO +1 -1
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit.egg-info/SOURCES.txt +4 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyproject.toml +2 -2
- pyplaykit-1.20.0/utils/project_config.py +187 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/yaml_config_reader.py +47 -1
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/.github/copilot-instructions.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/.github/prompts/review-execution-plan-and-implement-next-task.prompt.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/.github/prompts/run-unit-tests-and-coverage.prompt.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/.github/prompts/security-audit-and-consolidated-report.prompt.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/CHOOSE_YOUR_STRUCTURE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/CLAUDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/COLUMN_MAPPING_AND_IGNORE_FIELDS_GUIDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/COMMANDS_FOR_YOUR_PROJECTS.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/COMMIT_SUMMARY.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/CONTRIBUTING.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/CORRECTED_PROJECT_NAMES.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/DATABASE_IMPLEMENTATION_SUMMARY.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/DELIVERABLES_SUMMARY.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/ENTERPRISE_TEST_STRUCTURE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/FINAL_PROJECT_SETUP.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/GAP_TRACKER.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/HOW_TO_ACCESS_DOCS.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/INIT_COMMAND_EXAMPLES.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/KEY_BASED_MATCHING_SOLUTION.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/MIGRATION_COMPLETE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/MIGRATION_PLAN.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/PIP_INSTALL_GUIDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/PYPLAYKIT_CLIENT_OVERVIEW.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/QUICK_DB_REFERENCE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/QUICK_REFERENCE_COMPARISON_FEATURES.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/QUICK_START_QE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/STRUCTURE_COMPARISON.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/TEST_LOCATION_CHEATSHEET.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/VISUAL_COMPARISON.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/WINDOWS_INSTALL_GUIDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/YOUR_PROJECTS_IMPLEMENTATION_GUIDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/YOUR_SETUP_SUMMARY.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/bin/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/components/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/components/base_component.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/components/data_table.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/components/form_field.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/components/modal.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/config/config.yaml +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/config/data_comparison_profiles.yaml +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/config/environments.yaml +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/core/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/core/base_page.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/core/base_test.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/core/browser_factory.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/core/playwright_manager.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/demo/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/demo/functional/database/file_comparison/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/demo/functional/database/postgres_src_tgt/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/dist_pkg/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/dist_pkg/distribution.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/API_TESTING_GUIDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/CLI_REFERENCE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/COMPETITIVE_ANALYSIS.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/COVERAGE_IMPROVEMENTS.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/CUSTOMER_SCENARIOS.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/DATABASE_SUPPORT.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/DATA_VALIDATION_GUIDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/DELIVERABLES_INDEX.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/EXAMPLE_TESTS_SUMMARY.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/Enterprise-Framework-Assessment-REVISED.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/Enterprise-Readiness-Assessment.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/Example-Tests-Guide.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/Execution-Plan-Backlog-and-Closure-Tracker.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/FRAMEWORK_CONTRIBUTION_GUIDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/01_ARCHITECTURE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/02_DEPLOYMENT_RUNBOOK.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/03_ACCESS_MATRIX.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/04_CLIENT_CONTACT_MATRIX.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/05_OPEN_RISKS_REGISTER.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/06_PENDING_ENHANCEMENTS.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/07_PRODUCT_ROADMAP.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/08_ENVIRONMENT_DETAILS.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/09_OPERATIONAL_SOPS.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/10_ESCALATION_MATRIX.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/11_KT_RECORDINGS_INDEX.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/12_REVERSE_KT_SIGNOFF.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/13_LEADERSHIP_SIGNOFF.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/KT/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/MCP_SERVER_DESIGN.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/MULTI_DB_VALIDATION_GUIDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/MULTI_PROJECT_STRUCTURE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/PIP_INSTALL_GUIDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/PyPlayKit-Framework-Overview.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/PyPlayKit-Usage-Scenarios.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/QE_VISUAL_GUIDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/RESILIENCE_GUIDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/RUN_TESTS_QUICK_REFERENCE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/TEST_ORGANIZATION.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/docs/Usage-Scenarios-Feasibility-Analysis.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/integrations/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/integrations/adapters.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/mcp_server/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/mcp_server/_ast_utils.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/mcp_server/_config_utils.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/mcp_server/cli.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/mcp_server/server.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/mcp_server/tools/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/mcp_server/tools/package_discovery.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/mcp_server/tools/project_introspection.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/mcp_server/tools/project_state.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/orchestration/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/orchestration/enforcer.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/orchestration/planner.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pages/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pages/dashboard_page.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pages/login_page.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pages/saucedemo_inventory_page.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pages/saucedemo_login_page.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/plugins/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/plugins/api_plugin.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/plugins/base.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/plugins/data_plugin.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/plugins/registry.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/plugins/security_plugin.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit/PIP_INSTALL_GUIDE.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit/config/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit/config/config.yaml +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit/config/environments.yaml +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit/show_docs.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit.egg-info/dependency_links.txt +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit.egg-info/entry_points.txt +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit.egg-info/requires.txt +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/pyplaykit.egg-info/top_level.txt +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/resilience/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/resilience/locator_recovery.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/setup.cfg +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/test_data/api/ecom/auth_payloads.json +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/test_data/api/ecom/product_payloads.json +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/test_data/api_test_data.json +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/test_data/data_validation_test_data.json +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/test_data/login_test_data.json +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/test_data/orangehrm_login_data.json +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/test_data/ui_test_data.json +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/tests/projects/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/tests/projects/customs_modernization/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/tests/projects/demo/functional/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/tests/projects/demo/functional/api/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/tests/projects/demo/functional/database/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/tests/projects/demo/functional/ui/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/tests/projects/demo/integration/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/tests/projects/dispatcho/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/tests/projects/timelyquote/README.md +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/api_client.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/api_test_helper.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/assertion_helper.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/auth_manager.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/comparison_config_loader.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/data_comparison_report.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/data_comparison_utils.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/data_loader.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/data_source.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/data_validator.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/database_clients.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_client.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_drivers/__init__.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_drivers/db2.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_drivers/informix.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_drivers/mysql.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_drivers/oracle.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_drivers/snowflake.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_drivers/sqlite.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_drivers/sqlserver.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_factory.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_fixtures.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_pool.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/db_validation_helper.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/environment_validator.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/file_reader.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/graphql_client.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/logger.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/observability.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/observability_report.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/response_validator.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/screenshot_helper.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/soap_client.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/tdm.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/transformation_validator.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/ui_db_validator.py +0 -0
- {pyplaykit-1.19.2 → pyplaykit-1.20.0}/utils/version_checker.py +0 -0
|
@@ -11,6 +11,22 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
## [1.20.0] — 2026-08-14
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Multi-project environment configuration is now wired end-to-end** — the per-project config files under `config/projects/<project>.yaml` (previously present but inert) are now resolved at runtime. A project can be selected via the new `--pyplaykit-project` pytest option, the `PYPLAYKIT_PROJECT` environment variable, or automatic detection from the test path (`tests/<project>/…`, session-level unanimous). When a project is active, its `environments.<env>` node is deep-merged over the global `environments.yaml` defaults (project wins); the resolved `project`, `api_base_url`, `api_endpoints`, `test_users`, and `features` are surfaced in `runtime_options`. `ConfigReader` gains `set_project()` / `get_project()` and project-aware `get_environment_settings()`. New shared helper `utils/project_config.py` provides `${VAR}` env interpolation, DSN parsing, deep-merge, project loading, and path-based detection.
|
|
19
|
+
- **No secrets in config** — project files describe databases with a single non-secret `database_url` DSN (host/port/database only); credentials continue to come from the `SRC_DB_USER` / `SRC_DB_PASSWORD` (and `TGT_*`) environment variables via `get_src_db_config()` / `get_tgt_db_config()`.
|
|
20
|
+
- **Backward-compatible** — with no project selected, configuration resolves exactly as before, byte-for-byte. Existing single-project flat `environments.yaml` layouts are unaffected.
|
|
21
|
+
- `pyplaykit init --project-names=a,b,c` scaffolds `config/projects/<name>.yaml` for each named project.
|
|
22
|
+
- **`pyplaykit init` now scaffolds a `pages/` package** — generates `pages/__init__.py` and a starter `pages/login_page.py` (a `BasePage`-conforming `LoginPage`) so page objects have a scaffolded home and `from pages.login_page import LoginPage` resolves immediately after init.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **`pages/orangehrm_login_page.py` now conforms to the `BasePage` contract** — constructed as `OrangeHRMLoginPage(page, resilience_policy)` and the custom navigation method was renamed to `open(base_url)` (delegating to the inherited `navigate(url)`) so it no longer shadows the `BasePage.navigate` signature. Callers and unit tests updated accordingly.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
14
30
|
## [1.19.2] — 2026-07-24
|
|
15
31
|
|
|
16
32
|
### Fixed
|
|
@@ -13,27 +13,29 @@ project:
|
|
|
13
13
|
- customer_mgmt
|
|
14
14
|
- modernization
|
|
15
15
|
|
|
16
|
-
# Environment-specific URLs
|
|
16
|
+
# Environment-specific URLs. database_url carries only the non-secret
|
|
17
|
+
# host/port/database; DB credentials come from the SRC_DB_USER / SRC_DB_PASSWORD
|
|
18
|
+
# (and TGT_*) environment variables — never store passwords here.
|
|
17
19
|
environments:
|
|
18
20
|
dev:
|
|
19
21
|
base_url: "https://dev.customers.internal.com"
|
|
20
22
|
api_base_url: "https://api.dev.customers.internal.com"
|
|
21
|
-
database_url: "postgresql://
|
|
23
|
+
database_url: "postgresql://dev-db:5432/customers_dev"
|
|
22
24
|
|
|
23
25
|
qa:
|
|
24
26
|
base_url: "https://qa.customers.internal.com"
|
|
25
27
|
api_base_url: "https://api.qa.customers.internal.com"
|
|
26
|
-
database_url: "postgresql://
|
|
28
|
+
database_url: "postgresql://qa-db:5432/customers_qa"
|
|
27
29
|
|
|
28
30
|
uat:
|
|
29
31
|
base_url: "https://uat.customers.internal.com"
|
|
30
32
|
api_base_url: "https://api.uat.customers.internal.com"
|
|
31
|
-
database_url: "postgresql://
|
|
33
|
+
database_url: "postgresql://uat-db:5432/customers_uat"
|
|
32
34
|
|
|
33
35
|
prod:
|
|
34
36
|
base_url: "https://customers.internal.com"
|
|
35
37
|
api_base_url: "https://api.customers.internal.com"
|
|
36
|
-
database_url: "postgresql://
|
|
38
|
+
database_url: "postgresql://prod-db:5432/customers_prod"
|
|
37
39
|
|
|
38
40
|
# API endpoints
|
|
39
41
|
api_endpoints:
|
|
@@ -13,27 +13,29 @@ project:
|
|
|
13
13
|
- logistics
|
|
14
14
|
- dispatch
|
|
15
15
|
|
|
16
|
-
# Environment-specific URLs
|
|
16
|
+
# Environment-specific URLs. database_url carries only the non-secret
|
|
17
|
+
# host/port/database; DB credentials come from the SRC_DB_USER / SRC_DB_PASSWORD
|
|
18
|
+
# (and TGT_*) environment variables — never store passwords here.
|
|
17
19
|
environments:
|
|
18
20
|
dev:
|
|
19
21
|
base_url: "https://dev.dispatcho.com"
|
|
20
22
|
api_base_url: "https://api.dev.dispatcho.com"
|
|
21
|
-
database_url: "postgresql://
|
|
23
|
+
database_url: "postgresql://dev-db:5432/dispatcho_dev"
|
|
22
24
|
|
|
23
25
|
qa:
|
|
24
26
|
base_url: "https://qa.dispatcho.com"
|
|
25
27
|
api_base_url: "https://api.qa.dispatcho.com"
|
|
26
|
-
database_url: "postgresql://
|
|
28
|
+
database_url: "postgresql://qa-db:5432/dispatcho_qa"
|
|
27
29
|
|
|
28
30
|
uat:
|
|
29
31
|
base_url: "https://uat.dispatcho.com"
|
|
30
32
|
api_base_url: "https://api.uat.dispatcho.com"
|
|
31
|
-
database_url: "postgresql://
|
|
33
|
+
database_url: "postgresql://uat-db:5432/dispatcho_uat"
|
|
32
34
|
|
|
33
35
|
prod:
|
|
34
36
|
base_url: "https://www.dispatcho.com"
|
|
35
37
|
api_base_url: "https://api.dispatcho.com"
|
|
36
|
-
database_url: "postgresql://
|
|
38
|
+
database_url: "postgresql://prod-db:5432/dispatcho_prod"
|
|
37
39
|
|
|
38
40
|
# API endpoints
|
|
39
41
|
api_endpoints:
|
|
@@ -12,27 +12,29 @@ project:
|
|
|
12
12
|
- timelyquote
|
|
13
13
|
- quotes
|
|
14
14
|
|
|
15
|
-
# Environment-specific URLs
|
|
15
|
+
# Environment-specific URLs. database_url carries only the non-secret
|
|
16
|
+
# host/port/database; DB credentials come from the SRC_DB_USER / SRC_DB_PASSWORD
|
|
17
|
+
# (and TGT_*) environment variables — never store passwords here.
|
|
16
18
|
environments:
|
|
17
19
|
dev:
|
|
18
20
|
base_url: "https://dev.timelyquote.com"
|
|
19
21
|
api_base_url: "https://api.dev.timelyquote.com"
|
|
20
|
-
database_url: "postgresql://
|
|
22
|
+
database_url: "postgresql://dev-db:5432/timelyquote_dev"
|
|
21
23
|
|
|
22
24
|
qa:
|
|
23
25
|
base_url: "https://qa.timelyquote.com"
|
|
24
26
|
api_base_url: "https://api.qa.timelyquote.com"
|
|
25
|
-
database_url: "postgresql://
|
|
27
|
+
database_url: "postgresql://qa-db:5432/timelyquote_qa"
|
|
26
28
|
|
|
27
29
|
uat:
|
|
28
30
|
base_url: "https://uat.timelyquote.com"
|
|
29
31
|
api_base_url: "https://api.uat.timelyquote.com"
|
|
30
|
-
database_url: "postgresql://
|
|
32
|
+
database_url: "postgresql://uat-db:5432/timelyquote_uat"
|
|
31
33
|
|
|
32
34
|
prod:
|
|
33
35
|
base_url: "https://www.timelyquote.com"
|
|
34
36
|
api_base_url: "https://api.timelyquote.com"
|
|
35
|
-
database_url: "postgresql://
|
|
37
|
+
database_url: "postgresql://prod-db:5432/timelyquote_prod"
|
|
36
38
|
|
|
37
39
|
# API endpoints
|
|
38
40
|
api_endpoints:
|
|
@@ -1,12 +1,21 @@
|
|
|
1
|
+
"""Login page object for the OrangeHRM demo application."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
1
5
|
from playwright.sync_api import Page
|
|
6
|
+
|
|
2
7
|
from core.base_page import BasePage
|
|
3
|
-
from utils.yaml_config_reader import ConfigReader
|
|
4
8
|
from utils.logger import get_logger
|
|
5
9
|
|
|
10
|
+
|
|
6
11
|
class OrangeHRMLoginPage(BasePage):
|
|
7
12
|
"""
|
|
8
13
|
Page object for the OrangeHRM Login page.
|
|
9
14
|
Encapsulates locators and actions related to the login functionality.
|
|
15
|
+
|
|
16
|
+
Follows the standard PyPlayKit POM contract:
|
|
17
|
+
``OrangeHRMLoginPage(page, runtime_options["resilience_policy"])``.
|
|
18
|
+
Use :meth:`open` to navigate to the login screen for a given base URL.
|
|
10
19
|
"""
|
|
11
20
|
|
|
12
21
|
# Locators
|
|
@@ -16,15 +25,15 @@ class OrangeHRMLoginPage(BasePage):
|
|
|
16
25
|
DASHBOARD_HEADER = "h6.oxd-text.oxd-text--h6.oxd-topbar-header-breadcrumb-module" # A locator to verify successful login
|
|
17
26
|
INVALID_CREDENTIALS_MESSAGE = "div.oxd-alert-content.oxd-alert-content--error > p.oxd-text--p"
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
LOGIN_PATH = "/web/index.php/auth/login"
|
|
29
|
+
|
|
30
|
+
def __init__(self, page: Page, resilience_policy: dict[str, Any] | None = None):
|
|
31
|
+
super().__init__(page, resilience_policy)
|
|
22
32
|
self.logger = get_logger(OrangeHRMLoginPage.__name__)
|
|
23
|
-
self.base_url = self.config.get_base_url(self.config.get_env()) # Get base URL for the current environment
|
|
24
33
|
|
|
25
|
-
def
|
|
26
|
-
"""Navigates to the OrangeHRM login page."""
|
|
27
|
-
self.
|
|
34
|
+
def open(self, base_url: str):
|
|
35
|
+
"""Navigates to the OrangeHRM login page for the given base URL."""
|
|
36
|
+
self.navigate(base_url.rstrip("/") + self.LOGIN_PATH)
|
|
28
37
|
self.logger.info(f"Navigated to: {self.page.url}")
|
|
29
38
|
|
|
30
39
|
def login(self, username, password):
|
|
@@ -59,6 +59,123 @@ log_cli = false
|
|
|
59
59
|
log_cli_level = INFO
|
|
60
60
|
'''
|
|
61
61
|
|
|
62
|
+
_PAGES_INIT_TEMPLATE = '''\
|
|
63
|
+
"""Project page objects.
|
|
64
|
+
|
|
65
|
+
Page objects live in this package so ``from pages.<name> import <Page>`` resolves
|
|
66
|
+
to *your* repository's code. Every page object subclasses
|
|
67
|
+
``core.base_page.BasePage`` and is constructed as
|
|
68
|
+
``MyPage(page, runtime_options["resilience_policy"])``.
|
|
69
|
+
"""
|
|
70
|
+
'''
|
|
71
|
+
|
|
72
|
+
_PAGES_LOGIN_PAGE_TEMPLATE = '''\
|
|
73
|
+
"""Starter page object — copy this pattern for your own pages.
|
|
74
|
+
|
|
75
|
+
Locators live as class constants; methods expose intent (``login``,
|
|
76
|
+
``is_logged_in``) rather than raw selectors. Construct with the resilience
|
|
77
|
+
policy so self-healing locators work when enabled:
|
|
78
|
+
|
|
79
|
+
from pages.login_page import LoginPage
|
|
80
|
+
login_page = LoginPage(page, runtime_options["resilience_policy"])
|
|
81
|
+
login_page.navigate(runtime_options["base_url"])
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
from core.base_page import BasePage
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class LoginPage(BasePage):
|
|
88
|
+
"""Page object for a generic login screen (SauceDemo selectors by default)."""
|
|
89
|
+
|
|
90
|
+
# Locators as class constants — never put raw selectors in tests.
|
|
91
|
+
USERNAME_INPUT = "#user-name"
|
|
92
|
+
PASSWORD_INPUT = "#password"
|
|
93
|
+
LOGIN_BUTTON = "#login-button"
|
|
94
|
+
ERROR_BANNER = "[data-test='error']"
|
|
95
|
+
INVENTORY_CONTAINER = "[data-test='inventory-container']"
|
|
96
|
+
|
|
97
|
+
def login(self, username: str, password: str) -> None:
|
|
98
|
+
"""Fill credentials and submit the login form."""
|
|
99
|
+
self.fill(self.USERNAME_INPUT, username)
|
|
100
|
+
self.fill(self.PASSWORD_INPUT, password)
|
|
101
|
+
self.click(self.LOGIN_BUTTON)
|
|
102
|
+
|
|
103
|
+
def get_error_message(self) -> str:
|
|
104
|
+
"""Return the login error banner text."""
|
|
105
|
+
return self.text(self.ERROR_BANNER)
|
|
106
|
+
|
|
107
|
+
def is_logged_in(self) -> bool:
|
|
108
|
+
"""Return True when the post-login landing element is visible."""
|
|
109
|
+
return self.is_visible(self.INVENTORY_CONTAINER, timeout=5000)
|
|
110
|
+
'''
|
|
111
|
+
|
|
112
|
+
# Per-project config template. ``__NAME__`` / ``__UPPER__`` tokens are replaced
|
|
113
|
+
# with the project name (lower) and upper-cased form. Credentials never live in
|
|
114
|
+
# config — DB creds come from SRC_DB_USER/SRC_DB_PASSWORD env vars and the
|
|
115
|
+
# database_url below carries only the non-secret host/port/database.
|
|
116
|
+
_PROJECT_CONFIG_TEMPLATE = '''\
|
|
117
|
+
# __NAME__ Project Configuration
|
|
118
|
+
#
|
|
119
|
+
# When a test runs under tests/__NAME__/... (or with --pyplaykit-project __NAME__),
|
|
120
|
+
# these settings are deep-merged over the global config/environments.yaml defaults.
|
|
121
|
+
# ${VAR} placeholders are expanded from environment variables at load time.
|
|
122
|
+
|
|
123
|
+
project:
|
|
124
|
+
name: "__NAME__"
|
|
125
|
+
description: "TODO: describe the __NAME__ project"
|
|
126
|
+
team:
|
|
127
|
+
lead: "TBD"
|
|
128
|
+
engineers: []
|
|
129
|
+
slack_channel: "#__NAME__-qa"
|
|
130
|
+
|
|
131
|
+
markers:
|
|
132
|
+
- __NAME__
|
|
133
|
+
|
|
134
|
+
# Environment-specific URLs. database_url carries only non-secret parts
|
|
135
|
+
# (host/port/database); DB credentials come from SRC_DB_USER / SRC_DB_PASSWORD.
|
|
136
|
+
environments:
|
|
137
|
+
dev:
|
|
138
|
+
base_url: "https://dev.__NAME__.example.com"
|
|
139
|
+
api_base_url: "https://api.dev.__NAME__.example.com"
|
|
140
|
+
database_url: "postgresql://dev-db:5432/__NAME___dev"
|
|
141
|
+
qa:
|
|
142
|
+
base_url: "https://qa.__NAME__.example.com"
|
|
143
|
+
api_base_url: "https://api.qa.__NAME__.example.com"
|
|
144
|
+
database_url: "postgresql://qa-db:5432/__NAME___qa"
|
|
145
|
+
uat:
|
|
146
|
+
base_url: "https://uat.__NAME__.example.com"
|
|
147
|
+
api_base_url: "https://api.uat.__NAME__.example.com"
|
|
148
|
+
database_url: "postgresql://uat-db:5432/__NAME___uat"
|
|
149
|
+
prod:
|
|
150
|
+
base_url: "https://www.__NAME__.example.com"
|
|
151
|
+
api_base_url: "https://api.__NAME__.example.com"
|
|
152
|
+
database_url: "postgresql://prod-db:5432/__NAME___prod"
|
|
153
|
+
|
|
154
|
+
# API endpoints (relative to api_base_url)
|
|
155
|
+
api_endpoints:
|
|
156
|
+
example: "/api/v1/example"
|
|
157
|
+
|
|
158
|
+
# Test users — credentials sourced from environment variables, never hardcoded.
|
|
159
|
+
test_users:
|
|
160
|
+
standard_user:
|
|
161
|
+
username: "${__UPPER___USERNAME}"
|
|
162
|
+
password: "${__UPPER___PASSWORD}"
|
|
163
|
+
admin_user:
|
|
164
|
+
username: "${__UPPER___ADMIN_USERNAME}"
|
|
165
|
+
password: "${__UPPER___ADMIN_PASSWORD}"
|
|
166
|
+
|
|
167
|
+
# Feature flags
|
|
168
|
+
features:
|
|
169
|
+
example_feature: true
|
|
170
|
+
|
|
171
|
+
# Test execution settings
|
|
172
|
+
execution:
|
|
173
|
+
browser: "chromium"
|
|
174
|
+
headless: true
|
|
175
|
+
timeout: 30000
|
|
176
|
+
retries: 2
|
|
177
|
+
'''
|
|
178
|
+
|
|
62
179
|
_EXAMPLE_UI = '''\
|
|
63
180
|
"""Demo UI validation test — runs out of the box against saucedemo.com.
|
|
64
181
|
|
|
@@ -1637,6 +1754,65 @@ tests/
|
|
|
1637
1754
|
pyplaykit init . --multi --project-names=shop,admin,mobile
|
|
1638
1755
|
```
|
|
1639
1756
|
|
|
1757
|
+
This generates the `tests/<project>/` tree **and** a matching
|
|
1758
|
+
`config/projects/<project>.yaml` for each name, so config and tests are created
|
|
1759
|
+
in lockstep.
|
|
1760
|
+
|
|
1761
|
+
## Per-Project Configuration
|
|
1762
|
+
|
|
1763
|
+
Each project has its own `config/projects/<project>.yaml` describing
|
|
1764
|
+
environment URLs, API endpoints, test users, and feature flags:
|
|
1765
|
+
|
|
1766
|
+
```yaml
|
|
1767
|
+
project:
|
|
1768
|
+
name: "shop"
|
|
1769
|
+
environments:
|
|
1770
|
+
qa:
|
|
1771
|
+
base_url: "https://qa.shop.example.com"
|
|
1772
|
+
api_base_url: "https://api.qa.shop.example.com"
|
|
1773
|
+
database_url: "postgresql://qa-db:5432/shop_qa" # non-secret parts only
|
|
1774
|
+
test_users:
|
|
1775
|
+
standard_user:
|
|
1776
|
+
username: "${SHOP_USERNAME}" # expanded from environment variables
|
|
1777
|
+
password: "${SHOP_PASSWORD}"
|
|
1778
|
+
```
|
|
1779
|
+
|
|
1780
|
+
When a project is active, its `environments.<env>` node is **deep-merged over**
|
|
1781
|
+
the global `config/environments.yaml` defaults (project wins; anything the
|
|
1782
|
+
project omits — e.g. `tgt_db`, `auth` — is inherited). Database credentials are
|
|
1783
|
+
never stored in config: only the non-secret host/port/database come from
|
|
1784
|
+
`database_url`; the user and password come from the `SRC_DB_USER` /
|
|
1785
|
+
`SRC_DB_PASSWORD` (and `TGT_*`) environment variables. `${VAR}` placeholders are
|
|
1786
|
+
expanded from the environment at load time.
|
|
1787
|
+
|
|
1788
|
+
Legacy single-project repos with a flat `config/environments.yaml` and no
|
|
1789
|
+
project keep resolving exactly as before.
|
|
1790
|
+
|
|
1791
|
+
## Selecting the Active Project
|
|
1792
|
+
|
|
1793
|
+
The active project is **auto-detected from the test path** (`tests/<project>/…`),
|
|
1794
|
+
so engineers rarely pass a flag:
|
|
1795
|
+
|
|
1796
|
+
```bash
|
|
1797
|
+
pytest tests/shop/ --pyplaykit-env qa # resolves shop's QA URLs/DB
|
|
1798
|
+
pytest tests/admin/ --pyplaykit-env qa # resolves admin's QA URLs/DB
|
|
1799
|
+
```
|
|
1800
|
+
|
|
1801
|
+
To pin a project explicitly (or when one run mixes projects), pass the flag or
|
|
1802
|
+
env var — these override auto-detection:
|
|
1803
|
+
|
|
1804
|
+
```bash
|
|
1805
|
+
pytest tests/ --pyplaykit-project shop
|
|
1806
|
+
PYPLAYKIT_PROJECT=shop pytest tests/
|
|
1807
|
+
```
|
|
1808
|
+
|
|
1809
|
+
When a single invocation collects tests from more than one project, no project
|
|
1810
|
+
is pinned and resolution falls back to the flat global config — run one project
|
|
1811
|
+
per invocation, or pass `--pyplaykit-project`.
|
|
1812
|
+
|
|
1813
|
+
Project-scoped values are exposed on `runtime_options`: `project`, `base_url`,
|
|
1814
|
+
`api_base_url`, `api_endpoints`, `test_users`, and `features`.
|
|
1815
|
+
|
|
1640
1816
|
## Running Tests by Project
|
|
1641
1817
|
|
|
1642
1818
|
```bash
|
|
@@ -1933,6 +2109,13 @@ def _init(
|
|
|
1933
2109
|
shutil.copy2(client_overview_src, client_overview_dest)
|
|
1934
2110
|
print(f" created {client_overview_dest}")
|
|
1935
2111
|
|
|
2112
|
+
# Create the project pages/ package so `from pages.<name> import <Page>`
|
|
2113
|
+
# resolves to the user's own repository (not the installed framework samples).
|
|
2114
|
+
pages_dir = project_dir / "pages"
|
|
2115
|
+
pages_dir.mkdir(exist_ok=True)
|
|
2116
|
+
_write_if_new(pages_dir / "__init__.py", _PAGES_INIT_TEMPLATE)
|
|
2117
|
+
_write_if_new(pages_dir / "login_page.py", _PAGES_LOGIN_PAGE_TEMPLATE)
|
|
2118
|
+
|
|
1936
2119
|
# Create enterprise-scale test structure
|
|
1937
2120
|
print()
|
|
1938
2121
|
tests_root = project_dir / "tests"
|
|
@@ -1944,9 +2127,18 @@ def _init(
|
|
|
1944
2127
|
names = project_names or ["project1"]
|
|
1945
2128
|
print(" Creating MULTI-PROJECT structure...")
|
|
1946
2129
|
_write_if_new(tests_root / "README.md", _MULTI_PROJECT_README)
|
|
2130
|
+
projects_config_dir = config_dest / "projects"
|
|
2131
|
+
projects_config_dir.mkdir(parents=True, exist_ok=True)
|
|
1947
2132
|
for name in names:
|
|
1948
2133
|
print(f" Creating project: {name}")
|
|
1949
2134
|
_create_functional_structure(tests_root / name / "functional", tests_root)
|
|
2135
|
+
# Generate a per-project config so the test tree and config surface
|
|
2136
|
+
# are produced in lockstep.
|
|
2137
|
+
project_config_file = projects_config_dir / f"{name}.yaml"
|
|
2138
|
+
rendered = _PROJECT_CONFIG_TEMPLATE.replace("__NAME__", name).replace(
|
|
2139
|
+
"__UPPER__", name.upper().replace("-", "_")
|
|
2140
|
+
)
|
|
2141
|
+
_write_if_new(project_config_file, rendered)
|
|
1950
2142
|
else:
|
|
1951
2143
|
print(" Creating SINGLE-PROJECT test structure...")
|
|
1952
2144
|
_create_functional_structure(tests_root / "functional", tests_root)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Customers Modernization Project Configuration
|
|
2
|
+
|
|
3
|
+
project:
|
|
4
|
+
name: "Customers Modernization"
|
|
5
|
+
description: "Customer management system modernization initiative"
|
|
6
|
+
team:
|
|
7
|
+
lead: "TBD"
|
|
8
|
+
engineers: []
|
|
9
|
+
slack_channel: "#customers-qa"
|
|
10
|
+
|
|
11
|
+
markers:
|
|
12
|
+
- customers_modernization
|
|
13
|
+
- customer_mgmt
|
|
14
|
+
- modernization
|
|
15
|
+
|
|
16
|
+
# Environment-specific URLs. database_url carries only the non-secret
|
|
17
|
+
# host/port/database; DB credentials come from the SRC_DB_USER / SRC_DB_PASSWORD
|
|
18
|
+
# (and TGT_*) environment variables — never store passwords here.
|
|
19
|
+
environments:
|
|
20
|
+
dev:
|
|
21
|
+
base_url: "https://dev.customers.internal.com"
|
|
22
|
+
api_base_url: "https://api.dev.customers.internal.com"
|
|
23
|
+
database_url: "postgresql://dev-db:5432/customers_dev"
|
|
24
|
+
|
|
25
|
+
qa:
|
|
26
|
+
base_url: "https://qa.customers.internal.com"
|
|
27
|
+
api_base_url: "https://api.qa.customers.internal.com"
|
|
28
|
+
database_url: "postgresql://qa-db:5432/customers_qa"
|
|
29
|
+
|
|
30
|
+
uat:
|
|
31
|
+
base_url: "https://uat.customers.internal.com"
|
|
32
|
+
api_base_url: "https://api.uat.customers.internal.com"
|
|
33
|
+
database_url: "postgresql://uat-db:5432/customers_uat"
|
|
34
|
+
|
|
35
|
+
prod:
|
|
36
|
+
base_url: "https://customers.internal.com"
|
|
37
|
+
api_base_url: "https://api.customers.internal.com"
|
|
38
|
+
database_url: "postgresql://prod-db:5432/customers_prod"
|
|
39
|
+
|
|
40
|
+
# API endpoints
|
|
41
|
+
api_endpoints:
|
|
42
|
+
customers: "/api/v1/customers"
|
|
43
|
+
accounts: "/api/v1/accounts"
|
|
44
|
+
profiles: "/api/v1/profiles"
|
|
45
|
+
preferences: "/api/v1/preferences"
|
|
46
|
+
contacts: "/api/v1/contacts"
|
|
47
|
+
|
|
48
|
+
# Test data
|
|
49
|
+
test_users:
|
|
50
|
+
standard_user:
|
|
51
|
+
username: "${CUSTOMERS_USERNAME}"
|
|
52
|
+
password: "${CUSTOMERS_PASSWORD}"
|
|
53
|
+
admin_user:
|
|
54
|
+
username: "${CUSTOMERS_ADMIN_USERNAME}"
|
|
55
|
+
password: "${CUSTOMERS_ADMIN_PASSWORD}"
|
|
56
|
+
data_analyst:
|
|
57
|
+
username: "${CUSTOMERS_ANALYST_USERNAME}"
|
|
58
|
+
password: "${CUSTOMERS_ANALYST_PASSWORD}"
|
|
59
|
+
|
|
60
|
+
# Feature flags
|
|
61
|
+
features:
|
|
62
|
+
customer_360_view: true
|
|
63
|
+
data_migration: true
|
|
64
|
+
legacy_integration: true
|
|
65
|
+
analytics_dashboard: true
|
|
66
|
+
|
|
67
|
+
# Test execution settings
|
|
68
|
+
execution:
|
|
69
|
+
browser: "chromium"
|
|
70
|
+
headless: true
|
|
71
|
+
timeout: 30000
|
|
72
|
+
retries: 2
|
|
73
|
+
|
|
74
|
+
# Migration-specific settings
|
|
75
|
+
migration:
|
|
76
|
+
legacy_system_url: "https://legacy.customers.internal.com"
|
|
77
|
+
data_validation: true
|
|
78
|
+
parallel_run: true # Run both old and new systems in parallel
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Dispatcho Project Configuration
|
|
2
|
+
|
|
3
|
+
project:
|
|
4
|
+
name: "Dispatcho"
|
|
5
|
+
description: "Dispatch and logistics management system"
|
|
6
|
+
team:
|
|
7
|
+
lead: "TBD"
|
|
8
|
+
engineers: []
|
|
9
|
+
slack_channel: "#dispatcho-qa"
|
|
10
|
+
|
|
11
|
+
markers:
|
|
12
|
+
- dispatcho
|
|
13
|
+
- logistics
|
|
14
|
+
- dispatch
|
|
15
|
+
|
|
16
|
+
# Environment-specific URLs. database_url carries only the non-secret
|
|
17
|
+
# host/port/database; DB credentials come from the SRC_DB_USER / SRC_DB_PASSWORD
|
|
18
|
+
# (and TGT_*) environment variables — never store passwords here.
|
|
19
|
+
environments:
|
|
20
|
+
dev:
|
|
21
|
+
base_url: "https://dev.dispatcho.com"
|
|
22
|
+
api_base_url: "https://api.dev.dispatcho.com"
|
|
23
|
+
database_url: "postgresql://dev-db:5432/dispatcho_dev"
|
|
24
|
+
|
|
25
|
+
qa:
|
|
26
|
+
base_url: "https://qa.dispatcho.com"
|
|
27
|
+
api_base_url: "https://api.qa.dispatcho.com"
|
|
28
|
+
database_url: "postgresql://qa-db:5432/dispatcho_qa"
|
|
29
|
+
|
|
30
|
+
uat:
|
|
31
|
+
base_url: "https://uat.dispatcho.com"
|
|
32
|
+
api_base_url: "https://api.uat.dispatcho.com"
|
|
33
|
+
database_url: "postgresql://uat-db:5432/dispatcho_uat"
|
|
34
|
+
|
|
35
|
+
prod:
|
|
36
|
+
base_url: "https://www.dispatcho.com"
|
|
37
|
+
api_base_url: "https://api.dispatcho.com"
|
|
38
|
+
database_url: "postgresql://prod-db:5432/dispatcho_prod"
|
|
39
|
+
|
|
40
|
+
# API endpoints
|
|
41
|
+
api_endpoints:
|
|
42
|
+
orders: "/api/v1/orders"
|
|
43
|
+
drivers: "/api/v1/drivers"
|
|
44
|
+
routes: "/api/v1/routes"
|
|
45
|
+
tracking: "/api/v1/tracking"
|
|
46
|
+
dispatches: "/api/v1/dispatches"
|
|
47
|
+
|
|
48
|
+
# Test data
|
|
49
|
+
test_users:
|
|
50
|
+
dispatcher:
|
|
51
|
+
username: "${DISPATCHO_DISPATCHER_USERNAME}"
|
|
52
|
+
password: "${DISPATCHO_DISPATCHER_PASSWORD}"
|
|
53
|
+
driver:
|
|
54
|
+
username: "${DISPATCHO_DRIVER_USERNAME}"
|
|
55
|
+
password: "${DISPATCHO_DRIVER_PASSWORD}"
|
|
56
|
+
admin_user:
|
|
57
|
+
username: "${DISPATCHO_ADMIN_USERNAME}"
|
|
58
|
+
password: "${DISPATCHO_ADMIN_PASSWORD}"
|
|
59
|
+
|
|
60
|
+
# Feature flags
|
|
61
|
+
features:
|
|
62
|
+
real_time_tracking: true
|
|
63
|
+
route_optimization: true
|
|
64
|
+
driver_mobile_app: true
|
|
65
|
+
|
|
66
|
+
# Test execution settings
|
|
67
|
+
execution:
|
|
68
|
+
browser: "chromium"
|
|
69
|
+
headless: true
|
|
70
|
+
timeout: 30000
|
|
71
|
+
retries: 2
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# TimelyQuote Project Configuration
|
|
2
|
+
|
|
3
|
+
project:
|
|
4
|
+
name: "TimelyQuote"
|
|
5
|
+
description: "Quote management and generation system"
|
|
6
|
+
team:
|
|
7
|
+
lead: "TBD"
|
|
8
|
+
engineers: []
|
|
9
|
+
slack_channel: "#timelyquote-qa"
|
|
10
|
+
|
|
11
|
+
markers:
|
|
12
|
+
- timelyquote
|
|
13
|
+
- quotes
|
|
14
|
+
|
|
15
|
+
# Environment-specific URLs. database_url carries only the non-secret
|
|
16
|
+
# host/port/database; DB credentials come from the SRC_DB_USER / SRC_DB_PASSWORD
|
|
17
|
+
# (and TGT_*) environment variables — never store passwords here.
|
|
18
|
+
environments:
|
|
19
|
+
dev:
|
|
20
|
+
base_url: "https://dev.timelyquote.com"
|
|
21
|
+
api_base_url: "https://api.dev.timelyquote.com"
|
|
22
|
+
database_url: "postgresql://dev-db:5432/timelyquote_dev"
|
|
23
|
+
|
|
24
|
+
qa:
|
|
25
|
+
base_url: "https://qa.timelyquote.com"
|
|
26
|
+
api_base_url: "https://api.qa.timelyquote.com"
|
|
27
|
+
database_url: "postgresql://qa-db:5432/timelyquote_qa"
|
|
28
|
+
|
|
29
|
+
uat:
|
|
30
|
+
base_url: "https://uat.timelyquote.com"
|
|
31
|
+
api_base_url: "https://api.uat.timelyquote.com"
|
|
32
|
+
database_url: "postgresql://uat-db:5432/timelyquote_uat"
|
|
33
|
+
|
|
34
|
+
prod:
|
|
35
|
+
base_url: "https://www.timelyquote.com"
|
|
36
|
+
api_base_url: "https://api.timelyquote.com"
|
|
37
|
+
database_url: "postgresql://prod-db:5432/timelyquote_prod"
|
|
38
|
+
|
|
39
|
+
# API endpoints
|
|
40
|
+
api_endpoints:
|
|
41
|
+
quotes: "/api/v1/quotes"
|
|
42
|
+
customers: "/api/v1/customers"
|
|
43
|
+
products: "/api/v1/products"
|
|
44
|
+
pricing: "/api/v1/pricing"
|
|
45
|
+
|
|
46
|
+
# Test data
|
|
47
|
+
test_users:
|
|
48
|
+
standard_user:
|
|
49
|
+
username: "${TIMELYQUOTE_USERNAME}"
|
|
50
|
+
password: "${TIMELYQUOTE_PASSWORD}"
|
|
51
|
+
admin_user:
|
|
52
|
+
username: "${TIMELYQUOTE_ADMIN_USERNAME}"
|
|
53
|
+
password: "${TIMELYQUOTE_ADMIN_PASSWORD}"
|
|
54
|
+
|
|
55
|
+
# Feature flags
|
|
56
|
+
features:
|
|
57
|
+
quote_generation: true
|
|
58
|
+
pdf_export: true
|
|
59
|
+
email_notifications: true
|
|
60
|
+
|
|
61
|
+
# Test execution settings
|
|
62
|
+
execution:
|
|
63
|
+
browser: "chromium"
|
|
64
|
+
headless: true
|
|
65
|
+
timeout: 30000
|
|
66
|
+
retries: 2
|