ace-support-test-helpers 0.14.5 → 0.14.7

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f964e2cbd1eb428c260e5190ddaefbef7905d1ee86e894cbcab9a2d2b985b628
4
- data.tar.gz: 6b8e0b1f8c3e0e88638d99b8d4abaea0a8378262bbae3c3784ae519d5859ecc2
3
+ metadata.gz: a767b70c09feaae225240738ac2f27a142d03699e5238554b461d4c5131ab621
4
+ data.tar.gz: c2c991117721c5feec55811f404ebf805a75eef80f5ac17df84f4b31067efcbd
5
5
  SHA512:
6
- metadata.gz: 8da847ee96be275ce048c97e55d3a0c6c659c2bf73ac472fbf4001fd3ca6eabc907658a2d2c333843f65dc059bb69b87cdec2ed1afa4965a8608ba4ccad5e174
7
- data.tar.gz: 6f5b8c776f80d9a799e06c64cc0238cefc346fec2f98715e92767369f56e2222a24dc84c4ff1070dc210ba54b09f3244f751de978ef695b4839604a4ca3a276b
6
+ metadata.gz: 9834e606ddf335a0fe451d288987273ce0c508f47527855a9ffc05f1fdcedbb332d8db4bc589b2681c5bbaf9961f75b9a65ec7c0672b9b6eadf0ca8122ef9979
7
+ data.tar.gz: 8041dc0beebc3d0f4be3168eec4d73412163bd0052402bf9630d00e0de63e261e33fc444dc7891c47fb00a939877eed564876e99ebea711c054e28af14c3c755
data/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.14.7] - 2026-10-04
11
+
12
+ ### Technical
13
+
14
+ - Verify full source-repository and base-reference provenance in shared PR lifecycle receipts.
15
+
16
+ ## [0.14.6] - 2026-09-28
17
+
10
18
  ## [0.14.5] - 2026-09-24
11
19
 
