test(interface): cover the merge-path bundled-regression branches

mergedFlagContractOtherwiseChanged was only ever exercised on the path where
every condition holds still, because `||` short-circuits: with no reviewed
entry the first operand already decides the outcome and the function is never
called at all. That left its five regression branches uncovered and put
changed-code coverage at 88.0952% against a 100% target.

Add the merge-path counterpart of the checkCompatibility bundled-regression
table, pairing each of shorthand / required / hidden / no-opt / scope with the
reviewed type change and requiring the type failure to reappear. Changed-code
coverage is now 100%.
This commit is contained in:
chichuan
2026-08-10 15:02:08 +08:00
parent cd02fe71e6
commit 43121f1d8f
@@ -401,6 +401,66 @@ func TestMergeAcceptsReviewedFlagTypeChangeAndKeepsHistoricalType(t *testing.T)
}
}
// mergeContracts applies the same "nothing else moved" condition as
// checkCompatibility, but against two recorded contracts rather than a live
// pflag definition. Each case bundles one unrelated regression with the reviewed
// type change and requires the type failure to reappear, anchoring
// mergedFlagContractOtherwiseChanged against the checks it mirrors.
func TestMergeRejectsReviewedFlagTypeChangeWithBundledRegression(t *testing.T) {
registerReviewedFixture(t, flagTypeChange{CommandPath: "dws old", Flag: "policy", From: "string", To: "int"})
tests := []struct {
name string
historical func(*cobra.Command)
current func(*cobra.Command)
}{
{
name: "lost shorthand",
historical: func(command *cobra.Command) { command.Flags().StringP("policy", "p", "", "policy") },
current: func(command *cobra.Command) { command.Flags().Int("policy", 0, "policy") },
},
{
name: "became required",
historical: func(command *cobra.Command) { command.Flags().String("policy", "", "policy") },
current: func(command *cobra.Command) {
command.Flags().Int("policy", 0, "policy")
_ = command.MarkFlagRequired("policy")
},
},
{
name: "became hidden",
historical: func(command *cobra.Command) { command.Flags().String("policy", "", "policy") },
current: func(command *cobra.Command) {
command.Flags().Int("policy", 0, "policy")
_ = command.Flags().MarkHidden("policy")
},
},
{
name: "changed no-opt value",
historical: func(command *cobra.Command) { command.Flags().String("policy", "", "policy") },
current: func(command *cobra.Command) {
command.Flags().Int("policy", 0, "policy")
command.Flags().Lookup("policy").NoOptDefVal = "4"
},
},
{
name: "narrowed persistent scope",
historical: func(command *cobra.Command) { command.PersistentFlags().String("policy", "", "policy") },
current: func(command *cobra.Command) { command.Flags().Int("policy", 0, "policy") },
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
_, failures := mergeContracts(
snapshot(policyRoot(test.historical)),
snapshot(policyRoot(test.current)),
)
assertFailureContains(t, failures, typeChangedFailure)
})
}
}
// The behaviour tests above register their own fixtures, so they cannot catch a
// production entry whose key is spelled in the wrong form — that mistake
// disables the exemption silently and only a real gate run reports it. Recompute