Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
106 changes: 106 additions & 0 deletions .github/workflows/bcit-integration-test-deep-linking.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: BCIT Deep Linking Integration Test
permissions:
contents: read

on:
pull_request:
types: [opened, synchronize, reopened, labeled]
workflow_dispatch:
inputs:
ref:
description: 'Branch or commit to test (leave empty for current branch)'
required: false
type: string

jobs:
deep-linking-test:
name: BCIT Deep Linking Integration Test
runs-on: macos-latest
timeout-minutes: 30
env:
XCODE_VERSION: '16.4'
if: >
github.event_name == 'workflow_dispatch' ||
(
github.event_name == 'pull_request' && (
contains(github.event.pull_request.labels.*.name, 'bcit') ||
contains(github.event.pull_request.labels.*.name, 'BCIT') ||
contains(github.event.pull_request.labels.*.name, 'bcit-deeplink') ||
contains(github.event.pull_request.labels.*.name, 'BCIT-DEEPLINK') ||
contains(github.event.pull_request.labels.*.name, 'bcit-deep-linking') ||
contains(github.event.pull_request.labels.*.name, 'BCIT-DEEP-LINKING') ||
contains(github.event.pull_request.labels.*.name, 'Bcit') ||
contains(github.event.pull_request.labels.*.name, 'Bcit-Deeplink') ||
startsWith(github.event.pull_request.head.ref, 'release/')
)
)

steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.ref || github.ref }}

- name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'BCIT Deep Linking Integration Test' step
Uses Step
uses 'maxim-lobanov/setup-xcode' with ref 'v1', not a pinned commit hash
with:
xcode-version: ${{ env.XCODE_VERSION }}

- name: Validate Xcode Version
run: |
echo "πŸ” Validating Xcode version and environment..."
echo "DEVELOPER_DIR: $DEVELOPER_DIR"

# Check xcodebuild version
echo "πŸ” Checking xcodebuild version..."
ACTUAL_XCODE_VERSION=$(xcodebuild -version | head -n 1 | awk '{print $2}')
echo "Xcode version: $ACTUAL_XCODE_VERSION"
echo "Expected version: $XCODE_VERSION"

# Check xcodebuild path
XCODEBUILD_PATH=$(which xcodebuild)
echo "xcodebuild path: $XCODEBUILD_PATH"

# Verify we're using the correct Xcode version
if echo "$ACTUAL_XCODE_VERSION" | grep -q "$XCODE_VERSION"; then
echo "βœ… Using correct Xcode version: $ACTUAL_XCODE_VERSION"
else
echo "❌ Incorrect Xcode version!"
echo "Current: $ACTUAL_XCODE_VERSION"
echo "Expected: $XCODE_VERSION"
exit 1
fi

- name: Setup Local Environment
working-directory: tests/business-critical-integration
run: |
echo "πŸš€ Setting up local environment for integration tests..."

# Run setup script with parameters from repository secrets
./scripts/setup-local-environment.sh \
"${{ secrets.BCIT_TEST_PROJECT_ID }}" \
"${{ secrets.BCIT_ITERABLE_SERVER_KEY }}" \
"${{ secrets.BCIT_ITERABLE_API_KEY }}"

- name: Validate Setup
working-directory: tests/business-critical-integration
run: |
echo "πŸ” Validating environment setup..."
./scripts/validate-setup.sh

- name: Run Deep Linking Tests
working-directory: tests/business-critical-integration
run: |
echo "πŸ§ͺ Running deep linking integration tests..."
CI=true ./scripts/run-tests.sh deeplink

- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v4
with:
name: deep-linking-test-results
path: |
tests/business-critical-integration/reports/
tests/business-critical-integration/screenshots/
tests/business-critical-integration/logs/
retention-days: 7
73 changes: 73 additions & 0 deletions tests/business-critical-integration/AGENT_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,77 @@ CI=1 ./scripts/run-tests.sh
- Updates JSON configuration automatically with date-prefixed email
- Maintains backward compatibility with existing test infrastructure

## Deep Link Integration Tests (SDK-292)

### Overview
Comprehensive deep link routing test infrastructure for validating URL delegate and custom action delegate callbacks.

### What's Tested
1. **URL Delegate Registration & Callbacks**
- Delegate registration during SDK initialization
- URL parameter extraction and validation
- `tester://` scheme handling for test deep links

2. **Custom Action Delegate Registration & Callbacks**
- Delegate registration and method invocation
- Custom action type and data parameter validation

3. **Deep Link Integration Flows**
- Deep link routing from push notifications
- Deep link routing from in-app messages
- Deep link routing from embedded messages

4. **Alert-Based Validation**
- Alert content validation for deep link callbacks
- Expected vs actual URL comparison
- Multiple alert sequence handling