12
20
  ### Fixed
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ace
4
+ module TestSupport
5
+ # Shared PR-lifecycle contract parity suite.
6
+ #
7
+ # Provider packages include this module and supply scripted runners per
8
+ # symbolic scenario, proving identical normalized receipts, exact-identity
9
+ # matching, expected-head enforcement, idempotent create, unknown-outcome
10
+ # classification, and capability classification across every provider —
11
+ # with no network and no provider CLI.
12
+ #
13
+ # Host test class contract:
14
+ # - #build_provider(runner) -> Ace::Git::Providers::Base on the runner
15
+ # - #lifecycle_runner(scenario) -> scripted runner for the scenario
16
+ # - #ready_supported? [Boolean] provider can mark drafts ready
17
+ # - #merge_supported? [Boolean] provider enforces head atomically
18
+ module PullRequestLifecycleContract
19
+ SERVER_URL = "https://forge.example.com/owner/repo"
20
+ HEAD_SHA = "fc14c43d3660ac6c133959a6dec29603413f0e8a"
21
+ OTHER_SHA = "0123456789abcdef0123456789abcdef01234567"
22
+
23
+ IDENTITY = {
24
+ head_repository_url: SERVER_URL,
25
+ head_ref: "feature/x",
26
+ base_repository_url: SERVER_URL,
27
+ base_ref: "main"
28
+ }.freeze
29
+
30
+ # Create kwargs: the base repository is always the resolved server.
31
+ CREATE_IDENTITY = IDENTITY.except(:base_repository_url).freeze
32
+
33
+ def test_lifecycle_find_matches_exact_identity_with_provenance
34
+ prs = build_provider(lifecycle_runner(:find_single)).find_open_pull_requests(**IDENTITY)
35
+ assert_equal [25], prs.map(&:number)
36
+ pr = prs.first
37
+ assert_equal HEAD_SHA, pr.head_sha
38
+ assert_equal "feature/x", pr.head_ref
39
+ assert_equal "main", pr.base_ref
40
+ assert_equal SERVER_URL, pr.head_repository_url
41
+ assert_equal SERVER_URL, pr.base_repository_url
42
+ end
43
+
44
+ def test_lifecycle_create_proves_head_and_reports_created
45
+ provider = build_provider(lifecycle_runner(:create_new))
46
+ receipt = provider.create_pull_request(
47
+ **CREATE_IDENTITY, expected_head: HEAD_SHA, title: "Ship it"
48
+ )
49
+ assert_instance_of Ace::Git::ProviderMutationReceipt, receipt
50
+ assert_equal :create, receipt.operation
51
+ assert_equal :created, receipt.idempotency
52
+ assert_equal 25, receipt.pull_request.number
53
+ assert_equal "feature/x", receipt.pull_request.head_ref
54
+ assert_equal "main", receipt.pull_request.base_ref
55
+ assert_equal SERVER_URL, receipt.pull_request.head_repository_url
56
+ assert_equal true, receipt.pull_request.draft
57
+ assert_equal HEAD_SHA, receipt.pull_request.head_sha
58
+ assert_equal SERVER_URL, receipt.pull_request.base_repository_url
59
+ assert_equal HEAD_SHA, receipt.to_h.dig(:pull_request, :head_sha)
60
+ end
61
+
62
+ def test_lifecycle_create_reconciles_to_exact_open_match
63
+ receipt = build_provider(lifecycle_runner(:create_existing)).create_pull_request(
64
+ **CREATE_IDENTITY, expected_head: HEAD_SHA, title: "Ship it"
65
+ )
66
+ assert_equal :existing, receipt.idempotency
67
+ assert_equal 25, receipt.pull_request.number
68
+ end
69
+
70
+ def test_lifecycle_create_rejects_stale_expected_head_without_mutation
71
+ provider = build_provider(lifecycle_runner(:create_existing))
72
+ error = assert_raises(Ace::Git::ProviderExpectedHeadConflictError) do
73
+ provider.create_pull_request(
74
+ **CREATE_IDENTITY, expected_head: OTHER_SHA, title: "Ship it"
75
+ )
76
+ end
77
+ assert_match(/head changed|does not match/i, error.message)
78
+ end
79
+
80
+ def test_lifecycle_create_conflicts_on_multiple_exact_matches
81
+ provider = build_provider(lifecycle_runner(:find_multi))
82
+ error = assert_raises(Ace::Git::ProviderConflictingMatchesError) do
83
+ provider.create_pull_request(
84
+ **CREATE_IDENTITY, expected_head: HEAD_SHA, title: "Ship it"
85
+ )
86
+ end
87
+ assert_match(/match/i, error.message)
88
+ end
89
+
90
+ def test_lifecycle_create_reports_unknown_outcome_with_reconciliation_identity
91
+ provider = build_provider(lifecycle_runner(:create_unknown))
92
+ error = assert_raises(Ace::Git::ProviderUnknownOutcomeError) do
93
+ provider.create_pull_request(
94
+ **CREATE_IDENTITY, expected_head: HEAD_SHA, title: "Ship it"
95
+ )
96
+ end
97
+ assert_match(/reconcile by exact identity/i, error.message)
98
+ assert_match(%r{owner/repo}, error.message)
99
+ end
100
+
101
+ def test_lifecycle_update_enforces_expected_head
102
+ provider = build_provider(lifecycle_runner(:update_stale))
103
+ error = assert_raises(Ace::Git::ProviderExpectedHeadConflictError) do
104
+ provider.update_pull_request(number: 25, expected_head: OTHER_SHA, title: "New title")
105
+ end
106
+ assert_match(/head changed/i, error.message)
107
+
108
+ receipt = build_provider(lifecycle_runner(:update_ok))
109
+ .update_pull_request(number: 25, expected_head: HEAD_SHA, title: "New title")
110
+ assert_equal :update, receipt.operation
111
+ assert_equal HEAD_SHA, receipt.pull_request.head_sha
112
+ end
113
+
114
+ def test_lifecycle_ready_classifies_capability
115
+ provider = build_provider(lifecycle_runner(ready_supported? ? :ready_ok : :ready_unsupported))
116
+ if ready_supported?
117
+ receipt = provider.ready_pull_request(number: 25, expected_head: HEAD_SHA)
118
+ assert_equal :ready, receipt.operation
119
+ else
120
+ error = assert_raises(Ace::Git::ProviderUnsupportedCapabilityError) do
121
+ provider.ready_pull_request(number: 25, expected_head: HEAD_SHA)
122
+ end
123
+ assert_match(/ready|capab|support/i, error.message)
124
+ end
125
+ end
126
+
127
+ def test_lifecycle_merge_enforces_expected_head_atomically
128
+ provider = build_provider(lifecycle_runner(merge_supported? ? :merge_ok : :merge_unsupported))
129
+ if merge_supported?
130
+ receipt = provider.merge_pull_request(number: 25, expected_head: HEAD_SHA, method: :squash)
131
+ assert_equal :merge, receipt.operation
132
+ assert_equal HEAD_SHA, receipt.pull_request.head_sha
133
+
134
+ error = assert_raises(Ace::Git::ProviderExpectedHeadConflictError) do
135
+ build_provider(lifecycle_runner(:merge_stale))
136
+ .merge_pull_request(number: 25, expected_head: OTHER_SHA, method: :squash)
137
+ end
138
+ assert_match(/head|match/i, error.message)
139
+ else
140
+ error = assert_raises(Ace::Git::ProviderUnsupportedCapabilityError) do
141
+ provider.merge_pull_request(number: 25, expected_head: HEAD_SHA, method: :squash)
142
+ end
143
+ assert_match(/atomic|expected[- ]head|capab|support/i, error.message)
144
+ end
145
+ end
146
+
147
+ def test_lifecycle_merge_rejects_unknown_methods
148
+ provider = build_provider(lifecycle_runner(:find_single))
149
+ assert_raises(ArgumentError) do
150
+ provider.merge_pull_request(number: 25, expected_head: HEAD_SHA, method: :fast_forward)
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ace
4
4
  module TestSupport
5
- VERSION = "0.14.5"
5
+ VERSION = "0.14.7"
6
6
  end
7
7
  end
@@ -22,6 +22,7 @@ require_relative "test_support/fixtures/http_mocks" # Shared HTTP mocks for LLM
22
22
  require_relative "test_support/fixtures/prompt_helpers" # Shared prompt stubbing helpers
23
23
  require_relative "test_support/fixtures/test_runner_mocks" # Shared test runner mocks
24
24
  require_relative "test_support/provider_contract" # Provider contract parity suite for forge provider gems
25
+ require_relative "test_support/pull_request_lifecycle_contract" # PR lifecycle contract parity suite
25
26
 
26
27
  # Configure Minitest reporters by default
27
28
  Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ace-support-test-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.5
4
+ version: 0.14.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michal Czyz
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-09-24 00:00:00.000000000 Z
10
+ date: 2026-10-04 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: minitest
@@ -63,6 +63,7 @@ files:
63
63
  - lib/ace/test_support/fixtures/test_runner_mocks.rb
64
64
  - lib/ace/test_support/performance_helpers.rb
65
65
  - lib/ace/test_support/provider_contract.rb
66
+ - lib/ace/test_support/pull_request_lifecycle_contract.rb
66
67
  - lib/ace/test_support/sandbox_package_copy.rb
67
68
  - lib/ace/test_support/subprocess_runner.rb
68
69
  - lib/ace/test_support/test_environment.rb