flow_chat 0.8.2 → 0.9.0

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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.cliff.toml +74 -0
  3. data/.github/workflows/ci.yml +2 -3
  4. data/.github/workflows/release.yml +56 -0
  5. data/.standard.yml +4 -0
  6. data/CHANGELOG.md +22 -0
  7. data/CLAUDE.md +327 -0
  8. data/CONTRIBUTING.md +134 -0
  9. data/Gemfile +1 -0
  10. data/README.md +290 -105
  11. data/Rakefile +5 -1
  12. data/SECURITY.md +42 -349
  13. data/docs/architecture.md +510 -0
  14. data/docs/async-background-processing.md +298 -0
  15. data/docs/configuration.md +556 -226
  16. data/docs/factory-pattern.md +355 -0
  17. data/docs/gateway-context-variables.md +171 -0
  18. data/docs/gateway-development.md +723 -0
  19. data/docs/getting-started.md +429 -0
  20. data/docs/instrumentation.md +264 -153
  21. data/docs/platforms/telegram.md +1013 -0
  22. data/docs/platforms/ussd.md +693 -0
  23. data/docs/platforms/whatsapp.md +1395 -0
  24. data/docs/testing.md +243 -365
  25. data/examples/custom_session_id_example.rb +119 -0
  26. data/examples/http_controller.rb +11 -11
  27. data/examples/intercom_configuration_example.rb +118 -0
  28. data/examples/intercom_controller.rb +194 -0
  29. data/examples/multi_tenant_whatsapp_controller.rb +4 -4
  30. data/examples/ussd_controller.rb +9 -9
  31. data/examples/whatsapp_controller.rb +2 -2
  32. data/flow_chat.gemspec +4 -0
  33. data/lib/flow_chat/{base_app.rb → app.rb} +16 -9
  34. data/lib/flow_chat/async_job.rb +176 -0
  35. data/lib/flow_chat/config.rb +10 -30
  36. data/lib/flow_chat/{base_executor.rb → executor.rb} +6 -11
  37. data/lib/flow_chat/factory.rb +94 -0
  38. data/lib/flow_chat/gateway_async_support.rb +106 -0
  39. data/lib/flow_chat/generic_async_job.rb +30 -0
  40. data/lib/flow_chat/http/gateway/simple.rb +81 -33
  41. data/lib/flow_chat/http/renderer.rb +3 -3
  42. data/lib/flow_chat/instrumentation/setup.rb +1 -1
  43. data/lib/flow_chat/instrumentation.rb +23 -0
  44. data/lib/flow_chat/intercom/client.rb +155 -0
  45. data/lib/flow_chat/intercom/configuration.rb +149 -0
  46. data/lib/flow_chat/intercom/gateway/intercom_api.rb +396 -0
  47. data/lib/flow_chat/intercom/renderer.rb +71 -0
  48. data/lib/flow_chat/phone_number_util.rb +37 -35
  49. data/lib/flow_chat/processor.rb +188 -0
  50. data/lib/flow_chat/renderers/markdown_support.rb +58 -0
  51. data/lib/flow_chat/session/middleware.rb +25 -9
  52. data/lib/flow_chat/telegram/client.rb +240 -0
  53. data/lib/flow_chat/telegram/configuration.rb +118 -0
  54. data/lib/flow_chat/telegram/gateway/bot_api.rb +300 -0
  55. data/lib/flow_chat/telegram/middleware/choice_mapper.rb +35 -0
  56. data/lib/flow_chat/telegram/renderer.rb +125 -0
  57. data/lib/flow_chat/telegram.rb +7 -0
  58. data/lib/flow_chat/ussd/gateway/nalo.rb +24 -4
  59. data/lib/flow_chat/ussd/middleware/pagination.rb +9 -5
  60. data/lib/flow_chat/ussd/renderer.rb +1 -1
  61. data/lib/flow_chat/version.rb +1 -1
  62. data/lib/flow_chat/whatsapp/client.rb +144 -13
  63. data/lib/flow_chat/whatsapp/configuration.rb +1 -1
  64. data/lib/flow_chat/whatsapp/gateway/cloud_api.rb +132 -96
  65. data/lib/flow_chat/whatsapp/id_generator.rb +124 -0
  66. data/lib/flow_chat/whatsapp/middleware/choice_mapper.rb +147 -0
  67. data/lib/flow_chat/whatsapp/renderer.rb +145 -11
  68. data/lib/flow_chat.rb +11 -1
  69. data/lib/tasks/release.rake +165 -0
  70. metadata +84 -25
  71. data/docs/flows.md +0 -320
  72. data/docs/http-gateway-protocol.md +0 -432
  73. data/docs/images/simulator.png +0 -0
  74. data/docs/media.md +0 -153
  75. data/docs/sessions.md +0 -433
  76. data/docs/ussd-setup.md +0 -322
  77. data/docs/whatsapp-setup.md +0 -162
  78. data/examples/whatsapp_message_job.rb +0 -113
  79. data/lib/flow_chat/base_processor.rb +0 -146
  80. data/lib/flow_chat/http/app.rb +0 -6
  81. data/lib/flow_chat/http/middleware/executor.rb +0 -24
  82. data/lib/flow_chat/http/processor.rb +0 -33
  83. data/lib/flow_chat/session/rails_session_store.rb +0 -68
  84. data/lib/flow_chat/ussd/app.rb +0 -6
  85. data/lib/flow_chat/ussd/gateway/nsano.rb +0 -96
  86. data/lib/flow_chat/ussd/middleware/executor.rb +0 -24
  87. data/lib/flow_chat/ussd/processor.rb +0 -39
  88. data/lib/flow_chat/whatsapp/app.rb +0 -29
  89. data/lib/flow_chat/whatsapp/middleware/executor.rb +0 -24
  90. data/lib/flow_chat/whatsapp/processor.rb +0 -32
  91. data/lib/flow_chat/whatsapp/send_job_support.rb +0 -79
