Skip to content

chore: [SDK-4716] revamp iOS examples/demo for cross-SDK parity#1663

Merged
fadi-george merged 23 commits into
mainfrom
fadi/sdk-4716
May 27, 2026
Merged

chore: [SDK-4716] revamp iOS examples/demo for cross-SDK parity#1663
fadi-george merged 23 commits into
mainfrom
fadi/sdk-4716

Conversation

@fadi-george
Copy link
Copy Markdown
Collaborator

@fadi-george fadi-george commented May 25, 2026

Description

One Line Summary

Rework examples/demo to match the shared sdk-shared/demo spec and reach feature and structure parity with the Capacitor demo.

Appium Tests:

━━━ Running: ios / ios ━━━
[INFO] === OneSignal E2E — ios / ios ===

[INFO] Skipping build (--skip-build), using existing app
[INFO] Simulator already running
[INFO] Starting Appium on port 4723...
[INFO] Appium ready (pid 76797)
[INFO] Uninstalling com.onesignal.example...
[INFO] Installing test dependencies...
VITE+ - The Unified Toolchain for the Web

bun install v1.3.14 (0d9b296a)

Checked 643 installs across 645 packages (no changes) [174.00ms]

tip: Available short aliases: i = install, rm = remove, un = uninstall, up = update, ls = list, ln = link
[INFO] Running tests (conf: wdio.ios.conf.ts, spec: <conf default>)...
Deleting user: appium-ios
User deleted successfully

Execution of 1 workers started at 2026-05-25T18:24:52.058Z

