@loyalytics/swan-react-native-sdk 2.1.3-beta.2 → 2.1.3-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,266 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Swan SDK - Carousel Push Notification Test Script
5
- *
6
- * Sends test carousel push notifications via Firebase Admin SDK.
7
- * Requires firebase-admin to be installed (already in devDependencies).
8
- *
9
- * Usage:
10
- * node scripts/test-carousel-push.js --token <FCM_TOKEN> [--mode manual|auto] [--scenario <name>]
11
- *
12
- * Environment:
13
- * GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-key.json
14
- *
15
- * Scenarios:
16
- * manual-3 — Manual carousel with 3 products (default)
17
- * auto-5 — Auto carousel with 5 products, 2s interval (ViewFlipper)
18
- * filmstrip-4 — Filmstrip variant with 4 products (3-image preview strip)
19
- * single-item — Single item carousel (should hide arrows)
20
- * invalid-json — Invalid carouselItems JSON (tests fallback)
21
- * no-images — Items without imageUrl (tests filtering)
22
- */
23
-
24
- const admin = require('firebase-admin');
25
-
26
- // Parse CLI args
27
- const args = process.argv.slice(2);
28
- const getArg = (name) => {
29
- const idx = args.indexOf(`--${name}`);
30
- return idx !== -1 ? args[idx + 1] : undefined;
31
- };
32
-
33
- const fcmToken = getArg('token');
34
- const mode = getArg('mode') || 'manual';
35
- const scenarioName = getArg('scenario') || 'manual-3';
36
-
37
- if (!fcmToken) {
38
- console.error(
39
- 'Usage: node scripts/test-carousel-push.js --token <FCM_TOKEN> [--mode manual|auto] [--scenario <name>]'
40
- );
41
- console.error(
42
- '\nAvailable scenarios: manual-3, auto-5, filmstrip-4, single-item, invalid-json, no-images'
43
- );
44
- process.exit(1);
45
- }
46
-
47
- // Initialize Firebase Admin
48
- if (!admin.apps.length) {
49
- admin.initializeApp({
50
- credential: admin.credential.applicationDefault(),
51
- });
52
- }
53
-
54
- const SAMPLE_IMAGES = [
55
- 'https://picsum.photos/seed/swan1/400/200',
56
- 'https://picsum.photos/seed/swan2/400/200',
57
- 'https://picsum.photos/seed/swan3/400/200',
58
- 'https://picsum.photos/seed/swan4/400/200',
59
- 'https://picsum.photos/seed/swan5/400/200',
60
- ];
61
-
62
- const scenarios = {
63
- 'manual-3': {
64
- name: 'Manual carousel — 3 products',
65
- data: {
66
- notificationType: 'carousel',
67
- carouselMode: 'manual',
68
- title: 'Flash Sale - Top Picks!',
69
- body: 'Swipe to see our best deals',
70
- channelId: 'swan_promotional',
71
- carouselItems: JSON.stringify([
72
- {
73
- imageUrl: SAMPLE_IMAGES[0],
74
- title: 'Wireless Earbuds',
75
- body: '50% off - $29.99',
76
- route: '/product/101',
77
- },
78
- {
79
- imageUrl: SAMPLE_IMAGES[1],
80
- title: 'Smart Watch',
81
- body: 'New arrival',
82
- route: '/product/102',
83
- },
84
- {
85
- imageUrl: SAMPLE_IMAGES[2],
86
- title: 'Phone Case',
87
- body: 'Best seller',
88
- route: '/product/103',
89
- },
90
- ]),
91
- },
92
- },
93
- 'auto-5': {
94
- name: 'Auto carousel — 5 products, 2s interval (ViewFlipper)',
95
- data: {
96
- notificationType: 'carousel',
97
- carouselMode: 'auto',
98
- carouselInterval: '2000',
99
- title: 'Recommended for You',
100
- body: 'Based on your recent browsing',
101
- channelId: 'swan_general',
102
- defaultRoute: '/recommended',
103
- carouselItems: JSON.stringify([
104
- {
105
- imageUrl: SAMPLE_IMAGES[0],
106
- title: 'Product A',
107
- body: '$19.99',
108
- route: '/product/201',
109
- },
110
- {
111
- imageUrl: SAMPLE_IMAGES[1],
112
- title: 'Product B',
113
- body: '$24.99',
114
- route: '/product/202',
115
- },
116
- {
117
- imageUrl: SAMPLE_IMAGES[2],
118
- title: 'Product C',
119
- body: '$14.99',
120
- route: '/product/203',
121
- },
122
- {
123
- imageUrl: SAMPLE_IMAGES[3],
124
- title: 'Product D',
125
- body: '$39.99',
126
- route: '/product/204',
127
- },
128
- {
129
- imageUrl: SAMPLE_IMAGES[4],
130
- title: 'Product E',
131
- body: '$9.99',
132
- route: '/product/205',
133
- },
134
- ]),
135
- },
136
- },
137
- 'filmstrip-4': {
138
- name: 'Filmstrip carousel — 4 products with side previews',
139
- data: {
140
- notificationType: 'carousel',
141
- carouselMode: 'manual',
142
- carouselVariant: 'filmstrip',
143
- title: 'Summer Collection',
144
- body: 'Tap the side images to browse',
145
- channelId: 'swan_promotional',
146
- carouselItems: JSON.stringify([
147
- {
148
- imageUrl: SAMPLE_IMAGES[0],
149
- title: 'Summer Dress',
150
- body: '$49.99',
151
- route: '/product/401',
152
- },
153
- {
154
- imageUrl: SAMPLE_IMAGES[1],
155
- title: 'Beach Sandals',
156
- body: '$29.99',
157
- route: '/product/402',
158
- },
159
- {
160
- imageUrl: SAMPLE_IMAGES[2],
161
- title: 'Sun Hat',
162
- body: '$19.99',
163
- route: '/product/403',
164
- },
165
- {
166
- imageUrl: SAMPLE_IMAGES[3],
167
- title: 'Sunglasses',
168
- body: '$34.99',
169
- route: '/product/404',
170
- },
171
- ]),
172
- },
173
- },
174
- 'single-item': {
175
- name: 'Single item carousel (should look like normal image notification)',
176
- data: {
177
- notificationType: 'carousel',
178
- carouselMode: 'manual',
179
- title: 'Just for You',
180
- body: 'Check this out',
181
- channelId: 'swan_promotional',
182
- carouselItems: JSON.stringify([
183
- {
184
- imageUrl: SAMPLE_IMAGES[0],
185
- title: 'Featured Product',
186
- body: 'Limited time offer',
187
- route: '/product/301',
188
- },
189
- ]),
190
- },
191
- },
192
- 'invalid-json': {
193
- name: 'Invalid carouselItems JSON (should fall back to standard notification)',
194
- data: {
195
- notificationType: 'carousel',
196
- carouselMode: 'manual',
197
- title: 'Bad Payload Test',
198
- body: 'Should show as standard notification',
199
- channelId: 'swan_general',
200
- carouselItems: 'this is not valid json {{{',
201
- },
202
- },
203
- 'no-images': {
204
- name: 'Items without imageUrl (should filter and fall back)',
205
- data: {
206
- notificationType: 'carousel',
207
- carouselMode: 'manual',
208
- title: 'No Images Test',
209
- body: 'Items lack imageUrl',
210
- channelId: 'swan_general',
211
- carouselItems: JSON.stringify([
212
- { title: 'No image 1', body: 'Missing imageUrl' },
213
- { title: 'No image 2', body: 'Also missing' },
214
- ]),
215
- },
216
- },
217
- };
218
-
219
- async function sendPush(scenario) {
220
- console.log(`\nSending: ${scenario.name}`);
221
- console.log(`Mode: ${scenario.data.carouselMode || 'manual'}`);
222
- console.log(`Token: ${fcmToken.substring(0, 20)}...`);
223
-
224
- const message = {
225
- token: fcmToken,
226
- data: scenario.data,
227
- android: {
228
- priority: 'high',
229
- },
230
- apns: {
231
- payload: {
232
- aps: {
233
- 'mutable-content': 1,
234
- 'category': 'swan_carousel',
235
- },
236
- },
237
- },
238
- };
239
-
240
- try {
241
- const response = await admin.messaging().send(message);
242
- console.log(`Sent successfully! messageId: ${response}`);
243
- return response;
244
- } catch (error) {
245
- console.error(`Failed to send: ${error.message}`);
246
- return null;
247
- }
248
- }
249
-
250
- async function main() {
251
- const scenario = scenarios[scenarioName];
252
- if (!scenario) {
253
- console.error(`Unknown scenario: ${scenarioName}`);
254
- console.error(`Available: ${Object.keys(scenarios).join(', ')}`);
255
- process.exit(1);
256
- }
257
-
258
- // Override mode if --mode flag is provided and scenario supports it
259
- if (mode && scenario.data.carouselMode !== undefined) {
260
- scenario.data.carouselMode = mode;
261
- }
262
-
263
- await sendPush(scenario);
264
- }
265
-
266
- main().catch(console.error);