data/docs/testing.md CHANGED
@@ -1,30 +1,29 @@
1
- # Testing Guide
1
+ # Testing & Simulation
2
2
 
3
- FlowChat provides comprehensive testing capabilities for both USSD and WhatsApp flows. This guide covers everything from unit testing individual flows to using the powerful built-in simulator for interactive testing.
3
+ FlowChat provides a sophisticated web-based simulator for testing conversational flows across multiple platforms (USSD, WhatsApp, HTTP) without requiring actual gateway integrations.
4
4
 
5
- ## Testing Approaches
5
+ ## Built-in Web Simulator
6
6
 
7
- FlowChat supports multiple testing strategies depending on your needs:
7
+ ### Overview
8
8
 
9
- | Approach | Best For | Setup Complexity | Real API Calls |
10
- |----------|----------|------------------|----------------|
11
- | **Unit Testing** | Individual flow logic | Low | No |
12
- | **Simulator Mode** | Integration testing, development | Medium | No |
13
- | **Skip Validation** | Staging environments | Medium | Yes |
14
- | **Full Integration** | Production-like testing | High | Yes |
9
+ The FlowChat simulator is a browser-based testing interface that provides:
15
10
 
16
- ## Quick Start: Interactive Simulator
11
+ - **Multi-Platform Testing**: USSD, WhatsApp, and HTTP with platform-specific UI
12
+ - **Real-Time Request Logging**: Complete HTTP traffic monitoring and debugging
13
+ - **Security**: HMAC-signed cookie authentication
14
+ - **Platform-Specific Rendering**: Accurate simulation of each platform's behavior
15
+ - **Configuration Management**: Test multiple endpoints from a single interface
17
16
 
18
- The fastest way to test your flows is with the built-in web simulator:
17
+ ### Setup & Configuration
19
18
 
20
- ### 1. Configure Simulator
19
+ #### 1. Basic Configuration
21
20
 