[0-0] RUNNING in iOS(26.2) on iOS - file:///tests/specs/01_user.spec.ts, file:///tests/specs/02_push.spec.ts, file:///tests/specs/03_iam.spec.ts, file:///tests/specs/04_alias.spec.ts, file:///tests/specs/05_email.spec.ts, file:///tests/specs/06_sms.spec.ts, file:///tests/specs/07_tag.spec.ts, file:///tests/specs/08_outcome.spec.ts, file:///tests/specs/09_trigger.spec.ts, file:///tests/specs/10_event.spec.ts, file:///tests/specs/11_location.spec.ts, file:///tests/specs/12_activity.spec.ts
[App.app iOS #0-0]
[App.app iOS #0-0] » /tests/specs/01_user.spec.ts
[App.app iOS #0-0] User
[App.app iOS #0-0]    ✓ should start as anonymous
[App.app iOS #0-0]    ✓ can login and logout
[App.app iOS #0-0]
[App.app iOS #0-0] » /tests/specs/02_push.spec.ts
[App.app iOS #0-0] Push Subscription
[App.app iOS #0-0]    ✓ should show correct tooltip info
[App.app iOS #0-0]    ✓ should have push ID and be enabled initially
[App.app iOS #0-0]    ✓ can send an image notification
[App.app iOS #0-0]
[App.app iOS #0-0] » /tests/specs/03_iam.spec.ts
[App.app iOS #0-0] In-App Messaging
[App.app iOS #0-0]    ✓ should show correct tooltip info
[App.app iOS #0-0]    ✓ can show iam messages
[App.app iOS #0-0]    ✓ can pause iam
[App.app iOS #0-0]
[App.app iOS #0-0] » /tests/specs/04_alias.spec.ts
[App.app iOS #0-0] Aliases
[App.app iOS #0-0]    ✓ should show correct tooltip info
[App.app iOS #0-0]    ✓ can add an alias
[App.app iOS #0-0]    ✓ can add multiple aliases
[App.app iOS #0-0]
[App.app iOS #0-0] » /tests/specs/05_email.spec.ts
[App.app iOS #0-0] Emails
[App.app iOS #0-0]    ✓ should show correct tooltip info
[App.app iOS #0-0]    ✓ can add and remove email
[App.app iOS #0-0]
[App.app iOS #0-0] » /tests/specs/06_sms.spec.ts
[App.app iOS #0-0] SMS
[App.app iOS #0-0]    ✓ should show correct tooltip info
[App.app iOS #0-0]    ✓ can add and remove sms
[App.app iOS #0-0]
[App.app iOS #0-0] » /tests/specs/07_tag.spec.ts
[App.app iOS #0-0] Tags
[App.app iOS #0-0]    ✓ should show correct tooltip info
[App.app iOS #0-0]    ✓ can add and remove a tag
[App.app iOS #0-0]    ✓ can add and remove multiple tags
[App.app iOS #0-0]
[App.app iOS #0-0] » /tests/specs/08_outcome.spec.ts
[App.app iOS #0-0] Outcomes
[App.app iOS #0-0]    ✓ should show correct tooltip info
[App.app iOS #0-0]    ✓ can send a normal outcome
[App.app iOS #0-0]    ✓ can send a unique outcome
[App.app iOS #0-0]    ✓ can send an outcome with value
[App.app iOS #0-0]
[App.app iOS #0-0] » /tests/specs/09_trigger.spec.ts
[App.app iOS #0-0] Triggers
[App.app iOS #0-0]    ✓ should show correct tooltip info
[App.app iOS #0-0]    ✓ can add and remove trigger
[App.app iOS #0-0]    ✓ can add and remove multiple triggers
[App.app iOS #0-0]    ✓ can clear all triggers
[App.app iOS #0-0]
[App.app iOS #0-0] » /tests/specs/10_event.spec.ts
[App.app iOS #0-0] Custom Events
[App.app iOS #0-0]    ✓ should show correct tooltip info
[App.app iOS #0-0]    ✓ can send a custom event with no properties
[App.app iOS #0-0]    ✓ can send a custom event with properties
[App.app iOS #0-0]
[App.app iOS #0-0] » /tests/specs/11_location.spec.ts
[App.app iOS #0-0] Location
[App.app iOS #0-0]    ✓ can show correct tooltip info
[App.app iOS #0-0]    ✓ can prompt for location
[App.app iOS #0-0]    ✓ can share location
[App.app iOS #0-0]
[App.app iOS #0-0] » /tests/specs/12_activity.spec.ts
[App.app iOS #0-0] Live Activities
[App.app iOS #0-0]    ✓ can show correct tooltip info
[App.app iOS #0-0]    ✓ can start a live, update, and exit activity
[0-0] PASSED in iOS(26.2) on iOS - file:///tests/specs/01_user.spec.ts, file:///tests/specs/02_push.spec.ts, file:///tests/specs/03_iam.spec.ts, file:///tests/specs/04_alias.spec.ts, file:///tests/specs/05_email.spec.ts, file:///tests/specs/06_sms.spec.ts, file:///tests/specs/07_tag.spec.ts, file:///tests/specs/08_outcome.spec.ts, file:///tests/specs/09_trigger.spec.ts, file:///tests/specs/10_event.spec.ts, file:///tests/specs/11_location.spec.ts, file:///tests/specs/12_activity.spec.ts

 "spec" Reporter:
------------------------------------------------------------------
[App.app iOS #0-0] Running: App.app on iOS
[App.app iOS #0-0] Session ID: 87a7c67b-4f25-4919-a6c9-38b118e2d1c7
[App.app iOS #0-0]
[App.app iOS #0-0] 34 passing (4m 42s)


Spec Files:      1 passed, 1 total (100% completed) in 00:04:52  


[INFO] === Done ===

━━━ Summary ━━━
  PASS  ios / ios

[INFO] All combos passed

Details

Motivation

The iOS demo was a simple SwiftUI sample that diverged from the cross-SDK demo spec. The shared spec standardizes sections, accessibility identifiers, credential handling, and UI styling so a single Appium suite can target every platform. This PR brings the iOS demo to that standard and unblocks shared E2E coverage.

Scope

  • Confined to examples/demo. No SDK source changes.
  • Replaces the prior root-level SwiftUI sample and the iOS_SDK/OneSignalSwiftUIExample app, both removed.
  • Adds OneSignalNotificationServiceExtension and OneSignalWidget (Live Activities) targets.
  • Adopts the shared design tokens via Theme.swift, centered tooltip dialogs, snake_case accessibility ids, app-bar logo with iOS text, a white launch screen, and the official app icon.
  • Centralizes the app id and REST API key in a single Secrets.plist via SecretsConfig.
  • Externalizes per-developer signing to a gitignored Local.xcconfig (referenced by Build.xcconfig) so xcodegen generate no longer wipes team ids.
  • Bundle ids: app com.onesignal.example, NSE com.onesignal.example.NSE, widget com.onesignal.example.LA.

Other

The Xcode project is generated from examples/demo/project.yml via xcodegen. The committed App.xcodeproj/project.pbxproj is regenerable. Build.xcconfig does an optional include of Local.xcconfig so per-developer overrides survive regeneration without leaking into the repo.

Testing

Manual testing

Built and ran the App scheme on the iPhone 17 simulator via iOS_SDK/OneSignalSDK.xcworkspace. Verified:

  • Launch screen renders the OneSignal logo on a white background and dismisses correctly.
  • App icon shows the solid white icon variant.
  • Every section renders with the typography, dividers, spacing, and accessibility ids defined by sdk-shared/demo/build.md and styles.md.
  • Tooltip info icons open the centered dialog with dynamic height; backdrop tap dismisses.
  • Push, IAM, location, aliases, tags, emails, SMS, outcomes, triggers, custom events, and Live Activity flows all behave as expected (start, fetch user, optimistic add and remove, REST send).
  • Secrets.plist is read at startup. Missing app id falls back to the placeholder; missing API key disables Live Activity update and end with the expected hint.
  • Re-ran xcodegen generate and confirmed DEVELOPMENT_TEAM from Local.xcconfig is preserved in the regenerated project.pbxproj.

Affected code checklist

None of the SDK code paths below were touched. All changes are confined to examples/demo.

  • Notifications
    • Display
    • Open
    • Push Processing
    • Confirm Deliveries
  • Outcomes
  • Sessions
  • In-App Messaging
  • REST API requests
  • Public API changes

Checklist

Overview

  • I have filled out all REQUIRED sections above
  • PR does one thing
    • If it is hard to explain how any code changes are related to each other then it most likely needs to be more than one PR
  • Any Public API changes are explained in the PR details and conform to existing APIs

Testing

  • I have included test coverage for these changes, or explained why they are not needed
  • All automated tests pass, or I explained why that is not possible
  • I have personally tested this on my device, or explained why that is not possible

Final pass

  • Code is as readable as possible.
    • Simplify with less code, followed by splitting up code into well named functions and variables, followed by adding comments to the code.
  • I have reviewed this PR myself, ensuring it meets each checklist item
    • WIP (Work In Progress) is ok, but explain what is still in progress and what you would like feedback on. Start the PR title with "WIP" to indicate this.

Made with Cursor

@fadi-george fadi-george requested a review from nan-li May 25, 2026 18:26
@fadi-george fadi-george marked this pull request as ready for review May 25, 2026 18:26
@fadi-george fadi-george changed the title feat: [SDK-4716] revamp iOS examples/demo for cross-SDK parity chore: [SDK-4716] revamp iOS examples/demo for cross-SDK parity May 25, 2026
Comment thread examples/demo/App/ViewModels/OneSignalViewModel.swift
fadi-george and others added 3 commits May 25, 2026 11:49
Per sdk-shared/demo/build.md Prompt 7.6, snackbar/toast state must
live in the UI layer, not in the state management layer.

- New ToastPresenter (@mainactor ObservableObject) injected via
  @EnvironmentObject, with a named toastDurationMs constant
- OneSignalViewModel drops toastMessage / showToast / dismiss task
- OutcomesSection, CustomEventsSection, LocationSection call
  toast.show(...) after the SDK action instead of routing through
  the ViewModel
- checkLocationShared() returns Bool so the section formats the
  message rather than the ViewModel

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread examples/demo/App/ViewModels/OneSignalViewModel.swift Outdated
Comment thread examples/demo/App/ViewModels/OneSignalViewModel.swift Outdated
Comment thread examples/demo/App/Info.plist Outdated
fadi-george and others added 2 commits May 26, 2026 13:34
- Guard fetchUserDataFromApi with a requestSequence counter so a
  slow fetch for an earlier onesignal_id can't overwrite results
  from a later fetch (logout -> login race).
- Drop the redundant CachedConsentRequired / CachedPrivacyConsent
  UserDefaults caching in the view model; OneSignalService is the
  single source of truth.
- Remove the unused 100ms Task.sleep at the tail of
  fetchUserDataFromApi.
- Update UIRequiredDeviceCapabilities from armv7 to arm64.

Co-authored-by: Cursor <cursoragent@cursor.com>
Mirror the Capacitor useOneSignal hook's preference flow so the demo
restores user state on cold launch instead of resetting to defaults.

- Introduce PreferencesService (UserDefaults-backed) as the single source
  of truth for consent, IAM-paused, location-shared, and the last-logged-in
  external user id, keyed under onesignal.demo.*.
- OneSignalService.initialize now feeds cached consent into the SDK before
  OneSignal.initialize, then restores IAM-paused, location-shared, and
  re-logs the stored external user id once the SDK is ready.
- Setters on OneSignalService write through PreferencesService and forward
  to the SDK, so the view model can hydrate @published state from the
  service and get cached values for free.
- Seed externalUserId in the view model from prefs as a fallback so the
  UI shows the right id immediately on launch even before the SDK's
  user-state observer fires.

Co-authored-by: Cursor <cursoragent@cursor.com>
@fadi-george fadi-george merged commit 23516e4 into main May 27, 2026
2 of 3 checks passed
@fadi-george fadi-george deleted the fadi/sdk-4716 branch May 27, 2026 17:30
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.

2 participants