Files
Victor Lyuboslavsky e4025a8193 Always display Windows ESP error when software install fails (#47522)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #45948

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

- [x] Timeouts are implemented and retries are limited to avoid infinite
loops

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

* **New Features**
* Updated Windows ESP failure copy with clearer “Reset your device to
try again…” wording.
* When not all apps are required, added a **“Reset PC and Continue
Anyway”** soft-block option and continuable error text that lists failed
app names with truncation (“N more”).
* **Bug Fixes**
* Improved SyncML generation by escaping XML-sensitive characters in
embedded text.
* **Tests**
* Added/expanded unit and property-based tests covering continuable
error formatting, soft-block behavior, and SyncML XML escaping.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-18 06:35:57 +01:00

70 lines
2.4 KiB
Go

package microsoft_mdm
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestESPSoftwareFailureContinuableErrorText(t *testing.T) {
tests := []struct {
name string
failedNames []string
want string
}{
{
name: "no names falls back to generic text",
failedNames: nil,
want: "Some software failed to install. " + espContinuableErrorSuffix,
},
{
name: "empty names are skipped",
failedNames: []string{"", ""},
want: "Some software failed to install. " + espContinuableErrorSuffix,
},
{
name: "one name",
failedNames: []string{"Slack"},
want: "Slack failed to install. " + espContinuableErrorSuffix,
},
{
name: "two names",
failedNames: []string{"Slack", "Zoom"},
want: "Slack and Zoom failed to install. " + espContinuableErrorSuffix,
},
{
// The cap (espMaxFailedNamesShown) is 3, so three names list in full.
name: "three names use Oxford comma",
failedNames: []string{"Slack", "Zoom", "Docker"},
want: "Slack, Zoom, and Docker failed to install. " + espContinuableErrorSuffix,
},
{
// Above the cap, the rest is summarized as "N more": four names -> first three plus "and 1 more".
name: "four names list first three and one more",
failedNames: []string{"Slack", "Zoom", "Docker", "1Password"},
want: "Slack, Zoom, Docker, and 1 more failed to install. " + espContinuableErrorSuffix,
},
{
name: "six names list first three and three more",
failedNames: []string{"Slack", "Zoom", "Docker", "1Password", "Notion", "Chrome"},
want: "Slack, Zoom, Docker, and 3 more failed to install. " + espContinuableErrorSuffix,
},
{
name: "empty name mixed in is skipped",
failedNames: []string{"Slack", "", "Zoom"},
want: "Slack and Zoom failed to install. " + espContinuableErrorSuffix,
},
{
// Empties are dropped before the cap is applied, so this counts as four names, not seven.
name: "empties are dropped before the cap is counted",
failedNames: []string{"Slack", "", "Zoom", "", "Docker", "", "1Password"},
want: "Slack, Zoom, Docker, and 1 more failed to install. " + espContinuableErrorSuffix,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.want, ESPSoftwareFailureContinuableErrorText(tc.failedNames))
})
}
}