22
21
  ```ruby
23
- # config/initializers/flowchat.rb
24
- FlowChat::Config.simulator_secret = Rails.application.secret_key_base + "_simulator"
22
+ # config/initializers/flow_chat.rb
23
+ FlowChat::Config.simulator_secret = "your_secure_secret_key_here"
25
24
  ```
26
25
 
27
- ### 2. Create Simulator Controller
26
+ #### 2. Create Simulator Controller
28
27
 
29
28
  ```ruby
30
29
  # app/controllers/simulator_controller.rb
@@ -37,439 +36,318 @@ class SimulatorController < ApplicationController
37
36
 
38
37
  protected
39
38
 
39
+ # Configure available test endpoints
40
40
  def configurations
41
41
  {
42
- ussd: {
43
- name: "USSD Integration",
44
- icon: "📱",
42
+ ussd_main: {
43
+ name: "USSD (Nalo)",
44
+ description: "USSD integration using Nalo gateway",
45
45
  processor_type: "ussd",
46
46
  gateway: "nalo",
47
47
  endpoint: "/ussd",
48
- color: "#007bff"
48
+ icon: "📱",
49
+ color: "#28a745",
50
+ settings: {
51
+ phone_number: default_phone_number,
52
+ session_timeout: 300
53
+ }
49
54
  },
50
- whatsapp: {
51
- name: "WhatsApp Integration",
52
- icon: "💬",
53
- processor_type: "whatsapp",
54
- gateway: "cloud_api",
55
+ whatsapp_main: {
56
+ name: "WhatsApp (Cloud API)",
57
+ description: "WhatsApp integration using Cloud API",
58
+ processor_type: "whatsapp",
59
+ gateway: "cloud_api",
55
60
  endpoint: "/whatsapp/webhook",
56
- color: "#25D366"
61
+ icon: "💬",
62
+ color: "#25D366",
63
+ settings: {
64
+ phone_number: default_phone_number,
65
+ contact_name: default_contact_name
66
+ }
67
+ },
68
+ http_api: {
69
+ name: "HTTP API",
70
+ description: "JSON HTTP API endpoint",
71
+ processor_type: "http",
72
+ gateway: "http_simple",
73
+ endpoint: "/http/webhook",
74
+ icon: "🌐",
75
+ color: "#0066cc",
76
+ settings: {
77
+ user_id: default_phone_number
78
+ }
57
79
  }
58
80
  }
59
81
  end
60
82
 
61
- def default_config_key
62
- :whatsapp
63
- end
64
-
65
83
  def default_phone_number
66
- "+1234567890"
84
+ "+233244123456"
67
85
  end
68
86
 
69
87
  def default_contact_name
70
- "Test User"
88
+ "John Doe"
89
+ end
90
+
91
+ def default_config_key
92
+ :ussd_main
71
93
  end
72
94
  end
73
95
  ```
74
96
 
75
- ### 3. Add Route
97
+ #### 3. Add Route
76
98
 
77
99
  ```ruby
78
100
  # config/routes.rb
79
101
  Rails.application.routes.draw do
80
102
  get '/simulator' => 'simulator#index'
81
- # ... your other routes
103
+ # ... other routes
82
104
  end
83
105
  ```
84
106
 
85
- ### 4. Enable Simulator in Controllers
107
+ ### Security Features
86
108
 
