Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion scripts/powershell/create-new-feature.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,14 @@ function Get-BranchName {
} else {
# Fallback to original logic if no meaningful words found
$result = ConvertTo-CleanBranchName -Name $Description
$fallbackWords = ($result -split '-') | Where-Object { $_ } | Select-Object -First 3
# @() keeps this an array. ConvertTo-CleanBranchName blanks every
# non-[a-z0-9] character, so a description written in a non-Latin script
# (or made only of punctuation) leaves nothing for the pipeline to
# emit -- it yields $null, and [string]::Join on $null throws
# ArgumentNullException. With $ErrorActionPreference = 'Stop' that is
# terminating, so the script died with a .NET stack trace and exit 1
# where the bash and Python twins both return an empty suffix.
$fallbackWords = @(($result -split '-') | Where-Object { $_ } | Select-Object -First 3)
return [string]::Join('-', $fallbackWords)
}
}
Expand Down
53 changes: 53 additions & 0 deletions tests/test_create_new_feature_python_parity.py
Original file line number Diff line number Diff line change
Expand Up @@ -1065,3 +1065,56 @@ def test_all_variants_corrected_prefix_skips_timestamp_collision(repo: Path) ->
assert json_stdout(py)["FEATURE_NUM"] == "20260320"
for result in (bash, ps, py):
assert "using 20260320 instead" in result.stderr


@pytest.mark.skipif(not HAS_POWERSHELL, reason="no PowerShell available")
@pytest.mark.parametrize(
"description",
["!!! ??? ***", "добавить", "添加用户"],
ids=["punctuation_only", "cyrillic", "han"],
)
def test_powershell_survives_description_with_no_ascii_words(
tmp_path: Path, description: str
):
"""A description with no [a-z0-9] characters must not crash the PS twin.

``ConvertTo-CleanBranchName`` blanks every non-ASCII character, so the
fallback pipeline yields nothing and ``[string]::Join`` received ``$null``
— an ArgumentNullException, made terminating by
``$ErrorActionPreference = 'Stop'``. The script died with a .NET stack
trace and exit 1 where the bash and Python twins both return an empty
suffix. This fires for any feature phrased in a non-Latin script.
"""
repo = _setup_repo(tmp_path)

ps = run(ps_cmd(repo, SCRIPT, "-Json", "-DryRun", description), repo)

assert ps.returncode == 0, ps.stderr
assert "ArgumentNullException" not in ps.stderr
assert "Join" not in ps.stderr
assert json_stdout(ps)["BRANCH_NAME"] == "001-"


@requires_bash
@pytest.mark.skipif(not HAS_POWERSHELL, reason="no PowerShell available")
def test_no_ascii_word_description_matches_across_twins(tmp_path: Path):
"""All three twins agree on the branch name for such a description."""
description = "добавить"

bash_repo = _setup_repo(tmp_path, "b")
py_repo = _setup_repo(tmp_path, "p")
ps_repo = _setup_repo(tmp_path, "s")

bash = run(bash_cmd(bash_repo, SCRIPT, "--json", "--dry-run", description), bash_repo)
py = run(py_cmd(py_repo, SCRIPT, "--json", "--dry-run", description), py_repo)
ps = run(ps_cmd(ps_repo, SCRIPT, "-Json", "-DryRun", description), ps_repo)

assert bash.returncode == py.returncode == ps.returncode == 0, (
bash.stderr, py.stderr, ps.stderr,
)
names = {
json_stdout(bash)["BRANCH_NAME"],
json_stdout(py)["BRANCH_NAME"],
json_stdout(ps)["BRANCH_NAME"],
}
assert names == {"001-"}, names