Skip to content

feat(tests): add functional test suite for real API testing#13

Merged
azconger merged 3 commits intomainfrom
feature/functional-testing
Jan 25, 2026
Merged

feat(tests): add functional test suite for real API testing#13
azconger merged 3 commits intomainfrom
feature/functional-testing

Conversation

@azconger
Copy link
Copy Markdown
Contributor

Summary

  • Add comprehensive functional test suite that exercises HawkOp commands against the real StackHawk API
  • Fix infinite 401 retry loop when endpoints require feature flags not enabled for the organization
  • Fix dry-run validation order in team commands to allow previewing with placeholder IDs
  • Improve error messages for invalid organization IDs

Key Changes

Functional Test Suite (73 tests)

  • Read-only tests: org, app, scan, user, team, policy, repo, audit, oas, config, secret, cache commands
  • Mutation tests: team create/delete/rename with automatic RAII cleanup
  • Error tests: invalid IDs, missing arguments, unknown commands
  • Safety guards: Production API requires explicit HAWKOP_FUNCTIONAL_TESTS_CONFIRM=yes
  • Feature flag handling: Tests gracefully skip with warnings when features aren't enabled

Bug Fixes

  • 401 infinite loop: CLI now distinguishes between authentication failure (refresh token) and authorization failure (feature/role), preventing infinite retry loops
  • Dry-run validation: Team add/remove user/app commands now check --dry-run before validating user/app existence, allowing previews with placeholder IDs
  • Bad request errors: Invalid org IDs now show contextual help: "Invalid or inaccessible organization 'xxx'. Run hawkop org list to see available organizations."

Test Plan

  • All 73 functional tests pass with HAWKOP_PROFILE=test make functional-test
  • All 209 unit tests pass with cargo test
  • Clippy clean
  • Feature flag tests show warnings when features aren't enabled:
    ⚠️  SKIPPED: config list command requires 'hosted-scan-configs' feature flag
       This feature may not be enabled for the test organization.
       Error: Access denied. The endpoint '...' may require a feature flag...
    

Usage

# Run functional tests against test environment
HAWKOP_PROFILE=test make functional-test

# Preview what tests would run
HAWKOP_PROFILE=test make functional-test-dry-run

# Run against production (requires confirmation)
HAWKOP_PROFILE=default HAWKOP_FUNCTIONAL_TESTS_CONFIRM=yes make functional-test

🤖 Generated with Claude Code

azconger and others added 3 commits January 24, 2026 17:33
Add opt-in functional tests that exercise HawkOp commands against the
real StackHawk API with safety guards for production environments.

Test infrastructure:
- Add `functional-tests` Cargo feature (opt-in, not in default)
- Add FunctionalTestContext with production API safety checks
- Add TestTeam RAII wrapper for automatic cleanup
- Add predicates dev dependency for flexible assertions

Test coverage (75 tests total):
- 34 read-only tests (org, app, scan, user, team, policy, repo, oas,
  config, secret, audit, cache, version, help, completion commands)
- 18 mutation tests with automatic cleanup using hawkop-functest-* naming
- 18 error scenario tests for invalid IDs, missing args, etc.
- 2 tests ignored (require hosted scan configs feature)

Safety features:
- Production API warning banner with HAWKOP_FUNCTIONAL_TESTS_CONFIRM=yes
- Profile-based configuration via HAWKOP_PROFILE
- Dry-run preview mode (lists tests without execution)

Makefile targets:
- `make functional-test` - run tests (requires HAWKOP_PROFILE)
- `make functional-test-dry-run` - preview test list

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, when an endpoint returned 401 due to feature/role restrictions
(not expired token), the client would infinitely retry after refreshing
the token. This happened because there was no tracking of whether a
token refresh had already been attempted.

Changes:
- Add `token_refreshed: bool` parameter to all retry functions to track
  if a token refresh has already been attempted
- Add `ApiError::UnauthorizedFeature` variant for 401s after token refresh
- Add `ApiError::unauthorized_feature()` helper to format helpful messages
- Add `get_current_user_role()` method to fetch user's org role for errors
- Error message now shows: endpoint URL, user's role, and possible causes

Affected functions:
- request_with_retry()
- request_with_body_retry()
- request_delete_with_retry()

Example error output:
  Access denied. The endpoint 'https://api.stackhawk.com/api/v1/configuration/...'
  may require a feature flag not enabled for your organization, or elevated privileges.

  Your current role: MEMBER

  Possible causes:
    • This feature requires a plan upgrade or feature flag
    • Your role may not have access (Owner/Admin/Member)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…vior

- Fix dry-run validation order in team commands (add_user, remove_user,
  add_app, remove_app) - now checks --dry-run before resolving users/apps
- Add bad_request_message() helper for contextual 400 error messages
- Add run_feature_flag_dependent() test helper for graceful handling of
  missing feature flags (oas, config endpoints)
- Fix test_cache_path_shows_path to check for directory not filename
- Remove invalid test_status_json_format (status doesn't support --format)
- Remove invalid test_scan_get_missing_id (scan get shows latest by design)
- Add --nocapture to Makefile so feature flag warnings are visible

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@azconger azconger merged commit bc0b393 into main Jan 25, 2026
5 checks passed
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.

1 participant