87
- ```ruby
88
- # app/controllers/whatsapp_controller.rb
89
- class WhatsappController < ApplicationController
90
- skip_forgery_protection
109
+ #### HMAC-Signed Cookies
91
110
 
92
- def webhook
93
- enable_simulator = Rails.env.development? # enabled in development by default
94
- processor = FlowChat::Whatsapp::Processor.new(self, enable_simulator:) do |config|
95
- config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
96
- config.use_session_store FlowChat::Session::CacheSessionStore
97
- end
111
+ The simulator uses secure, timestamped cookies for authentication:
98
112
 
99
- processor.run WelcomeFlow, :main_page
100
- end
113
+ ```ruby
114
+ # Automatic cookie generation in simulator controller
115
+ def set_simulator_cookie
116
+ simulator_secret = FlowChat::Config.simulator_secret
117
+ timestamp = Time.now.to_i
118
+ message = "simulator:#{timestamp}"
119
+ signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), simulator_secret, message)
120
+
121
+ cookies[:flowchat_simulator] = {
122
+ value: "#{timestamp}:#{signature}",
123
+ expires: 24.hours.from_now,
124
+ secure: request.ssl?, # HTTPS only in production
125
+ httponly: true, # Prevent XSS
126
+ same_site: :lax # CSRF protection
127
+ }
101
128
  end
102
129
  ```
103
130
 
104
- ### 5. Test Your Flows
131
+ #### Automatic Enablement
132
+
133
+ Simulator mode is automatically enabled when:
105
134
 
106
- Visit [http://localhost:3000/simulator](http://localhost:3000/simulator) and start testing!
135
+ ```ruby
136
+ # In processor initialization
137
+ enable_simulator: Rails.env.local? # true for development/test
138
+ ```
107
139
 
108
- **Simulator Features:**
109
- - 📱 **Visual Interface** - Phone-like display showing actual conversation
110
- - 🔄 **Platform Switching** - Toggle between USSD and WhatsApp modes
111
- - 📊 **Request Logging** - See HTTP requests and responses in real-time
112
- - 🎯 **Interactive Testing** - Character counting, validation, session management
113
- - 🛠️ **Developer Tools** - Reset sessions, view connection status
140
+ ### Platform-Specific Features
114
141
 
115
- ## Unit Testing
142
+ #### USSD Testing
116
143
 
117
- Test individual flows in isolation:
144
+ **Interface**: Menu-style display with character limits and pagination
118
145
 
119
- ### Basic Flow Testing
146
+ **Features**:
147
+ - Network-specific character limits (MTN: 160, Airtel: 140, etc.)
148
+ - Session timeout simulation
149
+ - Menu option selection
150
+ - Automatic pagination for long content
120
151
 
152
+ **Request Format**:
121
153
  ```ruby
