Skip to content

fix(surveys): honor choice option shuffling - #811

Open
lucasheriques wants to merge 2 commits into
mainfrom
lucas/surveys-shuffle-options
Open

fix(surveys): honor choice option shuffling#811
lucasheriques wants to merge 2 commits into
mainfrom
lucas/surveys-shuffle-options

Conversation

@lucasheriques

@lucasheriques lucasheriques commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

💡 Motivation and Context

Honor the existing shuffleOptions flag in the built-in iOS survey UI, moving toward survey feature parity across all PostHog SDKs. Matches web behavior for single- and multiple-choice questions:

  • Shuffle regular choices, keeping Other last. False or absent keeps the configured order.
  • Keep the order stable while answering; shuffle again for the next question.
  • Preserve original choice indices for selection, translated labels and response/branching mapping.

No public API changes. The shared renderer owns the display order; the raw survey choices remain unchanged. Separate from partial responses/resume (#807) and auto-submit (#808). Android counterpart: PostHog/posthog-android#772.

💚 How did you test it?

  • Parameterized order tests cover enabled/disabled shuffling, the web unchanged-order fallback, empty/short lists and duplicate labels. They failed before implementation and pass now.
  • make test passed: 794 Swift Testing tests plus the legacy suite. make format, make lint, make apiCheck and the CodeScene safeguard passed.
  • SDK builds passed for iOS, macOS and Catalyst. make build then stopped at the unavailable tvOS SDK; watchOS/visionOS SDKs are also missing locally. No new mounted iOS UI tests in this PR.

The full suite exposed a logs-queue test relying on a 100 ms retry delay; a separate test-only commit replaces it with bounded polling.

📝 Checklist

  • Reviewed the code and added regression tests.
  • Added a patch changeset with pnpm changeset.
  • Public API unchanged.

🤖 Agent context

Autonomy: Human-driven (agent-assisted). Codex implemented and tested this through CLI tools. Human review is required.

Replace a fixed 100 ms wait between retry attempts with the existing
bounded polling helper. An in-flight first upload could otherwise swallow
the second flush and leave the test waiting for a retry it never requested.

Verification: make test passed (794 Swift Testing tests, plus legacy tests).
Use the existing shuffleOptions flag in the shared choice renderer. Keep
Other last and retain original choice indices for selection, translated
labels and response mapping. Store the order in view state and reset it
when moving to another question or changing the choice count.

Match the web fallback when randomization returns the original order.
Add parameterized shuffle, disabled, short-list and duplicate-choice tests.

Verification: make test; focused SurveyChoiceOrderTests; make format;
make lint; make apiCheck; CodeScene safeguard passed. make build passed
iOS, macOS and Catalyst, then stopped at missing tvOS SDK. watchOS and
visionOS SDKs are also unavailable locally. No public API changes.
@greptile-apps

greptile-apps Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
### Issue 1
PostHog/Surveys/QuestionTypes.swift:192
**Translation reshuffles active choices**

When a live translation changes the current question's choice count, this ID recreates `MultipleChoiceOptions` and generates a new random display order. The parent keeps the selected indices and open-choice input, so the visible options can move beneath an existing selection while the person is still answering. This breaks the intended stable display order and the existing in-place translation update behavior.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "fix(surveys): honor choice option shuffl..." | Re-trigger Greptile

shuffleOptions: question.shuffleOptions
)
.id(question.choices.count)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Translation reshuffles active choices

When a live translation changes the current question's choice count, this ID recreates MultipleChoiceOptions and generates a new random display order. The parent keeps the selected indices and open-choice input, so the visible options can move beneath an existing selection while the person is still answering. This breaks the intended stable display order and the existing in-place translation update behavior.

Knowledge Base Used:

Prompt To Fix With AI
This is a comment left during a code review.
Path: PostHog/Surveys/QuestionTypes.swift
Line: 192

Comment:
**Translation reshuffles active choices**

When a live translation changes the current question's choice count, this ID recreates `MultipleChoiceOptions` and generates a new random display order. The parent keeps the selected indices and open-choice input, so the visible options can move beneath an existing selection while the person is still answering. This breaks the intended stable display order and the existing in-place translation update behavior.

**Knowledge Base Used:**
- [Surveys](https://app.greptile.com/posthog-org-19734/-/custom-context/knowledge-base/posthog/posthog-ios/-/docs/surveys.md)
- [In-app experiences](https://app.greptile.com/posthog-org-19734/-/custom-context/knowledge-base/posthog/posthog-ios/-/docs/in-app-experiences.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

posthog-ios Compliance Report

Date: 2026-09-09 22:06:34 UTC
Duration: 231662ms

✅ All Tests Passed!

45/45 tests passed


Capture Tests

29/29 tests passed

View Details
Test Status Duration
Format Validation.Event Has Required Fields 2936ms
Format Validation.Event Has Uuid 2893ms
Format Validation.Event Has Lib Properties 2774ms
Format Validation.Distinct Id Is String 2976ms
Format Validation.Token Is Present 2805ms
Format Validation.Custom Properties Preserved 515ms
Format Validation.Event Has Timestamp 2876ms
Retry Behavior.Retries On 503 11768ms
Retry Behavior.Does Not Retry On 400 4888ms
Retry Behavior.Does Not Retry On 401 4883ms
Retry Behavior.Respects Retry After Header 7870ms
Retry Behavior.Implements Backoff 21928ms
Retry Behavior.Retries On 500 9343ms
Retry Behavior.Retries On 502 10030ms
Retry Behavior.Retries On 504 5552ms
Retry Behavior.Max Retries Respected 21815ms
Deduplication.Generates Unique Uuids 3051ms
Deduplication.Preserves Uuid On Retry 9166ms
Deduplication.Preserves Uuid And Timestamp On Retry 16491ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry 8219ms
Deduplication.No Duplicate Events In Batch 3112ms
Deduplication.Different Events Have Different Uuids 3001ms
Compression.Sends Gzip When Enabled 2846ms
Batch Format.Uses Proper Batch Structure 2853ms
Batch Format.Flush With No Events Sends Nothing 331ms
Batch Format.Multiple Events Batched Together 2974ms
Error Handling.Does Not Retry On 403 4878ms
Error Handling.Does Not Retry On 413 4934ms
Error Handling.Retries On 408 5447ms

Feature_Flags Tests

16/16 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id 2932ms
Request Payload.Flags Request Uses V2 Query Param 2882ms
Request Payload.Flags Request Hits Flags Path Not Decide 3051ms
Request Payload.Flags Request Omits Authorization Header 2848ms
Request Payload.Token In Flags Body Matches Init 2843ms
Request Payload.Groups Round Trip 3144ms
Request Payload.Groups Default To Empty Object 3402ms
Request Payload.Person Properties Distinct Id Auto Populated When Caller Omits It 2792ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False 2861ms
Request Payload.Disable Geoip Omitted Defaults To False 2843ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key 2857ms
Request Lifecycle.No Flags Request On Init Alone 108ms
Request Lifecycle.No Flags Request On Normal Capture 2765ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests 5616ms
Request Lifecycle.Mock Response Value Is Returned To Caller 2940ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event 3145ms

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