|
| 1 | +describe('Comprehensive Demo Flow with Wallet Integration', () => { |
| 2 | + // Test wallet address (using a valid Stellar testnet address format) |
| 3 | + const TEST_WALLET_ADDRESS = 'GABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'; |
| 4 | + |
| 5 | + beforeEach(() => { |
| 6 | + // Visit the demos page |
| 7 | + cy.visit('/demos'); |
| 8 | + |
| 9 | + // Wait for the page to load |
| 10 | + cy.get('h1', { timeout: 10000 }).should('be.visible'); |
| 11 | + |
| 12 | + // Clear any existing localStorage data |
| 13 | + cy.clearLocalStorage(); |
| 14 | + }); |
| 15 | + |
| 16 | + it('should complete full immersive demo flow with wallet connection', () => { |
| 17 | + // Step 1: Verify page loads correctly |
| 18 | + cy.title().should('contain', 'NEXUS EXPERIENCE'); |
| 19 | + cy.get('h1').should('contain', 'STELLAR NEXUS EXPERIENCE'); |
| 20 | + |
| 21 | + // Step 2: Find and interact with the first demo card |
| 22 | + cy.get('.demo-card').first().should('be.visible'); |
| 23 | + cy.get('.demo-card') |
| 24 | + .first() |
| 25 | + .within(() => { |
| 26 | + cy.get('h3').should('contain', 'Baby Steps to Riches'); |
| 27 | + cy.get('h4').should('contain', 'Basic Escrow Flow Demo'); |
| 28 | + }); |
| 29 | + |
| 30 | + // Step 3: Launch the immersive demo |
| 31 | + cy.get('.demo-card') |
| 32 | + .first() |
| 33 | + .scrollIntoView() |
| 34 | + .within(() => { |
| 35 | + cy.get('button').contains('LAUNCH DEMO').click({ force: true }); |
| 36 | + }); |
| 37 | + |
| 38 | + // Step 4: Verify immersive modal opens |
| 39 | + cy.get('[data-testid="immersive-demo-modal"]', { timeout: 5000 }).should('be.visible'); |
| 40 | + |
| 41 | + // Step 5: Verify warning step is shown |
| 42 | + cy.get('[data-testid="demo-warning-step"]').should('be.visible'); |
| 43 | + cy.get('[data-testid="demo-warning-step"]').within(() => { |
| 44 | + cy.get('h2').should('contain', 'Demo Warning'); |
| 45 | + cy.get('[data-testid="estimated-time"]').should('be.visible'); |
| 46 | + cy.get('[data-testid="attention-required"]').should('be.visible'); |
| 47 | + cy.get('[data-testid="wallet-connection-check"]').should('be.visible'); |
| 48 | + }); |
| 49 | + |
| 50 | + // Step 6: Start the demo |
| 51 | + cy.get('[data-testid="start-demo-button"]').click(); |
| 52 | + |
| 53 | + // Step 7: Verify demo content step is shown |
| 54 | + cy.get('[data-testid="demo-content-step"]', { timeout: 5000 }).should('be.visible'); |
| 55 | + |
| 56 | + // Step 8: Connect wallet using the test address |
| 57 | + cy.window().then((win) => { |
| 58 | + // Mock Freighter wallet availability |
| 59 | + win.stellar = { |
| 60 | + isConnected: () => Promise.resolve(false), |
| 61 | + connect: () => Promise.resolve({ publicKey: TEST_WALLET_ADDRESS }), |
| 62 | + signTransaction: () => Promise.resolve('mock-signed-xdr'), |
| 63 | + submitTransaction: () => Promise.resolve({ hash: 'mock-tx-hash' }) |
| 64 | + }; |
| 65 | + }); |
| 66 | + |
| 67 | + // Step 9: Look for wallet connection UI and connect |
| 68 | + cy.get('body').then(($body) => { |
| 69 | + // Check if wallet sidebar or connection UI is visible |
| 70 | + if ($body.find('[data-testid="wallet-sidebar"]').length > 0) { |
| 71 | + cy.get('[data-testid="wallet-sidebar"]').should('be.visible'); |
| 72 | + |
| 73 | + // Look for connect button in wallet sidebar |
| 74 | + cy.get('[data-testid="wallet-sidebar"]').within(() => { |
| 75 | + cy.get('button').contains(/connect|Connect/).click({ force: true }); |
| 76 | + }); |
| 77 | + } else if ($body.find('button').filter(':contains("Connect")').length > 0) { |
| 78 | + cy.get('button').contains('Connect').click({ force: true }); |
| 79 | + } |
| 80 | + }); |
| 81 | + |
| 82 | + // Step 10: Enter test wallet address |
| 83 | + cy.get('body').then(($body) => { |
| 84 | + if ($body.find('input[type="text"]').length > 0) { |
| 85 | + cy.get('input[type="text"]').first().type(TEST_WALLET_ADDRESS); |
| 86 | + cy.get('button').contains(/connect|Connect|Submit/).click({ force: true }); |
| 87 | + } |
| 88 | + }); |
| 89 | + |
| 90 | + // Step 11: Verify wallet connection success |
| 91 | + cy.get('body').then(($body) => { |
| 92 | + // Look for connection success indicators |
| 93 | + if ($body.find('[data-testid="wallet-connected"]').length > 0) { |
| 94 | + cy.get('[data-testid="wallet-connected"]').should('be.visible'); |
| 95 | + } else if ($body.find('.text-green').length > 0) { |
| 96 | + cy.get('.text-green').should('contain', 'Connected'); |
| 97 | + } |
| 98 | + }); |
| 99 | + |
| 100 | + // Step 12: Proceed with demo steps |
| 101 | + cy.get('[data-testid="demo-content-step"]').within(() => { |
| 102 | + // Look for demo step buttons or interactive elements |
| 103 | + cy.get('button').first().click({ force: true }); |
| 104 | + }); |
| 105 | + |
| 106 | + // Step 13: Complete demo steps (simulate the escrow flow) |
| 107 | + cy.get('body').then(($body) => { |
| 108 | + // Look for step-by-step buttons |
| 109 | + const stepButtons = $body.find('button').filter((i, el) => { |
| 110 | + const text = Cypress.$(el).text().toLowerCase(); |
| 111 | + return text.includes('initialize') || text.includes('fund') || |
| 112 | + text.includes('complete') || text.includes('approve') || |
| 113 | + text.includes('release') || text.includes('step'); |
| 114 | + }); |
| 115 | + |
| 116 | + if (stepButtons.length > 0) { |
| 117 | + // Click through available demo steps |
| 118 | + stepButtons.each((i, button) => { |
| 119 | + if (i < 3) { // Limit to first 3 steps to avoid infinite loops |
| 120 | + cy.wrap(button).click({ force: true }); |
| 121 | + cy.wait(1000); // Wait between steps |
| 122 | + } |
| 123 | + }); |
| 124 | + } |
| 125 | + }); |
| 126 | + |
| 127 | + // Step 14: Complete the demo |
| 128 | + cy.get('body').then(($body) => { |
| 129 | + if ($body.find('[data-testid="complete-demo-button"]').length > 0) { |
| 130 | + cy.get('[data-testid="complete-demo-button"]').click(); |
| 131 | + } else if ($body.find('button').filter(':contains("Complete")').length > 0) { |
| 132 | + cy.get('button').contains('Complete').click({ force: true }); |
| 133 | + } |
| 134 | + }); |
| 135 | + |
| 136 | + // Step 15: Verify feedback step is shown |
| 137 | + cy.get('[data-testid="demo-feedback-step"]', { timeout: 5000 }).should('be.visible'); |
| 138 | + cy.get('[data-testid="demo-feedback-step"]').within(() => { |
| 139 | + cy.get('h2').should('contain', 'Demo Feedback'); |
| 140 | + }); |
| 141 | + |
| 142 | + // Step 16: Fill out feedback form |
| 143 | + cy.get('[data-testid="demo-feedback-step"]').within(() => { |
| 144 | + // Rate the demo (5 stars) |
| 145 | + if (cy.get('[data-testid="rating-stars"]').length > 0) { |
| 146 | + cy.get('[data-testid="rating-stars"]').find('button').last().click(); |
| 147 | + } |
| 148 | + |
| 149 | + // Select difficulty |
| 150 | + if (cy.get('[data-testid="difficulty-select"]').length > 0) { |
| 151 | + cy.get('[data-testid="difficulty-select"]').select('Easy'); |
| 152 | + } |
| 153 | + |
| 154 | + // Select recommendation |
| 155 | + if (cy.get('[data-testid="recommendation-select"]').length > 0) { |
| 156 | + cy.get('[data-testid="recommendation-select"]').select('Yes'); |
| 157 | + } |
| 158 | + |
| 159 | + // Add feedback comment |
| 160 | + if (cy.get('[data-testid="feedback-textarea"]').length > 0) { |
| 161 | + cy.get('[data-testid="feedback-textarea"]').type( |
| 162 | + 'This comprehensive demo was excellent! Great integration with wallet connection.' |
| 163 | + ); |
| 164 | + } |
| 165 | + }); |
| 166 | + |
| 167 | + // Step 17: Submit feedback |
| 168 | + cy.get('[data-testid="submit-feedback-button"]').click(); |
| 169 | + |
| 170 | + // Step 18: Verify success message and modal closes |
| 171 | + cy.get('[data-testid="feedback-success"]', { timeout: 5000 }).should('be.visible'); |
| 172 | + cy.get('[data-testid="immersive-demo-modal"]').should('not.exist'); |
| 173 | + |
| 174 | + // Step 19: Verify demo completion is recorded |
| 175 | + cy.get('.demo-card') |
| 176 | + .first() |
| 177 | + .within(() => { |
| 178 | + // Look for completion indicators |
| 179 | + cy.get('body').then(($body) => { |
| 180 | + if ($body.find('[data-testid="demo-completion-status"]').length > 0) { |
| 181 | + cy.get('[data-testid="demo-completion-status"]').should('contain', 'Completed'); |
| 182 | + } |
| 183 | + }); |
| 184 | + }); |
| 185 | + }); |
| 186 | + |
| 187 | + it('should handle wallet connection errors gracefully', () => { |
| 188 | + // Launch demo |
| 189 | + cy.get('.demo-card') |
| 190 | + .first() |
| 191 | + .scrollIntoView() |
| 192 | + .within(() => { |
| 193 | + cy.get('button').contains('LAUNCH DEMO').click({ force: true }); |
| 194 | + }); |
| 195 | + |
| 196 | + // Start demo |
| 197 | + cy.get('[data-testid="start-demo-button"]').click(); |
| 198 | + |
| 199 | + // Mock wallet connection failure |
| 200 | + cy.window().then((win) => { |
| 201 | + win.stellar = { |
| 202 | + isConnected: () => Promise.resolve(false), |
| 203 | + connect: () => Promise.reject(new Error('Connection failed')), |
| 204 | + signTransaction: () => Promise.reject(new Error('Signing failed')), |
| 205 | + submitTransaction: () => Promise.reject(new Error('Transaction failed')) |
| 206 | + }; |
| 207 | + }); |
| 208 | + |
| 209 | + // Try to connect wallet |
| 210 | + cy.get('body').then(($body) => { |
| 211 | + if ($body.find('button').filter(':contains("Connect")').length > 0) { |
| 212 | + cy.get('button').contains('Connect').click({ force: true }); |
| 213 | + } |
| 214 | + }); |
| 215 | + |
| 216 | + // Verify error handling |
| 217 | + cy.get('body').then(($body) => { |
| 218 | + // Look for error messages or toast notifications |
| 219 | + if ($body.find('.toast-error').length > 0) { |
| 220 | + cy.get('.toast-error').should('be.visible'); |
| 221 | + } else if ($body.find('.text-red').length > 0) { |
| 222 | + cy.get('.text-red').should('contain', 'error'); |
| 223 | + } |
| 224 | + }); |
| 225 | + }); |
| 226 | + |
| 227 | + it('should track demo progress and timing correctly', () => { |
| 228 | + // Launch demo |
| 229 | + cy.get('.demo-card') |
| 230 | + .first() |
| 231 | + .scrollIntoView() |
| 232 | + .within(() => { |
| 233 | + cy.get('button').contains('LAUNCH DEMO').click({ force: true }); |
| 234 | + }); |
| 235 | + |
| 236 | + // Start demo |
| 237 | + cy.get('[data-testid="start-demo-button"]').click(); |
| 238 | + |
| 239 | + // Verify progress tracking elements |
| 240 | + cy.get('[data-testid="demo-content-step"]').within(() => { |
| 241 | + // Check for progress bar |
| 242 | + if (cy.get('[data-testid="demo-progress"]').length > 0) { |
| 243 | + cy.get('[data-testid="demo-progress"]').should('be.visible'); |
| 244 | + cy.get('[data-testid="demo-progress"]').within(() => { |
| 245 | + cy.get('.progress-bar').should('have.attr', 'style').and('contain', 'width'); |
| 246 | + }); |
| 247 | + } |
| 248 | + |
| 249 | + // Check for timer |
| 250 | + if (cy.get('[data-testid="demo-timer"]').length > 0) { |
| 251 | + cy.get('[data-testid="demo-timer"]').should('be.visible'); |
| 252 | + cy.get('[data-testid="demo-timer"]').should('not.contain', '00:00'); |
| 253 | + } |
| 254 | + }); |
| 255 | + |
| 256 | + // Wait a bit to see progress update |
| 257 | + cy.wait(2000); |
| 258 | + |
| 259 | + // Verify progress has updated |
| 260 | + cy.get('[data-testid="demo-progress"]').then(($progress) => { |
| 261 | + if ($progress.length > 0) { |
| 262 | + cy.get('[data-testid="demo-progress"]').should('not.contain', '0%'); |
| 263 | + } |
| 264 | + }); |
| 265 | + }); |
| 266 | + |
| 267 | + it('should persist demo completion data', () => { |
| 268 | + // Complete a demo |
| 269 | + cy.get('.demo-card') |
| 270 | + .first() |
| 271 | + .scrollIntoView() |
| 272 | + .within(() => { |
| 273 | + cy.get('button').contains('LAUNCH DEMO').click({ force: true }); |
| 274 | + }); |
| 275 | + |
| 276 | + cy.get('[data-testid="start-demo-button"]').click(); |
| 277 | + |
| 278 | + // Complete demo quickly |
| 279 | + cy.get('body').then(($body) => { |
| 280 | + if ($body.find('[data-testid="complete-demo-button"]').length > 0) { |
| 281 | + cy.get('[data-testid="complete-demo-button"]').click(); |
| 282 | + } |
| 283 | + }); |
| 284 | + |
| 285 | + // Submit feedback |
| 286 | + cy.get('[data-testid="demo-feedback-step"]').within(() => { |
| 287 | + if (cy.get('[data-testid="rating-stars"]').length > 0) { |
| 288 | + cy.get('[data-testid="rating-stars"]').find('button').last().click(); |
| 289 | + } |
| 290 | + }); |
| 291 | + |
| 292 | + cy.get('[data-testid="submit-feedback-button"]').click(); |
| 293 | + |
| 294 | + // Verify data is persisted in localStorage |
| 295 | + cy.window().then((win) => { |
| 296 | + const feedback = win.localStorage.getItem('demoFeedback'); |
| 297 | + expect(feedback).to.not.be.null; |
| 298 | + |
| 299 | + const feedbackData = JSON.parse(feedback); |
| 300 | + expect(feedbackData).to.have.property('hello-milestone'); |
| 301 | + expect(feedbackData['hello-milestone']).to.have.property('rating'); |
| 302 | + expect(feedbackData['hello-milestone']).to.have.property('timestamp'); |
| 303 | + }); |
| 304 | + }); |
| 305 | +}); |
0 commit comments