122
- # test/flows/welcome_flow_test.rb
123
- require 'test_helper'
124
-
125
- class WelcomeFlowTest < ActiveSupport::TestCase
126
- def setup
127
- @context = FlowChat::Context.new
128
- @context.session = FlowChat::Session::CacheSessionStore.new
129
- @context.session.init_session("test_session")
130
- end
154
+ {
155
+ msisdn: "+233244123456",
156
+ text: "user_input",
157
+ session_id: "session_123",
158
+ network: "mtn"
159
+ }
160
+ ```
131
161
 
132
- test "welcome flow collects name and shows greeting" do
133
- # Simulate user entering name
134
- @context.input = "John Doe"
135
- app = FlowChat::Ussd::App.new(@context)
136
-
137
- # Expect flow to terminate with greeting
138
- error = assert_raises(FlowChat::Interrupt::Terminate) do
139
- flow = WelcomeFlow.new(app)
140
- flow.main_page
141
- end
142
-
143
- assert_includes error.prompt, "Hello, John Doe"
144
- end
162
+ #### WhatsApp Testing
163
+
164
+ **Interface**: Chat-style interface with contact avatars and message history
165
+
166
+ **Features**:
167
+ - Contact name and avatar display
168
+ - Interactive buttons and lists
169
+ - Media support (images, documents, audio, video)
170
+ - Cloud API webhook simulation
171
+
172
+ **Request Format**:
173
+ ```javascript
174
+ {
175
+ simulator_mode: true,
176
+ entry: [{
177
+ changes: [{
178
+ value: {
179
+ messaging_product: "whatsapp",
180
+ metadata: {
181
+ display_phone_number: "233244123456",
182
+ phone_number_id: "phone_number_id_123"
183
+ },
184
+ messages: [{
185
+ text: { body: "user_input" },
186
+ type: 'text'
187
+ }],
188
+ contacts: [{
189
+ profile: { name: "John Doe" },
190
+ wa_id: "233244123456"
191
+ }]
192
+ }
193
+ }]
194
+ }]
195
+ }
196
+ ```
145
197
 
146
- test "flow handles validation errors" do
147
- # Test with empty input
148
- @context.input = ""
149
- app = FlowChat::Ussd::App.new(@context)
150
-
151
- # Should prompt for input again
152
- error = assert_raises(FlowChat::Interrupt::Input) do
153
- flow = RegistrationFlow.new(app)
154
- flow.collect_email
155
- end
156
-
157
- assert_includes error.prompt, "Email is required"
158
- end
159
- end
198
+ **Response Handling**:
199
+ ```javascript
200
+ // Simulator expects JSON response for full simulation
201
+ {
202
+ mode: "simulator",
203
+ webhook_processed: true,
204
+ would_send: {
205
+ to: "233244123456",
206
+ type: "text",
207
+ text: { body: "Response message" }
208
+ },
209
+ message_info: {
210
+ to: "233244123456",
211
+ contact_name: "John Doe",
212
+ timestamp: "2024-01-01T12:00:00Z"
213
+ }
214
+ }
160
215
  ```
161
216
 
162
- ### Testing Complex Flows
217
+ #### HTTP Testing
163
218
 
164
- ```ruby
165
- # test/flows/registration_flow_test.rb
166
- class RegistrationFlowTest < ActiveSupport::TestCase
167
- test "complete registration flow" do
168
- context = FlowChat::Context.new
169
- context.session = FlowChat::Session::CacheSessionStore.new
170
- context.session.init_session("test_session")
171
-
172
- # Step 1: Enter email
173
- context.input = "john@example.com"
174
- app = FlowChat::Ussd::App.new(context)
175
-
176
- assert_raises(FlowChat::Interrupt::Input) do
177
- flow = RegistrationFlow.new(app)
178
- flow.main_page
179
- end
180
-
181
- # Verify email was stored
182
- assert_equal "john@example.com", context.session.get(:email)
183
-
184
- # Step 2: Enter age
185
- context.input = "25"
186
-
187
- assert_raises(FlowChat::Interrupt::Input) do
188
- flow = RegistrationFlow.new(app)
189
- flow.main_page # Continue from where we left off
190
- end
191
-
192
- # Step 3: Confirm
193
- context.input = "yes"
194
-
195
- assert_raises(FlowChat::Interrupt::Terminate) do
196
- flow = RegistrationFlow.new(app)
197
- flow.main_page
198
- end
199
- end
200
- end
219
+ **Interface**: API-style interface showing JSON request/response
220
+
221
+ **Features**:
222
+ - JSON payload display
223
+ - Session management
224
+ - Custom headers
225
+ - Error handling
226
+
227
+ **Request Format**:
228
+ ```javascript
229
+ {
230
+ session_id: "session_123",
231
+ user_id: "+233244123456",
232
+ input: "user_input",
233
+ simulator_mode: true
234
+ }
201
235
  ```
202
236
 
203
- ## Integration Testing
237
+ ### Request Logging & Debugging
204
238
 
205
- ### Environment Configuration
239
+ #### Real-Time Traffic Monitoring
206
240
 
207
- Set up different testing modes per environment:
241
+ The simulator provides comprehensive request logging:
208
242
 