### Key Files
- `DeepLinkingIntegrationTests.swift`: Main test suite with 8 comprehensive test methods
- `DeepLinkHelpers.swift`: Alert validation, URL extraction, and comparison utilities
- `MockDelegates.swift`: Mock URL and custom action delegates with verification helpers
- `AppDelegate.swift`: Production delegates implementation (lines 334-392)
- `AppDelegate+IntegrationTest.swift`: Delegate wiring during SDK init (lines 79-80)

### Test Infrastructure
- **Mock Delegates**: Full verification support with call history tracking
- **Alert Helpers**: `AlertExpectation` for declarative alert validation
- **URL Validation**: Component-by-component URL comparison utilities
- **CI Support**: Uses simulated push notifications for deep link testing

### Running Deep Link Tests

#### Local Testing
```bash
./scripts/run-tests.sh deeplink
```

#### CI Testing
```bash
CI=1 ./scripts/run-tests.sh deeplink
```

### GitHub Actions Workflow
- **File**: `.github/workflows/bcit-integration-test-deep-linking.yml`
- **Triggers**: PR labels (`bcit`, `bcit-deeplink`), workflow_dispatch, release branches
- **Timeout**: 30 minutes
- **Artifacts**: Test results, screenshots, logs (7-day retention)

### Current Scope (Pre-Custom Domain)
- βœ… Delegate registration and callback validation
- βœ… Alert-based deep link verification
- βœ… Integration with push, in-app, and embedded messages
- βœ… URL parameter and context validation
- ⏸️ Wrapped link testing (requires custom domains)
- ⏸️ External source simulation (requires custom domains)

### Future Enhancements
Once custom domains are configured:
1. Wrapped universal link testing
2. External source simulation (Reminders, Notes, Messages)
3. End-to-end click tracking validation
4. Cross-platform attribution testing

## Benefits
- βœ… Push notification tests run successfully in CI
- βœ… No changes to existing local testing workflow
Expand All @@ -169,3 +240,5 @@ CI=1 ./scripts/run-tests.sh
- βœ… **NEW**: Enhanced logging provides comprehensive visibility into push simulation process
- βœ… **NEW**: Robust file-based communication between iOS test and macOS test runner
- βœ… **NEW**: Daily test user creation with date-prefixed emails for fresh testing environment
- βœ… **NEW**: Deep link routing test framework with comprehensive delegate validation
- βœ… **NEW**: Alert-based verification system for non-domain-dependent deep link testing
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@
8A24D3B12E4508F400B53850 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Tests/DeepLinkingIntegrationTests.swift,
Tests/EmbeddedMessageIntegrationTests.swift,
Tests/InAppMessageIntegrationTests.swift,
Tests/IntegrationTestBase.swift,
Tests/PushNotificationIntegrationTests.swift,
Tests/Utilities/CampaignManager.swift,
Tests/Utilities/DeepLinkHelpers.swift,
Tests/Utilities/IterableAPIClient.swift,
Tests/Utilities/MetricsValidator.swift,
Tests/Utilities/MockDelegates.swift,
Tests/Utilities/PushNotificationSender.swift,
Tests/Utilities/ScreenshotCapture.swift,
);
Expand All @@ -51,14 +54,17 @@
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
SupportingFiles/Info.plist,
Tests/DeepLinkingIntegrationTests.swift,
Tests/EmbeddedMessageIntegrationTests.swift,
Tests/InAppMessageIntegrationTests.swift,
Tests/Incomplete/DeepLinkingIntegrationTests.swift,
Tests/IntegrationTestBase.swift,
Tests/PushNotificationIntegrationTests.swift,
Tests/Utilities/CampaignManager.swift,
Tests/Utilities/DeepLinkHelpers.swift,
Tests/Utilities/IterableAPIClient.swift,
Tests/Utilities/MetricsValidator.swift,
Tests/Utilities/MockDelegates.swift,
Tests/Utilities/PushNotificationSender.swift,
Tests/Utilities/ScreenshotCapture.swift,
);
Expand Down Expand Up @@ -87,6 +93,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8A24D33A2E44F30600B53850 /* IterableAppExtensions in Frameworks */,
8A24D33C2E44F30600B53850 /* IterableSDK in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -167,6 +175,8 @@
);
name = "IterableSDK-Integration-TesterUITests";
packageProductDependencies = (
8A24D3392E44F30600B53850 /* IterableAppExtensions */,
8A24D33B2E44F30600B53850 /* IterableSDK */,
);
productName = "IterableSDK-Integration-TesterUITests";
productReference = 8AB716322E3119A3004AAB74 /* IterableSDK-Integration-TesterUITests.xctest */;
Expand Down
Loading
Loading