209
- ```ruby
210
- # config/initializers/flowchat.rb
211
- case Rails.env
212
- when 'development'
213
- # Use simulator for easy testing
214
- FlowChat::Config.whatsapp.message_handling_mode = :simulator
215
- FlowChat::Config.simulator_secret = Rails.application.secret_key_base + "_dev"
216
-
217
- when 'test'
218
- # Use simulator for automated tests
219
- FlowChat::Config.whatsapp.message_handling_mode = :simulator
220
- FlowChat::Config.simulator_secret = "test_secret_key"
221
-
222
- when 'staging'
223
- # Use inline mode with real WhatsApp API but skip validation for testing
224
- FlowChat::Config.whatsapp.message_handling_mode = :inline
225
- FlowChat::Config.simulator_secret = ENV['FLOWCHAT_SIMULATOR_SECRET']
226
-
227
- when 'production'
228
- # Use background jobs with full security
229
- FlowChat::Config.whatsapp.message_handling_mode = :background
230
- FlowChat::Config.whatsapp.background_job_class = 'WhatsappMessageJob'
231
- # No simulator secret in production
232
- end
243
+ ```javascript
244
+ // Automatic logging of all HTTP traffic
245
+ addRequestLog('POST', endpoint, requestData, responseData, statusCode, errorMessage)
233
246
  ```
234
247
 
235
- ### Simulator Mode Testing
248
+ **Log Information**:
249
+ - Request method and URL
250
+ - Complete request payload
251
+ - Response status and data
252
+ - Timestamps and duration
253
+ - Error messages with helpful debugging hints
236
254
 
237
- Test webhook endpoints using simulator mode:
255
+ #### Error Handling
238
256
 
239
- ```ruby
240
- # test/controllers/whatsapp_controller_test.rb
241
- class WhatsappControllerTest < ActionDispatch::IntegrationTest
242
- test "processes whatsapp message in simulator mode" do
243
- webhook_payload = {
244
- entry: [{
245
- changes: [{
246
- value: {
247
- messages: [{
248
- from: "1234567890",
249
- text: { body: "Hello" },
250
- type: "text",
251
- id: "msg_123",
252
- timestamp: Time.now.to_i
253
- }]
254
- }
255
- }]
256
- }],
257
- simulator_mode: true # Enable simulator mode
258
- }
257
+ The simulator provides detailed error messages for common issues:
259
258
 
260
- # Generate valid simulator cookie
261
- valid_cookie = generate_simulator_cookie
262
-
263
- post "/whatsapp/webhook",
264
- params: webhook_payload,
265
- cookies: { flowchat_simulator: valid_cookie }
266
-
267
- assert_response :success
268
-
269
- # In simulator mode, response contains message data
270
- response_data = JSON.parse(response.body)
271
- assert response_data.key?("text")
272
- assert_includes response_data["text"], "What's your name?"
273
- end
259
+ - **Connection Failures**: CORS, SSL, network issues
260
+ - **404 Not Found**: Route configuration problems
261
+ - **500 Server Errors**: Application errors
262
+ - **Authentication Issues**: Invalid simulator cookies
274
263
 
275
- test "multi-step flow maintains state" do
276
- valid_cookie = generate_simulator_cookie
277
-
278
- # Step 1: Start conversation
279
- post_simulator_message("start", valid_cookie)
280
- assert_response :success
281
-
282
- # Step 2: Enter name
283
- post_simulator_message("John", valid_cookie)
284
- assert_response :success
285
-
286
- response_data = JSON.parse(response.body)
287
- assert_includes response_data["text"], "Hello John"
288
- end
264
+ ### Enabling Simulator Mode in Your Endpoints
289
265
 
290
- private
266
+ #### For WhatsApp Endpoints
291
267
 
292
- def generate_simulator_cookie(secret = "test_secret_key")
293
- timestamp = Time.now.to_i
294
- message = "simulator:#{timestamp}"
295
- signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), secret, message)
296
- "#{timestamp}:#{signature}"
297
- end
268
+ Your WhatsApp processor automatically handles simulator mode:
298
269
 
299
- def post_simulator_message(text, cookie)
300
- webhook_payload = {
301
- entry: [{
302
- changes: [{
303
- value: {
304
- messages: [{
305
- from: "1234567890",
306
- text: { body: text },
307
- type: "text",
308
- id: "msg_#{rand(1000)}",
309
- timestamp: Time.now.to_i
310
- }]
311
- }
312
- }]
313
- }],
314
- simulator_mode: true
315
- }
270
+ ```ruby
271
+ class WhatsappController < ApplicationController
272
+ def webhook
273
+ processor = FlowCha::Processor.new(self, enable_simulator: !Rails.env.production?) do |config|
274
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
275
+ config.use_session_store FlowChat::Session::CacheSessionStore
276
+ end
316
277
 
317
- post "/whatsapp/webhook",
318
- params: webhook_payload,
319
- cookies: { flowchat_simulator: cookie }
278
+ processor.run WelcomeFlow, :main_page
320
279
  end
321
280
  end
322
281
  ```
323
282
 
324
- ### Testing with Disabled Validation
283
+ #### For HTTP Endpoints
325
284
 
326
- For staging environments where you want to test real endpoints:
285
+ HTTP endpoints work automatically with the simulator:
327
286
 
328
287
  ```ruby
329
- test "webhook with disabled validation" do
330
- # Create config with validation disabled
331
- config = FlowChat::Whatsapp::Configuration.new(:test_config)
332
- config.access_token = "test_token"
333
- config.phone_number_id = "test_phone_id"
334
- config.verify_token = "test_verify"
335
- config.skip_signature_validation = true # Disable validation for testing
336
-
337
- webhook_payload = {
338
- entry: [{
339
- changes: [{
340
- value: {
341
- messages: [{
342
- from: "1234567890",
343
- text: { body: "Hello" },
344
- type: "text"
345
- }]
346
- }
347
- }]
348
- }]
349
- }
288
+ class HttpController < ApplicationController
289
+ def webhook
290
+ processor = FlowChat::Processor.new(self) do |config|
291
+ config.use_gateway FlowChat::Http::Gateway::Simple
292
+ config.use_session_store FlowChat::Session::CacheSessionStore
293
+ end
350
294
 
351
- post "/whatsapp/webhook",
352
- params: webhook_payload.to_json,
353
- headers: { "Content-Type" => "application/json" }
354
-
355
- assert_response :success
295
+ processor.run WelcomeFlow, :main_page
296
+ end
356
297
  end
357
298
  ```
358
299
 
359
- ## Advanced Testing Scenarios
300
+ ### Usage Workflow
360
301
 
361
- ### Testing Error Handling
302
+ #### 1. Start the Simulator
362
303
 
363
- ```ruby
364
- test "handles validation errors gracefully" do
365
- valid_cookie = generate_simulator_cookie
366
-
367
- # Send invalid email
368
- post_simulator_message("invalid-email", valid_cookie)
369
-
370
- response_data = JSON.parse(response.body)
371
- assert_includes response_data["text"], "Invalid email format"
372
-
373
- # Send valid email - should proceed
374
- post_simulator_message("john@example.com", valid_cookie)
375
-
376
- response_data = JSON.parse(response.body)
377
- refute_includes response_data["text"], "Invalid email"
378
- end
304
+ ```bash
305
+ rails server
306
+ # Visit http://localhost:3000/simulator
379
307
  ```
380
308
 
381
- ### Testing Media Responses
309
+ #### 2. Configure Test Environment
382
310
 
383
- ```ruby
384
- test "media responses in simulator mode" do
385
- valid_cookie = generate_simulator_cookie
386
-
387
- post_simulator_message("help", valid_cookie)
388
-
389
- response_data = JSON.parse(response.body)
390
-
391
- # Check media is included
392
- assert response_data.key?("media")
393
- assert_equal "image", response_data["media"]["type"]
394
- assert response_data["media"]["url"].present?
395
- end
396
- ```
311
+ - Select endpoint from configuration dropdown
312
+ - Set phone number and contact name
313
+ - Choose platform type (USSD/WhatsApp/HTTP)
397
314
 
398
- ### Testing Session Persistence
315
+ #### 3. Test Conversation Flows
399
316
 
400
- ```ruby
401
- test "session data persists across requests" do
402
- valid_cookie = generate_simulator_cookie
403
-
404
- # First request - enter name
405
- post_simulator_message("John", valid_cookie)
406
-
407
- # Second request - session should remember name
408
- post_simulator_message("continue", valid_cookie)
409
-
410
- response_data = JSON.parse(response.body)
411
- assert_includes response_data["text"], "John" # Name should be remembered
412
- end
413
- ```
317
+ - Click "Start Session" to begin
318
+ - Send messages through the platform-specific interface
319
+ - Monitor request/response logs in real-time
320
+ - Reset session to test different scenarios
414
321
 
415
- ## Performance Testing
322
+ #### 4. Debug Issues
416
323
 
417
- ### Load Testing Background Jobs
324
+ - Check request logs for HTTP traffic details
325
+ - Verify endpoint responses and status codes
326
+ - Review error messages for configuration issues
327
+ - Test different platforms and configurations
418
328
 
419
- ```ruby
420
- test "handles high message volume with background jobs" do
421
- # Switch to background mode for this test
422
- original_mode = FlowChat::Config.whatsapp.message_handling_mode
423
- FlowChat::Config.whatsapp.message_handling_mode = :background
424
-
425
- messages = 10.times.map do |i|
426
- create_whatsapp_message_payload("user#{i}")
427
- end
428
-
429
- assert_enqueued_jobs 10 do
430
- messages.each do |msg|
431
- post "/whatsapp/webhook", params: msg
432
- end
433
- end
434
- ensure
435
- FlowChat::Config.whatsapp.message_handling_mode = original_mode
436
- end
437
- ```
329
+ ### Best Practices
438
330
 
439
- ## Debugging Tests
331
+ #### Security
440
332
 
441
- ### Enable Debug Logging
333
+ - Always set `FlowChat::Config.simulator_secret` in production
334
+ - Use secure cookies over HTTPS in production
335
+ - Restrict simulator access to development/staging environments
442
336
 
443
- ```ruby
444
- # config/environments/test.rb
445
- config.log_level = :debug
337
+ #### Testing Strategy
446
338
 
447
- # In tests
448
- Rails.logger.debug "Current session data: #{context.session.data}"
449
- ```
339
+ 1. **Start with Simulator**: Test flows before gateway integration
340
+ 2. **Test All Platforms**: Verify behavior across USSD, WhatsApp, HTTP
341
+ 3. **Check Character Limits**: Test USSD character restrictions
342
+ 4. **Verify Session Management**: Test session boundaries and persistence
343
+ 5. **Monitor Request Logs**: Debug integration issues in real-time
344
+
345
+ #### Performance
346
+
347
+ - Use simulator for rapid prototyping and debugging
348
+ - Test edge cases and error conditions safely
349
+ - Validate webhook payloads before production deployment
350
+
351
+ The FlowChat simulator provides a complete testing environment that accurately simulates real-world platform behavior while offering comprehensive debugging capabilities for efficient development and testing workflows.
450
352
 
451
- ### Inspect Flow State
452
353
 
453
- ```ruby
454
- test "debug flow execution" do
455
- context = FlowChat::Context.new
456
- context.session = FlowChat::Session::CacheSessionStore.new
457
- context.session.init_session("debug_session")
458
-
459
- # Add debugging
460
- context.input = "test@example.com"
461
- app = FlowChat::Ussd::App.new(context)
462
-
463
- flow = RegistrationFlow.new(app)
464
-
465
- # Inspect state before execution
466
- puts "Session before: #{context.session.data}"
467
-
468
- begin
469
- flow.main_page
470
- rescue FlowChat::Interrupt::Input => e
471
- puts "Flow interrupted with: #{e.prompt}"
472
- puts "Session after: #{context.session.data}"
473
- end
474
- end
475
- ```