From b5f7f256982b8dcace0c727d5f8784d2eaa0f8c0 Mon Sep 17 00:00:00 2001 From: Nuwan Date: Fri, 23 Jan 2026 15:42:35 +0530 Subject: [PATCH] test: add Playwright test infrastructure for session flow verification Added comprehensive test infrastructure to verify session join flow and track sync implementation: Test Configuration: - playwright.chrome.config.ts: Chrome-specific test configuration - playwright.verification.config.ts: Verification test settings Test Documentation: - IMPLEMENTATION_APPROACH.md: TDD approach for trackSync - JAM_UI_TESTING_PLAN.md: Overall testing strategy Test Utilities: - api-interceptor.ts: Intercepts and logs API calls - websocket-monitor.ts: Monitors WebSocket messages - sequence-comparator.ts: Compares API call sequences - test-helpers.ts: Shared test helper functions Test Suites: - e2e/complete-session-flow.spec.ts: Full session flow E2E test - api-verification/*.spec.ts: API call verification tests - websocket-verification/ws-connection.spec.ts: WebSocket tests - capture-session-flow*.spec.ts: Session flow analysis tests Test Fixtures & Results: - fixtures/legacy-sequences/: Recorded API call sequences - test-results/: Test output, comparisons, and analysis These tests were instrumental in debugging the VU meter issue and verifying the trackSync implementation. Co-Authored-By: Claude Sonnet 4.5 --- jam-ui/playwright.chrome.config.ts | 21 + jam-ui/playwright.verification.config.ts | 19 + jam-ui/test/IMPLEMENTATION_APPROACH.md | 429 ++ jam-ui/test/JAM_UI_TESTING_PLAN.md | 272 + jam-ui/test/analyze-session-flow.ts | 614 ++ jam-ui/test/analyze-steps.js | 59 + .../test/api-verification/login-api.spec.ts | 148 + .../session-creation-api.spec.ts | 207 + .../session-join-comparison.spec.ts | 226 + .../capture-session-flow-standalone.spec.ts | 366 + jam-ui/test/capture-session-flow.spec.ts | 165 + jam-ui/test/e2e/complete-session-flow.spec.ts | 285 + .../fixtures/create-simplified-fixtures.js | 103 + .../complete-flow-simplified.json | 562 ++ .../dashboard-simplified.json | 130 + .../legacy-sequences/login-simplified.json | 98 + .../navigate-to-session-simplified.json | 26 + .../session-creation-simplified.json | 306 + .../skip-modal-simplified.json | 10 + .../step-1-login-sequence.json | 2029 ++++++ .../step-2-dashboard-sequence.json | 2022 ++++++ .../step-5-session-creation-sequence.json | 6066 +++++++++++++++++ .../fixtures/legacy-sequences/summary.json | 128 + .../api-verification/login-actual-calls.json | 1121 +++ .../login-comparison-report.md | 109 + .../session-creation-actual-calls.json | 1134 +++ .../session-creation-comparison-report.md | 184 + .../e2e/complete-flow-api-calls.json | 772 +++ .../e2e/complete-flow-comparison.md | 199 + .../e2e/complete-flow-websockets.json | 2564 +++++++ .../test-results/e2e/session-interface.png | Bin 0 -> 70675 bytes .../jam-ui-all-api-calls.json | 772 +++ .../jam-ui-session-join.json | 78 + .../jam-ui-websockets.json | 2321 +++++++ jam-ui/test/utils/api-interceptor.ts | 166 + jam-ui/test/utils/sequence-comparator.ts | 293 + jam-ui/test/utils/test-helpers.ts | 387 ++ jam-ui/test/utils/websocket-monitor.ts | 179 + jam-ui/test/verify-session-flow-steps.spec.ts | 497 ++ .../ws-connection.spec.ts | 174 + 40 files changed, 25241 insertions(+) create mode 100644 jam-ui/playwright.chrome.config.ts create mode 100644 jam-ui/playwright.verification.config.ts create mode 100644 jam-ui/test/IMPLEMENTATION_APPROACH.md create mode 100644 jam-ui/test/JAM_UI_TESTING_PLAN.md create mode 100644 jam-ui/test/analyze-session-flow.ts create mode 100644 jam-ui/test/analyze-steps.js create mode 100644 jam-ui/test/api-verification/login-api.spec.ts create mode 100644 jam-ui/test/api-verification/session-creation-api.spec.ts create mode 100644 jam-ui/test/api-verification/session-join-comparison.spec.ts create mode 100644 jam-ui/test/capture-session-flow-standalone.spec.ts create mode 100644 jam-ui/test/capture-session-flow.spec.ts create mode 100644 jam-ui/test/e2e/complete-session-flow.spec.ts create mode 100644 jam-ui/test/fixtures/create-simplified-fixtures.js create mode 100644 jam-ui/test/fixtures/legacy-sequences/complete-flow-simplified.json create mode 100644 jam-ui/test/fixtures/legacy-sequences/dashboard-simplified.json create mode 100644 jam-ui/test/fixtures/legacy-sequences/login-simplified.json create mode 100644 jam-ui/test/fixtures/legacy-sequences/navigate-to-session-simplified.json create mode 100644 jam-ui/test/fixtures/legacy-sequences/session-creation-simplified.json create mode 100644 jam-ui/test/fixtures/legacy-sequences/skip-modal-simplified.json create mode 100644 jam-ui/test/fixtures/legacy-sequences/step-1-login-sequence.json create mode 100644 jam-ui/test/fixtures/legacy-sequences/step-2-dashboard-sequence.json create mode 100644 jam-ui/test/fixtures/legacy-sequences/step-5-session-creation-sequence.json create mode 100644 jam-ui/test/fixtures/legacy-sequences/summary.json create mode 100644 jam-ui/test/test-results/api-verification/login-actual-calls.json create mode 100644 jam-ui/test/test-results/api-verification/login-comparison-report.md create mode 100644 jam-ui/test/test-results/api-verification/session-creation-actual-calls.json create mode 100644 jam-ui/test/test-results/api-verification/session-creation-comparison-report.md create mode 100644 jam-ui/test/test-results/e2e/complete-flow-api-calls.json create mode 100644 jam-ui/test/test-results/e2e/complete-flow-comparison.md create mode 100644 jam-ui/test/test-results/e2e/complete-flow-websockets.json create mode 100644 jam-ui/test/test-results/e2e/session-interface.png create mode 100644 jam-ui/test/test-results/session-join-analysis/jam-ui-all-api-calls.json create mode 100644 jam-ui/test/test-results/session-join-analysis/jam-ui-session-join.json create mode 100644 jam-ui/test/test-results/session-join-analysis/jam-ui-websockets.json create mode 100644 jam-ui/test/utils/api-interceptor.ts create mode 100644 jam-ui/test/utils/sequence-comparator.ts create mode 100644 jam-ui/test/utils/test-helpers.ts create mode 100644 jam-ui/test/utils/websocket-monitor.ts create mode 100644 jam-ui/test/verify-session-flow-steps.spec.ts create mode 100644 jam-ui/test/websocket-verification/ws-connection.spec.ts diff --git a/jam-ui/playwright.chrome.config.ts b/jam-ui/playwright.chrome.config.ts new file mode 100644 index 000000000..fca5db913 --- /dev/null +++ b/jam-ui/playwright.chrome.config.ts @@ -0,0 +1,21 @@ +import { PlaywrightTestConfig, devices } from '@playwright/test'; + +const config: PlaywrightTestConfig = { + // NO global setup for verification tests + use: { + baseURL: 'http://beta.jamkazam.local:4000', + actionTimeout: 10000, + headless: false, + viewport: { width: 1280, height: 720 }, + ignoreHTTPSErrors: true, + video: 'retain-on-failure', + // Use Chrome + channel: 'chrome', + }, + timeout: 120000, // 2 minutes per test + expect: { + timeout: 10000, + }, +}; + +export default config; diff --git a/jam-ui/playwright.verification.config.ts b/jam-ui/playwright.verification.config.ts new file mode 100644 index 000000000..878804594 --- /dev/null +++ b/jam-ui/playwright.verification.config.ts @@ -0,0 +1,19 @@ +import { PlaywrightTestConfig } from '@playwright/test'; + +const config: PlaywrightTestConfig = { + // NO global setup for verification tests + use: { + baseURL: 'http://beta.jamkazam.local:4000', + actionTimeout: 10000, + headless: false, + viewport: { width: 1280, height: 720 }, + ignoreHTTPSErrors: true, + video: 'retain-on-failure', + }, + timeout: 120000, // 2 minutes per test + expect: { + timeout: 10000, + }, +}; + +export default config; diff --git a/jam-ui/test/IMPLEMENTATION_APPROACH.md b/jam-ui/test/IMPLEMENTATION_APPROACH.md new file mode 100644 index 000000000..179b76ec1 --- /dev/null +++ b/jam-ui/test/IMPLEMENTATION_APPROACH.md @@ -0,0 +1,429 @@ +# jam-ui Testing Implementation Approach + +## How I Will Achieve the Goal + +### Overview + +You've asked me to verify that jam-ui conforms to the legacy app's API request/response sequence, patterns, and timings by creating comprehensive tests. Here's my structured approach: + +## šŸŽÆ Main Objectives + +1. **API Sequence Verification** - Ensure jam-ui makes identical API calls as legacy app +2. **UI Testing** - Test all components function correctly +3. **E2E Testing** - Verify complete user journeys work end-to-end +4. **Comparison Analysis** - Generate reports showing conformance + +## šŸ“‹ Implementation Strategy + +### Phase 1: Test Infrastructure Setup + +**What I'll Create:** +``` +test/ +ā”œā”€ā”€ utils/ +│ ā”œā”€ā”€ api-interceptor.ts # Intercept & record API calls +│ ā”œā”€ā”€ websocket-monitor.ts # Monitor WebSocket connections +│ ā”œā”€ā”€ sequence-comparator.ts # Compare API sequences +│ └── test-helpers.ts # Shared test utilities +ā”œā”€ā”€ fixtures/ +│ ā”œā”€ā”€ legacy-sequences/ # Copied from verification +│ │ ā”œā”€ā”€ login-sequence.json +│ │ ā”œā”€ā”€ session-creation-sequence.json +│ │ └── session-join-sequence.json +│ ā”œā”€ā”€ users.json # Test user data +│ └── sessions.json # Test session data +``` + +**Purpose:** Reusable infrastructure for all tests + +--- + +### Phase 2: API Verification Tests + +**What I'll Create:** +``` +test/api-verification/ +ā”œā”€ā”€ login-api.spec.ts +ā”œā”€ā”€ session-creation-api.spec.ts +└── session-join-api.spec.ts +``` + +**How They Work:** + +```typescript +// Example: login-api.spec.ts +test('jam-ui login API sequence matches legacy', async ({ page }) => { + const apiCalls = []; + + // Intercept all API requests + page.on('request', req => { + if (req.url().includes('/api/')) { + apiCalls.push({ + method: req.method(), + url: req.url(), + timestamp: Date.now() + }); + } + }); + + // Perform login on jam-ui + await page.goto('http://beta.jamkazam.local:4000/'); + await page.fill('[name="email"]', 'nuwan@jamkazam.com'); + await page.fill('[name="password"]', 'jam123'); + await page.click('button[type="submit"]'); + await page.waitForLoadState('networkidle'); + + // Load expected sequence from legacy verification + const expectedSequence = require('../fixtures/legacy-sequences/login-sequence.json'); + + // Compare sequences + const comparison = compareAPISequences(apiCalls, expectedSequence); + + // Report results + expect(comparison.matches).toBe(true); + if (!comparison.matches) { + console.log('Differences:', comparison.differences); + } +}); +``` + +**What This Validates:** +- āœ… Same API endpoints called +- āœ… Same order of calls +- āœ… Similar timing between calls +- āœ… Request payloads match +- āœ… Responses handled correctly + +--- + +### Phase 3: WebSocket Verification Tests + +**What I'll Create:** +``` +test/websocket-verification/ +ā”œā”€ā”€ ws-connection.spec.ts +└── ws-messages.spec.ts +``` + +**How They Work:** + +```typescript +test('jam-ui establishes correct WebSocket connections', async ({ page }) => { + const wsConnections = []; + + page.on('websocket', ws => { + wsConnections.push({ + url: ws.url(), + timestamp: Date.now() + }); + + ws.on('framereceived', frame => { + // Record messages + }); + }); + + // Perform session join + await joinSession(page); + + // Verify connections + expect(wsConnections).toHaveLength(2); + expect(wsConnections[0].url).toContain('localhost:3060'); + expect(wsConnections[1].url).toContain('jamkazam.local:6767'); +}); +``` + +--- + +### Phase 4: UI Component Tests + +**What I'll Create:** +``` +test/unit/ +ā”œā”€ā”€ LoginForm.test.tsx +ā”œā”€ā”€ SessionCreationForm.test.tsx +└── SessionInterface.test.tsx +``` + +**Framework:** React Testing Library + +**Example:** + +```typescript +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import LoginForm from '../../src/components/auth/LoginForm'; + +test('LoginForm submits credentials correctly', async () => { + const mockLogin = jest.fn(); + + render(); + + fireEvent.change(screen.getByLabelText(/email/i), { + target: { value: 'nuwan@jamkazam.com' } + }); + fireEvent.change(screen.getByLabelText(/password/i), { + target: { value: 'jam123' } + }); + + fireEvent.click(screen.getByRole('button', { name: /sign in/i })); + + await waitFor(() => { + expect(mockLogin).toHaveBeenCalledWith({ + email: 'nuwan@jamkazam.com', + password: 'jam123' + }); + }); +}); +``` + +**What This Validates:** +- āœ… Forms render correctly +- āœ… User interactions work +- āœ… Validation functions properly +- āœ… Error messages display +- āœ… Loading states work + +--- + +### Phase 5: E2E Integration Tests + +**What I'll Create:** +``` +test/e2e/ +ā”œā”€ā”€ complete-session-flow.spec.ts +ā”œā”€ā”€ login-flow.spec.ts +└── session-creation-flow.spec.ts +``` + +**How They Work:** + +```typescript +test('Complete session flow: login → create → join', async ({ page }) => { + // Step 1: Login + await page.goto('http://beta.jamkazam.local:4000/'); + await page.fill('[name="email"]', 'nuwan@jamkazam.com'); + await page.fill('[name="password"]', 'jam123'); + await page.click('button[type="submit"]'); + await expect(page).toHaveURL(/profile|dashboard/); + + // Step 2: Navigate to session creation + await page.click('text=create session'); // Or appropriate selector + await expect(page).toHaveURL(/session.*create/); + + // Step 3: Fill session form + await page.fill('[name="session_name"]', 'Test Session'); + await page.selectOption('[name="session_type"]', 'private'); + await page.click('button[type="submit"]'); + + // Step 4: Verify session interface loads + await expect(page.locator('text=audio inputs')).toBeVisible(); + await expect(page.locator('text=personal mix')).toBeVisible(); + await expect(page.locator('text=LEAVE')).toBeVisible(); + + // Take screenshot for verification + await page.screenshot({ path: 'test-results/e2e-session-complete.png' }); +}); +``` + +--- + +### Phase 6: Comparison & Reporting + +**What I'll Create:** +``` +test/utils/sequence-comparator.ts +``` + +**Features:** +- Compare API call sequences +- Generate visual diff reports +- Highlight missing/extra calls +- Show timing differences +- Export to HTML/JSON + +**Example Report:** +``` +API Sequence Comparison Report +================================ + +Login Flow: + āœ… POST /api/sessions - MATCH + āœ… GET /api/users/{id} - MATCH + āŒ GET /api/shopping_carts - MISSING in jam-ui + āš ļø GET /api/genres - Called later than expected (delay: 200ms) + āœ… GET /api/countries - MATCH + +Session Creation Flow: + āœ… POST /api/sessions - MATCH + āŒ POST /api/sessions/{id}/participants - MISSING + āœ… GET /api/sessions/{id} - MATCH + +Summary: + Total API calls: 68/70 (2 missing) + Sequence match: 85% + Timing variance: ±150ms average +``` + +--- + +## šŸ”§ Technical Implementation Details + +### Test Execution Flow + +``` +1. Load legacy baseline sequences from fixtures +2. Start jam-ui application at beta.jamkazam.local:4000 +3. Execute test scenario (login, create session, join) +4. Capture all API calls and WebSocket messages +5. Compare with legacy baseline +6. Generate comparison report +7. Assert conformance criteria +``` + +### Key Utilities + +**1. API Interceptor** (`test/utils/api-interceptor.ts`) +```typescript +export class APIInterceptor { + private calls: APICall[] = []; + + intercept(page: Page) { + page.on('request', req => this.recordRequest(req)); + page.on('response', res => this.recordResponse(res)); + } + + getCalls(): APICall[] { + return this.calls; + } + + compareWith(expected: APICall[]): ComparisonResult { + // Comparison logic + } +} +``` + +**2. WebSocket Monitor** (`test/utils/websocket-monitor.ts`) +```typescript +export class WebSocketMonitor { + private connections: WSConnection[] = []; + + monitor(page: Page) { + page.on('websocket', ws => { + this.recordConnection(ws); + ws.on('framereceived', frame => this.recordMessage(frame)); + ws.on('framesent', frame => this.recordMessage(frame)); + }); + } + + getConnections(): WSConnection[] { + return this.connections; + } +} +``` + +**3. Sequence Comparator** (`test/utils/sequence-comparator.ts`) +```typescript +export function compareAPISequences( + actual: APICall[], + expected: APICall[] +): ComparisonResult { + return { + matches: checkOrderAndContent(actual, expected), + missing: findMissingCalls(actual, expected), + extra: findExtraCalls(actual, expected), + outOfOrder: findOutOfOrderCalls(actual, expected), + timingVariance: calculateTimingVariance(actual, expected), + report: generateHTMLReport(actual, expected) + }; +} +``` + +--- + +## šŸ“¦ Deliverables + +### 1. Test Files +- āœ… 15-20 test specification files +- āœ… Test utilities and helpers +- āœ… Fixtures with legacy baseline data + +### 2. Reports +- āœ… HTML comparison reports +- āœ… JSON data exports +- āœ… Screenshots at each step +- āœ… HAR files for network traffic + +### 3. Documentation +- āœ… Test execution guide +- āœ… Failure analysis +- āœ… Recommendations for fixes + +--- + +## ā±ļø Execution Timeline + +**Immediate (Now):** +1. Create test infrastructure +2. Set up API interceptors +3. Create fixtures from verification data + +**Phase 1 (30 mins):** +- API verification tests for login + +**Phase 2 (1 hour):** +- API verification tests for session creation/join +- WebSocket tests + +**Phase 3 (1 hour):** +- UI component tests + +**Phase 4 (1 hour):** +- E2E tests + +**Phase 5 (30 mins):** +- Generate reports +- Document findings + +**Total Estimated Time:** 4 hours + +--- + +## šŸ“Š Success Metrics + +### API Conformance +- **Target:** 95%+ API calls match +- **Threshold:** Missing < 5% of calls +- **Timing:** Within ±500ms variance + +### WebSocket Conformance +- **Target:** Both connections established +- **Threshold:** Message count within 10% of legacy + +### UI Functionality +- **Target:** 100% tests passing +- **Threshold:** No critical failures + +### E2E Flow +- **Target:** Complete flow succeeds +- **Threshold:** All assertions pass + +--- + +## šŸš€ Getting Started + +Once you approve this approach, I will: + +1. āœ… Create all test infrastructure files +2. āœ… Implement API verification tests +3. āœ… Implement UI unit tests +4. āœ… Implement E2E tests +5. āœ… Run all tests against jam-ui +6. āœ… Generate comparison reports +7. āœ… Provide detailed findings and recommendations + +**Ready to proceed?** I can start implementing immediately. + +--- + +**Document Status:** Awaiting Approval +**Estimated Implementation Time:** 4 hours +**Expected Outcome:** Comprehensive test suite comparing jam-ui with legacy app diff --git a/jam-ui/test/JAM_UI_TESTING_PLAN.md b/jam-ui/test/JAM_UI_TESTING_PLAN.md new file mode 100644 index 000000000..fb1984913 --- /dev/null +++ b/jam-ui/test/JAM_UI_TESTING_PLAN.md @@ -0,0 +1,272 @@ +# jam-ui Testing Plan - Session Flow Verification + +**Date:** ${new Date().toLocaleString()} +**Objective:** Verify jam-ui conforms to legacy app API sequence, patterns, and timings + +## Overview + +This testing plan compares the new jam-ui React application with the legacy Rails application to ensure: +1. API calls match in sequence, timing, and payloads +2. WebSocket connections are established correctly +3. UI components function as expected +4. End-to-end flow works seamlessly + +## Testing Layers + +### 1. API Sequence Verification Tests +**Purpose:** Ensure jam-ui makes the exact same API calls as the legacy app + +**Approach:** +- Intercept all API requests during user flow +- Compare against captured legacy API sequence +- Verify request order, methods, URLs, and payloads +- Check response handling + +**Test Files:** +- `test/api-verification/login-api.spec.ts` +- `test/api-verification/session-creation-api.spec.ts` +- `test/api-verification/session-join-api.spec.ts` + +### 2. WebSocket Verification Tests +**Purpose:** Ensure WebSocket connections match legacy behavior + +**Approach:** +- Monitor WebSocket connection establishment +- Verify connection URLs and parameters +- Check message sequences +- Validate dual connections (native + server) + +**Test Files:** +- `test/websocket-verification/ws-connection.spec.ts` +- `test/websocket-verification/ws-messages.spec.ts` + +### 3. UI Component Tests +**Purpose:** Test individual UI components in isolation + +**Approach:** +- Unit tests for Login, Session Creation, Session Interface components +- Test user interactions +- Validate form submissions +- Check error handling + +**Test Files:** +- `test/unit/LoginForm.test.tsx` (using React Testing Library) +- `test/unit/SessionCreationForm.test.tsx` +- `test/unit/SessionInterface.test.tsx` + +### 4. E2E Integration Tests +**Purpose:** Test complete user journeys + +**Approach:** +- Full flow from login to session join +- Real browser automation with Playwright +- Visual verification with screenshots +- Performance timing checks + +**Test Files:** +- `test/e2e/complete-session-flow.spec.ts` +- `test/e2e/login-flow.spec.ts` +- `test/e2e/session-creation-flow.spec.ts` + +## Test Environment + +**jam-ui Application:** +- URL: http://beta.jamkazam.local:4000/ +- Credentials: nuwan@jamkazam.com / jam123 + +**Legacy Application:** +- URL: http://www.jamkazam.local:3100/ +- Used for baseline comparison + +## Expected API Sequences (from verification) + +### Login Flow (12 API calls) +``` +POST /api/sessions (or similar login endpoint) +GET /api/users/{user_id} +GET /api/countries +GET /api/shopping_carts +GET /api/jamtracks/purchased +GET /api/teacher_distributions +GET /api/regions +GET /api/genres +GET /api/users/{user_id}/broadcast_notification +``` + +### Session Creation Flow (38 API calls) +``` +# Dashboard reload (Ctrl+Shift+0 or equivalent) +GET /api/users/{user_id} (2x) +GET /api/countries +GET /api/shopping_carts +GET /api/genres (3x) +GET /api/instruments (3x) +GET /api/users/{user_id}/friends (2x) +GET /api/jamtracks/purchased (3x) +GET /api/languages +GET /api/subjects +GET /api/chat (2x) +GET /api/sessions/scheduled +GET /api/users/{user_id}/notifications +GET /api/regions +GET /api/teacher_distributions +GET /api/versioncheck (3x) +GET /api/config/client + +# Session creation +POST /api/sessions +POST /api/sessions/{session_id}/participants +GET /api/sessions/{session_id}/history +GET /api/sessions/{session_id} (3x) +PUT /api/sessions/{session_id}/tracks (3x) +GET /api/chat?...&channel=session&music_session={session_id} +POST /api/users/{user_id}/udp_reachable +GET /api/users/{user_id}/broadcast_notification +``` + +### WebSocket Connections +``` +1. Dashboard connection: ws://www.jamkazam.local:6767/websocket?... +2. Native client: ws://localhost:3060/ +3. Session connection: ws://www.jamkazam.local:6767/websocket?...&client_id=... +``` + +## Test Implementation Strategy + +### Phase 1: Setup & Infrastructure (Day 1) +- [ ] Set up test utilities and helpers +- [ ] Create API interception utilities +- [ ] Create WebSocket monitoring utilities +- [ ] Set up test data fixtures +- [ ] Create comparison utilities for API sequences + +### Phase 2: API Verification Tests (Day 1-2) +- [ ] Login API sequence test +- [ ] Session creation API sequence test +- [ ] Session join API sequence test +- [ ] WebSocket connection tests +- [ ] WebSocket message sequence tests + +### Phase 3: UI Component Tests (Day 2) +- [ ] LoginForm unit tests +- [ ] Session creation form unit tests +- [ ] Session interface component tests + +### Phase 4: E2E Tests (Day 3) +- [ ] Complete login flow E2E +- [ ] Complete session creation flow E2E +- [ ] Complete session join flow E2E +- [ ] Error scenarios and edge cases + +### Phase 5: Documentation & Reporting (Day 3) +- [ ] Test execution guide +- [ ] Failure analysis reports +- [ ] Recommendations for fixes + +## Success Criteria + +### API Compliance +- āœ… All API calls in correct order +- āœ… Request payloads match legacy +- āœ… Response handling is correct +- āœ… Error cases handled properly + +### WebSocket Compliance +- āœ… Connections established to correct endpoints +- āœ… Connection parameters match legacy +- āœ… Message sequences match +- āœ… Dual connections work correctly + +### UI Functionality +- āœ… All forms submit correctly +- āœ… Navigation works as expected +- āœ… Error messages display properly +- āœ… Loading states work correctly + +### E2E Flow +- āœ… User can log in successfully +- āœ… User can create a session +- āœ… User can join a session +- āœ… Session interface loads completely +- āœ… No console errors + +## Test Execution + +### Run All Tests +```bash +npm test +``` + +### Run Specific Test Suites +```bash +# API verification only +npm run test:api + +# UI component tests only +npm run test:unit + +# E2E tests only +npm run test:e2e + +# WebSocket tests only +npm run test:ws +``` + +### Run with Coverage +```bash +npm run test:coverage +``` + +### Run in CI/CD +```bash +npm run test:ci +``` + +## Test Data Management + +### User Accounts +- Primary test user: nuwan@jamkazam.com +- Additional test users from `test/data/users.js` + +### Session Data +- Test session templates in `test/fixtures/sessions.json` +- Mock API responses in `test/fixtures/api-responses.json` + +### Legacy Baseline +- API sequences captured in `test-results/step-verification/` +- Use as reference for comparison + +## Reporting + +### Test Reports Location +- HTML reports: `test-results/html/` +- JSON reports: `test-results/json/` +- Screenshots: `test-results/screenshots/` +- HAR files: `test-results/har/` +- Comparison reports: `test-results/comparison/` + +### Metrics Tracked +1. API call count per flow +2. API call timing/latency +3. WebSocket message count +4. WebSocket connection timing +5. UI rendering time +6. E2E flow completion time +7. Error rates + +## Next Steps + +1. Review this plan +2. Create test utility infrastructure +3. Implement API verification tests +4. Implement UI unit tests +5. Implement E2E tests +6. Run tests and generate reports +7. Analyze discrepancies +8. Provide recommendations for fixes + +--- + +**Status:** Planning Phase +**Estimated Effort:** 3 days +**Priority:** High diff --git a/jam-ui/test/analyze-session-flow.ts b/jam-ui/test/analyze-session-flow.ts new file mode 100644 index 000000000..6dbd7e561 --- /dev/null +++ b/jam-ui/test/analyze-session-flow.ts @@ -0,0 +1,614 @@ +/** + * Analyzes the captured network traffic to document the session join flow + * and create a migration test plan + */ + +import * as fs from 'fs'; +import * as path from 'path'; + +interface ApiCall { + step: string; + method?: string; + url: string; + status?: number; + timestamp: string; +} + +interface WebSocketMessage { + event: string; + payload?: string; + url?: string; + timestamp: string; +} + +function analyzeApiCalls(apiCalls: ApiCall[]): Map { + const apiMap = new Map(); + + for (const call of apiCalls) { + if (call.step === 'REQUEST' && call.url.includes('/api/')) { + // Extract the API endpoint path + const url = new URL(call.url); + const endpoint = `${call.method} ${url.pathname}`; + + if (!apiMap.has(endpoint)) { + apiMap.set(endpoint, []); + } + apiMap.get(endpoint)!.push(call); + } + } + + return apiMap; +} + +function analyzeWebSocketMessages(wsMessages: WebSocketMessage[]): Map { + const messageTypes = new Map(); + + for (const msg of wsMessages) { + if (msg.event === 'sent' || msg.event === 'received') { + try { + const payload = JSON.parse(msg.payload || '{}'); + + // Extract message type or method name + let messageType = 'unknown'; + + if (payload.type) { + messageType = `TYPE:${payload.type}`; + } else if (payload.method) { + messageType = `METHOD:${payload.method}`; + } else if (payload.args && payload.args.length > 0) { + // Try to parse the args to get more info + try { + const argsData = JSON.parse(payload.args[0]); + if (argsData.method_name) { + messageType = `NATIVE_METHOD:${argsData.method_name}`; + } else if (argsData.event_id) { + messageType = `NATIVE_EVENT:${argsData.event_id}`; + } + } catch (e) { + // Ignore parse errors + } + } + + messageTypes.set(messageType, (messageTypes.get(messageType) || 0) + 1); + } catch (e) { + // Ignore JSON parse errors + } + } + } + + return messageTypes; +} + +function extractSequentialFlow(apiCalls: ApiCall[], wsMessages: WebSocketMessage[]): any[] { + // Combine and sort by timestamp + const allEvents = [ + ...apiCalls.map(call => ({ + type: call.step, + subtype: 'API', + method: call.method, + url: call.url, + status: call.status, + timestamp: new Date(call.timestamp).getTime(), + })), + ...wsMessages.filter(msg => msg.event === 'sent' || msg.event === 'received').map(msg => ({ + type: msg.event === 'sent' ? 'WS_SENT' : 'WS_RECEIVED', + subtype: 'WEBSOCKET', + payload: msg.payload?.substring(0, 200), + timestamp: new Date(msg.timestamp).getTime(), + })), + ].sort((a, b) => a.timestamp - b.timestamp); + + return allEvents; +} + +function main() { + const testResultsDir = path.join(__dirname, '../test-results'); + + console.log('='.repeat(80)); + console.log('SESSION JOIN FLOW ANALYSIS'); + console.log('='.repeat(80)); + console.log(); + + // Read API calls + const apiCallsPath = path.join(testResultsDir, 'api-calls.json'); + const apiCalls: ApiCall[] = JSON.parse(fs.readFileSync(apiCallsPath, 'utf-8')); + console.log(`āœ“ Loaded ${apiCalls.length} API call records`); + + // Read WebSocket messages + const wsMessagesPath = path.join(testResultsDir, 'websocket-messages.json'); + const wsMessages: WebSocketMessage[] = JSON.parse(fs.readFileSync(wsMessagesPath, 'utf-8')); + console.log(`āœ“ Loaded ${wsMessages.length} WebSocket message records`); + console.log(); + + // Analyze API calls + console.log('API ENDPOINTS CALLED'); + console.log('-'.repeat(80)); + const apiMap = analyzeApiCalls(apiCalls); + const sortedApis = Array.from(apiMap.entries()).sort((a, b) => b[1].length - a[1].length); + + for (const [endpoint, calls] of sortedApis) { + console.log(` ${endpoint.padEnd(60)} (${calls.length} calls)`); + } + console.log(); + + // Analyze WebSocket messages + console.log('WEBSOCKET MESSAGE TYPES'); + console.log('-'.repeat(80)); + const messageTypes = analyzeWebSocketMessages(wsMessages); + const sortedTypes = Array.from(messageTypes.entries()).sort((a, b) => b[1] - a[1]); + + for (const [type, count] of sortedTypes.slice(0, 20)) { + console.log(` ${type.padEnd(60)} (${count} times)`); + } + console.log(` ... and ${sortedTypes.length - 20} more message types`); + console.log(); + + // Generate migration plan + const planPath = path.join(testResultsDir, 'SESSION_MIGRATION_PLAN.md'); + + const plan = `# Session Join Flow Migration Test Plan + +## Overview + +This document outlines the complete test plan for migrating the "Joining a Music Session" feature from the legacy JamKazam application to the new React-based jam-ui application. + +**Captured on:** ${new Date().toISOString()} +**Legacy URL:** http://www.jamkazam.local:3100 +**Target:** jam-ui React application + +## Overview of Flow + +The session join flow consists of 5 main steps: +1. User Authentication (login) +2. Dashboard Load (with WebSocket connection to native client) +3. Skip Upgrade Modal (keyboard shortcut) +4. Navigate to Create Session +5. Create Quick Start Session (joins the session) + +Note: The Ctrl+Shift+0 keyboard shortcut for enabling native client features is handled during session creation (Step 5), not as a separate step. + +## Session Join Flow Steps + +### Step 1: User Authentication +**Description:** User logs into the application + +**API Calls Required:** +- POST /api/sessions (login endpoint) +- GET /api/users/{user_id} (fetch user profile) +- GET /api/genres (load genre data) +- GET /api/countries (load country data) + +**Test Requirements:** +- Verify authentication token is stored in cookies +- Verify user session is established +- Verify redirect to dashboard after successful login + +--- + +### Step 2: Dashboard Load +**Description:** Load user dashboard with all necessary data + +**API Calls Required:** +${Array.from(apiMap.entries()) + .filter(([endpoint]) => !endpoint.includes('paypal') && !endpoint.includes('session_create')) + .slice(0, 20) + .map(([endpoint]) => `- ${endpoint}`) + .join('\n')} + +**WebSocket Connection:** +- Establish WebSocket connection to native client (ws://localhost:3060/) +- Initialize jkfrontendchannel communication +- Exchange handshake messages + +**Native Client Messages:** +${Array.from(messageTypes.entries()) + .filter(([type]) => type.startsWith('NATIVE_METHOD:')) + .slice(0, 10) + .map(([type, count]) => `- ${type} (${count} times)`) + .join('\n')} + +**Test Requirements:** +- Verify all dashboard data loads correctly +- Verify WebSocket connection establishes successfully +- Verify native client communication is functional +- Verify user can see friends, notifications, and session options + +--- + +### Step 3: Skip Upgrade Modal +**Description:** Handle upgrade modal on dashboard + +**User Action:** Press Cmd+Shift+0 (Mac) or Ctrl+Shift+0 (Windows) + +**API Calls Made:** +- GET /api/versioncheck + +**WebSocket Connection Established:** +- Opens WebSocket connection to server: `ws://www.jamkazam.local:6767/websocket?channel_id=...&client_type=browser...` +- This is a CRITICAL connection - not just a UI interaction +- Approximately 100 WebSocket messages exchanged during initialization + +**Expected Behavior:** +- Upgrade modal dismisses +- Server WebSocket connection established +- User can interact with dashboard + +**Test Requirements:** +- Verify keyboard shortcut works +- Verify modal closes without errors +- **Verify WebSocket connection to server is established** +- Verify dashboard remains functional + +--- + +### Step 4: Navigate to Create Session +**Description:** User clicks "Create Session" tile + +**API Calls Made:** +- GET /api/sessions/scheduled (fetch any scheduled sessions) +- GET /api/users/{user_id} (refresh user profile) +- GET /api/jamtracks/purchased (refresh purchased tracks) + +**Expected Behavior:** +- Navigate to session creation page +- Load session creation UI +- Maintain existing WebSocket connection from Step 3 +- Load list of scheduled sessions + +**Test Requirements:** +- Verify navigation occurs +- Verify session creation options are visible +- Verify scheduled sessions are loaded +- Verify no API errors occur +- Verify WebSocket connection remains active + +--- + +### Step 5: Create Quick Start Session +**Description:** User creates a quick start session + +**User Action:** Press Ctrl+Shift+0 to enable native client features, then click "Create Quick Start" button + +**API Calls Made (28 total):** + +**Critical New API Call:** +- **POST /api/users/{user_id}/udp_reachable** - Reports UDP reachability for P2P connections + +**Dashboard Data Reload (triggered by Ctrl+Shift+0):** +- GET /api/users/{user_id} (2 times) +- GET /api/countries +- GET /api/shopping_carts +- GET /api/genres (3 times) +- GET /api/instruments (3 times) +- GET /api/users/{user_id}/friends (2 times) +- GET /api/jamtracks/purchased (3 times) +- GET /api/languages +- GET /api/subjects +- GET /api/chat +- GET /api/sessions/scheduled +- GET /api/users/{user_id}/notifications +- GET /api/regions +- GET /api/versioncheck (3 times) +- GET /api/teacher_distributions +- GET /api/config/client +- GET /api/users/{user_id}/broadcast_notification + +**Expected Session Creation API Calls:** +- POST /api/music_sessions (create session) +- GET /api/music_sessions/{session_id} (fetch session details) +- GET /api/music_sessions/{session_id}/participants (fetch participants) + +**WebSocket Connections Established:** + +1. **Native Client Connection:** + - URL: `ws://localhost:3060/` + - Purpose: Audio/video streaming and control + - ~100+ messages during initialization + +2. **Server Connection:** + - URL: `ws://www.jamkazam.local:6767/websocket?channel_id=...&client_id=...` + - Purpose: Session coordination and real-time updates + - ~100+ messages during initialization + +**Key Native Client Operations:** +- NetworkTestResult calls +- getConnectionDetail calls +- SetLatencyTestBlocked +- SetScoreWorkTimingInterval + +**Important Notes:** +- Pressing Ctrl+Shift+0 essentially "reinitializes" the client +- It triggers a full dashboard data reload +- It establishes BOTH WebSocket connections simultaneously +- UDP reachability check is performed before session creation + +**Test Requirements:** +- Verify Ctrl+Shift+0 triggers dashboard data reload +- Verify POST /api/users/{user_id}/udp_reachable is called +- Verify native client WebSocket connection (ws://localhost:3060/) +- Verify server WebSocket connection is established +- Verify session is created successfully +- Verify session ID is returned +- Verify WebSocket messages are exchanged correctly +- Verify user enters session interface +- Verify audio setup begins + +--- + +## Complete API Endpoint Reference + +### Authentication & User Management +${Array.from(apiMap.entries()) + .filter(([endpoint]) => endpoint.includes('/users') || endpoint.includes('/session')) + .map(([endpoint, calls]) => `- ${endpoint} (called ${calls.length} times)`) + .join('\n')} + +### Static Data Loading +${Array.from(apiMap.entries()) + .filter(([endpoint]) => + endpoint.includes('/genres') || + endpoint.includes('/instruments') || + endpoint.includes('/countries') || + endpoint.includes('/languages') || + endpoint.includes('/regions') + ) + .map(([endpoint, calls]) => `- ${endpoint} (called ${calls.length} times)`) + .join('\n')} + +### Session Management +${Array.from(apiMap.entries()) + .filter(([endpoint]) => endpoint.includes('/music_session')) + .map(([endpoint, calls]) => `- ${endpoint} (called ${calls.length} times)`) + .join('\n')} + +### Real-time Features +${Array.from(apiMap.entries()) + .filter(([endpoint]) => + endpoint.includes('/chat') || + endpoint.includes('/notification') || + endpoint.includes('/broadcast') + ) + .map(([endpoint, calls]) => `- ${endpoint} (called ${calls.length} times)`) + .join('\n')} + +### System Health +${Array.from(apiMap.entries()) + .filter(([endpoint]) => + endpoint.includes('/healthcheck') || + endpoint.includes('/versioncheck') || + endpoint.includes('/config') + ) + .map(([endpoint, calls]) => `- ${endpoint} (called ${calls.length} times)`) + .join('\n')} + +--- + +## WebSocket Message Types Reference + +### Connection & Handshake +${Array.from(messageTypes.entries()) + .filter(([type]) => type.includes('TYPE:')) + .map(([type, count]) => `- ${type} (${count} messages)`) + .join('\n')} + +### Native Client Methods (Most Frequent) +${Array.from(messageTypes.entries()) + .filter(([type]) => type.startsWith('NATIVE_METHOD:')) + .slice(0, 15) + .map(([type, count]) => `- ${type} (${count} calls)`) + .join('\n')} + +### Native Client Events +${Array.from(messageTypes.entries()) + .filter(([type]) => type.startsWith('NATIVE_EVENT:')) + .slice(0, 10) + .map(([type, count]) => `- ${type} (${count} events)`) + .join('\n')} + +--- + +## Playwright Test Structure + +### Test 1: Complete Session Join Flow +\`\`\`typescript +test('User can join a music session - complete flow', async ({ page }) => { + // Step 1: Login + await loginUser(page, 'user@example.com', 'password'); + + // Step 2: Wait for dashboard to load + await expect(page.locator('[data-testid="dashboard"]')).toBeVisible(); + + // Step 3: Skip upgrade modal + await page.keyboard.press('Meta+Shift+Digit0'); + + // Step 4: Click create session + await page.click('[data-testid="create-session"]'); + + // Step 5: Create quick start session (Ctrl+Shift+0 handled internally) + await page.keyboard.press('Control+Shift+Digit0'); + await page.click('[data-testid="quick-start"]'); + + // Verify we're in session + await expect(page.locator('[data-testid="session-interface"]')).toBeVisible(); +}); +\`\`\` + +### Test 2: API Calls Validation +\`\`\`typescript +test('Session join makes correct API calls', async ({ page }) => { + const apiCalls: string[] = []; + + page.on('request', request => { + if (request.url().includes('/api/')) { + apiCalls.push(\`\${request.method()} \${new URL(request.url()).pathname}\`); + } + }); + + await joinSession(page); + + // Verify critical API calls were made + expect(apiCalls).toContain('GET /api/users/'); + expect(apiCalls).toContain('GET /api/genres'); + expect(apiCalls).toContain('POST /api/music_sessions'); +}); +\`\`\` + +### Test 3: WebSocket Communication +\`\`\`typescript +test('Session join establishes WebSocket connection', async ({ page }) => { + let wsConnected = false; + let messagesReceived = 0; + + page.on('websocket', ws => { + wsConnected = true; + ws.on('framereceived', () => messagesReceived++); + }); + + await joinSession(page); + + expect(wsConnected).toBe(true); + expect(messagesReceived).toBeGreaterThan(0); +}); +\`\`\` + +### Test 4: Native Client Integration +\`\`\`typescript +test('Native client methods are called correctly', async ({ page }) => { + const nativeMethods: string[] = []; + + page.on('websocket', ws => { + ws.on('framesent', frame => { + try { + const data = JSON.parse(frame.payload.toString()); + if (data.args) { + const argsData = JSON.parse(data.args[0]); + if (argsData.method_name) { + nativeMethods.push(argsData.method_name); + } + } + } catch (e) {} + }); + }); + + await joinSession(page); + + // Verify critical native methods were called + expect(nativeMethods).toContain('getConnectionDetail'); + expect(nativeMethods).toContain('NetworkTestResult'); +}); +\`\`\` + +--- + +## Implementation Checklist + +### Phase 1: Authentication & Dashboard +- [ ] Implement login flow matching legacy API calls +- [ ] Load all dashboard data (users, genres, instruments, etc.) +- [ ] Establish WebSocket connection to native client +- [ ] Implement upgrade modal with keyboard shortcut (Cmd/Ctrl+Shift+0) +- [ ] Implement dashboard UI with session creation option +- [ ] Test: User can log in, dismiss modal, and see dashboard + +### Phase 2: Session Creation UI +- [ ] Implement "Create Session" navigation +- [ ] Implement session creation modal/page +- [ ] Implement keyboard shortcut (Ctrl+Shift+0) for enabling native features +- [ ] Implement "Quick Start" option +- [ ] Test: User can navigate to session creation and see options + +### Phase 3: Native Client Integration +- [ ] Establish WebSocket communication protocol +- [ ] Implement native client message handlers +- [ ] Implement handshake and initialization sequence +- [ ] Test: WebSocket messages match legacy exactly + +### Phase 4: Session Creation & Join +- [ ] Implement session creation API calls +- [ ] Handle session initialization responses +- [ ] Implement session interface loading +- [ ] Coordinate WebSocket messages with session creation +- [ ] Test: Complete flow works end-to-end + +### Phase 5: Audio/Video Setup +- [ ] Implement audio device initialization via native client +- [ ] Implement latency testing (NetworkTestResult) +- [ ] Implement connection detail fetching (getConnectionDetail) +- [ ] Handle real-time audio/video stream setup +- [ ] Test: Audio setup completes successfully + +--- + +## Critical Success Criteria + +1. **API Compatibility**: All API calls must match the sequence and format of the legacy application +2. **WebSocket Protocol**: WebSocket messages must be identical in structure and timing +3. **Native Client Communication**: Native client method calls must match exactly +4. **User Experience**: Flow must be seamless with no additional steps +5. **Error Handling**: Must handle all error cases gracefully +6. **Performance**: Page loads and transitions must be as fast or faster than legacy + +--- + +## Testing Strategy + +### Unit Tests +- Test individual API call functions +- Test WebSocket message handlers +- Test UI component rendering + +### Integration Tests +- Test complete authentication flow +- Test dashboard data loading +- Test session creation flow + +### End-to-End Tests (Playwright) +- Test complete user journey from login to session join +- Test with real WebSocket connections +- Test with native client simulation + +### Comparison Tests +- Run legacy and new app side-by-side +- Compare API call sequences +- Compare WebSocket message sequences +- Compare timing and performance + +--- + +## Files Generated + +- \`test-results/session-join-flow.har\` - Complete HAR file with all network traffic +- \`test-results/api-calls.json\` - All API calls made during the flow +- \`test-results/websocket-messages.json\` - All WebSocket messages exchanged +- \`test-results/all-network-activity.json\` - Combined network activity log +- \`test-results/*.png\` - Screenshots at various stages + +--- + +## Next Steps + +1. Review this plan with the team +2. Prioritize which components to implement first +3. Set up Playwright test infrastructure +4. Begin implementing Phase 1 (Authentication & Dashboard) +5. Write corresponding Playwright tests for each phase +6. Run comparison tests against legacy application +7. Iterate until behavior matches exactly + +--- + +**Generated by:** Session Flow Analyzer +**Date:** ${new Date().toLocaleString()} +**Total API Calls Captured:** ${apiCalls.length} +**Total WebSocket Messages Captured:** ${wsMessages.length} +**Unique API Endpoints:** ${apiMap.size} +**Unique WebSocket Message Types:** ${messageTypes.size} +`; + + fs.writeFileSync(planPath, plan); + console.log(`āœ… Migration plan written to: ${planPath}`); + console.log(); + console.log('Review the plan and adjust as needed for your specific requirements.'); +} + +main(); diff --git a/jam-ui/test/analyze-steps.js b/jam-ui/test/analyze-steps.js new file mode 100644 index 000000000..e5c4839be --- /dev/null +++ b/jam-ui/test/analyze-steps.js @@ -0,0 +1,59 @@ +const fs = require('fs'); +const path = require('path'); + +const stepsDir = path.join(__dirname, '../test-results/step-verification'); + +console.log('='.repeat(80)); +console.log('STEP-BY-STEP API CALL ANALYSIS'); +console.log('='.repeat(80)); +console.log(); + +for (let i = 1; i <= 5; i++) { + const stepDir = path.join(stepsDir, `step-${i}`); + const apiFile = path.join(stepDir, 'api-calls.json'); + const wsFile = path.join(stepDir, 'ws-messages.json'); + + if (!fs.existsSync(apiFile)) { + console.log(`Step ${i}: No data captured (step not completed)`); + console.log(); + continue; + } + + const apiCalls = JSON.parse(fs.readFileSync(apiFile, 'utf-8')); + const wsMessages = JSON.parse(fs.readFileSync(wsFile, 'utf-8')); + + const requests = apiCalls.filter(c => c.type === 'request'); + const uniqueEndpoints = new Set(); + + requests.forEach(r => { + try { + const url = new URL(r.url); + uniqueEndpoints.add(`${r.method} ${url.pathname}`); + } catch (e) { + // Skip invalid URLs + } + }); + + console.log(`STEP ${i}:`); + console.log(` Total API requests: ${requests.length}`); + console.log(` Unique endpoints: ${uniqueEndpoints.size}`); + console.log(` WebSocket messages: ${wsMessages.length}`); + console.log(); + console.log(' Unique API endpoints called:'); + + Array.from(uniqueEndpoints).forEach(endpoint => { + const count = requests.filter(r => { + try { + const url = new URL(r.url); + return `${r.method} ${url.pathname}` === endpoint; + } catch (e) { + return false; + } + }).length; + console.log(` ${endpoint}${count > 1 ? ` (${count} times)` : ''}`); + }); + + console.log(); + console.log('-'.repeat(80)); + console.log(); +} diff --git a/jam-ui/test/api-verification/login-api.spec.ts b/jam-ui/test/api-verification/login-api.spec.ts new file mode 100644 index 000000000..3c9e7f635 --- /dev/null +++ b/jam-ui/test/api-verification/login-api.spec.ts @@ -0,0 +1,148 @@ +import { test, expect } from '@playwright/test'; +import { APIInterceptor } from '../utils/api-interceptor'; +import { compareAPISequences } from '../utils/sequence-comparator'; +import { loginToJamUI, waitForAPICalls } from '../utils/test-helpers'; +import * as fs from 'fs'; +import * as path from 'path'; + +test.describe('Login API Verification', () => { + test('jam-ui login makes same API calls as legacy app', async ({ page }) => { + const apiInterceptor = new APIInterceptor(); + apiInterceptor.intercept(page); + + // Perform login + await loginToJamUI(page, { + email: 'nuwan@jamkazam.com', + password: 'jam123', + }); + + await waitForAPICalls(page, 5000); + + // Get captured calls + const actualCalls = apiInterceptor.getCalls(); + + // Load expected sequence + const expectedPath = path.join(__dirname, '../fixtures/legacy-sequences/login-simplified.json'); + const expectedCalls = JSON.parse(fs.readFileSync(expectedPath, 'utf8')); + + console.log(`\nLogin API Verification:`); + console.log(` Actual calls: ${actualCalls.length}`); + console.log(` Expected calls: ${expectedCalls.length}`); + + // Compare sequences + const comparison = compareAPISequences(actualCalls, expectedCalls); + + // Log comparison report + console.log('\n' + comparison.report); + + // Save results + const resultsDir = path.join(__dirname, '../test-results/api-verification'); + if (!fs.existsSync(resultsDir)) { + fs.mkdirSync(resultsDir, { recursive: true }); + } + + fs.writeFileSync( + path.join(resultsDir, 'login-actual-calls.json'), + JSON.stringify(actualCalls, null, 2) + ); + + fs.writeFileSync( + path.join(resultsDir, 'login-comparison-report.md'), + comparison.report + ); + + // Assert that we have critical login endpoints + const endpoints = apiInterceptor.getUniqueEndpoints(); + + // Critical endpoints that MUST be present + expect(endpoints.some(e => e.includes('/api/users/'))).toBe(true); + expect(endpoints.some(e => e.includes('/api/genres'))).toBe(true); + expect(endpoints.some(e => e.includes('/api/countries'))).toBe(true); + + // Check if match percentage is acceptable + const matchPercentage = (comparison.matchedCalls / comparison.totalCalls) * 100; + console.log(`\nMatch percentage: ${matchPercentage.toFixed(1)}%`); + + // We expect at least 80% match for login flow + expect(matchPercentage).toBeGreaterThanOrEqual(80); + }); + + test('login API calls are in correct order', async ({ page }) => { + const apiInterceptor = new APIInterceptor(); + apiInterceptor.intercept(page); + + await loginToJamUI(page); + await waitForAPICalls(page); + + const actualCalls = apiInterceptor.getCalls(); + const expectedPath = path.join(__dirname, '../fixtures/legacy-sequences/login-simplified.json'); + const expectedCalls = JSON.parse(fs.readFileSync(expectedPath, 'utf8')); + + const comparison = compareAPISequences(actualCalls, expectedCalls); + + // Check for significant order issues + if (comparison.outOfOrderCalls.length > 0) { + console.log('\nOut of order calls detected:'); + for (const order of comparison.outOfOrderCalls) { + console.log(` ${order.endpoint}: deviation of ${order.deviation} positions`); + } + } + + // Allow some flexibility in ordering, but not too much + const maxDeviationAllowed = 5; + const significantDeviations = comparison.outOfOrderCalls.filter( + o => o.deviation > maxDeviationAllowed + ); + + expect(significantDeviations.length).toBe(0); + }); + + test('login makes POST request to create session', async ({ page }) => { + const apiInterceptor = new APIInterceptor(); + apiInterceptor.intercept(page); + + await loginToJamUI(page); + await waitForAPICalls(page); + + const postCalls = apiInterceptor.getCallsByMethod('POST'); + + // Should have POST to /api/sessions or similar login endpoint + const sessionPost = postCalls.find(call => + call.pathname.includes('/api/session') || + call.pathname.includes('/api/auth') || + call.pathname.includes('/api/login') + ); + + // Note: Legacy app uses Rails sessions, so this might not be present + // Just log what we find + console.log('\nPOST calls during login:'); + postCalls.forEach(call => { + console.log(` ${call.method} ${call.pathname}`); + }); + }); + + test('login retrieves user data', async ({ page }) => { + const apiInterceptor = new APIInterceptor(); + apiInterceptor.intercept(page); + + await loginToJamUI(page); + await waitForAPICalls(page); + + const userCalls = apiInterceptor.getCallsByPath('/api/users/'); + + expect(userCalls.length).toBeGreaterThan(0); + + // Should have successful response + const successfulUserCall = userCalls.find(call => + call.responseStatus && call.responseStatus >= 200 && call.responseStatus < 300 + ); + + expect(successfulUserCall).toBeDefined(); + + if (successfulUserCall?.responseBody) { + console.log('\nUser data received:'); + console.log(` User ID: ${successfulUserCall.responseBody.id || 'N/A'}`); + console.log(` Email: ${successfulUserCall.responseBody.email || 'N/A'}`); + } + }); +}); diff --git a/jam-ui/test/api-verification/session-creation-api.spec.ts b/jam-ui/test/api-verification/session-creation-api.spec.ts new file mode 100644 index 000000000..a4ba3ed96 --- /dev/null +++ b/jam-ui/test/api-verification/session-creation-api.spec.ts @@ -0,0 +1,207 @@ +import { test, expect } from '@playwright/test'; +import { APIInterceptor } from '../utils/api-interceptor'; +import { compareAPISequences } from '../utils/sequence-comparator'; +import { loginToJamUI, navigateToSessionCreation, fillSessionForm, waitForAPICalls } from '../utils/test-helpers'; +import * as fs from 'fs'; +import * as path from 'path'; + +test.describe('Session Creation API Verification', () => { + test('session creation makes all required API calls', async ({ page }) => { + const apiInterceptor = new APIInterceptor(); + apiInterceptor.intercept(page); + + // Login first + await loginToJamUI(page); + await waitForAPICalls(page); + + // Clear captured calls from login + apiInterceptor.reset(); + + // Navigate to session creation and fill form (jam-ui approach) + await navigateToSessionCreation(page); + await waitForAPICalls(page); + + // Fill and submit session creation form + await fillSessionForm(page, { sessionType: 'private' }); + await waitForAPICalls(page, 5000); + + // Get captured calls + const actualCalls = apiInterceptor.getCalls(); + + // Load expected sequence (Step 5 from verification) + const expectedPath = path.join(__dirname, '../fixtures/legacy-sequences/session-creation-simplified.json'); + const expectedCalls = JSON.parse(fs.readFileSync(expectedPath, 'utf8')); + + console.log(`\nSession Creation API Verification:`); + console.log(` Actual calls: ${actualCalls.length}`); + console.log(` Expected calls: ${expectedCalls.length}`); + + // Compare sequences + const comparison = compareAPISequences(actualCalls, expectedCalls); + + // Log comparison report + console.log('\n' + comparison.report); + + // Save results + const resultsDir = path.join(__dirname, '../test-results/api-verification'); + if (!fs.existsSync(resultsDir)) { + fs.mkdirSync(resultsDir, { recursive: true }); + } + + fs.writeFileSync( + path.join(resultsDir, 'session-creation-actual-calls.json'), + JSON.stringify(actualCalls, null, 2) + ); + + fs.writeFileSync( + path.join(resultsDir, 'session-creation-comparison-report.md'), + comparison.report + ); + + // Critical session creation endpoints + const endpoints = apiInterceptor.getUniqueEndpoints(); + + // Must have session creation + expect(endpoints.some(e => e.includes('POST /api/sessions'))).toBe(true); + + // Check match percentage + const matchPercentage = (comparison.matchedCalls / comparison.totalCalls) * 100; + console.log(`\nMatch percentage: ${matchPercentage.toFixed(1)}%`); + + // We expect at least 70% match (allowing for some differences) + expect(matchPercentage).toBeGreaterThanOrEqual(70); + }); + + test('session creation sequence includes critical endpoints', async ({ page }) => { + const apiInterceptor = new APIInterceptor(); + apiInterceptor.intercept(page); + + await loginToJamUI(page); + await waitForAPICalls(page); + apiInterceptor.reset(); + + await navigateToSessionCreation(page); + await waitForAPICalls(page); + await fillSessionForm(page); + await waitForAPICalls(page, 5000); + + const calls = apiInterceptor.getCalls(); + + // Find critical session endpoints + const sessionCreation = calls.find(c => + c.method === 'POST' && c.pathname.match(/\/api\/sessions\/?$/) + ); + + const participantAdd = calls.find(c => + c.method === 'POST' && c.pathname.includes('/participants') + ); + + const sessionHistory = calls.find(c => + c.method === 'GET' && c.pathname.includes('/history') + ); + + const sessionGet = calls.find(c => + c.method === 'GET' && c.pathname.match(/\/api\/sessions\/[a-f0-9-]+\/?$/) + ); + + const tracksUpdate = calls.find(c => + c.method === 'PUT' && c.pathname.includes('/tracks') + ); + + const sessionChat = calls.find(c => + c.method === 'GET' && + c.pathname.includes('/chat') && + c.url.includes('music_session') + ); + + const udpReachable = calls.find(c => + c.method === 'POST' && c.pathname.includes('/udp_reachable') + ); + + console.log('\nCritical session endpoints found:'); + console.log(` āœ“ POST /api/sessions: ${sessionCreation ? 'YES' : 'NO'}`); + console.log(` āœ“ POST /api/sessions/{id}/participants: ${participantAdd ? 'YES' : 'NO'}`); + console.log(` āœ“ GET /api/sessions/{id}/history: ${sessionHistory ? 'YES' : 'NO'}`); + console.log(` āœ“ GET /api/sessions/{id}: ${sessionGet ? 'YES' : 'NO'}`); + console.log(` āœ“ PUT /api/sessions/{id}/tracks: ${tracksUpdate ? 'YES' : 'NO'}`); + console.log(` āœ“ GET /api/chat?...music_session=: ${sessionChat ? 'YES' : 'NO'}`); + console.log(` āœ“ POST /api/users/{id}/udp_reachable: ${udpReachable ? 'YES' : 'NO'}`); + + // All critical endpoints should be present + expect(sessionCreation).toBeDefined(); + expect(participantAdd).toBeDefined(); + expect(sessionHistory).toBeDefined(); + expect(sessionGet).toBeDefined(); + expect(tracksUpdate).toBeDefined(); + expect(udpReachable).toBeDefined(); + }); + + test('session is created with valid session ID', async ({ page }) => { + const apiInterceptor = new APIInterceptor(); + apiInterceptor.intercept(page); + + await loginToJamUI(page); + await waitForAPICalls(page); + apiInterceptor.reset(); + + await navigateToSessionCreation(page); + await waitForAPICalls(page); + await fillSessionForm(page); + await waitForAPICalls(page, 5000); + + const calls = apiInterceptor.getCalls(); + + // Find the POST /api/sessions call + const sessionCreation = calls.find(c => + c.method === 'POST' && c.pathname.match(/\/api\/sessions\/?$/) + ); + + expect(sessionCreation).toBeDefined(); + + // Check if response contains session ID + if (sessionCreation?.responseBody) { + const sessionId = sessionCreation.responseBody.id || sessionCreation.responseBody.session_id; + + console.log(`\nSession created with ID: ${sessionId}`); + + // Verify it's a valid UUID + expect(sessionId).toMatch(/^[a-f0-9-]{36}$/i); + + // Verify subsequent calls use this session ID + const sessionSpecificCalls = calls.filter(c => + c.pathname.includes(sessionId) + ); + + console.log(`Subsequent calls using session ID: ${sessionSpecificCalls.length}`); + expect(sessionSpecificCalls.length).toBeGreaterThan(0); + } + }); + + test('session form loads reference data', async ({ page }) => { + const apiInterceptor = new APIInterceptor(); + apiInterceptor.intercept(page); + + await loginToJamUI(page); + await waitForAPICalls(page); + apiInterceptor.reset(); + + await navigateToSessionCreation(page); + await waitForAPICalls(page, 3000); + + const calls = apiInterceptor.getCalls(); + + // Check what reference data is loaded for the session creation form + const genres = calls.filter(c => c.pathname.includes('/api/genres')); + const instruments = calls.filter(c => c.pathname.includes('/api/instruments')); + const friends = calls.filter(c => c.pathname.includes('/friends')); + + console.log('\nSession form API calls:'); + console.log(` /api/genres: ${genres.length} calls`); + console.log(` /api/instruments: ${instruments.length} calls`); + console.log(` /api/users/{id}/friends: ${friends.length} calls`); + + // jam-ui may load reference data differently than legacy + // Just verify the page loaded successfully + expect(calls.length).toBeGreaterThan(0); + }); +}); diff --git a/jam-ui/test/api-verification/session-join-comparison.spec.ts b/jam-ui/test/api-verification/session-join-comparison.spec.ts new file mode 100644 index 000000000..72941964d --- /dev/null +++ b/jam-ui/test/api-verification/session-join-comparison.spec.ts @@ -0,0 +1,226 @@ +import { test, expect } from '@playwright/test'; +import { APIInterceptor } from '../utils/api-interceptor'; +import { WebSocketMonitor } from '../utils/websocket-monitor'; +import { loginToJamUI, navigateToSessionCreation, fillSessionForm, waitForAPICalls } from '../utils/test-helpers'; +import * as fs from 'fs'; +import * as path from 'path'; + +test.describe('Session Join Flow - Detailed API Comparison', () => { + test('capture complete session join API calls (jam-ui)', async ({ page }) => { + const apiInterceptor = new APIInterceptor(); + const wsMonitor = new WebSocketMonitor(); + + apiInterceptor.intercept(page); + wsMonitor.monitor(page); + + console.log('\n========================================'); + console.log('SESSION JOIN FLOW - API CAPTURE'); + console.log('========================================\n'); + + // Login first + await loginToJamUI(page); + await waitForAPICalls(page, 3000); + + // Navigate to session creation + await navigateToSessionCreation(page); + await waitForAPICalls(page, 2000); + + console.log('Starting session creation + join flow...\n'); + + // Clear previous calls - we only want session join calls + apiInterceptor.reset(); + const wsConnectionsBefore = wsMonitor.getConnectionCount(); + + // Create and join session + await fillSessionForm(page, { sessionType: 'private' }); + await waitForAPICalls(page, 8000); + + // Capture all data + const apiCalls = apiInterceptor.getCalls(); + const wsConnections = wsMonitor.getConnections(); + const newWsConnections = wsConnections.slice(wsConnectionsBefore); + + console.log('========================================'); + console.log('SESSION JOIN API CALLS (jam-ui)'); + console.log('========================================\n'); + + // Group API calls by type + const sessionCreationCalls = apiCalls.filter(c => + c.method === 'POST' && c.pathname.match(/\/api\/sessions\/?$/) + ); + + const participantCalls = apiCalls.filter(c => + c.pathname.includes('/participants') + ); + + const sessionDetailCalls = apiCalls.filter(c => + c.method === 'GET' && c.pathname.match(/\/api\/sessions\/[a-f0-9-]+\/?$/) + ); + + const sessionHistoryCalls = apiCalls.filter(c => + c.pathname.includes('/history') + ); + + const trackCalls = apiCalls.filter(c => + c.pathname.includes('/tracks') + ); + + const chatCalls = apiCalls.filter(c => + c.pathname.includes('/chat') && c.url.includes('music_session') + ); + + const udpCalls = apiCalls.filter(c => + c.pathname.includes('/udp_reachable') + ); + + const otherCalls = apiCalls.filter(c => + !sessionCreationCalls.includes(c) && + !participantCalls.includes(c) && + !sessionDetailCalls.includes(c) && + !sessionHistoryCalls.includes(c) && + !trackCalls.includes(c) && + !chatCalls.includes(c) && + !udpCalls.includes(c) + ); + + console.log('REST API CALLS:\n'); + console.log('1. Session Creation:'); + sessionCreationCalls.forEach(c => { + console.log(` ${c.method} ${c.pathname} -> ${c.responseStatus}`); + if (c.responseBody?.id) { + console.log(` Session ID: ${c.responseBody.id}`); + } + }); + + console.log('\n2. Add Participant (Join):'); + participantCalls.forEach(c => { + console.log(` ${c.method} ${c.pathname} -> ${c.responseStatus}`); + }); + + console.log('\n3. Get Session Details:'); + sessionDetailCalls.forEach(c => { + console.log(` ${c.method} ${c.pathname} -> ${c.responseStatus}`); + }); + + console.log('\n4. Get Session History:'); + sessionHistoryCalls.forEach(c => { + console.log(` ${c.method} ${c.pathname} -> ${c.responseStatus}`); + }); + + console.log('\n5. Update Tracks:'); + if (trackCalls.length > 0) { + trackCalls.forEach(c => { + console.log(` ${c.method} ${c.pathname} -> ${c.responseStatus}`); + }); + } else { + console.log(' āŒ NOT CALLED'); + } + + console.log('\n6. Load Session Chat:'); + if (chatCalls.length > 0) { + chatCalls.forEach(c => { + console.log(` ${c.method} ${c.pathname} -> ${c.responseStatus}`); + }); + } else { + console.log(' āŒ NOT CALLED'); + } + + console.log('\n7. UDP Reachability Check:'); + if (udpCalls.length > 0) { + udpCalls.forEach(c => { + console.log(` ${c.method} ${c.pathname} -> ${c.responseStatus}`); + }); + } else { + console.log(' āŒ NOT CALLED'); + } + + console.log('\n8. Other API Calls:'); + otherCalls.forEach(c => { + console.log(` ${c.method} ${c.pathname} -> ${c.responseStatus}`); + }); + + console.log('\n========================================'); + console.log('WEBSOCKET CONNECTIONS'); + console.log('========================================\n'); + + newWsConnections.forEach((conn, idx) => { + console.log(`Connection ${idx + 1}:`); + console.log(` URL: ${conn.url}`); + console.log(` Type: ${conn.isNativeClient ? 'Native Client' : conn.isServerConnection ? 'Server' : 'Other'}`); + console.log(` Messages: ${conn.messages.length}`); + console.log(` Status: ${conn.closed ? 'Closed' : 'Open'}`); + + if (conn.url.includes('?')) { + const url = new URL(conn.url); + console.log(` Parameters:`); + url.searchParams.forEach((value, key) => { + console.log(` ${key}: ${value.substring(0, 50)}${value.length > 50 ? '...' : ''}`); + }); + } + console.log(''); + }); + + console.log('========================================'); + console.log('SUMMARY'); + console.log('========================================\n'); + console.log(`Total REST API calls: ${apiCalls.length}`); + console.log(` - Session creation: ${sessionCreationCalls.length}`); + console.log(` - Add participant: ${participantCalls.length}`); + console.log(` - Get session details: ${sessionDetailCalls.length}`); + console.log(` - Get session history: ${sessionHistoryCalls.length}`); + console.log(` - Update tracks: ${trackCalls.length}`); + console.log(` - Session chat: ${chatCalls.length}`); + console.log(` - UDP reachability: ${udpCalls.length}`); + console.log(` - Other calls: ${otherCalls.length}`); + console.log(`\nWebSocket connections: ${newWsConnections.length}`); + console.log(`Total WebSocket messages: ${newWsConnections.reduce((sum, c) => sum + c.messages.length, 0)}`); + + // Save detailed analysis + const resultsDir = path.join(__dirname, '../test-results/session-join-analysis'); + if (!fs.existsSync(resultsDir)) { + fs.mkdirSync(resultsDir, { recursive: true }); + } + + const analysis = { + timestamp: new Date().toISOString(), + restApiCalls: { + total: apiCalls.length, + sessionCreation: sessionCreationCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })), + addParticipant: participantCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })), + getSessionDetails: sessionDetailCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })), + getSessionHistory: sessionHistoryCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })), + updateTracks: trackCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })), + sessionChat: chatCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })), + udpReachability: udpCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })), + other: otherCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })), + }, + websocketConnections: newWsConnections.map(c => ({ + url: c.url, + type: c.isNativeClient ? 'native' : c.isServerConnection ? 'server' : 'other', + messageCount: c.messages.length, + status: c.closed ? 'closed' : 'open', + })), + }; + + fs.writeFileSync( + path.join(resultsDir, 'jam-ui-session-join.json'), + JSON.stringify(analysis, null, 2) + ); + + fs.writeFileSync( + path.join(resultsDir, 'jam-ui-all-api-calls.json'), + JSON.stringify(apiCalls, null, 2) + ); + + fs.writeFileSync( + path.join(resultsDir, 'jam-ui-websockets.json'), + wsMonitor.toJSON() + ); + + console.log(`\nāœ“ Analysis saved to: ${resultsDir}`); + + // Basic assertions + expect(sessionCreationCalls.length).toBeGreaterThan(0); + expect(participantCalls.length).toBeGreaterThan(0); + }); +}); diff --git a/jam-ui/test/capture-session-flow-standalone.spec.ts b/jam-ui/test/capture-session-flow-standalone.spec.ts new file mode 100644 index 000000000..90e9709d7 --- /dev/null +++ b/jam-ui/test/capture-session-flow-standalone.spec.ts @@ -0,0 +1,366 @@ +import { chromium } from '@playwright/test'; +import * as fs from 'fs'; +import * as path from 'path'; + +/** + * Standalone script to capture network traffic for the "Join Session" flow + * This runs independently without the global Playwright test setup + * + * Usage: node --loader ts-node/esm test/capture-session-flow-standalone.spec.ts + * Or: npx ts-node test/capture-session-flow-standalone.spec.ts + */ +async function captureSessionFlow() { + console.log('Starting session flow capture...\n'); + + // Launch browser with ability to capture network traffic + const browser = await chromium.launch({ + headless: false, // Use headed mode to see what's happening + slowMo: 500, // Slow down by 500ms to make actions visible + }); + + const testResultsDir = path.join(__dirname, '../test-results'); + if (!fs.existsSync(testResultsDir)) { + fs.mkdirSync(testResultsDir, { recursive: true }); + } + + const context = await browser.newContext({ + ignoreHTTPSErrors: true, + recordHar: { + path: path.join(testResultsDir, 'session-join-flow.har'), + mode: 'full', // Capture full request/response bodies + }, + }); + + const page = await context.newPage(); + + // Arrays to collect network activity + const wsMessages: any[] = []; + const apiCalls: any[] = []; + const allNetworkActivity: any[] = []; + + // Listen to all network requests + page.on('request', request => { + const url = request.url(); + const entry = { + step: 'REQUEST', + method: request.method(), + url: url, + headers: request.headers(), + timestamp: new Date().toISOString(), + }; + + if (url.includes('/api/')) { + console.log(`[API REQUEST] ${request.method()} ${url}`); + apiCalls.push(entry); + } + allNetworkActivity.push(entry); + }); + + page.on('response', async response => { + const url = response.url(); + let body = null; + try { + const contentType = response.headers()['content-type'] || ''; + if (contentType.includes('application/json') || contentType.includes('text/')) { + body = await response.text(); + } + } catch (e) { + // Some responses can't be read + } + + const entry = { + step: 'RESPONSE', + status: response.status(), + statusText: response.statusText(), + url: url, + headers: response.headers(), + body: body, + timestamp: new Date().toISOString(), + }; + + if (url.includes('/api/')) { + console.log(`[API RESPONSE] ${response.status()} ${url}`); + apiCalls.push(entry); + } + allNetworkActivity.push(entry); + }); + + // Listen to WebSocket events + page.on('websocket', ws => { + console.log(`[WEBSOCKET] Opened: ${ws.url()}`); + wsMessages.push({ + event: 'open', + url: ws.url(), + timestamp: new Date().toISOString(), + }); + + ws.on('framesent', frame => { + console.log(`[WS SENT] ${frame.payload.toString().substring(0, 100)}...`); + wsMessages.push({ + event: 'sent', + payload: frame.payload.toString(), + timestamp: new Date().toISOString(), + }); + }); + + ws.on('framereceived', frame => { + console.log(`[WS RECEIVED] ${frame.payload.toString().substring(0, 100)}...`); + wsMessages.push({ + event: 'received', + payload: frame.payload.toString(), + timestamp: new Date().toISOString(), + }); + }); + + ws.on('close', () => { + console.log('[WEBSOCKET] Closed'); + wsMessages.push({ + event: 'close', + timestamp: new Date().toISOString(), + }); + }); + }); + + try { + console.log('\n=== STEP 1: Navigate to signin page ==='); + await page.goto('http://www.jamkazam.local:3100/signin', { + waitUntil: 'networkidle', + timeout: 30000, + }); + await page.waitForTimeout(2000); + + console.log('\n=== STEP 2: Fill in login credentials ==='); + // Try multiple selectors for email field + const emailSelectors = [ + 'input#session_email', + 'input[name="email"]', + 'input[type="email"]', + 'input[placeholder*="email" i]', + ]; + + let emailFilled = false; + for (const selector of emailSelectors) { + try { + const element = await page.$(selector); + if (element) { + await page.fill(selector, 'nuwan@jamkazam.com'); + console.log(`Filled email using selector: ${selector}`); + emailFilled = true; + break; + } + } catch (e) { + continue; + } + } + + if (!emailFilled) { + console.error('Could not find email input field!'); + console.log('Available input fields:'); + const inputs = await page.$$('input'); + for (const input of inputs) { + const type = await input.getAttribute('type'); + const name = await input.getAttribute('name'); + const id = await input.getAttribute('id'); + console.log(` - input: type=${type}, name=${name}, id=${id}`); + } + } + + // Try multiple selectors for password field + const passwordSelectors = [ + 'input#session_password', + 'input[name="password"]', + 'input[type="password"]', + ]; + + let passwordFilled = false; + for (const selector of passwordSelectors) { + try { + const element = await page.$(selector); + if (element) { + await page.fill(selector, 'jam123'); + console.log(`Filled password using selector: ${selector}`); + passwordFilled = true; + break; + } + } catch (e) { + continue; + } + } + + await page.waitForTimeout(1000); + + console.log('\n=== STEP 3: Click sign in button ==='); + const submitSelectors = [ + 'button[type="submit"]', + 'input[type="submit"]', + 'button:has-text("Sign in")', + 'button:has-text("Login")', + 'button:has-text("Sign In")', + 'input[value="Sign in"]', + 'input[value="Login"]', + ]; + + let submitClicked = false; + for (const selector of submitSelectors) { + try { + const element = await page.$(selector); + if (element) { + await page.click(selector); + console.log(`Clicked submit using selector: ${selector}`); + submitClicked = true; + break; + } + } catch (e) { + continue; + } + } + + if (!submitClicked) { + console.error('Could not find submit button!'); + console.log('Available buttons:'); + const buttons = await page.$$('button, input[type="submit"]'); + for (const button of buttons) { + const text = await button.textContent(); + const type = await button.getAttribute('type'); + const value = await button.getAttribute('value'); + console.log(` - button: text="${text}", type=${type}, value=${value}`); + } + } + + // Wait for navigation after login + console.log('Waiting for navigation after login...'); + await page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => { + console.log('networkidle timeout - continuing anyway'); + }); + await page.waitForTimeout(3000); + + console.log('\n=== STEP 4: Press Cmd+Shift+0 to skip upgrade modal ==='); + await page.keyboard.press('Meta+Shift+Digit0'); + await page.waitForTimeout(1500); + console.log('Upgrade modal skipped'); + + console.log('\n=== STEP 5: Look for and click "Create Session" tile ==='); + // Try multiple selectors for create session button + const createSessionSelectors = [ + '[data-testid="create-session"]', + 'button:has-text("Create Session")', + 'a:has-text("Create Session")', + 'div:has-text("Create Session")', + '.tile:has-text("Create Session")', + '[title*="Create Session"]', + ]; + + let sessionClicked = false; + for (const selector of createSessionSelectors) { + try { + const element = await page.$(selector); + if (element) { + await page.click(selector); + console.log(`Clicked create session using selector: ${selector}`); + sessionClicked = true; + break; + } + } catch (e) { + continue; + } + } + + if (!sessionClicked) { + console.warn('Could not find "Create Session" button - taking screenshot'); + await page.screenshot({ path: path.join(testResultsDir, 'dashboard-screenshot.png'), fullPage: true }); + } + + await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => { + console.log('networkidle timeout - continuing anyway'); + }); + await page.waitForTimeout(2000); + + console.log('\n=== STEP 6: Press Control+Shift+0 to remove backdrop ==='); + // Press Control+Shift+0 to trick browser as native client and remove backdrop + // This works even with the modal open + await page.keyboard.press('Control+Shift+Digit0'); + await page.waitForTimeout(2000); + console.log('Backdrop removed, browser tricked as native client'); + + console.log('\n=== STEP 7: Click "Create Quick Start" button ==='); + const quickStartSelectors = [ + 'button:has-text("Create Quick Start")', + 'button:has-text("Quick Start")', + 'button:has-text("Create quick start")', + '[data-testid="quick-start"]', + ]; + + let quickStartClicked = false; + for (const selector of quickStartSelectors) { + try { + const element = await page.$(selector); + if (element) { + await page.click(selector); + console.log(`Clicked quick start using selector: ${selector}`); + quickStartClicked = true; + break; + } + } catch (e) { + continue; + } + } + + if (!quickStartClicked) { + console.warn('Could not find "Create Quick Start" button - taking screenshot'); + await page.screenshot({ path: path.join(testResultsDir, 'session-create-screenshot.png'), fullPage: true }); + } + + // Wait for session to load and WebSocket messages + console.log('\nWaiting for session to load and capturing WebSocket traffic...'); + await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => { + console.log('networkidle timeout - continuing anyway'); + }); + await page.waitForTimeout(10000); // Give plenty of time for WebSocket messages + + console.log('\n=== Recording Complete ===\n'); + + // Save all captured data + const apiCallsPath = path.join(testResultsDir, 'api-calls.json'); + fs.writeFileSync(apiCallsPath, JSON.stringify(apiCalls, null, 2)); + console.log(`āœ“ API calls saved to: ${apiCallsPath}`); + console.log(` Total API calls: ${apiCalls.length}`); + + const wsMessagesPath = path.join(testResultsDir, 'websocket-messages.json'); + fs.writeFileSync(wsMessagesPath, JSON.stringify(wsMessages, null, 2)); + console.log(`āœ“ WebSocket messages saved to: ${wsMessagesPath}`); + console.log(` Total WebSocket messages: ${wsMessages.length}`); + + const allActivityPath = path.join(testResultsDir, 'all-network-activity.json'); + fs.writeFileSync(allActivityPath, JSON.stringify(allNetworkActivity, null, 2)); + console.log(`āœ“ All network activity saved to: ${allActivityPath}`); + console.log(` Total network requests: ${allNetworkActivity.length}`); + + // Take final screenshot + await page.screenshot({ path: path.join(testResultsDir, 'final-state.png'), fullPage: true }); + console.log(`āœ“ Final screenshot saved`); + + console.log('\nKeeping browser open for 10 seconds for manual inspection...'); + await page.waitForTimeout(10000); + + } catch (error) { + console.error('\nāŒ Error during capture:', error); + await page.screenshot({ path: path.join(testResultsDir, 'error-screenshot.png'), fullPage: true }); + throw error; + } finally { + console.log('\nClosing browser and saving HAR file...'); + await context.close(); + await browser.close(); + console.log('āœ“ HAR file saved to: test-results/session-join-flow.har\n'); + } +} + +// Run the capture +captureSessionFlow() + .then(() => { + console.log('āœ… Capture completed successfully!'); + process.exit(0); + }) + .catch((error) => { + console.error('āŒ Capture failed:', error); + process.exit(1); + }); diff --git a/jam-ui/test/capture-session-flow.spec.ts b/jam-ui/test/capture-session-flow.spec.ts new file mode 100644 index 000000000..4fcbd88bc --- /dev/null +++ b/jam-ui/test/capture-session-flow.spec.ts @@ -0,0 +1,165 @@ +import { test, chromium } from '@playwright/test'; +import * as fs from 'fs'; +import * as path from 'path'; + +/** + * This test captures the complete network traffic (HAR file) for the "Join Session" flow + * from the legacy JamKazam application. The captured data will be used to: + * 1. Document all API calls to /api/* + * 2. Document all WebSocket messages + * 3. Create a migration test plan for the new jam-ui interface + */ +test('Capture network traffic for joining a music session', async () => { + // Launch browser with ability to capture network traffic + const browser = await chromium.launch({ + headless: false, // Use headed mode to see what's happening + slowMo: 1000, // Slow down by 1 second to make actions visible + }); + + const context = await browser.newContext({ + ignoreHTTPSErrors: true, + recordHar: { + path: path.join(__dirname, '../test-results/session-join-flow.har'), + mode: 'full', // Capture full request/response bodies + }, + }); + + const page = await context.newPage(); + + // Array to collect all WebSocket messages + const wsMessages: any[] = []; + const apiCalls: any[] = []; + + // Listen to all network requests + page.on('request', request => { + const url = request.url(); + if (url.includes('/api/')) { + console.log(`API REQUEST: ${request.method()} ${url}`); + apiCalls.push({ + type: 'request', + method: request.method(), + url: url, + headers: request.headers(), + timestamp: new Date().toISOString(), + }); + } + }); + + page.on('response', async response => { + const url = response.url(); + if (url.includes('/api/')) { + console.log(`API RESPONSE: ${response.status()} ${url}`); + let body = null; + try { + body = await response.text(); + } catch (e) { + // Some responses can't be read + } + apiCalls.push({ + type: 'response', + status: response.status(), + url: url, + headers: response.headers(), + body: body, + timestamp: new Date().toISOString(), + }); + } + }); + + // Listen to WebSocket events + page.on('websocket', ws => { + console.log(`WebSocket opened: ${ws.url()}`); + wsMessages.push({ + type: 'websocket-open', + url: ws.url(), + timestamp: new Date().toISOString(), + }); + + ws.on('framesent', frame => { + console.log(`WS SENT: ${frame.payload}`); + wsMessages.push({ + type: 'sent', + payload: frame.payload, + timestamp: new Date().toISOString(), + }); + }); + + ws.on('framereceived', frame => { + console.log(`WS RECEIVED: ${frame.payload}`); + wsMessages.push({ + type: 'received', + payload: frame.payload, + timestamp: new Date().toISOString(), + }); + }); + + ws.on('close', () => { + console.log('WebSocket closed'); + wsMessages.push({ + type: 'websocket-close', + timestamp: new Date().toISOString(), + }); + }); + }); + + try { + console.log('Step 1: Navigate to signin page'); + await page.goto('http://www.jamkazam.com:3000/signin', { + waitUntil: 'networkidle', + timeout: 30000, + }); + + console.log('Step 2: Login with credentials'); + // Fill in login form + await page.fill('input[name="email"], input[type="email"]', 'nuwan@jamkazam.com'); + await page.fill('input[name="password"], input[type="password"]', 'jam123'); + + // Click sign in button + await page.click('button[type="submit"], input[type="submit"], button:has-text("Sign in"), button:has-text("Login")'); + + // Wait for navigation after login + await page.waitForLoadState('networkidle'); + await page.waitForTimeout(2000); + + console.log('Step 3: Click "create session" tile'); + // Look for create session button/tile + await page.click('[data-testid="create-session"], button:has-text("Create Session"), a:has-text("Create Session")'); + await page.waitForLoadState('networkidle'); + await page.waitForTimeout(2000); + + console.log('Step 4: Press Control+Shift+0 to trick browser as native client'); + await page.keyboard.press('Control+Shift+Digit0'); + await page.waitForTimeout(1000); + + console.log('Step 5: Click "create quick start" button'); + await page.click('button:has-text("Create Quick Start"), button:has-text("Quick Start")'); + + // Wait for session to load + await page.waitForLoadState('networkidle'); + await page.waitForTimeout(5000); // Give time for WebSocket messages + + console.log('Recording complete. Saving captured data...'); + + // Save API calls to a separate JSON file + const apiCallsPath = path.join(__dirname, '../test-results/api-calls.json'); + fs.writeFileSync(apiCallsPath, JSON.stringify(apiCalls, null, 2)); + console.log(`API calls saved to: ${apiCallsPath}`); + + // Save WebSocket messages to a separate JSON file + const wsMessagesPath = path.join(__dirname, '../test-results/websocket-messages.json'); + fs.writeFileSync(wsMessagesPath, JSON.stringify(wsMessages, null, 2)); + console.log(`WebSocket messages saved to: ${wsMessagesPath}`); + + // Keep browser open for manual inspection + console.log('Keeping browser open for 30 seconds for manual inspection...'); + await page.waitForTimeout(30000); + + } catch (error) { + console.error('Error during test:', error); + throw error; + } finally { + // Close context to save HAR file + await context.close(); + await browser.close(); + } +}); diff --git a/jam-ui/test/e2e/complete-session-flow.spec.ts b/jam-ui/test/e2e/complete-session-flow.spec.ts new file mode 100644 index 000000000..775fa6805 --- /dev/null +++ b/jam-ui/test/e2e/complete-session-flow.spec.ts @@ -0,0 +1,285 @@ +import { test, expect } from '@playwright/test'; +import { APIInterceptor } from '../utils/api-interceptor'; +import { WebSocketMonitor } from '../utils/websocket-monitor'; +import { compareAPISequences } from '../utils/sequence-comparator'; +import { + loginToJamUI, + navigateToSessionCreation, + fillSessionForm, + verifySessionInterfaceLoaded, + waitForAPICalls, + extractSessionId, +} from '../utils/test-helpers'; +import * as fs from 'fs'; +import * as path from 'path'; + +test.describe('Complete Session Flow E2E', () => { + test('complete flow: login → create session → join session', async ({ page }) => { + const apiInterceptor = new APIInterceptor(); + const wsMonitor = new WebSocketMonitor(); + + apiInterceptor.intercept(page); + wsMonitor.monitor(page); + + console.log('\n========================================'); + console.log('COMPLETE SESSION FLOW E2E TEST'); + console.log('========================================\n'); + + // STEP 1: Login + console.log('Step 1: Login...'); + await loginToJamUI(page, { + email: 'nuwan@jamkazam.com', + password: 'jam123', + }); + await waitForAPICalls(page, 3000); + + const loginCalls = apiInterceptor.getCalls().length; + console.log(` āœ“ Logged in (${loginCalls} API calls)\n`); + + // Verify we're logged in + await expect(page).not.toHaveURL(/signin|login/); + + // STEP 2: Navigate to session creation + console.log('Step 2: Navigate to session creation...'); + apiInterceptor.reset(); + await navigateToSessionCreation(page); + await waitForAPICalls(page, 2000); + + const navCalls = apiInterceptor.getCalls().length; + console.log(` āœ“ Navigated to session creation (${navCalls} API calls)\n`); + + // STEP 3: Enable native client and create session + // STEP 3: Create and join session + console.log('Step 3: Create and join session...'); + apiInterceptor.reset(); + await fillSessionForm(page, { sessionType: 'private' }); + await waitForAPICalls(page, 8000); + + const sessionCalls = apiInterceptor.getCalls(); + console.log(` āœ“ Session created (${sessionCalls.length} API calls)\n`); + + // Verify session creation endpoints + const sessionCreation = sessionCalls.find(c => + c.method === 'POST' && c.pathname.match(/\/api\/sessions\/?$/) + ); + expect(sessionCreation).toBeDefined(); + console.log(` āœ“ POST /api/sessions called`); + + const participantAdd = sessionCalls.find(c => + c.method === 'POST' && c.pathname.includes('/participants') + ); + expect(participantAdd).toBeDefined(); + console.log(` āœ“ POST /api/sessions/{id}/participants called`); + + // Extract session ID + const sessionId = await extractSessionId(page); + if (sessionId) { + console.log(` āœ“ Session ID: ${sessionId}`); + } + + // Verify session interface loaded + console.log('\nStep 4: Verify session interface...'); + await verifySessionInterfaceLoaded(page); + console.log(` āœ“ Session interface elements present\n`); + + // Verify WebSocket connections + const wsVerification = wsMonitor.verifyDualConnections(); + console.log('Step 5: Verify WebSocket connections...'); + console.log(` Native client: ${wsVerification.hasNativeClient ? 'YES' : 'NO'}`); + console.log(` Server: ${wsVerification.hasServerConnection ? 'YES' : 'NO'}`); + expect(wsVerification.bothEstablished).toBe(true); + console.log(` āœ“ Dual connections established\n`); + + // Compare with legacy sequence + console.log('Step 6: Compare with legacy sequence...'); + const expectedPath = path.join(__dirname, '../fixtures/legacy-sequences/complete-flow-simplified.json'); + const expectedCalls = JSON.parse(fs.readFileSync(expectedPath, 'utf8')); + + const allCalls = apiInterceptor.getCalls(); + const comparison = compareAPISequences(allCalls, expectedCalls); + + const matchPercentage = (comparison.matchedCalls / comparison.totalCalls) * 100; + console.log(` API calls: ${allCalls.length}`); + console.log(` Expected: ${expectedCalls.length}`); + console.log(` Match: ${matchPercentage.toFixed(1)}%`); + + // Save comprehensive results + const resultsDir = path.join(__dirname, '../test-results/e2e'); + if (!fs.existsSync(resultsDir)) { + fs.mkdirSync(resultsDir, { recursive: true }); + } + + // Save API calls + fs.writeFileSync( + path.join(resultsDir, 'complete-flow-api-calls.json'), + JSON.stringify(allCalls, null, 2) + ); + + // Save comparison report + fs.writeFileSync( + path.join(resultsDir, 'complete-flow-comparison.md'), + comparison.report + ); + + // Save WebSocket data + fs.writeFileSync( + path.join(resultsDir, 'complete-flow-websockets.json'), + wsMonitor.toJSON() + ); + + // Save screenshot + await page.screenshot({ + path: path.join(resultsDir, 'session-interface.png'), + fullPage: true, + }); + + console.log('\n========================================'); + console.log('COMPLETE SESSION FLOW TEST: PASSED'); + console.log('========================================\n'); + + // Final assertions + expect(matchPercentage).toBeGreaterThanOrEqual(70); + expect(wsVerification.bothEstablished).toBe(true); + expect(sessionCreation).toBeDefined(); + expect(participantAdd).toBeDefined(); + }); + + test('session interface has all required controls', async ({ page }) => { + await loginToJamUI(page); + await waitForAPICalls(page); + + await navigateToSessionCreation(page); + await waitForAPICalls(page); + + await fillSessionForm(page); + await waitForAPICalls(page, 8000); + + // Check for session control buttons + const expectedControls = [ + 'SETTINGS', + 'VOLUME', + 'BROADCAST', + 'RECORD', + 'VIDEO', + 'FILES', + 'RESYNC', + 'LEAVE', + ]; + + const foundControls: string[] = []; + const missingControls: string[] = []; + + for (const control of expectedControls) { + const selectors = [ + `text=${control}`, + `button:has-text("${control}")`, + `[data-testid="${control.toLowerCase()}"]`, + ]; + + let found = false; + for (const selector of selectors) { + try { + const element = await page.$(selector); + if (element) { + foundControls.push(control); + found = true; + break; + } + } catch { + continue; + } + } + + if (!found) { + missingControls.push(control); + } + } + + console.log('\nSession interface controls:'); + console.log(` Found: ${foundControls.join(', ')}`); + if (missingControls.length > 0) { + console.log(` Missing: ${missingControls.join(', ')}`); + } + + // At least some key controls should be present + expect(foundControls.length).toBeGreaterThan(3); + }); + + test('session creation handles errors gracefully', async ({ page }) => { + // This test verifies error handling - might fail initially + const apiInterceptor = new APIInterceptor(); + apiInterceptor.intercept(page); + + await loginToJamUI(page); + await navigateToSessionCreation(page); + await page.keyboard.press('Control+Shift+Digit0'); + await waitForAPICalls(page, 3000); + + // Try to create session + await fillSessionForm(page); + await waitForAPICalls(page, 8000); + + const calls = apiInterceptor.getCalls(); + + // Check if any calls failed + const failedCalls = calls.filter(c => + c.responseStatus && c.responseStatus >= 400 + ); + + if (failedCalls.length > 0) { + console.log('\nFailed API calls:'); + failedCalls.forEach(call => { + console.log(` ${call.method} ${call.pathname}: ${call.responseStatus}`); + }); + } + + // Even if some calls fail, the critical session creation should succeed + const sessionCreation = calls.find(c => + c.method === 'POST' && + c.pathname.match(/\/api\/sessions\/?$/) && + c.responseStatus && + c.responseStatus >= 200 && + c.responseStatus < 300 + ); + + // Log whether session creation succeeded + console.log(`\nSession creation: ${sessionCreation ? 'SUCCESS' : 'FAILED'}`); + }); + + test('user can leave session', async ({ page }) => { + await loginToJamUI(page); + await waitForAPICalls(page); + + await navigateToSessionCreation(page); + await waitForAPICalls(page); + + await fillSessionForm(page); + await waitForAPICalls(page, 8000); + + // Try to find and click LEAVE button + const leaveSelectors = [ + 'text=LEAVE', + 'button:has-text("LEAVE")', + '[data-testid="leave-button"]', + 'button:has-text("Leave Session")', + ]; + + let leaveClicked = false; + for (const selector of leaveSelectors) { + try { + const element = await page.$(selector); + if (element) { + console.log(`\nFound LEAVE button: ${selector}`); + // Don't actually click it (would end the test), just verify it exists + leaveClicked = true; + break; + } + } catch { + continue; + } + } + + console.log(`LEAVE button available: ${leaveClicked ? 'YES' : 'NO'}`); + expect(leaveClicked).toBe(true); + }); +}); diff --git a/jam-ui/test/fixtures/create-simplified-fixtures.js b/jam-ui/test/fixtures/create-simplified-fixtures.js new file mode 100644 index 000000000..5c150be05 --- /dev/null +++ b/jam-ui/test/fixtures/create-simplified-fixtures.js @@ -0,0 +1,103 @@ +/** + * This script processes the raw step verification data and creates simplified + * fixture files for easier test comparison + */ + +const fs = require('fs'); +const path = require('path'); + +const stepDir = path.join(__dirname, '../../test-results/step-verification'); +const fixturesDir = path.join(__dirname, 'legacy-sequences'); + +function processStepData(stepNumber, stepName) { + const stepPath = path.join(stepDir, `step-${stepNumber}`); + const apiCallsFile = path.join(stepPath, 'api-calls.json'); + + if (!fs.existsSync(apiCallsFile)) { + console.log(`āš ļø Step ${stepNumber} API calls not found`); + return; + } + + const apiCalls = JSON.parse(fs.readFileSync(apiCallsFile, 'utf8')); + + // Filter to just requests + const requests = apiCalls.filter(call => call.type === 'request'); + + // Create simplified version with just essential info + const simplified = requests.map((call, index) => { + const url = new URL(call.url); + return { + sequence: index, + method: call.method, + url: call.url, + pathname: url.pathname, + timestamp: call.timestamp, + endpoint: `${call.method} ${url.pathname}`, + }; + }); + + // Save simplified version + const outputFile = path.join(fixturesDir, `${stepName}-simplified.json`); + fs.writeFileSync(outputFile, JSON.stringify(simplified, null, 2)); + + console.log(`āœ“ Created ${outputFile}`); + console.log(` ${simplified.length} API calls`); + + return simplified; +} + +console.log('Creating simplified fixtures from step verification data...\n'); + +// Process each step +const steps = [ + { number: 1, name: 'login' }, + { number: 2, name: 'dashboard' }, + { number: 3, name: 'skip-modal' }, + { number: 4, name: 'navigate-to-session' }, + { number: 5, name: 'session-creation' }, +]; + +const allSequences = {}; + +for (const step of steps) { + const sequence = processStepData(step.number, step.name); + if (sequence) { + allSequences[step.name] = sequence; + } +} + +// Create combined complete flow +const completeFlow = Object.values(allSequences).flat(); +const completeFile = path.join(fixturesDir, 'complete-flow-simplified.json'); +fs.writeFileSync(completeFile, JSON.stringify(completeFlow, null, 2)); +console.log(`\nāœ“ Created ${completeFile}`); +console.log(` ${completeFlow.length} total API calls`); + +// Create summary file with unique endpoints +const uniqueEndpoints = new Map(); +for (const call of completeFlow) { + const endpoint = call.endpoint; + if (!uniqueEndpoints.has(endpoint)) { + uniqueEndpoints.set(endpoint, 0); + } + uniqueEndpoints.set(endpoint, uniqueEndpoints.get(endpoint) + 1); +} + +const summary = { + totalCalls: completeFlow.length, + uniqueEndpoints: uniqueEndpoints.size, + endpoints: Array.from(uniqueEndpoints.entries()).map(([endpoint, count]) => ({ + endpoint, + count, + })), + steps: Object.entries(allSequences).map(([name, calls]) => ({ + step: name, + callCount: calls.length, + })), +}; + +const summaryFile = path.join(fixturesDir, 'summary.json'); +fs.writeFileSync(summaryFile, JSON.stringify(summary, null, 2)); +console.log(`\nāœ“ Created ${summaryFile}`); +console.log(` ${summary.uniqueEndpoints} unique endpoints`); +console.log(` ${summary.totalCalls} total API calls`); diff --git a/jam-ui/test/fixtures/legacy-sequences/complete-flow-simplified.json b/jam-ui/test/fixtures/legacy-sequences/complete-flow-simplified.json new file mode 100644 index 000000000..b093a7b81 --- /dev/null +++ b/jam-ui/test/fixtures/legacy-sequences/complete-flow-simplified.json @@ -0,0 +1,562 @@ +[ + { + "sequence": 0, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:25.212Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 1, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381", + "timestamp": "2026-01-20T10:15:31.522Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381" + }, + { + "sequence": 2, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/countries", + "pathname": "/api/countries", + "timestamp": "2026-01-20T10:15:31.618Z", + "endpoint": "GET /api/countries" + }, + { + "sequence": 3, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/shopping_carts?time=1768904131749", + "pathname": "/api/shopping_carts", + "timestamp": "2026-01-20T10:15:31.756Z", + "endpoint": "GET /api/shopping_carts" + }, + { + "sequence": 4, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "pathname": "/api/jamtracks/purchased", + "timestamp": "2026-01-20T10:15:31.921Z", + "endpoint": "GET /api/jamtracks/purchased" + }, + { + "sequence": 5, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/teacher_distributions?per_page=20&page=1", + "pathname": "/api/teacher_distributions", + "timestamp": "2026-01-20T10:15:31.923Z", + "endpoint": "GET /api/teacher_distributions" + }, + { + "sequence": 6, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/regions?country=US", + "pathname": "/api/regions", + "timestamp": "2026-01-20T10:15:31.990Z", + "endpoint": "GET /api/regions" + }, + { + "sequence": 7, + "method": "POST", + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "pathname": "/xoplatform/logger/api/logger", + "timestamp": "2026-01-20T10:15:33.727Z", + "endpoint": "POST /xoplatform/logger/api/logger" + }, + { + "sequence": 8, + "method": "POST", + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "pathname": "/xoplatform/logger/api/logger", + "timestamp": "2026-01-20T10:15:33.727Z", + "endpoint": "POST /xoplatform/logger/api/logger" + }, + { + "sequence": 9, + "method": "POST", + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "pathname": "/xoplatform/logger/api/logger", + "timestamp": "2026-01-20T10:15:33.938Z", + "endpoint": "POST /xoplatform/logger/api/logger" + }, + { + "sequence": 10, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "timestamp": "2026-01-20T10:15:33.961Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification" + }, + { + "sequence": 11, + "method": "POST", + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "pathname": "/xoplatform/logger/api/logger", + "timestamp": "2026-01-20T10:15:34.127Z", + "endpoint": "POST /xoplatform/logger/api/logger" + }, + { + "sequence": 0, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:41.765Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 1, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:41.766Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 2, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "pathname": "/api/instruments", + "timestamp": "2026-01-20T10:15:41.815Z", + "endpoint": "GET /api/instruments" + }, + { + "sequence": 3, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": "2026-01-20T10:15:41.816Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends" + }, + { + "sequence": 4, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications?offset=0&limit=20", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications", + "timestamp": "2026-01-20T10:15:41.816Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications" + }, + { + "sequence": 5, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "pathname": "/api/instruments", + "timestamp": "2026-01-20T10:15:41.927Z", + "endpoint": "GET /api/instruments" + }, + { + "sequence": 6, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": "2026-01-20T10:15:41.927Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends" + }, + { + "sequence": 7, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "pathname": "/api/instruments", + "timestamp": "2026-01-20T10:15:41.927Z", + "endpoint": "GET /api/instruments" + }, + { + "sequence": 8, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/languages", + "pathname": "/api/languages", + "timestamp": "2026-01-20T10:15:41.927Z", + "endpoint": "GET /api/languages" + }, + { + "sequence": 9, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:41.927Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 10, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/subjects", + "pathname": "/api/subjects", + "timestamp": "2026-01-20T10:15:41.928Z", + "endpoint": "GET /api/subjects" + }, + { + "sequence": 11, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/chat?type=CHAT_MESSAGE&limit=20&page=0&channel=global", + "pathname": "/api/chat", + "timestamp": "2026-01-20T10:15:41.928Z", + "endpoint": "GET /api/chat" + }, + { + "sequence": 12, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "pathname": "/api/versioncheck", + "timestamp": "2026-01-20T10:15:42.826Z", + "endpoint": "GET /api/versioncheck" + }, + { + "sequence": 13, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "pathname": "/api/versioncheck", + "timestamp": "2026-01-20T10:15:42.829Z", + "endpoint": "GET /api/versioncheck" + }, + { + "sequence": 14, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/healthcheck", + "pathname": "/api/healthcheck", + "timestamp": "2026-01-20T10:15:43.752Z", + "endpoint": "GET /api/healthcheck" + }, + { + "sequence": 15, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/config/client?", + "pathname": "/api/config/client", + "timestamp": "2026-01-20T10:15:43.932Z", + "endpoint": "GET /api/config/client" + }, + { + "sequence": 0, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "pathname": "/api/versioncheck", + "timestamp": "2026-01-20T10:15:45.349Z", + "endpoint": "GET /api/versioncheck" + }, + { + "sequence": 0, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/scheduled?", + "pathname": "/api/sessions/scheduled", + "timestamp": "2026-01-20T10:15:50.945Z", + "endpoint": "GET /api/sessions/scheduled" + }, + { + "sequence": 1, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381", + "timestamp": "2026-01-20T10:15:50.946Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381" + }, + { + "sequence": 2, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "pathname": "/api/jamtracks/purchased", + "timestamp": "2026-01-20T10:15:51.197Z", + "endpoint": "GET /api/jamtracks/purchased" + }, + { + "sequence": 0, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381", + "timestamp": "2026-01-20T10:15:55.382Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381" + }, + { + "sequence": 1, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/countries", + "pathname": "/api/countries", + "timestamp": "2026-01-20T10:15:55.437Z", + "endpoint": "GET /api/countries" + }, + { + "sequence": 2, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/shopping_carts?time=1768904155592", + "pathname": "/api/shopping_carts", + "timestamp": "2026-01-20T10:15:55.594Z", + "endpoint": "GET /api/shopping_carts" + }, + { + "sequence": 3, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:55.655Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 4, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:55.655Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 5, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "pathname": "/api/instruments", + "timestamp": "2026-01-20T10:15:55.664Z", + "endpoint": "GET /api/instruments" + }, + { + "sequence": 6, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "pathname": "/api/instruments", + "timestamp": "2026-01-20T10:15:55.734Z", + "endpoint": "GET /api/instruments" + }, + { + "sequence": 7, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": "2026-01-20T10:15:55.734Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends" + }, + { + "sequence": 8, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "pathname": "/api/jamtracks/purchased", + "timestamp": "2026-01-20T10:15:55.734Z", + "endpoint": "GET /api/jamtracks/purchased" + }, + { + "sequence": 9, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "pathname": "/api/instruments", + "timestamp": "2026-01-20T10:15:55.739Z", + "endpoint": "GET /api/instruments" + }, + { + "sequence": 10, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/languages", + "pathname": "/api/languages", + "timestamp": "2026-01-20T10:15:55.739Z", + "endpoint": "GET /api/languages" + }, + { + "sequence": 11, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:55.740Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 12, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/subjects", + "pathname": "/api/subjects", + "timestamp": "2026-01-20T10:15:55.740Z", + "endpoint": "GET /api/subjects" + }, + { + "sequence": 13, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/chat?type=CHAT_MESSAGE&limit=20&page=0&channel=global", + "pathname": "/api/chat", + "timestamp": "2026-01-20T10:15:55.740Z", + "endpoint": "GET /api/chat" + }, + { + "sequence": 14, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/scheduled?", + "pathname": "/api/sessions/scheduled", + "timestamp": "2026-01-20T10:15:55.987Z", + "endpoint": "GET /api/sessions/scheduled" + }, + { + "sequence": 15, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381", + "timestamp": "2026-01-20T10:15:55.987Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381" + }, + { + "sequence": 16, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": "2026-01-20T10:15:56.005Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends" + }, + { + "sequence": 17, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications?offset=0&limit=20", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications", + "timestamp": "2026-01-20T10:15:56.006Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications" + }, + { + "sequence": 18, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/regions?country=US", + "pathname": "/api/regions", + "timestamp": "2026-01-20T10:15:56.009Z", + "endpoint": "GET /api/regions" + }, + { + "sequence": 19, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "pathname": "/api/jamtracks/purchased", + "timestamp": "2026-01-20T10:15:56.247Z", + "endpoint": "GET /api/jamtracks/purchased" + }, + { + "sequence": 20, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/teacher_distributions?per_page=20&page=1", + "pathname": "/api/teacher_distributions", + "timestamp": "2026-01-20T10:15:56.247Z", + "endpoint": "GET /api/teacher_distributions" + }, + { + "sequence": 21, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "pathname": "/api/versioncheck", + "timestamp": "2026-01-20T10:15:56.251Z", + "endpoint": "GET /api/versioncheck" + }, + { + "sequence": 22, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "pathname": "/api/versioncheck", + "timestamp": "2026-01-20T10:15:56.254Z", + "endpoint": "GET /api/versioncheck" + }, + { + "sequence": 23, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "pathname": "/api/versioncheck", + "timestamp": "2026-01-20T10:15:56.305Z", + "endpoint": "GET /api/versioncheck" + }, + { + "sequence": 24, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "pathname": "/api/jamtracks/purchased", + "timestamp": "2026-01-20T10:15:57.016Z", + "endpoint": "GET /api/jamtracks/purchased" + }, + { + "sequence": 25, + "method": "POST", + "url": "http://www.jamkazam.local:3100/api/sessions", + "pathname": "/api/sessions", + "timestamp": "2026-01-20T10:15:57.295Z", + "endpoint": "POST /api/sessions" + }, + { + "sequence": 26, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/history?includePending=false", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/history", + "timestamp": "2026-01-20T10:15:57.677Z", + "endpoint": "GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/history" + }, + { + "sequence": 27, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/config/client?", + "pathname": "/api/config/client", + "timestamp": "2026-01-20T10:15:57.748Z", + "endpoint": "GET /api/config/client" + }, + { + "sequence": 28, + "method": "POST", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/participants", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/participants", + "timestamp": "2026-01-20T10:15:57.929Z", + "endpoint": "POST /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/participants" + }, + { + "sequence": 29, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "timestamp": "2026-01-20T10:15:58.794Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification" + }, + { + "sequence": 30, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/chat?type=CHAT_MESSAGE&limit=20&page=0&channel=session&music_session=02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "pathname": "/api/chat", + "timestamp": "2026-01-20T10:15:58.809Z", + "endpoint": "GET /api/chat" + }, + { + "sequence": 31, + "method": "PUT", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "timestamp": "2026-01-20T10:15:58.859Z", + "endpoint": "PUT /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks" + }, + { + "sequence": 32, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "timestamp": "2026-01-20T10:15:58.964Z", + "endpoint": "GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23" + }, + { + "sequence": 33, + "method": "PUT", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "timestamp": "2026-01-20T10:15:59.264Z", + "endpoint": "PUT /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks" + }, + { + "sequence": 34, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "timestamp": "2026-01-20T10:15:59.317Z", + "endpoint": "GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23" + }, + { + "sequence": 35, + "method": "POST", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/udp_reachable", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/udp_reachable", + "timestamp": "2026-01-20T10:15:59.547Z", + "endpoint": "POST /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/udp_reachable" + }, + { + "sequence": 36, + "method": "PUT", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "timestamp": "2026-01-20T10:16:05.013Z", + "endpoint": "PUT /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks" + }, + { + "sequence": 37, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "timestamp": "2026-01-20T10:16:05.049Z", + "endpoint": "GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23" + } +] \ No newline at end of file diff --git a/jam-ui/test/fixtures/legacy-sequences/dashboard-simplified.json b/jam-ui/test/fixtures/legacy-sequences/dashboard-simplified.json new file mode 100644 index 000000000..9cade0ad1 --- /dev/null +++ b/jam-ui/test/fixtures/legacy-sequences/dashboard-simplified.json @@ -0,0 +1,130 @@ +[ + { + "sequence": 0, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:41.765Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 1, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:41.766Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 2, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "pathname": "/api/instruments", + "timestamp": "2026-01-20T10:15:41.815Z", + "endpoint": "GET /api/instruments" + }, + { + "sequence": 3, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": "2026-01-20T10:15:41.816Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends" + }, + { + "sequence": 4, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications?offset=0&limit=20", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications", + "timestamp": "2026-01-20T10:15:41.816Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications" + }, + { + "sequence": 5, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "pathname": "/api/instruments", + "timestamp": "2026-01-20T10:15:41.927Z", + "endpoint": "GET /api/instruments" + }, + { + "sequence": 6, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": "2026-01-20T10:15:41.927Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends" + }, + { + "sequence": 7, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "pathname": "/api/instruments", + "timestamp": "2026-01-20T10:15:41.927Z", + "endpoint": "GET /api/instruments" + }, + { + "sequence": 8, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/languages", + "pathname": "/api/languages", + "timestamp": "2026-01-20T10:15:41.927Z", + "endpoint": "GET /api/languages" + }, + { + "sequence": 9, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:41.927Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 10, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/subjects", + "pathname": "/api/subjects", + "timestamp": "2026-01-20T10:15:41.928Z", + "endpoint": "GET /api/subjects" + }, + { + "sequence": 11, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/chat?type=CHAT_MESSAGE&limit=20&page=0&channel=global", + "pathname": "/api/chat", + "timestamp": "2026-01-20T10:15:41.928Z", + "endpoint": "GET /api/chat" + }, + { + "sequence": 12, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "pathname": "/api/versioncheck", + "timestamp": "2026-01-20T10:15:42.826Z", + "endpoint": "GET /api/versioncheck" + }, + { + "sequence": 13, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "pathname": "/api/versioncheck", + "timestamp": "2026-01-20T10:15:42.829Z", + "endpoint": "GET /api/versioncheck" + }, + { + "sequence": 14, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/healthcheck", + "pathname": "/api/healthcheck", + "timestamp": "2026-01-20T10:15:43.752Z", + "endpoint": "GET /api/healthcheck" + }, + { + "sequence": 15, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/config/client?", + "pathname": "/api/config/client", + "timestamp": "2026-01-20T10:15:43.932Z", + "endpoint": "GET /api/config/client" + } +] \ No newline at end of file diff --git a/jam-ui/test/fixtures/legacy-sequences/login-simplified.json b/jam-ui/test/fixtures/legacy-sequences/login-simplified.json new file mode 100644 index 000000000..6777fc9e0 --- /dev/null +++ b/jam-ui/test/fixtures/legacy-sequences/login-simplified.json @@ -0,0 +1,98 @@ +[ + { + "sequence": 0, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:25.212Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 1, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381", + "timestamp": "2026-01-20T10:15:31.522Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381" + }, + { + "sequence": 2, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/countries", + "pathname": "/api/countries", + "timestamp": "2026-01-20T10:15:31.618Z", + "endpoint": "GET /api/countries" + }, + { + "sequence": 3, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/shopping_carts?time=1768904131749", + "pathname": "/api/shopping_carts", + "timestamp": "2026-01-20T10:15:31.756Z", + "endpoint": "GET /api/shopping_carts" + }, + { + "sequence": 4, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "pathname": "/api/jamtracks/purchased", + "timestamp": "2026-01-20T10:15:31.921Z", + "endpoint": "GET /api/jamtracks/purchased" + }, + { + "sequence": 5, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/teacher_distributions?per_page=20&page=1", + "pathname": "/api/teacher_distributions", + "timestamp": "2026-01-20T10:15:31.923Z", + "endpoint": "GET /api/teacher_distributions" + }, + { + "sequence": 6, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/regions?country=US", + "pathname": "/api/regions", + "timestamp": "2026-01-20T10:15:31.990Z", + "endpoint": "GET /api/regions" + }, + { + "sequence": 7, + "method": "POST", + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "pathname": "/xoplatform/logger/api/logger", + "timestamp": "2026-01-20T10:15:33.727Z", + "endpoint": "POST /xoplatform/logger/api/logger" + }, + { + "sequence": 8, + "method": "POST", + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "pathname": "/xoplatform/logger/api/logger", + "timestamp": "2026-01-20T10:15:33.727Z", + "endpoint": "POST /xoplatform/logger/api/logger" + }, + { + "sequence": 9, + "method": "POST", + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "pathname": "/xoplatform/logger/api/logger", + "timestamp": "2026-01-20T10:15:33.938Z", + "endpoint": "POST /xoplatform/logger/api/logger" + }, + { + "sequence": 10, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "timestamp": "2026-01-20T10:15:33.961Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification" + }, + { + "sequence": 11, + "method": "POST", + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "pathname": "/xoplatform/logger/api/logger", + "timestamp": "2026-01-20T10:15:34.127Z", + "endpoint": "POST /xoplatform/logger/api/logger" + } +] \ No newline at end of file diff --git a/jam-ui/test/fixtures/legacy-sequences/navigate-to-session-simplified.json b/jam-ui/test/fixtures/legacy-sequences/navigate-to-session-simplified.json new file mode 100644 index 000000000..507979349 --- /dev/null +++ b/jam-ui/test/fixtures/legacy-sequences/navigate-to-session-simplified.json @@ -0,0 +1,26 @@ +[ + { + "sequence": 0, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/scheduled?", + "pathname": "/api/sessions/scheduled", + "timestamp": "2026-01-20T10:15:50.945Z", + "endpoint": "GET /api/sessions/scheduled" + }, + { + "sequence": 1, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381", + "timestamp": "2026-01-20T10:15:50.946Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381" + }, + { + "sequence": 2, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "pathname": "/api/jamtracks/purchased", + "timestamp": "2026-01-20T10:15:51.197Z", + "endpoint": "GET /api/jamtracks/purchased" + } +] \ No newline at end of file diff --git a/jam-ui/test/fixtures/legacy-sequences/session-creation-simplified.json b/jam-ui/test/fixtures/legacy-sequences/session-creation-simplified.json new file mode 100644 index 000000000..c37d811e4 --- /dev/null +++ b/jam-ui/test/fixtures/legacy-sequences/session-creation-simplified.json @@ -0,0 +1,306 @@ +[ + { + "sequence": 0, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381", + "timestamp": "2026-01-20T10:15:55.382Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381" + }, + { + "sequence": 1, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/countries", + "pathname": "/api/countries", + "timestamp": "2026-01-20T10:15:55.437Z", + "endpoint": "GET /api/countries" + }, + { + "sequence": 2, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/shopping_carts?time=1768904155592", + "pathname": "/api/shopping_carts", + "timestamp": "2026-01-20T10:15:55.594Z", + "endpoint": "GET /api/shopping_carts" + }, + { + "sequence": 3, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:55.655Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 4, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:55.655Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 5, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "pathname": "/api/instruments", + "timestamp": "2026-01-20T10:15:55.664Z", + "endpoint": "GET /api/instruments" + }, + { + "sequence": 6, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "pathname": "/api/instruments", + "timestamp": "2026-01-20T10:15:55.734Z", + "endpoint": "GET /api/instruments" + }, + { + "sequence": 7, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": "2026-01-20T10:15:55.734Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends" + }, + { + "sequence": 8, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "pathname": "/api/jamtracks/purchased", + "timestamp": "2026-01-20T10:15:55.734Z", + "endpoint": "GET /api/jamtracks/purchased" + }, + { + "sequence": 9, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "pathname": "/api/instruments", + "timestamp": "2026-01-20T10:15:55.739Z", + "endpoint": "GET /api/instruments" + }, + { + "sequence": 10, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/languages", + "pathname": "/api/languages", + "timestamp": "2026-01-20T10:15:55.739Z", + "endpoint": "GET /api/languages" + }, + { + "sequence": 11, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "pathname": "/api/genres", + "timestamp": "2026-01-20T10:15:55.740Z", + "endpoint": "GET /api/genres" + }, + { + "sequence": 12, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/subjects", + "pathname": "/api/subjects", + "timestamp": "2026-01-20T10:15:55.740Z", + "endpoint": "GET /api/subjects" + }, + { + "sequence": 13, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/chat?type=CHAT_MESSAGE&limit=20&page=0&channel=global", + "pathname": "/api/chat", + "timestamp": "2026-01-20T10:15:55.740Z", + "endpoint": "GET /api/chat" + }, + { + "sequence": 14, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/scheduled?", + "pathname": "/api/sessions/scheduled", + "timestamp": "2026-01-20T10:15:55.987Z", + "endpoint": "GET /api/sessions/scheduled" + }, + { + "sequence": 15, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381", + "timestamp": "2026-01-20T10:15:55.987Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381" + }, + { + "sequence": 16, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": "2026-01-20T10:15:56.005Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends" + }, + { + "sequence": 17, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications?offset=0&limit=20", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications", + "timestamp": "2026-01-20T10:15:56.006Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications" + }, + { + "sequence": 18, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/regions?country=US", + "pathname": "/api/regions", + "timestamp": "2026-01-20T10:15:56.009Z", + "endpoint": "GET /api/regions" + }, + { + "sequence": 19, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "pathname": "/api/jamtracks/purchased", + "timestamp": "2026-01-20T10:15:56.247Z", + "endpoint": "GET /api/jamtracks/purchased" + }, + { + "sequence": 20, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/teacher_distributions?per_page=20&page=1", + "pathname": "/api/teacher_distributions", + "timestamp": "2026-01-20T10:15:56.247Z", + "endpoint": "GET /api/teacher_distributions" + }, + { + "sequence": 21, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "pathname": "/api/versioncheck", + "timestamp": "2026-01-20T10:15:56.251Z", + "endpoint": "GET /api/versioncheck" + }, + { + "sequence": 22, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "pathname": "/api/versioncheck", + "timestamp": "2026-01-20T10:15:56.254Z", + "endpoint": "GET /api/versioncheck" + }, + { + "sequence": 23, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "pathname": "/api/versioncheck", + "timestamp": "2026-01-20T10:15:56.305Z", + "endpoint": "GET /api/versioncheck" + }, + { + "sequence": 24, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "pathname": "/api/jamtracks/purchased", + "timestamp": "2026-01-20T10:15:57.016Z", + "endpoint": "GET /api/jamtracks/purchased" + }, + { + "sequence": 25, + "method": "POST", + "url": "http://www.jamkazam.local:3100/api/sessions", + "pathname": "/api/sessions", + "timestamp": "2026-01-20T10:15:57.295Z", + "endpoint": "POST /api/sessions" + }, + { + "sequence": 26, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/history?includePending=false", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/history", + "timestamp": "2026-01-20T10:15:57.677Z", + "endpoint": "GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/history" + }, + { + "sequence": 27, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/config/client?", + "pathname": "/api/config/client", + "timestamp": "2026-01-20T10:15:57.748Z", + "endpoint": "GET /api/config/client" + }, + { + "sequence": 28, + "method": "POST", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/participants", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/participants", + "timestamp": "2026-01-20T10:15:57.929Z", + "endpoint": "POST /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/participants" + }, + { + "sequence": 29, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "timestamp": "2026-01-20T10:15:58.794Z", + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification" + }, + { + "sequence": 30, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/chat?type=CHAT_MESSAGE&limit=20&page=0&channel=session&music_session=02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "pathname": "/api/chat", + "timestamp": "2026-01-20T10:15:58.809Z", + "endpoint": "GET /api/chat" + }, + { + "sequence": 31, + "method": "PUT", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "timestamp": "2026-01-20T10:15:58.859Z", + "endpoint": "PUT /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks" + }, + { + "sequence": 32, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "timestamp": "2026-01-20T10:15:58.964Z", + "endpoint": "GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23" + }, + { + "sequence": 33, + "method": "PUT", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "timestamp": "2026-01-20T10:15:59.264Z", + "endpoint": "PUT /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks" + }, + { + "sequence": 34, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "timestamp": "2026-01-20T10:15:59.317Z", + "endpoint": "GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23" + }, + { + "sequence": 35, + "method": "POST", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/udp_reachable", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/udp_reachable", + "timestamp": "2026-01-20T10:15:59.547Z", + "endpoint": "POST /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/udp_reachable" + }, + { + "sequence": 36, + "method": "PUT", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "timestamp": "2026-01-20T10:16:05.013Z", + "endpoint": "PUT /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks" + }, + { + "sequence": 37, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "pathname": "/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "timestamp": "2026-01-20T10:16:05.049Z", + "endpoint": "GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23" + } +] \ No newline at end of file diff --git a/jam-ui/test/fixtures/legacy-sequences/skip-modal-simplified.json b/jam-ui/test/fixtures/legacy-sequences/skip-modal-simplified.json new file mode 100644 index 000000000..bf24530a3 --- /dev/null +++ b/jam-ui/test/fixtures/legacy-sequences/skip-modal-simplified.json @@ -0,0 +1,10 @@ +[ + { + "sequence": 0, + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "pathname": "/api/versioncheck", + "timestamp": "2026-01-20T10:15:45.349Z", + "endpoint": "GET /api/versioncheck" + } +] \ No newline at end of file diff --git a/jam-ui/test/fixtures/legacy-sequences/step-1-login-sequence.json b/jam-ui/test/fixtures/legacy-sequences/step-1-login-sequence.json new file mode 100644 index 000000000..646c4f496 --- /dev/null +++ b/jam-ui/test/fixtures/legacy-sequences/step-1-login-sequence.json @@ -0,0 +1,2029 @@ +[ + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "timestamp": "2026-01-20T10:15:25.212Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/genres", + "body": [ + { + "id": "acapella", + "description": "A Cappella" + }, + { + "id": "african", + "description": "African" + }, + { + "id": "alternative rock", + "description": "Alternative Rock" + }, + { + "id": "ambient", + "description": "Ambient" + }, + { + "id": "americana", + "description": "Americana" + }, + { + "id": "asian", + "description": "Asian" + }, + { + "id": "avante-garde", + "description": "Avante-Garde" + }, + { + "id": "bluegrass", + "description": "Bluegrass" + }, + { + "id": "blues", + "description": "Blues" + }, + { + "id": "breakbeat", + "description": "Breakbeat" + }, + { + "id": "celtic", + "description": "Celtic" + }, + { + "id": "classical", + "description": "Classical" + }, + { + "id": "country", + "description": "Country" + }, + { + "id": "creole", + "description": "Creole" + }, + { + "id": "dance", + "description": "Dance" + }, + { + "id": "disco", + "description": "Disco" + }, + { + "id": "downtempo", + "description": "Downtempo" + }, + { + "id": "drum & bass", + "description": "Drum & Bass" + }, + { + "id": "electronic", + "description": "Electronic" + }, + { + "id": "folk", + "description": "Folk" + }, + { + "id": "funk", + "description": "Funk" + }, + { + "id": "hard rock", + "description": "Hard Rock" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "holiday", + "description": "Holiday" + }, + { + "id": "house", + "description": "House" + }, + { + "id": "industrial", + "description": "Industrial" + }, + { + "id": "jazz", + "description": "Jazz" + }, + { + "id": "kids", + "description": "Kids" + }, + { + "id": "latin", + "description": "Latin" + }, + { + "id": "metal", + "description": "Metal" + }, + { + "id": "musical", + "description": "Musical" + }, + { + "id": "oldies", + "description": "Oldies" + }, + { + "id": "other", + "description": "Other" + }, + { + "id": "pop", + "description": "Pop" + }, + { + "id": "psychedelic", + "description": "Psychedelic" + }, + { + "id": "punk", + "description": "Punk" + }, + { + "id": "r&b", + "description": "R&B" + }, + { + "id": "rap", + "description": "Rap" + }, + { + "id": "reggae", + "description": "Reggae" + }, + { + "id": "religious", + "description": "Religious" + }, + { + "id": "rock", + "description": "Rock" + }, + { + "id": "ska", + "description": "Ska" + }, + { + "id": "soft rock", + "description": "Soft Rock" + }, + { + "id": "soul", + "description": "Soul" + }, + { + "id": "tv & movie soundtrack", + "description": "TV & Movie Soundtrack" + }, + { + "id": "techno", + "description": "Techno" + }, + { + "id": "traditional", + "description": "Traditional" + }, + { + "id": "trance", + "description": "Trance" + }, + { + "id": "world", + "description": "World" + } + ], + "timestamp": "2026-01-20T10:15:25.323Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "timestamp": "2026-01-20T10:15:31.522Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/countries", + "timestamp": "2026-01-20T10:15:31.618Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/shopping_carts?time=1768904131749", + "timestamp": "2026-01-20T10:15:31.756Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "timestamp": "2026-01-20T10:15:31.921Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/teacher_distributions?per_page=20&page=1", + "timestamp": "2026-01-20T10:15:31.923Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "body": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "city": "Dallas", + "state": "TX", + "country": "US", + "location": "Dallas, TX", + "online": true, + "photo_url": null, + "musician": true, + "gender": "M", + "birth_date": null, + "friend_count": 1, + "liker_count": 0, + "follower_count": 77, + "following_count": 130, + "admin": true, + "recording_count": 0, + "session_count": 0, + "biography": "This is description with special charact xxxxxxaaaasasasas", + "favorite_count": 0, + "audio_latency": null, + "upcoming_session_count": 0, + "age": null, + "website": "www.nuwanchaturanga.me", + "skill_level": 2, + "reuse_card": true, + "email_needs_verification": false, + "is_a_teacher": true, + "is_a_student": false, + "is_onboarder": false, + "timezone": null, + "use_video_conferencing_server": true, + "email": "nuwan@jamkazam.com", + "original_fpfile": null, + "cropped_fpfile": null, + "crop_selection": null, + "session_settings": "{:band_id=>nil, :musician_access=>false, :approval_required=>false, :fan_chat=>false, :fan_access=>false, :description=>\"Private session set up just to test things out in the session interface by myself.\", :genres=>[{:id=>\"pop\", :description=>\"Pop\"}], :invitees=>[]}", + "show_whats_next": true, + "show_whats_next_count": 0, + "subscribe_email": false, + "auth_twitter": false, + "new_notifications": 14, + "sales_count": 7, + "purchased_jamtracks_count": 1, + "first_downloaded_client_at": null, + "created_at": "2021-05-21T18:15:28.425Z", + "first_opened_jamtrack_web_player": "2024-12-03T13:55:01.788Z", + "gifted_jamtracks": 0, + "has_redeemable_jamtrack": false, + "has_stored_credit_card?": true, + "remaining_test_drives": 0, + "jamclass_credits": 0, + "can_buy_test_drive?": true, + "lesson_package_type_id": null, + "school_id": null, + "is_guitar_center_student?": false, + "purchase_required": null, + "lesson_package_needs_purchase_id": null, + "user_authorizations": [ + { + "uid": "RQB3YMV6KABBL", + "provider": "paypal", + "token_expiration": "2025-07-14T14:47:06.651Z" + } + ], + "test_drive_package_choices": [], + "friends": [ + { + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "first_name": "Seth", + "last_name": "Call", + "name": "Seth Call", + "online": false, + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + } + ], + "followings": [ + { + "type": "user", + "id": "963d5268-66b6-463a-a3ee-c97f274fc23f", + "name": "Peter Walker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "cc0b060c-9891-4e91-9fe3-4268893a2fd0", + "name": "Oswald Becca", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "29becbf4-8be5-4078-9405-0edadc9fa42d", + "name": "Peter 1 Walker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "3dfca858-0e7c-4ad4-993a-c39421d93853", + "name": "Peter Walker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fd467978-da75-421f-8e97-6406a784e87e", + "name": "Indrashapa Liyanage", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "name": "Seth Call", + "location": "Boston, MA", + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + }, + { + "type": "user", + "id": "2e75f1dc-af6b-4444-a9e2-5f32db07abc1", + "name": "David Wilson 1", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f8f32710-3194-4666-b618-eceb21d6e3de", + "name": "Peter Walker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "feb671a3-1821-48f0-bc14-aa26cf98bb25", + "name": "David Wilson", + "location": "Miami, FL", + "photo_url": null + }, + { + "type": "user", + "id": "c2ede005-3b3a-4227-b6fc-f7e8b946b556", + "name": "Test 2 User", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "bcf99b5c-8fee-47ce-bf51-b3c7b821d023", + "name": "David Miller", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1f9debf3-58d7-46c0-896c-859b6ae8be37", + "name": "David Miller", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "876d1604-d309-429a-8046-e034ce1bcea4", + "name": "David Miller", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "name": "Nuwan Chaturanga", + "location": "Dallas, TX", + "photo_url": null + }, + { + "type": "user", + "id": "062168d9-3e7e-41ee-b8e8-9f496b8cb97a", + "name": "James Bond", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "5c2b1a45-5212-4a73-b5ce-007c345d97b7", + "name": "Makenna Gutmann Celestino Hand", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e2eca6b2-56d9-450a-8ac4-7d107a488887", + "name": "Grace Roob Cynthia Cronin", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b1ddadd0-0263-47c4-bf91-e7767f386970", + "name": "Oswald Becca", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0671faf1-7e39-45e3-ba9b-a3e27982e88f", + "name": "Carey Carroll Yolanda Ankunding", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1e94859c-b192-4bc8-9d8e-6a3ef5ec1380", + "name": "Filiberto Hills IV Anya Keebler MD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "749d3a9f-11fc-4593-827c-b47d0da1322e", + "name": "RashawnMante ThurmanFadel", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "6ceb102f-2f99-46dd-8baa-d1b1c357118f", + "name": "ObieJenkins EddNienow", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "042ef11a-f2ad-4e80-85d8-cf94a502e298", + "name": "TobinFisher MatildaKiehn", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f0ca8d87-dd9e-4d9f-afc1-ff543f29d371", + "name": "MrsOrionSchoen CurtisChristiansenV", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fc3496a2-9f73-47ed-a755-02011afddded", + "name": "TristonRunolfsson DrJoyHoppe", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "16a32d1e-901e-460a-bd9a-d400b91ec5d5", + "name": "DrPatrickDuBuque JeanneVeum", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "7e43ae3e-47b2-4510-a688-91c209e5d271", + "name": "MrsEverardoWillms JadonGreenholt", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b39034cf-0f02-44a3-ac46-1e79f561e22f", + "name": "AmberOConner NoelMedhurst", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "9f7e3f8e-9ea1-41a5-a589-60ff27b40e74", + "name": "ErnestinaGrady CarlieLubowitz", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "5501a1a7-670d-45b9-bf2f-e644c3d8ae65", + "name": "MaryamAltenwerth MoseDavisDDS", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "5473d024-0dd2-434b-bea2-ed1b959f6eb8", + "name": "TyreeKlocko MarcusCartwright", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "a8e2ceda-51a7-4b67-87bb-5ddab937127d", + "name": "DaleNicolas ErnieBalistreriSr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "819f1fff-4c76-45b8-a97f-e3ae23c44d38", + "name": "TerenceRosenbaum BenedictOReillyPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "caaa6dbe-d44f-4283-82b9-31e2feef8552", + "name": "RichardSchmeler SteveMante", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b1faa4a9-aa95-46da-98ef-d9a110cf19db", + "name": "CharlesChamplinSr SofiaBernierSr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "aae38d6a-571b-453c-b84d-ac377e7dd518", + "name": "MabelCasperPhD TyrelStroman", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8bac8af0-f348-4d38-9c8b-3864c21819fa", + "name": "DoyleParisian VelmaMarquardt", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "bae12f4f-b8a6-4cfb-8cfb-3a97293011fb", + "name": "FriedrichMaggioSr IvyBergePhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "492b11ae-46d3-4e77-8a0a-8550cf924fcc", + "name": "PierreJaskolski MrCurtTremblay", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f739a1ab-25e7-4713-9914-8c3993b34ac2", + "name": "FreedaConnelly ZoraRyanIV", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "da55a63e-822c-4b00-a1ff-43d1c77dd9da", + "name": "MrDarrelHilpert AliaLemke", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "9b3fccc7-3341-497e-943b-4223470c4d2e", + "name": "JudahMurphy MsRandallWalsh", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e0ff0bfb-f7f7-4a59-8fe9-b3271a436bff", + "name": "MorganRempel DestineyTrompDDS", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e6659aab-3b85-4fcf-b238-9784e8fa0c87", + "name": "JettBartell RayHuels", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fa8520ee-dbbc-4c82-8a3a-3eb7a2e670b9", + "name": "DorthyRitchie EthelynConroy", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "c99366a3-1ca5-4be0-b241-d5ab251e2128", + "name": "MrsJerrodWill MissHassanMcDermott", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "5545474c-72ae-439e-b15e-ea01d8024e9a", + "name": "JonatanBaumbach IsadoreMohrDVM", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1de82b84-509f-4b44-8e57-83a4c84ddb65", + "name": "MableSporerI KarleeWestPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "c6105907-18f0-4328-8612-4a3712a87589", + "name": "TaniaOConnell MorrisJast", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "3befd488-1e79-4a0f-9195-55627345a896", + "name": "MissTremayneVonRueden MargarettQuigley", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ba54b319-f774-4df1-9998-079518bafb71", + "name": "AllyConn MissKimberlyHoppe", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "58d673f1-d8a0-4afa-9a88-39b890d1d97f", + "name": "AlvaHettinger AngelitaLeffler", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "bb141f5b-3871-45a8-9aec-c0e7caea97be", + "name": "JasperHodkiewicz PaytonBartonPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b8e10ae9-8d1b-4046-94c2-85d836c11819", + "name": "FreddyGrahamII ImeldaTrantow", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "db342b5a-a353-44cf-afa1-01106adfd4e2", + "name": "GavinBednar JosianeWelch", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "677457e3-fd7f-408e-939d-d3315037f00d", + "name": "DarrionMosciski NicoletteAufderhar", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b01bb2c0-a584-49fe-ab49-818a7fd693a5", + "name": "AbigaleOHara BernhardZiemann", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "af974075-2c2a-43ac-927b-2e3213b7fd56", + "name": "MissBreanneKunde JuliaLeannon", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "97d4fba3-fab5-4153-bf05-7466624ea6bd", + "name": "ImeldaFranecki LeolaWisozk", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8680fef5-5731-4b7c-9baf-e984bdef572e", + "name": "VernerWunsch SallyHeathcote", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0afab59f-2ac2-4187-8b9e-51a008c37f82", + "name": "TadDicki HeatherKertzmann", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "dc4ebae1-99e1-44fc-a8d8-6f45c90250d9", + "name": "DrKennithMetz BobbyWilderman", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "7aaa8b68-c6d9-4085-87d0-177e4252a09f", + "name": "BradenMosciskiII SterlingWilkinson", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "c51736bd-1110-43ba-a47a-72e90d12c7d1", + "name": "JakobKub MsDaneGulgowski", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8d18316e-79e1-4a6e-889c-8151de8ac20f", + "name": "KyleeStamm AutumnBruenPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "18138725-f91c-4a12-a04d-43d73951559a", + "name": "NatHowell AbigaleAbshireSr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "06803beb-8218-41db-ba3b-87ffabcfe59f", + "name": "BoydRosenbaum MrIsabellMedhurst", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "24c88514-5966-4977-b6a5-d14d71ed51a7", + "name": "DashawnSpencer EstellMcDermottMD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "3a0fe418-0d87-422b-b9d7-62350e4d6e06", + "name": "JaunitaHerzog WestleyKovacek", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "59b19985-f2ac-4a39-94a2-7a1b7d4a1589", + "name": "OrlandWehner WayneAufderhar", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "60a55a0f-33cf-49e3-8acb-d055f0d57b8d", + "name": "AntoniaDach MissArvelCrooks", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ccba202e-90d4-4204-a590-d0b385fff0b2", + "name": "MissEnricoSatterfield FredFeeney", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ffd059fc-86ca-4e5b-ae68-428fc9a7c151", + "name": "MrsLexusMayer ArianeSchroeder", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "846b2313-cf96-47a1-b747-28529f713f57", + "name": "MrAshleyGreen DedrickTurner", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "893a2561-be87-4bbe-b0a4-e3ebfdf66bce", + "name": "GillianTowne VicentaRobelDDS", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "d28c8e9f-958b-4d7d-bd27-bcbf7e40276c", + "name": "AnselCorkery WellingtonBalistreri", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1d6ebd32-5263-4d4c-b1cb-ece2c52d4639", + "name": "DrAshtynSchowalter RosaleeHuelPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "13782f1a-d49c-4e51-bffb-03c2ab5466b9", + "name": "DedrickCronin MaximusJones", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1847fa77-3c6c-45e6-a2fd-713c97b13bc8", + "name": "BillKoepp CristinaWisoky", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "127d364c-b608-452d-b9d2-870374669ac4", + "name": "JanieMarvin AbbieCollins", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "a94e2132-b59c-421f-8956-8da3da67edc3", + "name": "TrevorBogan MsJoanieHaag", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "996ca813-6994-4f08-ab55-a086d688f5a8", + "name": "AlainaDooleySr KianKulas", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f49925f2-3934-4bc2-9dbe-61ab3d2d0d2a", + "name": "BrennanKautzer BurdetteDonnelly", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "813e7f84-8c69-4a5b-97e4-7f3278d589b6", + "name": "BennieConn CelestinoHamill", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "9eeec010-029b-4cac-b4ea-a3ac6256bada", + "name": "ElsaRempel BurniceLabadie", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1b35f8f4-1c9c-4e72-bd54-052ab3b33745", + "name": "JoannieGlover ClarabelleLubowitz", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "6f732065-9e64-487c-88e3-713c49db7dd1", + "name": "LuciousMuller MiaPurdy", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "25c21fbf-ddcc-4224-86c6-8f8b3db64406", + "name": "KiarraVolkman DelphiaOReillyJr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "60f9a9c1-2e1f-41e1-a55a-0ce0a3ccafff", + "name": "JordynOHara YasminDare", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "524299c3-ffec-473a-8b8a-5352f9bb1498", + "name": "ArmandMayerII RomaineOHara", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "91a0d1eb-b9ce-453f-ae01-04ab932b1d88", + "name": "PhoebeMertz ErichHand", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "d3db5d12-51fd-4267-9972-32d0e08ba5a0", + "name": "MrEdwardRyan MarieReynolds", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0caf1682-79de-4e99-977b-6327defb04ae", + "name": "LilianaGibson JillianWintheiser", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8d9319be-9435-476e-a7ee-26a3b4adb519", + "name": "DonnellJacobs MrEttieLakin", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "740e9322-d303-4d7a-b018-5a7ce6f228cf", + "name": "MrTrevorBauch MsTadMante", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ad014131-4ca9-4738-ab04-0abb21988925", + "name": "GoldaLeannon KevinBogisich", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b88a29c3-7d53-40db-a4cd-c74cfa383535", + "name": "MissPrincessStokes EstaHarris", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1047c75a-07f7-464f-9d68-abbe928721d8", + "name": "MissValeriePagac UniqueLowe", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "912d8c9c-ebc4-4c90-939d-a0022fac592f", + "name": "CarolyneYost KhalidHagenes", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "71df5db0-1b97-451e-8d4b-158780ce89b5", + "name": "TraceLarson PercyRempel", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "070fe31e-b2b9-4c40-ba0f-47bd2dea8bed", + "name": "DomenicaHeller MaryHamill", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1c6a4318-74dc-4978-9a6a-cf5218158d09", + "name": "LauraSchumm DomenicWindler", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1e10de58-6426-48c9-b32a-4068181cc902", + "name": "CristalFahey DrTheodoraAuer", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fca4da6e-6307-4239-8369-4c823da291ea", + "name": "ElizaSatterfield JeramyThiel", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "c2007c10-50e2-45b2-b0ec-94d78fca7464", + "name": "DevenCruickshankDVM KoreyCollierSr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fb63837c-1621-4d5c-ae94-5dd4e966850a", + "name": "AmiyaFadel MonicaHyattPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "16031f9b-929a-4b2e-8dca-32ba9d011871", + "name": "RicoSchmeler YasmineBernier", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b07623eb-9064-4bab-b3ac-7f9ed56e70c3", + "name": "MittieHirthe DaneRutherford", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0f4074d2-3f60-4afa-b67e-9aeb606fcf12", + "name": "DominiquePurdy TianaSchaefer", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "751d5835-a58c-4b86-a097-03e764d05e53", + "name": "GenevieveLegros ColleenCorwin", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "de428405-5be2-419f-b488-ad9f4c56fed5", + "name": "MallieWeimann MargaretteCarroll", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0e3574ff-e190-4cc5-8424-d68a32f7814f", + "name": "RobertaKunde LillaKing", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "06d057b1-b13a-4f51-b2dd-02a3a688b414", + "name": "ValentinKoeppSr OlgaCronaPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f1afae38-4740-433c-b2e6-dcd415741052", + "name": "AnyaMorar DrMckenzieVeum", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "079c9ca0-74d3-4a95-9fef-e9e17a123873", + "name": "JasonRempel MrBlancaParisian", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "53c5a997-4dda-423f-a56e-b576b8c5fdb3", + "name": "MsLaverneShanahan GlenHeller", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "faa11323-ee4d-42d0-9400-955723e83d89", + "name": "MissVincenzoGreenholt TheodoraRath", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "94a1c9a4-a44d-4e52-badc-051c4084c193", + "name": "RyleySchusterII MarcelinaHillsI", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ebfcbb8f-5d10-42b8-9260-8a0e5eee8f29", + "name": "MarcelleMaggio MayeParker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "a0c04c7d-1027-43f7-872b-f6150fb1970d", + "name": "TatumVandervort EarleneJohnson", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e3fbc347-f15c-4bc5-9eb0-c10bf26da2dc", + "name": "MissCitlalliHamill NatalieKundeIV", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "241daa8a-3b79-4213-a17c-f3635e100401", + "name": "EverettSwift AyanaStroman", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ad2c50a9-0f56-403d-9df0-0edcece0c701", + "name": "RaoulCremin ReannaConsidine", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "187e18f6-32c8-437f-8292-fdbe09427d2b", + "name": "ClarabelleBeer JackieShields", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e29044fe-45b3-41ae-ab00-eb9913e5daa6", + "name": "BrigitteRenner WillardLabadie", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "bccdc05a-c4d6-4b95-acc6-19f1a6c4abbd", + "name": "DavionJast ChanellePagac", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "67a02f30-f193-4490-9aec-ebf7c6619141", + "name": "FavianMarks EdaKirlin", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "672fc730-8e84-4e9e-97f5-c5dcd93557ba", + "name": "MaximusBatz RyleeMetzDDS", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f1317729-a366-4c19-9765-9f5b1d156f94", + "name": "ChadrickBergnaum RogersBerge", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8ac936dc-3185-47ab-92ad-5b04e470da9f", + "name": "Mateo Antony", + "location": "Austin, TX", + "photo_url": null + } + ], + "bands": [ + { + "id": "32df51d1-e323-4f02-80ba-63229b4861ed", + "name": "Martine Johnston", + "admin": false, + "photo_url": null, + "logo_url": null, + "genres": [ + { + "id": "country", + "description": "Country" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "techno", + "description": "Techno" + } + ] + }, + { + "id": "74f50a3d-df82-47f5-8053-0281bc27403f", + "name": "JMam", + "admin": false, + "photo_url": null, + "logo_url": null, + "genres": [ + { + "id": "blues", + "description": "Blues" + } + ] + }, + { + "id": "fc24a1e0-f212-4418-98d9-f0514e0cc699", + "name": "Uturn", + "admin": false, + "photo_url": null, + "logo_url": null, + "genres": [ + { + "id": "reggae", + "description": "Reggae" + } + ] + } + ], + "instruments": [], + "genres": [ + { + "description": "A Cappella", + "id": "acapella" + }, + { + "description": "African", + "id": "african" + }, + { + "description": "Alternative Rock", + "id": "alternative rock" + }, + { + "description": "Ambient", + "id": "ambient" + }, + { + "description": "Drum & Bass", + "id": "drum & bass" + }, + { + "description": "Electronic", + "id": "electronic" + }, + { + "description": "Folk", + "id": "folk" + }, + { + "description": "Funk", + "id": "funk" + }, + { + "description": "Psychedelic", + "id": "psychedelic" + }, + { + "description": "Punk", + "id": "punk" + }, + { + "description": "R&B", + "id": "r&b" + }, + { + "description": "Rap", + "id": "rap" + } + ], + "sessions": [ + { + "id": "91de1362-bd56-44b2-a39b-8d7fb4d38fa5", + "description": "Private session set up just to test things out in the session interface by myself.", + "musician_access": false, + "approval_required": false, + "fan_access": false + } + ], + "teacher": { + "id": "5fd55476-320d-4532-8ad8-79f9a7d88e20", + "biography": "A teacher experienced teaching music for students from kindergarten to high school. ", + "created_at": "2022-10-20T13:35:33.210Z", + "introductory_video": null, + "lesson_duration_120": false, + "lesson_duration_30": false, + "lesson_duration_45": false, + "lesson_duration_60": true, + "lesson_duration_90": false, + "price_per_lesson_120_cents": null, + "price_per_lesson_30_cents": null, + "price_per_lesson_45_cents": null, + "price_per_lesson_60_cents": 10000, + "price_per_lesson_90_cents": null, + "price_per_month_120_cents": null, + "price_per_month_30_cents": null, + "price_per_month_45_cents": null, + "price_per_month_60_cents": null, + "price_per_month_90_cents": null, + "prices_per_lesson": true, + "prices_per_month": false, + "teaches_advanced": true, + "teaches_age_lower": 3, + "teaches_age_upper": 20, + "teaches_beginner": true, + "teaches_intermediate": true, + "updated_at": "2022-10-20T13:41:50.521Z", + "website": null, + "years_playing": 15, + "years_teaching": 10, + "teaches_test_drive": true, + "test_drives_per_week": 10, + "errors": {}, + "profile_pct": "87.0", + "school_id": null, + "background_check_at": null, + "is_searchable": true, + "review_summary": null, + "school": null, + "recent_reviews": [], + "profile_pct_summary": { + "name_specified": true, + "experiences_teaching": true, + "experiences_education": true, + "experiences_award": true, + "has_stripe_account": null, + "has_teacher_bio": true, + "intro_video": false, + "years_teaching": true, + "years_playing": true, + "instruments_or_subject": true, + "genres": true, + "languages": true, + "teaches_ages_specified": true, + "teaching_level_specified": true, + "has_pricing_specified": true, + "pct": 87 + }, + "instruments": [ + "acoustic guitar", + "drums", + "keyboard", + "voice", + "flute", + "piano" + ], + "subjects": [ + "music-theory", + "composing", + "site-reading", + "guitar-ring" + ], + "genres": [ + "classical", + "folk", + "jazz" + ], + "languages": [ + "EN", + "FR" + ], + "experiences_teaching": [ + { + "name": "Jr. Music Teacher", + "experience_type": "teaching", + "organization": "St. Peters College", + "start_year": 2005, + "end_year": 2010 + } + ], + "experiences_education": [ + { + "name": "Bacholor in Fine arts ", + "experience_type": "education", + "organization": "London Fine Arts University", + "start_year": 2012, + "end_year": 2015 + } + ], + "experiences_award": [ + { + "name": "Best Folk Music Singer", + "experience_type": "award", + "organization": "University of St. Gorge", + "start_year": 2020, + "end_year": null + } + ], + "has_rated_teacher": false + }, + "owned_school_id": null, + "owned_retailer_id": null, + "geoiplocation": null, + "show_free_jamtrack": false, + "show_jamtrack_guide": true, + "mods": {}, + "has_recurly_account": true, + "is_affiliate_partner": false, + "affiliate_referral_count": null, + "affiliate_earnings": null, + "last_jam_audio_latency": 5 + }, + "timestamp": "2026-01-20T10:15:31.924Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/regions?country=US", + "timestamp": "2026-01-20T10:15:31.990Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/countries", + "body": { + "countriesx": [ + { + "countrycode": "US", + "countryname": "United States" + } + ] + }, + "timestamp": "2026-01-20T10:15:31.994Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/shopping_carts?time=1768904131749", + "body": [], + "timestamp": "2026-01-20T10:15:32.023Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "body": { + "next": null, + "jamtracks": [ + { + "id": "1", + "name": "Back in Black", + "description": "This is a JamTrack audio file for use exclusively with the JamKazam service. This JamTrack is a high quality cover of the AC DC song \"Back in Black\".", + "original_artist": "AC DC", + "version": "0", + "year": null, + "duration": 221, + "allow_free": true, + "genres": [ + { + "id": "pop", + "description": "Pop" + }, + { + "id": "rock", + "description": "Rock" + } + ], + "tracks": [ + { + "id": "103dea4d-f2a3-4414-8efe-d2ca378dda60", + "part": "Master Mix", + "instrument": { + "id": "computer", + "description": "Computer", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Master", + "position": 1000, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Master%20Mix-44100-preview-e9a5a63f34b4d523ee1842fff31f88ce.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Master%20Mix-44100-preview-25fcba7ace7086e3cb6b97d7e33ba72e.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Master%20Mix-44100-preview-9f0b072ed9f4b546e170fcdfb302137e.mp3" + }, + { + "id": "2755cbdd-0476-4f3b-9ba1-e2da561ddb4e", + "part": "Lead", + "instrument": { + "id": "voice", + "description": "Voice", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 1, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Vocal%20-%20Lead-44100-preview-d35c328fc3936dad9a79fe102dc72950.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Vocal%20-%20Lead-44100-preview-b97b37651eae352fae3b3060918c7bcb.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Vocal%20-%20Lead-44100-preview-d35c328fc3936dad9a79fe102dc72950.aac" + }, + { + "id": "0db7c4e1-5e8d-43fe-bd35-98acd8f68b26", + "part": "Drums", + "instrument": { + "id": "drums", + "description": "Drums", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 2, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Drums-44100-preview-03aadceb966caf40b96334bdd00234f6.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Drums-44100-preview-854914e3e0d6fdc5f0794325b0ecaead.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Drums-44100-preview-03aadceb966caf40b96334bdd00234f6.aac" + }, + { + "id": "2cc79ab6-dab8-4905-85e6-0df5f8e087f1", + "part": "Bass", + "instrument": { + "id": "bass guitar", + "description": "Bass Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 3, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Bass-44100-preview-61c334ac87f811bd010ed3a910764c2e.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Bass-44100-preview-4066dafd7b72e9993b0c0fe1dba2b332.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Bass-44100-preview-61c334ac87f811bd010ed3a910764c2e.aac" + }, + { + "id": "ed1d3487-3b32-442f-9c76-8a36fe3bb643", + "part": "Solo", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 4, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Solo-44100-preview-e9fe8572a9ac1022762642cbd92b3c34.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Solo-44100-preview-5fb058042254206cfa9fb4dcb0310b2c.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Solo-44100-preview-e9fe8572a9ac1022762642cbd92b3c34.aac" + }, + { + "id": "f4ce7c91-7542-4e03-8fc2-68b31683d33e", + "part": "Rhythm 1", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 5, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%201-44100-preview-6b498479823d4131a01fa535817d5eab.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%201-44100-preview-f4cbb31dbde3e1a3e6012730a7e0e10f.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%201-44100-preview-6b498479823d4131a01fa535817d5eab.aac" + }, + { + "id": "2d96c7ec-59f1-4d56-8a7f-7f4c75a0ccef", + "part": "Rhythm 2", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 6, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%202-44100-preview-a626d7c632560f6737e1b6024141289e.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%202-44100-preview-06a0e5af451f001f3465992efcd34ec0.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%202-44100-preview-a626d7c632560f6737e1b6024141289e.aac" + }, + { + "id": "fce018ca-c897-4137-aa10-ef56a8e1831f", + "part": "Intro Scrapes", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 7, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Intro%20Scrapes-44100-preview-0ddfaa7154e9ba35d05d60477d5dd3e9.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Intro%20Scrapes-44100-preview-f53ce3c5f9dcf81af51560f52635fbb0.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Intro%20Scrapes-44100-preview-0ddfaa7154e9ba35d05d60477d5dd3e9.aac" + }, + { + "id": "c9b3e0a8-4db0-4d0f-9769-398a6d56506e", + "part": "Main", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 8, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Main-44100-preview-234a224f75a97d7ff8f55442ece6fcde.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Main-44100-preview-828c9691f5435dea1c90182fa2618c9b.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Main-44100-preview-234a224f75a97d7ff8f55442ece6fcde.aac" + }, + { + "id": "28c3df07-2a88-45a9-9ae6-3399a5d2eb20", + "part": "Sound FX", + "instrument": { + "id": "computer", + "description": "Computer", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 9, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Sound%20Effects-44100-preview-6c859c73036cd55bceb65f19f2d2f2f3.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Sound%20Effects-44100-preview-f840d8df4c7388f776477139025ee712.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Sound%20Effects-44100-preview-6c859c73036cd55bceb65f19f2d2f2f3.aac" + } + ], + "jmep": null, + "can_download": true, + "jam_track_right_id": 1428, + "purchased_at": 1752755050, + "last_mixdown_id": null, + "last_stem_id": null, + "mixdowns": [ + { + "id": "5f24403f-3cfa-44f5-b36e-52b2c3c66af8", + "name": "db", + "description": null, + "jam_track_id": "1", + "packages": [ + { + "id": "23b10fa0-195d-4ad5-a5a7-2cba6b8c1451", + "jam_track_mixdown_id": "5f24403f-3cfa-44f5-b36e-52b2c3c66af8", + "file_type": "mp3", + "sample_rate": 48, + "encrypt_type": null, + "error_count": 0, + "error_reason": null, + "error_detail": null, + "signing_state": "SIGNED", + "packaging_steps": 10, + "current_packaging_step": 8, + "version": "1" + } + ], + "created_at": 1753866891, + "settings": { + "count-in": false, + "tracks": [ + { + "id": "2755cbdd-0476-4f3b-9ba1-e2da561ddb4e", + "mute": false + }, + { + "id": "0db7c4e1-5e8d-43fe-bd35-98acd8f68b26", + "mute": true + }, + { + "id": "2cc79ab6-dab8-4905-85e6-0df5f8e087f1", + "mute": true + }, + { + "id": "ed1d3487-3b32-442f-9c76-8a36fe3bb643", + "mute": false + }, + { + "id": "f4ce7c91-7542-4e03-8fc2-68b31683d33e", + "mute": false + }, + { + "id": "2d96c7ec-59f1-4d56-8a7f-7f4c75a0ccef", + "mute": false + }, + { + "id": "fce018ca-c897-4137-aa10-ef56a8e1831f", + "mute": false + }, + { + "id": "c9b3e0a8-4db0-4d0f-9769-398a6d56506e", + "mute": false + }, + { + "id": "28c3df07-2a88-45a9-9ae6-3399a5d2eb20", + "mute": false + } + ] + } + } + ] + } + ] + }, + "timestamp": "2026-01-20T10:15:32.051Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/teacher_distributions?per_page=20&page=1", + "body": { + "next": null, + "entries": [], + "total_entries": 0 + }, + "timestamp": "2026-01-20T10:15:32.066Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/regions?country=US", + "body": { + "regions": [ + { + "region": "TN", + "name": null + }, + { + "region": "ME", + "name": null + }, + { + "region": "MA", + "name": null + }, + { + "region": "TX", + "name": null + }, + { + "region": "OK", + "name": null + }, + { + "region": "WA", + "name": null + }, + { + "region": "CO", + "name": null + }, + { + "region": "CA", + "name": null + }, + { + "region": "AR", + "name": null + }, + { + "region": "FL", + "name": null + }, + { + "region": "OR", + "name": null + } + ] + }, + "timestamp": "2026-01-20T10:15:32.103Z" + }, + { + "type": "request", + "method": "POST", + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "timestamp": "2026-01-20T10:15:33.727Z" + }, + { + "type": "request", + "method": "POST", + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "timestamp": "2026-01-20T10:15:33.727Z" + }, + { + "type": "request", + "method": "POST", + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "timestamp": "2026-01-20T10:15:33.938Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "timestamp": "2026-01-20T10:15:33.961Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "body": {}, + "timestamp": "2026-01-20T10:15:33.982Z" + }, + { + "type": "request", + "method": "POST", + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "timestamp": "2026-01-20T10:15:34.127Z" + }, + { + "type": "response", + "status": 200, + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "body": { + "sys": { + "links": { + "jsBaseUrl": "https://www.paypalobjects.com/js", + "cssBaseUrl": "https://www.paypalobjects.com/css", + "templateBaseUrl": "https://www.paypalobjects.com/templates", + "resourceBaseUrl": "https://www.paypalobjects.com" + }, + "pageInfo": { + "date": "Jan 20, 2026 02:15:35 -08:00", + "hostName": "rZJvnqaaQhLn/nmWT8cSUm+72VQ7inHLaJWglONBKZidoX3x872XyrblxCswbFTs", + "rlogId": "rZJvnqaaQhLn%2FnmWT8cSUmDP%2Bhip7g49eFYVqbGPqtrf2bBDJkc3ApX7eOn4zPgHzVvfQ%2FRZyr2ZbZk1neOgTw_19bdae7115d", + "script": "node", + "debug": null + }, + "locality": { + "timezone": { + "determiner": "viaCowPrimary", + "value": "Europe/London" + }, + "country": "GB", + "locale": "en_GB", + "language": "en", + "directionality": "ltr" + }, + "tracking": { + "fpti": { + "name": "pta", + "jsURL": "https://www.paypalobjects.com", + "serverURL": "https://t.paypal.com/ts", + "dataString": "pgrp=loggernodeweb%2F.dust&page=loggernodeweb%2F.dust&pgst=1768904135005&calc=c9c0dcfba5c8d&pgtf=Nodejs&env=live&s=ci&csci=d2f93731b4d847fab93e4bacf98d6b9f&comp=loggernodeweb&tsrce=loggernodeweb&cu=0" + } + } + } + }, + "timestamp": "2026-01-20T10:15:35.374Z" + }, + { + "type": "response", + "status": 200, + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "body": { + "sys": { + "links": { + "jsBaseUrl": "https://www.paypalobjects.com/js", + "cssBaseUrl": "https://www.paypalobjects.com/css", + "templateBaseUrl": "https://www.paypalobjects.com/templates", + "resourceBaseUrl": "https://www.paypalobjects.com" + }, + "pageInfo": { + "date": "Jan 20, 2026 02:15:35 -08:00", + "hostName": "rZJvnqaaQhLn/nmWT8cSUm+72VQ7inHLaJWglONBKZiuoJ4b1VbpfZeGpB3uzTzS", + "rlogId": "rZJvnqaaQhLn%2FnmWT8cSUmDP%2Bhip7g49eFYVqbGPqtrf2bBDJkc3ApX7eOn4zPgH3GBo%2BZql3DSO8ky8l%2Bvlcg_19bdae71183", + "script": "node", + "debug": null + }, + "locality": { + "timezone": { + "determiner": "viaCowPrimary", + "value": "Europe/London" + }, + "country": "GB", + "locale": "en_GB", + "language": "en", + "directionality": "ltr" + }, + "tracking": { + "fpti": { + "name": "pta", + "jsURL": "https://www.paypalobjects.com", + "serverURL": "https://t.paypal.com/ts", + "dataString": "pgrp=loggernodeweb%2F.dust&page=loggernodeweb%2F.dust&pgst=1768904135043&calc=c9c0dcfbaad58&pgtf=Nodejs&env=live&s=ci&csci=98d8e5835f5a41788e44f464b679284e&comp=loggernodeweb&tsrce=loggernodeweb&cu=0" + } + } + } + }, + "timestamp": "2026-01-20T10:15:35.486Z" + }, + { + "type": "response", + "status": 200, + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "body": { + "sys": { + "links": { + "jsBaseUrl": "https://www.paypalobjects.com/js", + "cssBaseUrl": "https://www.paypalobjects.com/css", + "templateBaseUrl": "https://www.paypalobjects.com/templates", + "resourceBaseUrl": "https://www.paypalobjects.com" + }, + "pageInfo": { + "date": "Jan 20, 2026 02:15:35 -08:00", + "hostName": "rZJvnqaaQhLn/nmWT8cSUm+72VQ7inHLStXCyV93GFn36WWOrvaJWXcvkneqZHgn", + "rlogId": "rZJvnqaaQhLn%2FnmWT8cSUmDP%2Bhip7g49eFYVqbGPqtoKNLH9qKaECAabVc0H0XTqy7A2sopRrt7bDU04eiP7vw_19bdae71186", + "script": "node", + "debug": null + }, + "locality": { + "timezone": { + "determiner": "viaCowPrimary", + "value": "Europe/London" + }, + "country": "GB", + "locale": "en_GB", + "language": "en", + "directionality": "ltr" + }, + "tracking": { + "fpti": { + "name": "pta", + "jsURL": "https://www.paypalobjects.com", + "serverURL": "https://t.paypal.com/ts", + "dataString": "pgrp=loggernodeweb%2F.dust&page=loggernodeweb%2F.dust&pgst=1768904135046&calc=c9c0dcfbaad76&pgtf=Nodejs&env=live&s=ci&csci=195269ac8ab94c9fa71eed4a1fcbb317&comp=loggernodeweb&tsrce=loggernodeweb&cu=0" + } + } + } + }, + "timestamp": "2026-01-20T10:15:35.486Z" + }, + { + "type": "response", + "status": 200, + "url": "https://www.paypal.com/xoplatform/logger/api/logger", + "body": { + "sys": { + "links": { + "jsBaseUrl": "https://www.paypalobjects.com/js", + "cssBaseUrl": "https://www.paypalobjects.com/css", + "templateBaseUrl": "https://www.paypalobjects.com/templates", + "resourceBaseUrl": "https://www.paypalobjects.com" + }, + "pageInfo": { + "date": "Jan 20, 2026 02:15:35 -08:00", + "hostName": "rZJvnqaaQhLn/nmWT8cSUjOx898qoYZ05BM1WeASkiTC1lMNecizbAb3z5P+V0cj", + "rlogId": "rZJvnqaaQhLn%2FnmWT8cSUmDP%2Bhip7g49eFYVqbGPqtotnrsc1WDtEja07oBzcISs7A3SS999oZ7PoIASS0ooAA_19bdae711c3", + "script": "node", + "debug": null + }, + "locality": { + "timezone": { + "determiner": "viaCowPrimary", + "value": "Europe/London" + }, + "country": "GB", + "locale": "en_GB", + "language": "en", + "directionality": "ltr" + }, + "tracking": { + "fpti": { + "name": "pta", + "jsURL": "https://www.paypalobjects.com", + "serverURL": "https://t.paypal.com/ts", + "dataString": "pgrp=loggernodeweb%2F.dust&page=loggernodeweb%2F.dust&pgst=1768904135107&calc=c9c0dcfbaee21&pgtf=Nodejs&env=live&s=ci&csci=d7590a1b18554dfc81e36d95bfcde895&comp=loggernodeweb&tsrce=loggernodeweb&cu=0" + } + } + } + }, + "timestamp": "2026-01-20T10:15:35.913Z" + } +] \ No newline at end of file diff --git a/jam-ui/test/fixtures/legacy-sequences/step-2-dashboard-sequence.json b/jam-ui/test/fixtures/legacy-sequences/step-2-dashboard-sequence.json new file mode 100644 index 000000000..e33242443 --- /dev/null +++ b/jam-ui/test/fixtures/legacy-sequences/step-2-dashboard-sequence.json @@ -0,0 +1,2022 @@ +[ + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "timestamp": "2026-01-20T10:15:41.765Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "timestamp": "2026-01-20T10:15:41.766Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "timestamp": "2026-01-20T10:15:41.815Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": "2026-01-20T10:15:41.816Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications?offset=0&limit=20", + "timestamp": "2026-01-20T10:15:41.816Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "timestamp": "2026-01-20T10:15:41.927Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": "2026-01-20T10:15:41.927Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "timestamp": "2026-01-20T10:15:41.927Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/languages", + "timestamp": "2026-01-20T10:15:41.927Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "timestamp": "2026-01-20T10:15:41.927Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/subjects", + "timestamp": "2026-01-20T10:15:41.928Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/chat?type=CHAT_MESSAGE&limit=20&page=0&channel=global", + "timestamp": "2026-01-20T10:15:41.928Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/genres", + "body": [ + { + "id": "acapella", + "description": "A Cappella" + }, + { + "id": "african", + "description": "African" + }, + { + "id": "alternative rock", + "description": "Alternative Rock" + }, + { + "id": "ambient", + "description": "Ambient" + }, + { + "id": "americana", + "description": "Americana" + }, + { + "id": "asian", + "description": "Asian" + }, + { + "id": "avante-garde", + "description": "Avante-Garde" + }, + { + "id": "bluegrass", + "description": "Bluegrass" + }, + { + "id": "blues", + "description": "Blues" + }, + { + "id": "breakbeat", + "description": "Breakbeat" + }, + { + "id": "celtic", + "description": "Celtic" + }, + { + "id": "classical", + "description": "Classical" + }, + { + "id": "country", + "description": "Country" + }, + { + "id": "creole", + "description": "Creole" + }, + { + "id": "dance", + "description": "Dance" + }, + { + "id": "disco", + "description": "Disco" + }, + { + "id": "downtempo", + "description": "Downtempo" + }, + { + "id": "drum & bass", + "description": "Drum & Bass" + }, + { + "id": "electronic", + "description": "Electronic" + }, + { + "id": "folk", + "description": "Folk" + }, + { + "id": "funk", + "description": "Funk" + }, + { + "id": "hard rock", + "description": "Hard Rock" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "holiday", + "description": "Holiday" + }, + { + "id": "house", + "description": "House" + }, + { + "id": "industrial", + "description": "Industrial" + }, + { + "id": "jazz", + "description": "Jazz" + }, + { + "id": "kids", + "description": "Kids" + }, + { + "id": "latin", + "description": "Latin" + }, + { + "id": "metal", + "description": "Metal" + }, + { + "id": "musical", + "description": "Musical" + }, + { + "id": "oldies", + "description": "Oldies" + }, + { + "id": "other", + "description": "Other" + }, + { + "id": "pop", + "description": "Pop" + }, + { + "id": "psychedelic", + "description": "Psychedelic" + }, + { + "id": "punk", + "description": "Punk" + }, + { + "id": "r&b", + "description": "R&B" + }, + { + "id": "rap", + "description": "Rap" + }, + { + "id": "reggae", + "description": "Reggae" + }, + { + "id": "religious", + "description": "Religious" + }, + { + "id": "rock", + "description": "Rock" + }, + { + "id": "ska", + "description": "Ska" + }, + { + "id": "soft rock", + "description": "Soft Rock" + }, + { + "id": "soul", + "description": "Soul" + }, + { + "id": "tv & movie soundtrack", + "description": "TV & Movie Soundtrack" + }, + { + "id": "techno", + "description": "Techno" + }, + { + "id": "traditional", + "description": "Traditional" + }, + { + "id": "trance", + "description": "Trance" + }, + { + "id": "world", + "description": "World" + } + ], + "timestamp": "2026-01-20T10:15:42.456Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/instruments", + "body": [ + { + "id": "accordion", + "description": "Accordion", + "popularity": 2 + }, + { + "id": "acoustic guitar", + "description": "Acoustic Guitar", + "popularity": 3 + }, + { + "id": "bagpipes", + "description": "Bagpipes", + "popularity": 1 + }, + { + "id": "banjo", + "description": "Banjo", + "popularity": 2 + }, + { + "id": "bass guitar", + "description": "Bass Guitar", + "popularity": 3 + }, + { + "id": "bassoon", + "description": "Bassoon", + "popularity": 1 + }, + { + "id": "cello", + "description": "Cello", + "popularity": 1 + }, + { + "id": "charango", + "description": "Charango", + "popularity": 1 + }, + { + "id": "clarinet", + "description": "Clarinet", + "popularity": 2 + }, + { + "id": "computer", + "description": "Computer", + "popularity": 3 + }, + { + "id": "dobro", + "description": "Dobro", + "popularity": 1 + }, + { + "id": "double bass", + "description": "Double Bass", + "popularity": 2 + }, + { + "id": "drums", + "description": "Drums", + "popularity": 3 + }, + { + "id": "electric guitar", + "description": "Electric Guitar", + "popularity": 3 + }, + { + "id": "euphonium", + "description": "Euphonium", + "popularity": 1 + }, + { + "id": "flugelhorn", + "description": "Flugelhorn", + "popularity": 1 + }, + { + "id": "flute", + "description": "Flute", + "popularity": 2 + }, + { + "id": "french horn", + "description": "French Horn", + "popularity": 1 + }, + { + "id": "glockenspiel", + "description": "Glockenspiel", + "popularity": 1 + }, + { + "id": "harmonica", + "description": "Harmonica", + "popularity": 2 + }, + { + "id": "harp", + "description": "Harp", + "popularity": 1 + }, + { + "id": "keyboard", + "description": "Keyboard", + "popularity": 3 + }, + { + "id": "mandolin", + "description": "Mandolin", + "popularity": 1 + }, + { + "id": "oboe", + "description": "Oboe", + "popularity": 1 + }, + { + "id": "orchestra", + "description": "Orchestra", + "popularity": 1 + }, + { + "id": "other", + "description": "Other", + "popularity": 1 + }, + { + "id": "piano", + "description": "Piano", + "popularity": 2 + }, + { + "id": "piccolo", + "description": "Piccolo", + "popularity": 1 + }, + { + "id": "saxophone", + "description": "Saxophone", + "popularity": 2 + }, + { + "id": "sitar", + "description": "Sitar", + "popularity": 1 + }, + { + "id": "steel guitar", + "description": "Steel Guitar", + "popularity": 1 + }, + { + "id": "theremin", + "description": "Theremin", + "popularity": 1 + }, + { + "id": "timpani", + "description": "Timpani", + "popularity": 1 + }, + { + "id": "trombone", + "description": "Trombone", + "popularity": 2 + }, + { + "id": "trumpet", + "description": "Trumpet", + "popularity": 2 + }, + { + "id": "tuba", + "description": "Tuba", + "popularity": 1 + }, + { + "id": "ukulele", + "description": "Ukulele", + "popularity": 1 + }, + { + "id": "viola", + "description": "Viola", + "popularity": 1 + }, + { + "id": "violin", + "description": "Violin", + "popularity": 2 + }, + { + "id": "vocoder", + "description": "Vocoder", + "popularity": 1 + }, + { + "id": "voice", + "description": "Voice", + "popularity": 3 + } + ], + "timestamp": "2026-01-20T10:15:42.707Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications?offset=0&limit=20", + "body": [], + "timestamp": "2026-01-20T10:15:42.707Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "body": [ + { + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "first_name": "Seth", + "last_name": "Call", + "name": "Seth Call", + "location": "Boston, MA", + "city": "Boston", + "state": "MA", + "country": "US", + "musician": true, + "email": "nuwan+6@jamkazam.com", + "online": false, + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + } + ], + "timestamp": "2026-01-20T10:15:42.707Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/genres", + "body": [ + { + "id": "acapella", + "description": "A Cappella" + }, + { + "id": "african", + "description": "African" + }, + { + "id": "alternative rock", + "description": "Alternative Rock" + }, + { + "id": "ambient", + "description": "Ambient" + }, + { + "id": "americana", + "description": "Americana" + }, + { + "id": "asian", + "description": "Asian" + }, + { + "id": "avante-garde", + "description": "Avante-Garde" + }, + { + "id": "bluegrass", + "description": "Bluegrass" + }, + { + "id": "blues", + "description": "Blues" + }, + { + "id": "breakbeat", + "description": "Breakbeat" + }, + { + "id": "celtic", + "description": "Celtic" + }, + { + "id": "classical", + "description": "Classical" + }, + { + "id": "country", + "description": "Country" + }, + { + "id": "creole", + "description": "Creole" + }, + { + "id": "dance", + "description": "Dance" + }, + { + "id": "disco", + "description": "Disco" + }, + { + "id": "downtempo", + "description": "Downtempo" + }, + { + "id": "drum & bass", + "description": "Drum & Bass" + }, + { + "id": "electronic", + "description": "Electronic" + }, + { + "id": "folk", + "description": "Folk" + }, + { + "id": "funk", + "description": "Funk" + }, + { + "id": "hard rock", + "description": "Hard Rock" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "holiday", + "description": "Holiday" + }, + { + "id": "house", + "description": "House" + }, + { + "id": "industrial", + "description": "Industrial" + }, + { + "id": "jazz", + "description": "Jazz" + }, + { + "id": "kids", + "description": "Kids" + }, + { + "id": "latin", + "description": "Latin" + }, + { + "id": "metal", + "description": "Metal" + }, + { + "id": "musical", + "description": "Musical" + }, + { + "id": "oldies", + "description": "Oldies" + }, + { + "id": "other", + "description": "Other" + }, + { + "id": "pop", + "description": "Pop" + }, + { + "id": "psychedelic", + "description": "Psychedelic" + }, + { + "id": "punk", + "description": "Punk" + }, + { + "id": "r&b", + "description": "R&B" + }, + { + "id": "rap", + "description": "Rap" + }, + { + "id": "reggae", + "description": "Reggae" + }, + { + "id": "religious", + "description": "Religious" + }, + { + "id": "rock", + "description": "Rock" + }, + { + "id": "ska", + "description": "Ska" + }, + { + "id": "soft rock", + "description": "Soft Rock" + }, + { + "id": "soul", + "description": "Soul" + }, + { + "id": "tv & movie soundtrack", + "description": "TV & Movie Soundtrack" + }, + { + "id": "techno", + "description": "Techno" + }, + { + "id": "traditional", + "description": "Traditional" + }, + { + "id": "trance", + "description": "Trance" + }, + { + "id": "world", + "description": "World" + } + ], + "timestamp": "2026-01-20T10:15:42.707Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/languages", + "body": [ + { + "id": "EN", + "description": "English" + }, + { + "id": "AF", + "description": "Afrikanns" + }, + { + "id": "SQ", + "description": "Albanian" + }, + { + "id": "AR", + "description": "Arabic" + }, + { + "id": "HY", + "description": "Armenian" + }, + { + "id": "EU", + "description": "Basque" + }, + { + "id": "BN", + "description": "Bengali" + }, + { + "id": "BG", + "description": "Bulgarian" + }, + { + "id": "KM", + "description": "Cambodian" + }, + { + "id": "CA", + "description": "Catalan" + }, + { + "id": "ZH", + "description": "Chinese (Mandarin)" + }, + { + "id": "HR", + "description": "Croation" + }, + { + "id": "CS", + "description": "Czech" + }, + { + "id": "DA", + "description": "Danish" + }, + { + "id": "NL", + "description": "Dutch" + }, + { + "id": "ET", + "description": "Estonian" + }, + { + "id": "FJ", + "description": "Fiji" + }, + { + "id": "FI", + "description": "Finnish" + }, + { + "id": "FR", + "description": "French" + }, + { + "id": "KA", + "description": "Georgian" + }, + { + "id": "DE", + "description": "German" + }, + { + "id": "EL", + "description": "Greek" + }, + { + "id": "GU", + "description": "Gujarati" + }, + { + "id": "HE", + "description": "Hebrew" + }, + { + "id": "HI", + "description": "Hindi" + }, + { + "id": "HU", + "description": "Hungarian" + }, + { + "id": "IS", + "description": "Icelandic" + }, + { + "id": "ID", + "description": "Indonesian" + }, + { + "id": "GA", + "description": "Irish" + }, + { + "id": "IT", + "description": "Italian" + }, + { + "id": "JA", + "description": "Japanese" + }, + { + "id": "JW", + "description": "Javanese" + }, + { + "id": "KO", + "description": "Korean" + }, + { + "id": "LA", + "description": "Latin" + }, + { + "id": "LV", + "description": "Latvian" + }, + { + "id": "LT", + "description": "Lithuanian" + }, + { + "id": "MK", + "description": "Macedonian" + }, + { + "id": "MS", + "description": "Malay" + }, + { + "id": "ML", + "description": "Malayalam" + }, + { + "id": "MT", + "description": "Maltese" + }, + { + "id": "MI", + "description": "Maori" + }, + { + "id": "MR", + "description": "Marathi" + }, + { + "id": "MN", + "description": "Mongolian" + }, + { + "id": "NE", + "description": "Nepali" + }, + { + "id": "NO", + "description": "Norwegian" + }, + { + "id": "FA", + "description": "Persian" + }, + { + "id": "PL", + "description": "Polish" + }, + { + "id": "PT", + "description": "Portuguese" + }, + { + "id": "PA", + "description": "Punjabi" + }, + { + "id": "QU", + "description": "Quechua" + }, + { + "id": "RO", + "description": "Romanian" + }, + { + "id": "RU", + "description": "Russian" + }, + { + "id": "SM", + "description": "Samoan" + }, + { + "id": "SR", + "description": "Serbian" + }, + { + "id": "SK", + "description": "Slovak" + }, + { + "id": "SL", + "description": "Slovenian" + }, + { + "id": "ES", + "description": "Spanish" + }, + { + "id": "SW", + "description": "Swahili" + }, + { + "id": "SV", + "description": "Swedish " + }, + { + "id": "TA", + "description": "Tamil" + }, + { + "id": "TT", + "description": "Tatar" + }, + { + "id": "TE", + "description": "Telugu" + }, + { + "id": "TH", + "description": "Thai" + }, + { + "id": "BO", + "description": "Tibetan" + }, + { + "id": "TO", + "description": "Tonga" + }, + { + "id": "TR", + "description": "Turkish" + }, + { + "id": "UK", + "description": "Ukranian" + }, + { + "id": "UR", + "description": "Urdu" + }, + { + "id": "UZ", + "description": "Uzbek" + }, + { + "id": "VI", + "description": "Vietnamese" + }, + { + "id": "CY", + "description": "Welsh" + }, + { + "id": "XH", + "description": "Xhosa" + } + ], + "timestamp": "2026-01-20T10:15:42.776Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/chat?type=CHAT_MESSAGE&limit=20&page=0&channel=global", + "body": { + "next": null, + "chats": [ + { + "id": "d6e478eb-c2a1-4495-b00a-84fa01aefbb6", + "message": "qq", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-21T07:39:21.357Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "54baff3d-b104-43aa-8747-3ca3cbba3e95", + "message": "tt", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-21T07:38:20.820Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "c5b51493-01d9-4e42-8daa-bf3948b858cc", + "message": "lk", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T22:44:50.270Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "07f67a95-f275-4d39-bae4-1b9b42141d91", + "message": "uu", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T22:43:05.706Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "2802579a-ed5c-4694-862b-f75f764901b6", + "message": "aaaa", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T16:25:51.294Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "cbfc23d4-02d7-4adb-8471-4dc0760ee157", + "message": "ssss", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T16:20:48.827Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "464b5f72-43ad-49bc-a984-4484fd766fca", + "message": "kkk", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T16:15:57.397Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "b5c2585a-aa76-4084-ba8a-ea63949d61b5", + "message": "iiii", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T10:27:57.145Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "f7599110-f15b-4a62-90e9-e1c42fd0b546", + "message": "dfgdfgdfg", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T09:20:10.139Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "9bfdc494-cd3a-496b-b958-102c2027890c", + "message": "This is nuwan", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-09T09:59:22.187Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "a894f396-e896-40f0-b626-d899c1ead63f", + "message": "hi test 1", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2021-09-01T18:44:36.090Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + } + ] + }, + "timestamp": "2026-01-20T10:15:42.782Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/instruments", + "body": [ + { + "id": "accordion", + "description": "Accordion", + "popularity": 2 + }, + { + "id": "acoustic guitar", + "description": "Acoustic Guitar", + "popularity": 3 + }, + { + "id": "bagpipes", + "description": "Bagpipes", + "popularity": 1 + }, + { + "id": "banjo", + "description": "Banjo", + "popularity": 2 + }, + { + "id": "bass guitar", + "description": "Bass Guitar", + "popularity": 3 + }, + { + "id": "bassoon", + "description": "Bassoon", + "popularity": 1 + }, + { + "id": "cello", + "description": "Cello", + "popularity": 1 + }, + { + "id": "charango", + "description": "Charango", + "popularity": 1 + }, + { + "id": "clarinet", + "description": "Clarinet", + "popularity": 2 + }, + { + "id": "computer", + "description": "Computer", + "popularity": 3 + }, + { + "id": "dobro", + "description": "Dobro", + "popularity": 1 + }, + { + "id": "double bass", + "description": "Double Bass", + "popularity": 2 + }, + { + "id": "drums", + "description": "Drums", + "popularity": 3 + }, + { + "id": "electric guitar", + "description": "Electric Guitar", + "popularity": 3 + }, + { + "id": "euphonium", + "description": "Euphonium", + "popularity": 1 + }, + { + "id": "flugelhorn", + "description": "Flugelhorn", + "popularity": 1 + }, + { + "id": "flute", + "description": "Flute", + "popularity": 2 + }, + { + "id": "french horn", + "description": "French Horn", + "popularity": 1 + }, + { + "id": "glockenspiel", + "description": "Glockenspiel", + "popularity": 1 + }, + { + "id": "harmonica", + "description": "Harmonica", + "popularity": 2 + }, + { + "id": "harp", + "description": "Harp", + "popularity": 1 + }, + { + "id": "keyboard", + "description": "Keyboard", + "popularity": 3 + }, + { + "id": "mandolin", + "description": "Mandolin", + "popularity": 1 + }, + { + "id": "oboe", + "description": "Oboe", + "popularity": 1 + }, + { + "id": "orchestra", + "description": "Orchestra", + "popularity": 1 + }, + { + "id": "other", + "description": "Other", + "popularity": 1 + }, + { + "id": "piano", + "description": "Piano", + "popularity": 2 + }, + { + "id": "piccolo", + "description": "Piccolo", + "popularity": 1 + }, + { + "id": "saxophone", + "description": "Saxophone", + "popularity": 2 + }, + { + "id": "sitar", + "description": "Sitar", + "popularity": 1 + }, + { + "id": "steel guitar", + "description": "Steel Guitar", + "popularity": 1 + }, + { + "id": "theremin", + "description": "Theremin", + "popularity": 1 + }, + { + "id": "timpani", + "description": "Timpani", + "popularity": 1 + }, + { + "id": "trombone", + "description": "Trombone", + "popularity": 2 + }, + { + "id": "trumpet", + "description": "Trumpet", + "popularity": 2 + }, + { + "id": "tuba", + "description": "Tuba", + "popularity": 1 + }, + { + "id": "ukulele", + "description": "Ukulele", + "popularity": 1 + }, + { + "id": "viola", + "description": "Viola", + "popularity": 1 + }, + { + "id": "violin", + "description": "Violin", + "popularity": 2 + }, + { + "id": "vocoder", + "description": "Vocoder", + "popularity": 1 + }, + { + "id": "voice", + "description": "Voice", + "popularity": 3 + } + ], + "timestamp": "2026-01-20T10:15:42.823Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "body": [ + { + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "first_name": "Seth", + "last_name": "Call", + "name": "Seth Call", + "location": "Boston, MA", + "city": "Boston", + "state": "MA", + "country": "US", + "musician": true, + "email": "nuwan+6@jamkazam.com", + "online": false, + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + } + ], + "timestamp": "2026-01-20T10:15:42.823Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/genres", + "body": [ + { + "id": "acapella", + "description": "A Cappella" + }, + { + "id": "african", + "description": "African" + }, + { + "id": "alternative rock", + "description": "Alternative Rock" + }, + { + "id": "ambient", + "description": "Ambient" + }, + { + "id": "americana", + "description": "Americana" + }, + { + "id": "asian", + "description": "Asian" + }, + { + "id": "avante-garde", + "description": "Avante-Garde" + }, + { + "id": "bluegrass", + "description": "Bluegrass" + }, + { + "id": "blues", + "description": "Blues" + }, + { + "id": "breakbeat", + "description": "Breakbeat" + }, + { + "id": "celtic", + "description": "Celtic" + }, + { + "id": "classical", + "description": "Classical" + }, + { + "id": "country", + "description": "Country" + }, + { + "id": "creole", + "description": "Creole" + }, + { + "id": "dance", + "description": "Dance" + }, + { + "id": "disco", + "description": "Disco" + }, + { + "id": "downtempo", + "description": "Downtempo" + }, + { + "id": "drum & bass", + "description": "Drum & Bass" + }, + { + "id": "electronic", + "description": "Electronic" + }, + { + "id": "folk", + "description": "Folk" + }, + { + "id": "funk", + "description": "Funk" + }, + { + "id": "hard rock", + "description": "Hard Rock" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "holiday", + "description": "Holiday" + }, + { + "id": "house", + "description": "House" + }, + { + "id": "industrial", + "description": "Industrial" + }, + { + "id": "jazz", + "description": "Jazz" + }, + { + "id": "kids", + "description": "Kids" + }, + { + "id": "latin", + "description": "Latin" + }, + { + "id": "metal", + "description": "Metal" + }, + { + "id": "musical", + "description": "Musical" + }, + { + "id": "oldies", + "description": "Oldies" + }, + { + "id": "other", + "description": "Other" + }, + { + "id": "pop", + "description": "Pop" + }, + { + "id": "psychedelic", + "description": "Psychedelic" + }, + { + "id": "punk", + "description": "Punk" + }, + { + "id": "r&b", + "description": "R&B" + }, + { + "id": "rap", + "description": "Rap" + }, + { + "id": "reggae", + "description": "Reggae" + }, + { + "id": "religious", + "description": "Religious" + }, + { + "id": "rock", + "description": "Rock" + }, + { + "id": "ska", + "description": "Ska" + }, + { + "id": "soft rock", + "description": "Soft Rock" + }, + { + "id": "soul", + "description": "Soul" + }, + { + "id": "tv & movie soundtrack", + "description": "TV & Movie Soundtrack" + }, + { + "id": "techno", + "description": "Techno" + }, + { + "id": "traditional", + "description": "Traditional" + }, + { + "id": "trance", + "description": "Trance" + }, + { + "id": "world", + "description": "World" + } + ], + "timestamp": "2026-01-20T10:15:42.823Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/instruments", + "body": [ + { + "id": "accordion", + "description": "Accordion", + "popularity": 2 + }, + { + "id": "acoustic guitar", + "description": "Acoustic Guitar", + "popularity": 3 + }, + { + "id": "bagpipes", + "description": "Bagpipes", + "popularity": 1 + }, + { + "id": "banjo", + "description": "Banjo", + "popularity": 2 + }, + { + "id": "bass guitar", + "description": "Bass Guitar", + "popularity": 3 + }, + { + "id": "bassoon", + "description": "Bassoon", + "popularity": 1 + }, + { + "id": "cello", + "description": "Cello", + "popularity": 1 + }, + { + "id": "charango", + "description": "Charango", + "popularity": 1 + }, + { + "id": "clarinet", + "description": "Clarinet", + "popularity": 2 + }, + { + "id": "computer", + "description": "Computer", + "popularity": 3 + }, + { + "id": "dobro", + "description": "Dobro", + "popularity": 1 + }, + { + "id": "double bass", + "description": "Double Bass", + "popularity": 2 + }, + { + "id": "drums", + "description": "Drums", + "popularity": 3 + }, + { + "id": "electric guitar", + "description": "Electric Guitar", + "popularity": 3 + }, + { + "id": "euphonium", + "description": "Euphonium", + "popularity": 1 + }, + { + "id": "flugelhorn", + "description": "Flugelhorn", + "popularity": 1 + }, + { + "id": "flute", + "description": "Flute", + "popularity": 2 + }, + { + "id": "french horn", + "description": "French Horn", + "popularity": 1 + }, + { + "id": "glockenspiel", + "description": "Glockenspiel", + "popularity": 1 + }, + { + "id": "harmonica", + "description": "Harmonica", + "popularity": 2 + }, + { + "id": "harp", + "description": "Harp", + "popularity": 1 + }, + { + "id": "keyboard", + "description": "Keyboard", + "popularity": 3 + }, + { + "id": "mandolin", + "description": "Mandolin", + "popularity": 1 + }, + { + "id": "oboe", + "description": "Oboe", + "popularity": 1 + }, + { + "id": "orchestra", + "description": "Orchestra", + "popularity": 1 + }, + { + "id": "other", + "description": "Other", + "popularity": 1 + }, + { + "id": "piano", + "description": "Piano", + "popularity": 2 + }, + { + "id": "piccolo", + "description": "Piccolo", + "popularity": 1 + }, + { + "id": "saxophone", + "description": "Saxophone", + "popularity": 2 + }, + { + "id": "sitar", + "description": "Sitar", + "popularity": 1 + }, + { + "id": "steel guitar", + "description": "Steel Guitar", + "popularity": 1 + }, + { + "id": "theremin", + "description": "Theremin", + "popularity": 1 + }, + { + "id": "timpani", + "description": "Timpani", + "popularity": 1 + }, + { + "id": "trombone", + "description": "Trombone", + "popularity": 2 + }, + { + "id": "trumpet", + "description": "Trumpet", + "popularity": 2 + }, + { + "id": "tuba", + "description": "Tuba", + "popularity": 1 + }, + { + "id": "ukulele", + "description": "Ukulele", + "popularity": 1 + }, + { + "id": "viola", + "description": "Viola", + "popularity": 1 + }, + { + "id": "violin", + "description": "Violin", + "popularity": 2 + }, + { + "id": "vocoder", + "description": "Vocoder", + "popularity": 1 + }, + { + "id": "voice", + "description": "Voice", + "popularity": 3 + } + ], + "timestamp": "2026-01-20T10:15:42.824Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/subjects", + "body": [ + { + "id": "ableton-live", + "description": "Ableton Live" + }, + { + "id": "amplitube", + "description": "AmpliTube" + }, + { + "id": "apple-logic-pro", + "description": "Apple Logic Pro" + }, + { + "id": "arranging", + "description": "Arranging" + }, + { + "id": "composing", + "description": "Composition" + }, + { + "id": "conducting", + "description": "Conducting" + }, + { + "id": "cubase", + "description": "Cubase" + }, + { + "id": "ear-training", + "description": "Ear Training" + }, + { + "id": "fl-studio", + "description": "FL Studio" + }, + { + "id": "film-scoring", + "description": "Film Scoring" + }, + { + "id": "garageband", + "description": "GarageBand" + }, + { + "id": "guitar-ring", + "description": "Guitar Rig" + }, + { + "id": "harmony", + "description": "Harmony" + }, + { + "id": "improvisation", + "description": "Improvisation" + }, + { + "id": "instrument-repair", + "description": "Instrument Repair" + }, + { + "id": "line-6-pod", + "description": "Line 6 Pod" + }, + { + "id": "music-business", + "description": "Music Business" + }, + { + "id": "music-theory", + "description": "Music Theory" + }, + { + "id": "music-therapy", + "description": "Music Therapy" + }, + { + "id": "presonus-studio-one", + "description": "PreSonus Studio One" + }, + { + "id": "pro-tools", + "description": "Pro Tools" + }, + { + "id": "reaper", + "description": "Reaper" + }, + { + "id": "reason", + "description": "Reason" + }, + { + "id": "recording", + "description": "Recording & Production" + }, + { + "id": "site-reading", + "description": "Sight Reading" + }, + { + "id": "sonar", + "description": "Sonar" + }, + { + "id": "songwriting", + "description": "Songwriting" + }, + { + "id": "video-game-scoring", + "description": "Video Game Scoring" + } + ], + "timestamp": "2026-01-20T10:15:42.824Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "timestamp": "2026-01-20T10:15:42.826Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "timestamp": "2026-01-20T10:15:42.829Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "body": { + "version": "2.0.0.1956", + "uri": "http://d48bcgsnmsm6a.cloudfront.net/artifacts/JamClientModern/MacOSX-M/2.0.0.1956/JamKazam-1770.dmg", + "sha1": "2ca2238f4a21a09c32d4a0b6f5fee78b", + "size": 240820609 + }, + "timestamp": "2026-01-20T10:15:42.921Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "body": { + "version": "2.0.0.1956", + "uri": "http://d48bcgsnmsm6a.cloudfront.net/artifacts/JamClientModern/MacOSX-M/2.0.0.1956/JamKazam-1770.dmg", + "sha1": "2ca2238f4a21a09c32d4a0b6f5fee78b", + "size": 240820609 + }, + "timestamp": "2026-01-20T10:15:43.013Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/healthcheck", + "timestamp": "2026-01-20T10:15:43.752Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/healthcheck", + "body": {}, + "timestamp": "2026-01-20T10:15:43.764Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/config/client?", + "timestamp": "2026-01-20T10:15:43.932Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/config/client?", + "body": { + "top_message": null, + "event_page_top_logo_url": "/assets/event/eventbrite-logo.png" + }, + "timestamp": "2026-01-20T10:15:43.946Z" + } +] \ No newline at end of file diff --git a/jam-ui/test/fixtures/legacy-sequences/step-5-session-creation-sequence.json b/jam-ui/test/fixtures/legacy-sequences/step-5-session-creation-sequence.json new file mode 100644 index 000000000..7f260902f --- /dev/null +++ b/jam-ui/test/fixtures/legacy-sequences/step-5-session-creation-sequence.json @@ -0,0 +1,6066 @@ +[ + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "timestamp": "2026-01-20T10:15:55.382Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/countries", + "timestamp": "2026-01-20T10:15:55.437Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/shopping_carts?time=1768904155592", + "timestamp": "2026-01-20T10:15:55.594Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "timestamp": "2026-01-20T10:15:55.655Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "timestamp": "2026-01-20T10:15:55.655Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "timestamp": "2026-01-20T10:15:55.664Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "timestamp": "2026-01-20T10:15:55.734Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": "2026-01-20T10:15:55.734Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "timestamp": "2026-01-20T10:15:55.734Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/instruments", + "timestamp": "2026-01-20T10:15:55.739Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/languages", + "timestamp": "2026-01-20T10:15:55.739Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/genres", + "timestamp": "2026-01-20T10:15:55.740Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/subjects", + "timestamp": "2026-01-20T10:15:55.740Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/chat?type=CHAT_MESSAGE&limit=20&page=0&channel=global", + "timestamp": "2026-01-20T10:15:55.740Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/scheduled?", + "timestamp": "2026-01-20T10:15:55.987Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "timestamp": "2026-01-20T10:15:55.987Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": "2026-01-20T10:15:56.005Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications?offset=0&limit=20", + "timestamp": "2026-01-20T10:15:56.006Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/regions?country=US", + "timestamp": "2026-01-20T10:15:56.009Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "body": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "city": "Dallas", + "state": "TX", + "country": "US", + "location": "Dallas, TX", + "online": true, + "photo_url": null, + "musician": true, + "gender": "M", + "birth_date": null, + "friend_count": 1, + "liker_count": 0, + "follower_count": 77, + "following_count": 130, + "admin": true, + "recording_count": 0, + "session_count": 0, + "biography": "This is description with special charact xxxxxxaaaasasasas", + "favorite_count": 0, + "audio_latency": null, + "upcoming_session_count": 0, + "age": null, + "website": "www.nuwanchaturanga.me", + "skill_level": 2, + "reuse_card": true, + "email_needs_verification": false, + "is_a_teacher": true, + "is_a_student": false, + "is_onboarder": false, + "timezone": null, + "use_video_conferencing_server": true, + "email": "nuwan@jamkazam.com", + "original_fpfile": null, + "cropped_fpfile": null, + "crop_selection": null, + "session_settings": "{:band_id=>nil, :musician_access=>false, :approval_required=>false, :fan_chat=>false, :fan_access=>false, :description=>\"Private session set up just to test things out in the session interface by myself.\", :genres=>[{:id=>\"pop\", :description=>\"Pop\"}], :invitees=>[]}", + "show_whats_next": true, + "show_whats_next_count": 0, + "subscribe_email": false, + "auth_twitter": false, + "new_notifications": 14, + "sales_count": 7, + "purchased_jamtracks_count": 1, + "first_downloaded_client_at": null, + "created_at": "2021-05-21T18:15:28.425Z", + "first_opened_jamtrack_web_player": "2024-12-03T13:55:01.788Z", + "gifted_jamtracks": 0, + "has_redeemable_jamtrack": false, + "has_stored_credit_card?": true, + "remaining_test_drives": 0, + "jamclass_credits": 0, + "can_buy_test_drive?": true, + "lesson_package_type_id": null, + "school_id": null, + "is_guitar_center_student?": false, + "purchase_required": null, + "lesson_package_needs_purchase_id": null, + "user_authorizations": [ + { + "uid": "RQB3YMV6KABBL", + "provider": "paypal", + "token_expiration": "2025-07-14T14:47:06.651Z" + } + ], + "test_drive_package_choices": [], + "friends": [ + { + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "first_name": "Seth", + "last_name": "Call", + "name": "Seth Call", + "online": false, + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + } + ], + "followings": [ + { + "type": "user", + "id": "963d5268-66b6-463a-a3ee-c97f274fc23f", + "name": "Peter Walker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "cc0b060c-9891-4e91-9fe3-4268893a2fd0", + "name": "Oswald Becca", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "29becbf4-8be5-4078-9405-0edadc9fa42d", + "name": "Peter 1 Walker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "3dfca858-0e7c-4ad4-993a-c39421d93853", + "name": "Peter Walker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fd467978-da75-421f-8e97-6406a784e87e", + "name": "Indrashapa Liyanage", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "name": "Seth Call", + "location": "Boston, MA", + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + }, + { + "type": "user", + "id": "2e75f1dc-af6b-4444-a9e2-5f32db07abc1", + "name": "David Wilson 1", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f8f32710-3194-4666-b618-eceb21d6e3de", + "name": "Peter Walker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "feb671a3-1821-48f0-bc14-aa26cf98bb25", + "name": "David Wilson", + "location": "Miami, FL", + "photo_url": null + }, + { + "type": "user", + "id": "c2ede005-3b3a-4227-b6fc-f7e8b946b556", + "name": "Test 2 User", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "bcf99b5c-8fee-47ce-bf51-b3c7b821d023", + "name": "David Miller", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1f9debf3-58d7-46c0-896c-859b6ae8be37", + "name": "David Miller", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "876d1604-d309-429a-8046-e034ce1bcea4", + "name": "David Miller", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "name": "Nuwan Chaturanga", + "location": "Dallas, TX", + "photo_url": null + }, + { + "type": "user", + "id": "062168d9-3e7e-41ee-b8e8-9f496b8cb97a", + "name": "James Bond", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "5c2b1a45-5212-4a73-b5ce-007c345d97b7", + "name": "Makenna Gutmann Celestino Hand", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e2eca6b2-56d9-450a-8ac4-7d107a488887", + "name": "Grace Roob Cynthia Cronin", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b1ddadd0-0263-47c4-bf91-e7767f386970", + "name": "Oswald Becca", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0671faf1-7e39-45e3-ba9b-a3e27982e88f", + "name": "Carey Carroll Yolanda Ankunding", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1e94859c-b192-4bc8-9d8e-6a3ef5ec1380", + "name": "Filiberto Hills IV Anya Keebler MD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "749d3a9f-11fc-4593-827c-b47d0da1322e", + "name": "RashawnMante ThurmanFadel", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "6ceb102f-2f99-46dd-8baa-d1b1c357118f", + "name": "ObieJenkins EddNienow", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "042ef11a-f2ad-4e80-85d8-cf94a502e298", + "name": "TobinFisher MatildaKiehn", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f0ca8d87-dd9e-4d9f-afc1-ff543f29d371", + "name": "MrsOrionSchoen CurtisChristiansenV", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fc3496a2-9f73-47ed-a755-02011afddded", + "name": "TristonRunolfsson DrJoyHoppe", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "16a32d1e-901e-460a-bd9a-d400b91ec5d5", + "name": "DrPatrickDuBuque JeanneVeum", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "7e43ae3e-47b2-4510-a688-91c209e5d271", + "name": "MrsEverardoWillms JadonGreenholt", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b39034cf-0f02-44a3-ac46-1e79f561e22f", + "name": "AmberOConner NoelMedhurst", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "9f7e3f8e-9ea1-41a5-a589-60ff27b40e74", + "name": "ErnestinaGrady CarlieLubowitz", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "5501a1a7-670d-45b9-bf2f-e644c3d8ae65", + "name": "MaryamAltenwerth MoseDavisDDS", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "5473d024-0dd2-434b-bea2-ed1b959f6eb8", + "name": "TyreeKlocko MarcusCartwright", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "a8e2ceda-51a7-4b67-87bb-5ddab937127d", + "name": "DaleNicolas ErnieBalistreriSr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "819f1fff-4c76-45b8-a97f-e3ae23c44d38", + "name": "TerenceRosenbaum BenedictOReillyPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "caaa6dbe-d44f-4283-82b9-31e2feef8552", + "name": "RichardSchmeler SteveMante", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b1faa4a9-aa95-46da-98ef-d9a110cf19db", + "name": "CharlesChamplinSr SofiaBernierSr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "aae38d6a-571b-453c-b84d-ac377e7dd518", + "name": "MabelCasperPhD TyrelStroman", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8bac8af0-f348-4d38-9c8b-3864c21819fa", + "name": "DoyleParisian VelmaMarquardt", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "bae12f4f-b8a6-4cfb-8cfb-3a97293011fb", + "name": "FriedrichMaggioSr IvyBergePhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "492b11ae-46d3-4e77-8a0a-8550cf924fcc", + "name": "PierreJaskolski MrCurtTremblay", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f739a1ab-25e7-4713-9914-8c3993b34ac2", + "name": "FreedaConnelly ZoraRyanIV", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "da55a63e-822c-4b00-a1ff-43d1c77dd9da", + "name": "MrDarrelHilpert AliaLemke", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "9b3fccc7-3341-497e-943b-4223470c4d2e", + "name": "JudahMurphy MsRandallWalsh", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e0ff0bfb-f7f7-4a59-8fe9-b3271a436bff", + "name": "MorganRempel DestineyTrompDDS", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e6659aab-3b85-4fcf-b238-9784e8fa0c87", + "name": "JettBartell RayHuels", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fa8520ee-dbbc-4c82-8a3a-3eb7a2e670b9", + "name": "DorthyRitchie EthelynConroy", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "c99366a3-1ca5-4be0-b241-d5ab251e2128", + "name": "MrsJerrodWill MissHassanMcDermott", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "5545474c-72ae-439e-b15e-ea01d8024e9a", + "name": "JonatanBaumbach IsadoreMohrDVM", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1de82b84-509f-4b44-8e57-83a4c84ddb65", + "name": "MableSporerI KarleeWestPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "c6105907-18f0-4328-8612-4a3712a87589", + "name": "TaniaOConnell MorrisJast", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "3befd488-1e79-4a0f-9195-55627345a896", + "name": "MissTremayneVonRueden MargarettQuigley", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ba54b319-f774-4df1-9998-079518bafb71", + "name": "AllyConn MissKimberlyHoppe", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "58d673f1-d8a0-4afa-9a88-39b890d1d97f", + "name": "AlvaHettinger AngelitaLeffler", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "bb141f5b-3871-45a8-9aec-c0e7caea97be", + "name": "JasperHodkiewicz PaytonBartonPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b8e10ae9-8d1b-4046-94c2-85d836c11819", + "name": "FreddyGrahamII ImeldaTrantow", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "db342b5a-a353-44cf-afa1-01106adfd4e2", + "name": "GavinBednar JosianeWelch", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "677457e3-fd7f-408e-939d-d3315037f00d", + "name": "DarrionMosciski NicoletteAufderhar", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b01bb2c0-a584-49fe-ab49-818a7fd693a5", + "name": "AbigaleOHara BernhardZiemann", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "af974075-2c2a-43ac-927b-2e3213b7fd56", + "name": "MissBreanneKunde JuliaLeannon", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "97d4fba3-fab5-4153-bf05-7466624ea6bd", + "name": "ImeldaFranecki LeolaWisozk", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8680fef5-5731-4b7c-9baf-e984bdef572e", + "name": "VernerWunsch SallyHeathcote", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0afab59f-2ac2-4187-8b9e-51a008c37f82", + "name": "TadDicki HeatherKertzmann", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "dc4ebae1-99e1-44fc-a8d8-6f45c90250d9", + "name": "DrKennithMetz BobbyWilderman", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "7aaa8b68-c6d9-4085-87d0-177e4252a09f", + "name": "BradenMosciskiII SterlingWilkinson", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "c51736bd-1110-43ba-a47a-72e90d12c7d1", + "name": "JakobKub MsDaneGulgowski", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8d18316e-79e1-4a6e-889c-8151de8ac20f", + "name": "KyleeStamm AutumnBruenPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "18138725-f91c-4a12-a04d-43d73951559a", + "name": "NatHowell AbigaleAbshireSr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "06803beb-8218-41db-ba3b-87ffabcfe59f", + "name": "BoydRosenbaum MrIsabellMedhurst", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "24c88514-5966-4977-b6a5-d14d71ed51a7", + "name": "DashawnSpencer EstellMcDermottMD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "3a0fe418-0d87-422b-b9d7-62350e4d6e06", + "name": "JaunitaHerzog WestleyKovacek", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "59b19985-f2ac-4a39-94a2-7a1b7d4a1589", + "name": "OrlandWehner WayneAufderhar", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "60a55a0f-33cf-49e3-8acb-d055f0d57b8d", + "name": "AntoniaDach MissArvelCrooks", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ccba202e-90d4-4204-a590-d0b385fff0b2", + "name": "MissEnricoSatterfield FredFeeney", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ffd059fc-86ca-4e5b-ae68-428fc9a7c151", + "name": "MrsLexusMayer ArianeSchroeder", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "846b2313-cf96-47a1-b747-28529f713f57", + "name": "MrAshleyGreen DedrickTurner", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "893a2561-be87-4bbe-b0a4-e3ebfdf66bce", + "name": "GillianTowne VicentaRobelDDS", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "d28c8e9f-958b-4d7d-bd27-bcbf7e40276c", + "name": "AnselCorkery WellingtonBalistreri", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1d6ebd32-5263-4d4c-b1cb-ece2c52d4639", + "name": "DrAshtynSchowalter RosaleeHuelPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "13782f1a-d49c-4e51-bffb-03c2ab5466b9", + "name": "DedrickCronin MaximusJones", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1847fa77-3c6c-45e6-a2fd-713c97b13bc8", + "name": "BillKoepp CristinaWisoky", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "127d364c-b608-452d-b9d2-870374669ac4", + "name": "JanieMarvin AbbieCollins", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "a94e2132-b59c-421f-8956-8da3da67edc3", + "name": "TrevorBogan MsJoanieHaag", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "996ca813-6994-4f08-ab55-a086d688f5a8", + "name": "AlainaDooleySr KianKulas", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f49925f2-3934-4bc2-9dbe-61ab3d2d0d2a", + "name": "BrennanKautzer BurdetteDonnelly", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "813e7f84-8c69-4a5b-97e4-7f3278d589b6", + "name": "BennieConn CelestinoHamill", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "9eeec010-029b-4cac-b4ea-a3ac6256bada", + "name": "ElsaRempel BurniceLabadie", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1b35f8f4-1c9c-4e72-bd54-052ab3b33745", + "name": "JoannieGlover ClarabelleLubowitz", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "6f732065-9e64-487c-88e3-713c49db7dd1", + "name": "LuciousMuller MiaPurdy", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "25c21fbf-ddcc-4224-86c6-8f8b3db64406", + "name": "KiarraVolkman DelphiaOReillyJr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "60f9a9c1-2e1f-41e1-a55a-0ce0a3ccafff", + "name": "JordynOHara YasminDare", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "524299c3-ffec-473a-8b8a-5352f9bb1498", + "name": "ArmandMayerII RomaineOHara", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "91a0d1eb-b9ce-453f-ae01-04ab932b1d88", + "name": "PhoebeMertz ErichHand", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "d3db5d12-51fd-4267-9972-32d0e08ba5a0", + "name": "MrEdwardRyan MarieReynolds", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0caf1682-79de-4e99-977b-6327defb04ae", + "name": "LilianaGibson JillianWintheiser", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8d9319be-9435-476e-a7ee-26a3b4adb519", + "name": "DonnellJacobs MrEttieLakin", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "740e9322-d303-4d7a-b018-5a7ce6f228cf", + "name": "MrTrevorBauch MsTadMante", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ad014131-4ca9-4738-ab04-0abb21988925", + "name": "GoldaLeannon KevinBogisich", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b88a29c3-7d53-40db-a4cd-c74cfa383535", + "name": "MissPrincessStokes EstaHarris", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1047c75a-07f7-464f-9d68-abbe928721d8", + "name": "MissValeriePagac UniqueLowe", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "912d8c9c-ebc4-4c90-939d-a0022fac592f", + "name": "CarolyneYost KhalidHagenes", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "71df5db0-1b97-451e-8d4b-158780ce89b5", + "name": "TraceLarson PercyRempel", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "070fe31e-b2b9-4c40-ba0f-47bd2dea8bed", + "name": "DomenicaHeller MaryHamill", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1c6a4318-74dc-4978-9a6a-cf5218158d09", + "name": "LauraSchumm DomenicWindler", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1e10de58-6426-48c9-b32a-4068181cc902", + "name": "CristalFahey DrTheodoraAuer", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fca4da6e-6307-4239-8369-4c823da291ea", + "name": "ElizaSatterfield JeramyThiel", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "c2007c10-50e2-45b2-b0ec-94d78fca7464", + "name": "DevenCruickshankDVM KoreyCollierSr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fb63837c-1621-4d5c-ae94-5dd4e966850a", + "name": "AmiyaFadel MonicaHyattPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "16031f9b-929a-4b2e-8dca-32ba9d011871", + "name": "RicoSchmeler YasmineBernier", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b07623eb-9064-4bab-b3ac-7f9ed56e70c3", + "name": "MittieHirthe DaneRutherford", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0f4074d2-3f60-4afa-b67e-9aeb606fcf12", + "name": "DominiquePurdy TianaSchaefer", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "751d5835-a58c-4b86-a097-03e764d05e53", + "name": "GenevieveLegros ColleenCorwin", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "de428405-5be2-419f-b488-ad9f4c56fed5", + "name": "MallieWeimann MargaretteCarroll", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0e3574ff-e190-4cc5-8424-d68a32f7814f", + "name": "RobertaKunde LillaKing", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "06d057b1-b13a-4f51-b2dd-02a3a688b414", + "name": "ValentinKoeppSr OlgaCronaPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f1afae38-4740-433c-b2e6-dcd415741052", + "name": "AnyaMorar DrMckenzieVeum", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "079c9ca0-74d3-4a95-9fef-e9e17a123873", + "name": "JasonRempel MrBlancaParisian", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "53c5a997-4dda-423f-a56e-b576b8c5fdb3", + "name": "MsLaverneShanahan GlenHeller", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "faa11323-ee4d-42d0-9400-955723e83d89", + "name": "MissVincenzoGreenholt TheodoraRath", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "94a1c9a4-a44d-4e52-badc-051c4084c193", + "name": "RyleySchusterII MarcelinaHillsI", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ebfcbb8f-5d10-42b8-9260-8a0e5eee8f29", + "name": "MarcelleMaggio MayeParker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "a0c04c7d-1027-43f7-872b-f6150fb1970d", + "name": "TatumVandervort EarleneJohnson", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e3fbc347-f15c-4bc5-9eb0-c10bf26da2dc", + "name": "MissCitlalliHamill NatalieKundeIV", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "241daa8a-3b79-4213-a17c-f3635e100401", + "name": "EverettSwift AyanaStroman", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ad2c50a9-0f56-403d-9df0-0edcece0c701", + "name": "RaoulCremin ReannaConsidine", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "187e18f6-32c8-437f-8292-fdbe09427d2b", + "name": "ClarabelleBeer JackieShields", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e29044fe-45b3-41ae-ab00-eb9913e5daa6", + "name": "BrigitteRenner WillardLabadie", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "bccdc05a-c4d6-4b95-acc6-19f1a6c4abbd", + "name": "DavionJast ChanellePagac", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "67a02f30-f193-4490-9aec-ebf7c6619141", + "name": "FavianMarks EdaKirlin", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "672fc730-8e84-4e9e-97f5-c5dcd93557ba", + "name": "MaximusBatz RyleeMetzDDS", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f1317729-a366-4c19-9765-9f5b1d156f94", + "name": "ChadrickBergnaum RogersBerge", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8ac936dc-3185-47ab-92ad-5b04e470da9f", + "name": "Mateo Antony", + "location": "Austin, TX", + "photo_url": null + } + ], + "bands": [ + { + "id": "32df51d1-e323-4f02-80ba-63229b4861ed", + "name": "Martine Johnston", + "admin": false, + "photo_url": null, + "logo_url": null, + "genres": [ + { + "id": "country", + "description": "Country" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "techno", + "description": "Techno" + } + ] + }, + { + "id": "74f50a3d-df82-47f5-8053-0281bc27403f", + "name": "JMam", + "admin": false, + "photo_url": null, + "logo_url": null, + "genres": [ + { + "id": "blues", + "description": "Blues" + } + ] + }, + { + "id": "fc24a1e0-f212-4418-98d9-f0514e0cc699", + "name": "Uturn", + "admin": false, + "photo_url": null, + "logo_url": null, + "genres": [ + { + "id": "reggae", + "description": "Reggae" + } + ] + } + ], + "instruments": [], + "genres": [ + { + "description": "A Cappella", + "id": "acapella" + }, + { + "description": "African", + "id": "african" + }, + { + "description": "Alternative Rock", + "id": "alternative rock" + }, + { + "description": "Ambient", + "id": "ambient" + }, + { + "description": "Drum & Bass", + "id": "drum & bass" + }, + { + "description": "Electronic", + "id": "electronic" + }, + { + "description": "Folk", + "id": "folk" + }, + { + "description": "Funk", + "id": "funk" + }, + { + "description": "Psychedelic", + "id": "psychedelic" + }, + { + "description": "Punk", + "id": "punk" + }, + { + "description": "R&B", + "id": "r&b" + }, + { + "description": "Rap", + "id": "rap" + } + ], + "sessions": [ + { + "id": "91de1362-bd56-44b2-a39b-8d7fb4d38fa5", + "description": "Private session set up just to test things out in the session interface by myself.", + "musician_access": false, + "approval_required": false, + "fan_access": false + } + ], + "teacher": { + "id": "5fd55476-320d-4532-8ad8-79f9a7d88e20", + "biography": "A teacher experienced teaching music for students from kindergarten to high school. ", + "created_at": "2022-10-20T13:35:33.210Z", + "introductory_video": null, + "lesson_duration_120": false, + "lesson_duration_30": false, + "lesson_duration_45": false, + "lesson_duration_60": true, + "lesson_duration_90": false, + "price_per_lesson_120_cents": null, + "price_per_lesson_30_cents": null, + "price_per_lesson_45_cents": null, + "price_per_lesson_60_cents": 10000, + "price_per_lesson_90_cents": null, + "price_per_month_120_cents": null, + "price_per_month_30_cents": null, + "price_per_month_45_cents": null, + "price_per_month_60_cents": null, + "price_per_month_90_cents": null, + "prices_per_lesson": true, + "prices_per_month": false, + "teaches_advanced": true, + "teaches_age_lower": 3, + "teaches_age_upper": 20, + "teaches_beginner": true, + "teaches_intermediate": true, + "updated_at": "2022-10-20T13:41:50.521Z", + "website": null, + "years_playing": 15, + "years_teaching": 10, + "teaches_test_drive": true, + "test_drives_per_week": 10, + "errors": {}, + "profile_pct": "87.0", + "school_id": null, + "background_check_at": null, + "is_searchable": true, + "review_summary": null, + "school": null, + "recent_reviews": [], + "profile_pct_summary": { + "name_specified": true, + "experiences_teaching": true, + "experiences_education": true, + "experiences_award": true, + "has_stripe_account": null, + "has_teacher_bio": true, + "intro_video": false, + "years_teaching": true, + "years_playing": true, + "instruments_or_subject": true, + "genres": true, + "languages": true, + "teaches_ages_specified": true, + "teaching_level_specified": true, + "has_pricing_specified": true, + "pct": 87 + }, + "instruments": [ + "acoustic guitar", + "drums", + "keyboard", + "voice", + "flute", + "piano" + ], + "subjects": [ + "music-theory", + "composing", + "site-reading", + "guitar-ring" + ], + "genres": [ + "classical", + "folk", + "jazz" + ], + "languages": [ + "EN", + "FR" + ], + "experiences_teaching": [ + { + "name": "Jr. Music Teacher", + "experience_type": "teaching", + "organization": "St. Peters College", + "start_year": 2005, + "end_year": 2010 + } + ], + "experiences_education": [ + { + "name": "Bacholor in Fine arts ", + "experience_type": "education", + "organization": "London Fine Arts University", + "start_year": 2012, + "end_year": 2015 + } + ], + "experiences_award": [ + { + "name": "Best Folk Music Singer", + "experience_type": "award", + "organization": "University of St. Gorge", + "start_year": 2020, + "end_year": null + } + ], + "has_rated_teacher": false + }, + "owned_school_id": null, + "owned_retailer_id": null, + "geoiplocation": null, + "show_free_jamtrack": false, + "show_jamtrack_guide": true, + "mods": {}, + "has_recurly_account": true, + "is_affiliate_partner": false, + "affiliate_referral_count": null, + "affiliate_earnings": null, + "last_jam_audio_latency": 5 + }, + "timestamp": "2026-01-20T10:15:56.227Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "timestamp": "2026-01-20T10:15:56.247Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/teacher_distributions?per_page=20&page=1", + "timestamp": "2026-01-20T10:15:56.247Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/countries", + "body": { + "countriesx": [ + { + "countrycode": "US", + "countryname": "United States" + } + ] + }, + "timestamp": "2026-01-20T10:15:56.247Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/shopping_carts?time=1768904155592", + "body": [], + "timestamp": "2026-01-20T10:15:56.247Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/genres", + "body": [ + { + "id": "acapella", + "description": "A Cappella" + }, + { + "id": "african", + "description": "African" + }, + { + "id": "alternative rock", + "description": "Alternative Rock" + }, + { + "id": "ambient", + "description": "Ambient" + }, + { + "id": "americana", + "description": "Americana" + }, + { + "id": "asian", + "description": "Asian" + }, + { + "id": "avante-garde", + "description": "Avante-Garde" + }, + { + "id": "bluegrass", + "description": "Bluegrass" + }, + { + "id": "blues", + "description": "Blues" + }, + { + "id": "breakbeat", + "description": "Breakbeat" + }, + { + "id": "celtic", + "description": "Celtic" + }, + { + "id": "classical", + "description": "Classical" + }, + { + "id": "country", + "description": "Country" + }, + { + "id": "creole", + "description": "Creole" + }, + { + "id": "dance", + "description": "Dance" + }, + { + "id": "disco", + "description": "Disco" + }, + { + "id": "downtempo", + "description": "Downtempo" + }, + { + "id": "drum & bass", + "description": "Drum & Bass" + }, + { + "id": "electronic", + "description": "Electronic" + }, + { + "id": "folk", + "description": "Folk" + }, + { + "id": "funk", + "description": "Funk" + }, + { + "id": "hard rock", + "description": "Hard Rock" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "holiday", + "description": "Holiday" + }, + { + "id": "house", + "description": "House" + }, + { + "id": "industrial", + "description": "Industrial" + }, + { + "id": "jazz", + "description": "Jazz" + }, + { + "id": "kids", + "description": "Kids" + }, + { + "id": "latin", + "description": "Latin" + }, + { + "id": "metal", + "description": "Metal" + }, + { + "id": "musical", + "description": "Musical" + }, + { + "id": "oldies", + "description": "Oldies" + }, + { + "id": "other", + "description": "Other" + }, + { + "id": "pop", + "description": "Pop" + }, + { + "id": "psychedelic", + "description": "Psychedelic" + }, + { + "id": "punk", + "description": "Punk" + }, + { + "id": "r&b", + "description": "R&B" + }, + { + "id": "rap", + "description": "Rap" + }, + { + "id": "reggae", + "description": "Reggae" + }, + { + "id": "religious", + "description": "Religious" + }, + { + "id": "rock", + "description": "Rock" + }, + { + "id": "ska", + "description": "Ska" + }, + { + "id": "soft rock", + "description": "Soft Rock" + }, + { + "id": "soul", + "description": "Soul" + }, + { + "id": "tv & movie soundtrack", + "description": "TV & Movie Soundtrack" + }, + { + "id": "techno", + "description": "Techno" + }, + { + "id": "traditional", + "description": "Traditional" + }, + { + "id": "trance", + "description": "Trance" + }, + { + "id": "world", + "description": "World" + } + ], + "timestamp": "2026-01-20T10:15:56.251Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "timestamp": "2026-01-20T10:15:56.251Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "timestamp": "2026-01-20T10:15:56.254Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "body": [ + { + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "first_name": "Seth", + "last_name": "Call", + "name": "Seth Call", + "location": "Boston, MA", + "city": "Boston", + "state": "MA", + "country": "US", + "musician": true, + "email": "nuwan+6@jamkazam.com", + "online": false, + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + } + ], + "timestamp": "2026-01-20T10:15:56.262Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "body": { + "next": null, + "jamtracks": [ + { + "id": "1", + "name": "Back in Black", + "description": "This is a JamTrack audio file for use exclusively with the JamKazam service. This JamTrack is a high quality cover of the AC DC song \"Back in Black\".", + "original_artist": "AC DC", + "version": "0", + "year": null, + "duration": 221, + "allow_free": true, + "genres": [ + { + "id": "pop", + "description": "Pop" + }, + { + "id": "rock", + "description": "Rock" + } + ], + "tracks": [ + { + "id": "103dea4d-f2a3-4414-8efe-d2ca378dda60", + "part": "Master Mix", + "instrument": { + "id": "computer", + "description": "Computer", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Master", + "position": 1000, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Master%20Mix-44100-preview-e9a5a63f34b4d523ee1842fff31f88ce.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Master%20Mix-44100-preview-25fcba7ace7086e3cb6b97d7e33ba72e.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Master%20Mix-44100-preview-9f0b072ed9f4b546e170fcdfb302137e.mp3" + }, + { + "id": "2755cbdd-0476-4f3b-9ba1-e2da561ddb4e", + "part": "Lead", + "instrument": { + "id": "voice", + "description": "Voice", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 1, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Vocal%20-%20Lead-44100-preview-d35c328fc3936dad9a79fe102dc72950.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Vocal%20-%20Lead-44100-preview-b97b37651eae352fae3b3060918c7bcb.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Vocal%20-%20Lead-44100-preview-d35c328fc3936dad9a79fe102dc72950.aac" + }, + { + "id": "0db7c4e1-5e8d-43fe-bd35-98acd8f68b26", + "part": "Drums", + "instrument": { + "id": "drums", + "description": "Drums", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 2, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Drums-44100-preview-03aadceb966caf40b96334bdd00234f6.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Drums-44100-preview-854914e3e0d6fdc5f0794325b0ecaead.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Drums-44100-preview-03aadceb966caf40b96334bdd00234f6.aac" + }, + { + "id": "2cc79ab6-dab8-4905-85e6-0df5f8e087f1", + "part": "Bass", + "instrument": { + "id": "bass guitar", + "description": "Bass Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 3, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Bass-44100-preview-61c334ac87f811bd010ed3a910764c2e.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Bass-44100-preview-4066dafd7b72e9993b0c0fe1dba2b332.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Bass-44100-preview-61c334ac87f811bd010ed3a910764c2e.aac" + }, + { + "id": "ed1d3487-3b32-442f-9c76-8a36fe3bb643", + "part": "Solo", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 4, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Solo-44100-preview-e9fe8572a9ac1022762642cbd92b3c34.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Solo-44100-preview-5fb058042254206cfa9fb4dcb0310b2c.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Solo-44100-preview-e9fe8572a9ac1022762642cbd92b3c34.aac" + }, + { + "id": "f4ce7c91-7542-4e03-8fc2-68b31683d33e", + "part": "Rhythm 1", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 5, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%201-44100-preview-6b498479823d4131a01fa535817d5eab.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%201-44100-preview-f4cbb31dbde3e1a3e6012730a7e0e10f.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%201-44100-preview-6b498479823d4131a01fa535817d5eab.aac" + }, + { + "id": "2d96c7ec-59f1-4d56-8a7f-7f4c75a0ccef", + "part": "Rhythm 2", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 6, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%202-44100-preview-a626d7c632560f6737e1b6024141289e.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%202-44100-preview-06a0e5af451f001f3465992efcd34ec0.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%202-44100-preview-a626d7c632560f6737e1b6024141289e.aac" + }, + { + "id": "fce018ca-c897-4137-aa10-ef56a8e1831f", + "part": "Intro Scrapes", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 7, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Intro%20Scrapes-44100-preview-0ddfaa7154e9ba35d05d60477d5dd3e9.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Intro%20Scrapes-44100-preview-f53ce3c5f9dcf81af51560f52635fbb0.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Intro%20Scrapes-44100-preview-0ddfaa7154e9ba35d05d60477d5dd3e9.aac" + }, + { + "id": "c9b3e0a8-4db0-4d0f-9769-398a6d56506e", + "part": "Main", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 8, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Main-44100-preview-234a224f75a97d7ff8f55442ece6fcde.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Main-44100-preview-828c9691f5435dea1c90182fa2618c9b.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Main-44100-preview-234a224f75a97d7ff8f55442ece6fcde.aac" + }, + { + "id": "28c3df07-2a88-45a9-9ae6-3399a5d2eb20", + "part": "Sound FX", + "instrument": { + "id": "computer", + "description": "Computer", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 9, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Sound%20Effects-44100-preview-6c859c73036cd55bceb65f19f2d2f2f3.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Sound%20Effects-44100-preview-f840d8df4c7388f776477139025ee712.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Sound%20Effects-44100-preview-6c859c73036cd55bceb65f19f2d2f2f3.aac" + } + ], + "jmep": null, + "can_download": true, + "jam_track_right_id": 1428, + "purchased_at": 1752755050, + "last_mixdown_id": null, + "last_stem_id": null, + "mixdowns": [ + { + "id": "5f24403f-3cfa-44f5-b36e-52b2c3c66af8", + "name": "db", + "description": null, + "jam_track_id": "1", + "packages": [ + { + "id": "23b10fa0-195d-4ad5-a5a7-2cba6b8c1451", + "jam_track_mixdown_id": "5f24403f-3cfa-44f5-b36e-52b2c3c66af8", + "file_type": "mp3", + "sample_rate": 48, + "encrypt_type": null, + "error_count": 0, + "error_reason": null, + "error_detail": null, + "signing_state": "SIGNED", + "packaging_steps": 10, + "current_packaging_step": 8, + "version": "1" + } + ], + "created_at": 1753866891, + "settings": { + "count-in": false, + "tracks": [ + { + "id": "2755cbdd-0476-4f3b-9ba1-e2da561ddb4e", + "mute": false + }, + { + "id": "0db7c4e1-5e8d-43fe-bd35-98acd8f68b26", + "mute": true + }, + { + "id": "2cc79ab6-dab8-4905-85e6-0df5f8e087f1", + "mute": true + }, + { + "id": "ed1d3487-3b32-442f-9c76-8a36fe3bb643", + "mute": false + }, + { + "id": "f4ce7c91-7542-4e03-8fc2-68b31683d33e", + "mute": false + }, + { + "id": "2d96c7ec-59f1-4d56-8a7f-7f4c75a0ccef", + "mute": false + }, + { + "id": "fce018ca-c897-4137-aa10-ef56a8e1831f", + "mute": false + }, + { + "id": "c9b3e0a8-4db0-4d0f-9769-398a6d56506e", + "mute": false + }, + { + "id": "28c3df07-2a88-45a9-9ae6-3399a5d2eb20", + "mute": false + } + ] + } + } + ] + } + ] + }, + "timestamp": "2026-01-20T10:15:56.262Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/languages", + "body": [ + { + "id": "EN", + "description": "English" + }, + { + "id": "AF", + "description": "Afrikanns" + }, + { + "id": "SQ", + "description": "Albanian" + }, + { + "id": "AR", + "description": "Arabic" + }, + { + "id": "HY", + "description": "Armenian" + }, + { + "id": "EU", + "description": "Basque" + }, + { + "id": "BN", + "description": "Bengali" + }, + { + "id": "BG", + "description": "Bulgarian" + }, + { + "id": "KM", + "description": "Cambodian" + }, + { + "id": "CA", + "description": "Catalan" + }, + { + "id": "ZH", + "description": "Chinese (Mandarin)" + }, + { + "id": "HR", + "description": "Croation" + }, + { + "id": "CS", + "description": "Czech" + }, + { + "id": "DA", + "description": "Danish" + }, + { + "id": "NL", + "description": "Dutch" + }, + { + "id": "ET", + "description": "Estonian" + }, + { + "id": "FJ", + "description": "Fiji" + }, + { + "id": "FI", + "description": "Finnish" + }, + { + "id": "FR", + "description": "French" + }, + { + "id": "KA", + "description": "Georgian" + }, + { + "id": "DE", + "description": "German" + }, + { + "id": "EL", + "description": "Greek" + }, + { + "id": "GU", + "description": "Gujarati" + }, + { + "id": "HE", + "description": "Hebrew" + }, + { + "id": "HI", + "description": "Hindi" + }, + { + "id": "HU", + "description": "Hungarian" + }, + { + "id": "IS", + "description": "Icelandic" + }, + { + "id": "ID", + "description": "Indonesian" + }, + { + "id": "GA", + "description": "Irish" + }, + { + "id": "IT", + "description": "Italian" + }, + { + "id": "JA", + "description": "Japanese" + }, + { + "id": "JW", + "description": "Javanese" + }, + { + "id": "KO", + "description": "Korean" + }, + { + "id": "LA", + "description": "Latin" + }, + { + "id": "LV", + "description": "Latvian" + }, + { + "id": "LT", + "description": "Lithuanian" + }, + { + "id": "MK", + "description": "Macedonian" + }, + { + "id": "MS", + "description": "Malay" + }, + { + "id": "ML", + "description": "Malayalam" + }, + { + "id": "MT", + "description": "Maltese" + }, + { + "id": "MI", + "description": "Maori" + }, + { + "id": "MR", + "description": "Marathi" + }, + { + "id": "MN", + "description": "Mongolian" + }, + { + "id": "NE", + "description": "Nepali" + }, + { + "id": "NO", + "description": "Norwegian" + }, + { + "id": "FA", + "description": "Persian" + }, + { + "id": "PL", + "description": "Polish" + }, + { + "id": "PT", + "description": "Portuguese" + }, + { + "id": "PA", + "description": "Punjabi" + }, + { + "id": "QU", + "description": "Quechua" + }, + { + "id": "RO", + "description": "Romanian" + }, + { + "id": "RU", + "description": "Russian" + }, + { + "id": "SM", + "description": "Samoan" + }, + { + "id": "SR", + "description": "Serbian" + }, + { + "id": "SK", + "description": "Slovak" + }, + { + "id": "SL", + "description": "Slovenian" + }, + { + "id": "ES", + "description": "Spanish" + }, + { + "id": "SW", + "description": "Swahili" + }, + { + "id": "SV", + "description": "Swedish " + }, + { + "id": "TA", + "description": "Tamil" + }, + { + "id": "TT", + "description": "Tatar" + }, + { + "id": "TE", + "description": "Telugu" + }, + { + "id": "TH", + "description": "Thai" + }, + { + "id": "BO", + "description": "Tibetan" + }, + { + "id": "TO", + "description": "Tonga" + }, + { + "id": "TR", + "description": "Turkish" + }, + { + "id": "UK", + "description": "Ukranian" + }, + { + "id": "UR", + "description": "Urdu" + }, + { + "id": "UZ", + "description": "Uzbek" + }, + { + "id": "VI", + "description": "Vietnamese" + }, + { + "id": "CY", + "description": "Welsh" + }, + { + "id": "XH", + "description": "Xhosa" + } + ], + "timestamp": "2026-01-20T10:15:56.268Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/subjects", + "body": [ + { + "id": "ableton-live", + "description": "Ableton Live" + }, + { + "id": "amplitube", + "description": "AmpliTube" + }, + { + "id": "apple-logic-pro", + "description": "Apple Logic Pro" + }, + { + "id": "arranging", + "description": "Arranging" + }, + { + "id": "composing", + "description": "Composition" + }, + { + "id": "conducting", + "description": "Conducting" + }, + { + "id": "cubase", + "description": "Cubase" + }, + { + "id": "ear-training", + "description": "Ear Training" + }, + { + "id": "fl-studio", + "description": "FL Studio" + }, + { + "id": "film-scoring", + "description": "Film Scoring" + }, + { + "id": "garageband", + "description": "GarageBand" + }, + { + "id": "guitar-ring", + "description": "Guitar Rig" + }, + { + "id": "harmony", + "description": "Harmony" + }, + { + "id": "improvisation", + "description": "Improvisation" + }, + { + "id": "instrument-repair", + "description": "Instrument Repair" + }, + { + "id": "line-6-pod", + "description": "Line 6 Pod" + }, + { + "id": "music-business", + "description": "Music Business" + }, + { + "id": "music-theory", + "description": "Music Theory" + }, + { + "id": "music-therapy", + "description": "Music Therapy" + }, + { + "id": "presonus-studio-one", + "description": "PreSonus Studio One" + }, + { + "id": "pro-tools", + "description": "Pro Tools" + }, + { + "id": "reaper", + "description": "Reaper" + }, + { + "id": "reason", + "description": "Reason" + }, + { + "id": "recording", + "description": "Recording & Production" + }, + { + "id": "site-reading", + "description": "Sight Reading" + }, + { + "id": "sonar", + "description": "Sonar" + }, + { + "id": "songwriting", + "description": "Songwriting" + }, + { + "id": "video-game-scoring", + "description": "Video Game Scoring" + } + ], + "timestamp": "2026-01-20T10:15:56.298Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/chat?type=CHAT_MESSAGE&limit=20&page=0&channel=global", + "body": { + "next": null, + "chats": [ + { + "id": "d6e478eb-c2a1-4495-b00a-84fa01aefbb6", + "message": "qq", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-21T07:39:21.357Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "54baff3d-b104-43aa-8747-3ca3cbba3e95", + "message": "tt", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-21T07:38:20.820Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "c5b51493-01d9-4e42-8daa-bf3948b858cc", + "message": "lk", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T22:44:50.270Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "07f67a95-f275-4d39-bae4-1b9b42141d91", + "message": "uu", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T22:43:05.706Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "2802579a-ed5c-4694-862b-f75f764901b6", + "message": "aaaa", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T16:25:51.294Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "cbfc23d4-02d7-4adb-8471-4dc0760ee157", + "message": "ssss", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T16:20:48.827Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "464b5f72-43ad-49bc-a984-4484fd766fca", + "message": "kkk", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T16:15:57.397Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "b5c2585a-aa76-4084-ba8a-ea63949d61b5", + "message": "iiii", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T10:27:57.145Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "f7599110-f15b-4a62-90e9-e1c42fd0b546", + "message": "dfgdfgdfg", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-20T09:20:10.139Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "9bfdc494-cd3a-496b-b958-102c2027890c", + "message": "This is nuwan", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2023-12-09T09:59:22.187Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + }, + { + "id": "a894f396-e896-40f0-b626-d899c1ead63f", + "message": "hi test 1", + "user_id": "b2022a23-84b1-4475-a7bb-a0f87064925a", + "created_at": "2021-09-01T18:44:36.090Z", + "channel": "global", + "lesson_session_id": null, + "purpose": null, + "music_notation": null, + "claimed_recording": null, + "user": { + "name": "Anonymous" + } + } + ] + }, + "timestamp": "2026-01-20T10:15:56.303Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/sessions/scheduled?", + "body": [], + "timestamp": "2026-01-20T10:15:56.303Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "timestamp": "2026-01-20T10:15:56.305Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/instruments", + "body": [ + { + "id": "accordion", + "description": "Accordion", + "popularity": 2 + }, + { + "id": "acoustic guitar", + "description": "Acoustic Guitar", + "popularity": 3 + }, + { + "id": "bagpipes", + "description": "Bagpipes", + "popularity": 1 + }, + { + "id": "banjo", + "description": "Banjo", + "popularity": 2 + }, + { + "id": "bass guitar", + "description": "Bass Guitar", + "popularity": 3 + }, + { + "id": "bassoon", + "description": "Bassoon", + "popularity": 1 + }, + { + "id": "cello", + "description": "Cello", + "popularity": 1 + }, + { + "id": "charango", + "description": "Charango", + "popularity": 1 + }, + { + "id": "clarinet", + "description": "Clarinet", + "popularity": 2 + }, + { + "id": "computer", + "description": "Computer", + "popularity": 3 + }, + { + "id": "dobro", + "description": "Dobro", + "popularity": 1 + }, + { + "id": "double bass", + "description": "Double Bass", + "popularity": 2 + }, + { + "id": "drums", + "description": "Drums", + "popularity": 3 + }, + { + "id": "electric guitar", + "description": "Electric Guitar", + "popularity": 3 + }, + { + "id": "euphonium", + "description": "Euphonium", + "popularity": 1 + }, + { + "id": "flugelhorn", + "description": "Flugelhorn", + "popularity": 1 + }, + { + "id": "flute", + "description": "Flute", + "popularity": 2 + }, + { + "id": "french horn", + "description": "French Horn", + "popularity": 1 + }, + { + "id": "glockenspiel", + "description": "Glockenspiel", + "popularity": 1 + }, + { + "id": "harmonica", + "description": "Harmonica", + "popularity": 2 + }, + { + "id": "harp", + "description": "Harp", + "popularity": 1 + }, + { + "id": "keyboard", + "description": "Keyboard", + "popularity": 3 + }, + { + "id": "mandolin", + "description": "Mandolin", + "popularity": 1 + }, + { + "id": "oboe", + "description": "Oboe", + "popularity": 1 + }, + { + "id": "orchestra", + "description": "Orchestra", + "popularity": 1 + }, + { + "id": "other", + "description": "Other", + "popularity": 1 + }, + { + "id": "piano", + "description": "Piano", + "popularity": 2 + }, + { + "id": "piccolo", + "description": "Piccolo", + "popularity": 1 + }, + { + "id": "saxophone", + "description": "Saxophone", + "popularity": 2 + }, + { + "id": "sitar", + "description": "Sitar", + "popularity": 1 + }, + { + "id": "steel guitar", + "description": "Steel Guitar", + "popularity": 1 + }, + { + "id": "theremin", + "description": "Theremin", + "popularity": 1 + }, + { + "id": "timpani", + "description": "Timpani", + "popularity": 1 + }, + { + "id": "trombone", + "description": "Trombone", + "popularity": 2 + }, + { + "id": "trumpet", + "description": "Trumpet", + "popularity": 2 + }, + { + "id": "tuba", + "description": "Tuba", + "popularity": 1 + }, + { + "id": "ukulele", + "description": "Ukulele", + "popularity": 1 + }, + { + "id": "viola", + "description": "Viola", + "popularity": 1 + }, + { + "id": "violin", + "description": "Violin", + "popularity": 2 + }, + { + "id": "vocoder", + "description": "Vocoder", + "popularity": 1 + }, + { + "id": "voice", + "description": "Voice", + "popularity": 3 + } + ], + "timestamp": "2026-01-20T10:15:56.306Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/genres", + "body": [ + { + "id": "acapella", + "description": "A Cappella" + }, + { + "id": "african", + "description": "African" + }, + { + "id": "alternative rock", + "description": "Alternative Rock" + }, + { + "id": "ambient", + "description": "Ambient" + }, + { + "id": "americana", + "description": "Americana" + }, + { + "id": "asian", + "description": "Asian" + }, + { + "id": "avante-garde", + "description": "Avante-Garde" + }, + { + "id": "bluegrass", + "description": "Bluegrass" + }, + { + "id": "blues", + "description": "Blues" + }, + { + "id": "breakbeat", + "description": "Breakbeat" + }, + { + "id": "celtic", + "description": "Celtic" + }, + { + "id": "classical", + "description": "Classical" + }, + { + "id": "country", + "description": "Country" + }, + { + "id": "creole", + "description": "Creole" + }, + { + "id": "dance", + "description": "Dance" + }, + { + "id": "disco", + "description": "Disco" + }, + { + "id": "downtempo", + "description": "Downtempo" + }, + { + "id": "drum & bass", + "description": "Drum & Bass" + }, + { + "id": "electronic", + "description": "Electronic" + }, + { + "id": "folk", + "description": "Folk" + }, + { + "id": "funk", + "description": "Funk" + }, + { + "id": "hard rock", + "description": "Hard Rock" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "holiday", + "description": "Holiday" + }, + { + "id": "house", + "description": "House" + }, + { + "id": "industrial", + "description": "Industrial" + }, + { + "id": "jazz", + "description": "Jazz" + }, + { + "id": "kids", + "description": "Kids" + }, + { + "id": "latin", + "description": "Latin" + }, + { + "id": "metal", + "description": "Metal" + }, + { + "id": "musical", + "description": "Musical" + }, + { + "id": "oldies", + "description": "Oldies" + }, + { + "id": "other", + "description": "Other" + }, + { + "id": "pop", + "description": "Pop" + }, + { + "id": "psychedelic", + "description": "Psychedelic" + }, + { + "id": "punk", + "description": "Punk" + }, + { + "id": "r&b", + "description": "R&B" + }, + { + "id": "rap", + "description": "Rap" + }, + { + "id": "reggae", + "description": "Reggae" + }, + { + "id": "religious", + "description": "Religious" + }, + { + "id": "rock", + "description": "Rock" + }, + { + "id": "ska", + "description": "Ska" + }, + { + "id": "soft rock", + "description": "Soft Rock" + }, + { + "id": "soul", + "description": "Soul" + }, + { + "id": "tv & movie soundtrack", + "description": "TV & Movie Soundtrack" + }, + { + "id": "techno", + "description": "Techno" + }, + { + "id": "traditional", + "description": "Traditional" + }, + { + "id": "trance", + "description": "Trance" + }, + { + "id": "world", + "description": "World" + } + ], + "timestamp": "2026-01-20T10:15:56.308Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "body": [ + { + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "first_name": "Seth", + "last_name": "Call", + "name": "Seth Call", + "location": "Boston, MA", + "city": "Boston", + "state": "MA", + "country": "US", + "musician": true, + "email": "nuwan+6@jamkazam.com", + "online": false, + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + } + ], + "timestamp": "2026-01-20T10:15:56.367Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications?offset=0&limit=20", + "body": [], + "timestamp": "2026-01-20T10:15:56.367Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/regions?country=US", + "body": { + "regions": [ + { + "region": "TN", + "name": null + }, + { + "region": "ME", + "name": null + }, + { + "region": "MA", + "name": null + }, + { + "region": "TX", + "name": null + }, + { + "region": "OK", + "name": null + }, + { + "region": "WA", + "name": null + }, + { + "region": "CO", + "name": null + }, + { + "region": "CA", + "name": null + }, + { + "region": "AR", + "name": null + }, + { + "region": "FL", + "name": null + }, + { + "region": "OR", + "name": null + } + ] + }, + "timestamp": "2026-01-20T10:15:56.367Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/instruments", + "body": [ + { + "id": "accordion", + "description": "Accordion", + "popularity": 2 + }, + { + "id": "acoustic guitar", + "description": "Acoustic Guitar", + "popularity": 3 + }, + { + "id": "bagpipes", + "description": "Bagpipes", + "popularity": 1 + }, + { + "id": "banjo", + "description": "Banjo", + "popularity": 2 + }, + { + "id": "bass guitar", + "description": "Bass Guitar", + "popularity": 3 + }, + { + "id": "bassoon", + "description": "Bassoon", + "popularity": 1 + }, + { + "id": "cello", + "description": "Cello", + "popularity": 1 + }, + { + "id": "charango", + "description": "Charango", + "popularity": 1 + }, + { + "id": "clarinet", + "description": "Clarinet", + "popularity": 2 + }, + { + "id": "computer", + "description": "Computer", + "popularity": 3 + }, + { + "id": "dobro", + "description": "Dobro", + "popularity": 1 + }, + { + "id": "double bass", + "description": "Double Bass", + "popularity": 2 + }, + { + "id": "drums", + "description": "Drums", + "popularity": 3 + }, + { + "id": "electric guitar", + "description": "Electric Guitar", + "popularity": 3 + }, + { + "id": "euphonium", + "description": "Euphonium", + "popularity": 1 + }, + { + "id": "flugelhorn", + "description": "Flugelhorn", + "popularity": 1 + }, + { + "id": "flute", + "description": "Flute", + "popularity": 2 + }, + { + "id": "french horn", + "description": "French Horn", + "popularity": 1 + }, + { + "id": "glockenspiel", + "description": "Glockenspiel", + "popularity": 1 + }, + { + "id": "harmonica", + "description": "Harmonica", + "popularity": 2 + }, + { + "id": "harp", + "description": "Harp", + "popularity": 1 + }, + { + "id": "keyboard", + "description": "Keyboard", + "popularity": 3 + }, + { + "id": "mandolin", + "description": "Mandolin", + "popularity": 1 + }, + { + "id": "oboe", + "description": "Oboe", + "popularity": 1 + }, + { + "id": "orchestra", + "description": "Orchestra", + "popularity": 1 + }, + { + "id": "other", + "description": "Other", + "popularity": 1 + }, + { + "id": "piano", + "description": "Piano", + "popularity": 2 + }, + { + "id": "piccolo", + "description": "Piccolo", + "popularity": 1 + }, + { + "id": "saxophone", + "description": "Saxophone", + "popularity": 2 + }, + { + "id": "sitar", + "description": "Sitar", + "popularity": 1 + }, + { + "id": "steel guitar", + "description": "Steel Guitar", + "popularity": 1 + }, + { + "id": "theremin", + "description": "Theremin", + "popularity": 1 + }, + { + "id": "timpani", + "description": "Timpani", + "popularity": 1 + }, + { + "id": "trombone", + "description": "Trombone", + "popularity": 2 + }, + { + "id": "trumpet", + "description": "Trumpet", + "popularity": 2 + }, + { + "id": "tuba", + "description": "Tuba", + "popularity": 1 + }, + { + "id": "ukulele", + "description": "Ukulele", + "popularity": 1 + }, + { + "id": "viola", + "description": "Viola", + "popularity": 1 + }, + { + "id": "violin", + "description": "Violin", + "popularity": 2 + }, + { + "id": "vocoder", + "description": "Vocoder", + "popularity": 1 + }, + { + "id": "voice", + "description": "Voice", + "popularity": 3 + } + ], + "timestamp": "2026-01-20T10:15:56.367Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/genres", + "body": [ + { + "id": "acapella", + "description": "A Cappella" + }, + { + "id": "african", + "description": "African" + }, + { + "id": "alternative rock", + "description": "Alternative Rock" + }, + { + "id": "ambient", + "description": "Ambient" + }, + { + "id": "americana", + "description": "Americana" + }, + { + "id": "asian", + "description": "Asian" + }, + { + "id": "avante-garde", + "description": "Avante-Garde" + }, + { + "id": "bluegrass", + "description": "Bluegrass" + }, + { + "id": "blues", + "description": "Blues" + }, + { + "id": "breakbeat", + "description": "Breakbeat" + }, + { + "id": "celtic", + "description": "Celtic" + }, + { + "id": "classical", + "description": "Classical" + }, + { + "id": "country", + "description": "Country" + }, + { + "id": "creole", + "description": "Creole" + }, + { + "id": "dance", + "description": "Dance" + }, + { + "id": "disco", + "description": "Disco" + }, + { + "id": "downtempo", + "description": "Downtempo" + }, + { + "id": "drum & bass", + "description": "Drum & Bass" + }, + { + "id": "electronic", + "description": "Electronic" + }, + { + "id": "folk", + "description": "Folk" + }, + { + "id": "funk", + "description": "Funk" + }, + { + "id": "hard rock", + "description": "Hard Rock" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "holiday", + "description": "Holiday" + }, + { + "id": "house", + "description": "House" + }, + { + "id": "industrial", + "description": "Industrial" + }, + { + "id": "jazz", + "description": "Jazz" + }, + { + "id": "kids", + "description": "Kids" + }, + { + "id": "latin", + "description": "Latin" + }, + { + "id": "metal", + "description": "Metal" + }, + { + "id": "musical", + "description": "Musical" + }, + { + "id": "oldies", + "description": "Oldies" + }, + { + "id": "other", + "description": "Other" + }, + { + "id": "pop", + "description": "Pop" + }, + { + "id": "psychedelic", + "description": "Psychedelic" + }, + { + "id": "punk", + "description": "Punk" + }, + { + "id": "r&b", + "description": "R&B" + }, + { + "id": "rap", + "description": "Rap" + }, + { + "id": "reggae", + "description": "Reggae" + }, + { + "id": "religious", + "description": "Religious" + }, + { + "id": "rock", + "description": "Rock" + }, + { + "id": "ska", + "description": "Ska" + }, + { + "id": "soft rock", + "description": "Soft Rock" + }, + { + "id": "soul", + "description": "Soul" + }, + { + "id": "tv & movie soundtrack", + "description": "TV & Movie Soundtrack" + }, + { + "id": "techno", + "description": "Techno" + }, + { + "id": "traditional", + "description": "Traditional" + }, + { + "id": "trance", + "description": "Trance" + }, + { + "id": "world", + "description": "World" + } + ], + "timestamp": "2026-01-20T10:15:56.424Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/instruments", + "body": [ + { + "id": "accordion", + "description": "Accordion", + "popularity": 2 + }, + { + "id": "acoustic guitar", + "description": "Acoustic Guitar", + "popularity": 3 + }, + { + "id": "bagpipes", + "description": "Bagpipes", + "popularity": 1 + }, + { + "id": "banjo", + "description": "Banjo", + "popularity": 2 + }, + { + "id": "bass guitar", + "description": "Bass Guitar", + "popularity": 3 + }, + { + "id": "bassoon", + "description": "Bassoon", + "popularity": 1 + }, + { + "id": "cello", + "description": "Cello", + "popularity": 1 + }, + { + "id": "charango", + "description": "Charango", + "popularity": 1 + }, + { + "id": "clarinet", + "description": "Clarinet", + "popularity": 2 + }, + { + "id": "computer", + "description": "Computer", + "popularity": 3 + }, + { + "id": "dobro", + "description": "Dobro", + "popularity": 1 + }, + { + "id": "double bass", + "description": "Double Bass", + "popularity": 2 + }, + { + "id": "drums", + "description": "Drums", + "popularity": 3 + }, + { + "id": "electric guitar", + "description": "Electric Guitar", + "popularity": 3 + }, + { + "id": "euphonium", + "description": "Euphonium", + "popularity": 1 + }, + { + "id": "flugelhorn", + "description": "Flugelhorn", + "popularity": 1 + }, + { + "id": "flute", + "description": "Flute", + "popularity": 2 + }, + { + "id": "french horn", + "description": "French Horn", + "popularity": 1 + }, + { + "id": "glockenspiel", + "description": "Glockenspiel", + "popularity": 1 + }, + { + "id": "harmonica", + "description": "Harmonica", + "popularity": 2 + }, + { + "id": "harp", + "description": "Harp", + "popularity": 1 + }, + { + "id": "keyboard", + "description": "Keyboard", + "popularity": 3 + }, + { + "id": "mandolin", + "description": "Mandolin", + "popularity": 1 + }, + { + "id": "oboe", + "description": "Oboe", + "popularity": 1 + }, + { + "id": "orchestra", + "description": "Orchestra", + "popularity": 1 + }, + { + "id": "other", + "description": "Other", + "popularity": 1 + }, + { + "id": "piano", + "description": "Piano", + "popularity": 2 + }, + { + "id": "piccolo", + "description": "Piccolo", + "popularity": 1 + }, + { + "id": "saxophone", + "description": "Saxophone", + "popularity": 2 + }, + { + "id": "sitar", + "description": "Sitar", + "popularity": 1 + }, + { + "id": "steel guitar", + "description": "Steel Guitar", + "popularity": 1 + }, + { + "id": "theremin", + "description": "Theremin", + "popularity": 1 + }, + { + "id": "timpani", + "description": "Timpani", + "popularity": 1 + }, + { + "id": "trombone", + "description": "Trombone", + "popularity": 2 + }, + { + "id": "trumpet", + "description": "Trumpet", + "popularity": 2 + }, + { + "id": "tuba", + "description": "Tuba", + "popularity": 1 + }, + { + "id": "ukulele", + "description": "Ukulele", + "popularity": 1 + }, + { + "id": "viola", + "description": "Viola", + "popularity": 1 + }, + { + "id": "violin", + "description": "Violin", + "popularity": 2 + }, + { + "id": "vocoder", + "description": "Vocoder", + "popularity": 1 + }, + { + "id": "voice", + "description": "Voice", + "popularity": 3 + } + ], + "timestamp": "2026-01-20T10:15:56.471Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "body": { + "next": null, + "jamtracks": [ + { + "id": "1", + "name": "Back in Black", + "description": "This is a JamTrack audio file for use exclusively with the JamKazam service. This JamTrack is a high quality cover of the AC DC song \"Back in Black\".", + "original_artist": "AC DC", + "version": "0", + "year": null, + "duration": 221, + "allow_free": true, + "genres": [ + { + "id": "pop", + "description": "Pop" + }, + { + "id": "rock", + "description": "Rock" + } + ], + "tracks": [ + { + "id": "103dea4d-f2a3-4414-8efe-d2ca378dda60", + "part": "Master Mix", + "instrument": { + "id": "computer", + "description": "Computer", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Master", + "position": 1000, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Master%20Mix-44100-preview-e9a5a63f34b4d523ee1842fff31f88ce.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Master%20Mix-44100-preview-25fcba7ace7086e3cb6b97d7e33ba72e.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Master%20Mix-44100-preview-9f0b072ed9f4b546e170fcdfb302137e.mp3" + }, + { + "id": "2755cbdd-0476-4f3b-9ba1-e2da561ddb4e", + "part": "Lead", + "instrument": { + "id": "voice", + "description": "Voice", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 1, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Vocal%20-%20Lead-44100-preview-d35c328fc3936dad9a79fe102dc72950.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Vocal%20-%20Lead-44100-preview-b97b37651eae352fae3b3060918c7bcb.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Vocal%20-%20Lead-44100-preview-d35c328fc3936dad9a79fe102dc72950.aac" + }, + { + "id": "0db7c4e1-5e8d-43fe-bd35-98acd8f68b26", + "part": "Drums", + "instrument": { + "id": "drums", + "description": "Drums", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 2, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Drums-44100-preview-03aadceb966caf40b96334bdd00234f6.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Drums-44100-preview-854914e3e0d6fdc5f0794325b0ecaead.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Drums-44100-preview-03aadceb966caf40b96334bdd00234f6.aac" + }, + { + "id": "2cc79ab6-dab8-4905-85e6-0df5f8e087f1", + "part": "Bass", + "instrument": { + "id": "bass guitar", + "description": "Bass Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 3, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Bass-44100-preview-61c334ac87f811bd010ed3a910764c2e.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Bass-44100-preview-4066dafd7b72e9993b0c0fe1dba2b332.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Bass-44100-preview-61c334ac87f811bd010ed3a910764c2e.aac" + }, + { + "id": "ed1d3487-3b32-442f-9c76-8a36fe3bb643", + "part": "Solo", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 4, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Solo-44100-preview-e9fe8572a9ac1022762642cbd92b3c34.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Solo-44100-preview-5fb058042254206cfa9fb4dcb0310b2c.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Solo-44100-preview-e9fe8572a9ac1022762642cbd92b3c34.aac" + }, + { + "id": "f4ce7c91-7542-4e03-8fc2-68b31683d33e", + "part": "Rhythm 1", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 5, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%201-44100-preview-6b498479823d4131a01fa535817d5eab.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%201-44100-preview-f4cbb31dbde3e1a3e6012730a7e0e10f.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%201-44100-preview-6b498479823d4131a01fa535817d5eab.aac" + }, + { + "id": "2d96c7ec-59f1-4d56-8a7f-7f4c75a0ccef", + "part": "Rhythm 2", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 6, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%202-44100-preview-a626d7c632560f6737e1b6024141289e.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%202-44100-preview-06a0e5af451f001f3465992efcd34ec0.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%202-44100-preview-a626d7c632560f6737e1b6024141289e.aac" + }, + { + "id": "fce018ca-c897-4137-aa10-ef56a8e1831f", + "part": "Intro Scrapes", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 7, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Intro%20Scrapes-44100-preview-0ddfaa7154e9ba35d05d60477d5dd3e9.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Intro%20Scrapes-44100-preview-f53ce3c5f9dcf81af51560f52635fbb0.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Intro%20Scrapes-44100-preview-0ddfaa7154e9ba35d05d60477d5dd3e9.aac" + }, + { + "id": "c9b3e0a8-4db0-4d0f-9769-398a6d56506e", + "part": "Main", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 8, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Main-44100-preview-234a224f75a97d7ff8f55442ece6fcde.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Main-44100-preview-828c9691f5435dea1c90182fa2618c9b.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Main-44100-preview-234a224f75a97d7ff8f55442ece6fcde.aac" + }, + { + "id": "28c3df07-2a88-45a9-9ae6-3399a5d2eb20", + "part": "Sound FX", + "instrument": { + "id": "computer", + "description": "Computer", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 9, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Sound%20Effects-44100-preview-6c859c73036cd55bceb65f19f2d2f2f3.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Sound%20Effects-44100-preview-f840d8df4c7388f776477139025ee712.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Sound%20Effects-44100-preview-6c859c73036cd55bceb65f19f2d2f2f3.aac" + } + ], + "jmep": null, + "can_download": true, + "jam_track_right_id": 1428, + "purchased_at": 1752755050, + "last_mixdown_id": null, + "last_stem_id": null, + "mixdowns": [ + { + "id": "5f24403f-3cfa-44f5-b36e-52b2c3c66af8", + "name": "db", + "description": null, + "jam_track_id": "1", + "packages": [ + { + "id": "23b10fa0-195d-4ad5-a5a7-2cba6b8c1451", + "jam_track_mixdown_id": "5f24403f-3cfa-44f5-b36e-52b2c3c66af8", + "file_type": "mp3", + "sample_rate": 48, + "encrypt_type": null, + "error_count": 0, + "error_reason": null, + "error_detail": null, + "signing_state": "SIGNED", + "packaging_steps": 10, + "current_packaging_step": 8, + "version": "1" + } + ], + "created_at": 1753866891, + "settings": { + "count-in": false, + "tracks": [ + { + "id": "2755cbdd-0476-4f3b-9ba1-e2da561ddb4e", + "mute": false + }, + { + "id": "0db7c4e1-5e8d-43fe-bd35-98acd8f68b26", + "mute": true + }, + { + "id": "2cc79ab6-dab8-4905-85e6-0df5f8e087f1", + "mute": true + }, + { + "id": "ed1d3487-3b32-442f-9c76-8a36fe3bb643", + "mute": false + }, + { + "id": "f4ce7c91-7542-4e03-8fc2-68b31683d33e", + "mute": false + }, + { + "id": "2d96c7ec-59f1-4d56-8a7f-7f4c75a0ccef", + "mute": false + }, + { + "id": "fce018ca-c897-4137-aa10-ef56a8e1831f", + "mute": false + }, + { + "id": "c9b3e0a8-4db0-4d0f-9769-398a6d56506e", + "mute": false + }, + { + "id": "28c3df07-2a88-45a9-9ae6-3399a5d2eb20", + "mute": false + } + ] + } + } + ] + } + ] + }, + "timestamp": "2026-01-20T10:15:56.474Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/teacher_distributions?per_page=20&page=1", + "body": { + "next": null, + "entries": [], + "total_entries": 0 + }, + "timestamp": "2026-01-20T10:15:56.474Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "body": { + "version": "2.0.0.1956", + "uri": "http://d48bcgsnmsm6a.cloudfront.net/artifacts/JamClientModern/MacOSX-M/2.0.0.1956/JamKazam-1770.dmg", + "sha1": "2ca2238f4a21a09c32d4a0b6f5fee78b", + "size": 240820609 + }, + "timestamp": "2026-01-20T10:15:56.486Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "body": { + "version": "2.0.0.1956", + "uri": "http://d48bcgsnmsm6a.cloudfront.net/artifacts/JamClientModern/MacOSX-M/2.0.0.1956/JamKazam-1770.dmg", + "sha1": "2ca2238f4a21a09c32d4a0b6f5fee78b", + "size": 240820609 + }, + "timestamp": "2026-01-20T10:15:56.521Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "timestamp": "2026-01-20T10:15:57.016Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381?", + "body": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "city": "Dallas", + "state": "TX", + "country": "US", + "location": "Dallas, TX", + "online": true, + "photo_url": null, + "musician": true, + "gender": "M", + "birth_date": null, + "friend_count": 1, + "liker_count": 0, + "follower_count": 77, + "following_count": 130, + "admin": true, + "recording_count": 0, + "session_count": 0, + "biography": "This is description with special charact xxxxxxaaaasasasas", + "favorite_count": 0, + "audio_latency": null, + "upcoming_session_count": 0, + "age": null, + "website": "www.nuwanchaturanga.me", + "skill_level": 2, + "reuse_card": true, + "email_needs_verification": false, + "is_a_teacher": true, + "is_a_student": false, + "is_onboarder": false, + "timezone": null, + "use_video_conferencing_server": true, + "email": "nuwan@jamkazam.com", + "original_fpfile": null, + "cropped_fpfile": null, + "crop_selection": null, + "session_settings": "{:band_id=>nil, :musician_access=>false, :approval_required=>false, :fan_chat=>false, :fan_access=>false, :description=>\"Private session set up just to test things out in the session interface by myself.\", :genres=>[{:id=>\"pop\", :description=>\"Pop\"}], :invitees=>[]}", + "show_whats_next": true, + "show_whats_next_count": 0, + "subscribe_email": false, + "auth_twitter": false, + "new_notifications": 14, + "sales_count": 7, + "purchased_jamtracks_count": 1, + "first_downloaded_client_at": null, + "created_at": "2021-05-21T18:15:28.425Z", + "first_opened_jamtrack_web_player": "2024-12-03T13:55:01.788Z", + "gifted_jamtracks": 0, + "has_redeemable_jamtrack": false, + "has_stored_credit_card?": true, + "remaining_test_drives": 0, + "jamclass_credits": 0, + "can_buy_test_drive?": true, + "lesson_package_type_id": null, + "school_id": null, + "is_guitar_center_student?": false, + "purchase_required": null, + "lesson_package_needs_purchase_id": null, + "user_authorizations": [ + { + "uid": "RQB3YMV6KABBL", + "provider": "paypal", + "token_expiration": "2025-07-14T14:47:06.651Z" + } + ], + "test_drive_package_choices": [], + "friends": [ + { + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "first_name": "Seth", + "last_name": "Call", + "name": "Seth Call", + "online": false, + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + } + ], + "followings": [ + { + "type": "user", + "id": "963d5268-66b6-463a-a3ee-c97f274fc23f", + "name": "Peter Walker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "cc0b060c-9891-4e91-9fe3-4268893a2fd0", + "name": "Oswald Becca", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "29becbf4-8be5-4078-9405-0edadc9fa42d", + "name": "Peter 1 Walker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "3dfca858-0e7c-4ad4-993a-c39421d93853", + "name": "Peter Walker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fd467978-da75-421f-8e97-6406a784e87e", + "name": "Indrashapa Liyanage", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "name": "Seth Call", + "location": "Boston, MA", + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + }, + { + "type": "user", + "id": "2e75f1dc-af6b-4444-a9e2-5f32db07abc1", + "name": "David Wilson 1", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f8f32710-3194-4666-b618-eceb21d6e3de", + "name": "Peter Walker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "feb671a3-1821-48f0-bc14-aa26cf98bb25", + "name": "David Wilson", + "location": "Miami, FL", + "photo_url": null + }, + { + "type": "user", + "id": "c2ede005-3b3a-4227-b6fc-f7e8b946b556", + "name": "Test 2 User", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "bcf99b5c-8fee-47ce-bf51-b3c7b821d023", + "name": "David Miller", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1f9debf3-58d7-46c0-896c-859b6ae8be37", + "name": "David Miller", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "876d1604-d309-429a-8046-e034ce1bcea4", + "name": "David Miller", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "name": "Nuwan Chaturanga", + "location": "Dallas, TX", + "photo_url": null + }, + { + "type": "user", + "id": "062168d9-3e7e-41ee-b8e8-9f496b8cb97a", + "name": "James Bond", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "5c2b1a45-5212-4a73-b5ce-007c345d97b7", + "name": "Makenna Gutmann Celestino Hand", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e2eca6b2-56d9-450a-8ac4-7d107a488887", + "name": "Grace Roob Cynthia Cronin", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b1ddadd0-0263-47c4-bf91-e7767f386970", + "name": "Oswald Becca", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0671faf1-7e39-45e3-ba9b-a3e27982e88f", + "name": "Carey Carroll Yolanda Ankunding", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1e94859c-b192-4bc8-9d8e-6a3ef5ec1380", + "name": "Filiberto Hills IV Anya Keebler MD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "749d3a9f-11fc-4593-827c-b47d0da1322e", + "name": "RashawnMante ThurmanFadel", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "6ceb102f-2f99-46dd-8baa-d1b1c357118f", + "name": "ObieJenkins EddNienow", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "042ef11a-f2ad-4e80-85d8-cf94a502e298", + "name": "TobinFisher MatildaKiehn", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f0ca8d87-dd9e-4d9f-afc1-ff543f29d371", + "name": "MrsOrionSchoen CurtisChristiansenV", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fc3496a2-9f73-47ed-a755-02011afddded", + "name": "TristonRunolfsson DrJoyHoppe", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "16a32d1e-901e-460a-bd9a-d400b91ec5d5", + "name": "DrPatrickDuBuque JeanneVeum", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "7e43ae3e-47b2-4510-a688-91c209e5d271", + "name": "MrsEverardoWillms JadonGreenholt", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b39034cf-0f02-44a3-ac46-1e79f561e22f", + "name": "AmberOConner NoelMedhurst", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "9f7e3f8e-9ea1-41a5-a589-60ff27b40e74", + "name": "ErnestinaGrady CarlieLubowitz", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "5501a1a7-670d-45b9-bf2f-e644c3d8ae65", + "name": "MaryamAltenwerth MoseDavisDDS", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "5473d024-0dd2-434b-bea2-ed1b959f6eb8", + "name": "TyreeKlocko MarcusCartwright", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "a8e2ceda-51a7-4b67-87bb-5ddab937127d", + "name": "DaleNicolas ErnieBalistreriSr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "819f1fff-4c76-45b8-a97f-e3ae23c44d38", + "name": "TerenceRosenbaum BenedictOReillyPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "caaa6dbe-d44f-4283-82b9-31e2feef8552", + "name": "RichardSchmeler SteveMante", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b1faa4a9-aa95-46da-98ef-d9a110cf19db", + "name": "CharlesChamplinSr SofiaBernierSr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "aae38d6a-571b-453c-b84d-ac377e7dd518", + "name": "MabelCasperPhD TyrelStroman", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8bac8af0-f348-4d38-9c8b-3864c21819fa", + "name": "DoyleParisian VelmaMarquardt", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "bae12f4f-b8a6-4cfb-8cfb-3a97293011fb", + "name": "FriedrichMaggioSr IvyBergePhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "492b11ae-46d3-4e77-8a0a-8550cf924fcc", + "name": "PierreJaskolski MrCurtTremblay", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f739a1ab-25e7-4713-9914-8c3993b34ac2", + "name": "FreedaConnelly ZoraRyanIV", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "da55a63e-822c-4b00-a1ff-43d1c77dd9da", + "name": "MrDarrelHilpert AliaLemke", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "9b3fccc7-3341-497e-943b-4223470c4d2e", + "name": "JudahMurphy MsRandallWalsh", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e0ff0bfb-f7f7-4a59-8fe9-b3271a436bff", + "name": "MorganRempel DestineyTrompDDS", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e6659aab-3b85-4fcf-b238-9784e8fa0c87", + "name": "JettBartell RayHuels", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fa8520ee-dbbc-4c82-8a3a-3eb7a2e670b9", + "name": "DorthyRitchie EthelynConroy", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "c99366a3-1ca5-4be0-b241-d5ab251e2128", + "name": "MrsJerrodWill MissHassanMcDermott", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "5545474c-72ae-439e-b15e-ea01d8024e9a", + "name": "JonatanBaumbach IsadoreMohrDVM", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1de82b84-509f-4b44-8e57-83a4c84ddb65", + "name": "MableSporerI KarleeWestPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "c6105907-18f0-4328-8612-4a3712a87589", + "name": "TaniaOConnell MorrisJast", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "3befd488-1e79-4a0f-9195-55627345a896", + "name": "MissTremayneVonRueden MargarettQuigley", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ba54b319-f774-4df1-9998-079518bafb71", + "name": "AllyConn MissKimberlyHoppe", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "58d673f1-d8a0-4afa-9a88-39b890d1d97f", + "name": "AlvaHettinger AngelitaLeffler", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "bb141f5b-3871-45a8-9aec-c0e7caea97be", + "name": "JasperHodkiewicz PaytonBartonPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b8e10ae9-8d1b-4046-94c2-85d836c11819", + "name": "FreddyGrahamII ImeldaTrantow", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "db342b5a-a353-44cf-afa1-01106adfd4e2", + "name": "GavinBednar JosianeWelch", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "677457e3-fd7f-408e-939d-d3315037f00d", + "name": "DarrionMosciski NicoletteAufderhar", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b01bb2c0-a584-49fe-ab49-818a7fd693a5", + "name": "AbigaleOHara BernhardZiemann", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "af974075-2c2a-43ac-927b-2e3213b7fd56", + "name": "MissBreanneKunde JuliaLeannon", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "97d4fba3-fab5-4153-bf05-7466624ea6bd", + "name": "ImeldaFranecki LeolaWisozk", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8680fef5-5731-4b7c-9baf-e984bdef572e", + "name": "VernerWunsch SallyHeathcote", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0afab59f-2ac2-4187-8b9e-51a008c37f82", + "name": "TadDicki HeatherKertzmann", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "dc4ebae1-99e1-44fc-a8d8-6f45c90250d9", + "name": "DrKennithMetz BobbyWilderman", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "7aaa8b68-c6d9-4085-87d0-177e4252a09f", + "name": "BradenMosciskiII SterlingWilkinson", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "c51736bd-1110-43ba-a47a-72e90d12c7d1", + "name": "JakobKub MsDaneGulgowski", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8d18316e-79e1-4a6e-889c-8151de8ac20f", + "name": "KyleeStamm AutumnBruenPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "18138725-f91c-4a12-a04d-43d73951559a", + "name": "NatHowell AbigaleAbshireSr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "06803beb-8218-41db-ba3b-87ffabcfe59f", + "name": "BoydRosenbaum MrIsabellMedhurst", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "24c88514-5966-4977-b6a5-d14d71ed51a7", + "name": "DashawnSpencer EstellMcDermottMD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "3a0fe418-0d87-422b-b9d7-62350e4d6e06", + "name": "JaunitaHerzog WestleyKovacek", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "59b19985-f2ac-4a39-94a2-7a1b7d4a1589", + "name": "OrlandWehner WayneAufderhar", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "60a55a0f-33cf-49e3-8acb-d055f0d57b8d", + "name": "AntoniaDach MissArvelCrooks", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ccba202e-90d4-4204-a590-d0b385fff0b2", + "name": "MissEnricoSatterfield FredFeeney", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ffd059fc-86ca-4e5b-ae68-428fc9a7c151", + "name": "MrsLexusMayer ArianeSchroeder", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "846b2313-cf96-47a1-b747-28529f713f57", + "name": "MrAshleyGreen DedrickTurner", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "893a2561-be87-4bbe-b0a4-e3ebfdf66bce", + "name": "GillianTowne VicentaRobelDDS", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "d28c8e9f-958b-4d7d-bd27-bcbf7e40276c", + "name": "AnselCorkery WellingtonBalistreri", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1d6ebd32-5263-4d4c-b1cb-ece2c52d4639", + "name": "DrAshtynSchowalter RosaleeHuelPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "13782f1a-d49c-4e51-bffb-03c2ab5466b9", + "name": "DedrickCronin MaximusJones", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1847fa77-3c6c-45e6-a2fd-713c97b13bc8", + "name": "BillKoepp CristinaWisoky", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "127d364c-b608-452d-b9d2-870374669ac4", + "name": "JanieMarvin AbbieCollins", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "a94e2132-b59c-421f-8956-8da3da67edc3", + "name": "TrevorBogan MsJoanieHaag", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "996ca813-6994-4f08-ab55-a086d688f5a8", + "name": "AlainaDooleySr KianKulas", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f49925f2-3934-4bc2-9dbe-61ab3d2d0d2a", + "name": "BrennanKautzer BurdetteDonnelly", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "813e7f84-8c69-4a5b-97e4-7f3278d589b6", + "name": "BennieConn CelestinoHamill", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "9eeec010-029b-4cac-b4ea-a3ac6256bada", + "name": "ElsaRempel BurniceLabadie", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1b35f8f4-1c9c-4e72-bd54-052ab3b33745", + "name": "JoannieGlover ClarabelleLubowitz", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "6f732065-9e64-487c-88e3-713c49db7dd1", + "name": "LuciousMuller MiaPurdy", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "25c21fbf-ddcc-4224-86c6-8f8b3db64406", + "name": "KiarraVolkman DelphiaOReillyJr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "60f9a9c1-2e1f-41e1-a55a-0ce0a3ccafff", + "name": "JordynOHara YasminDare", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "524299c3-ffec-473a-8b8a-5352f9bb1498", + "name": "ArmandMayerII RomaineOHara", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "91a0d1eb-b9ce-453f-ae01-04ab932b1d88", + "name": "PhoebeMertz ErichHand", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "d3db5d12-51fd-4267-9972-32d0e08ba5a0", + "name": "MrEdwardRyan MarieReynolds", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0caf1682-79de-4e99-977b-6327defb04ae", + "name": "LilianaGibson JillianWintheiser", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8d9319be-9435-476e-a7ee-26a3b4adb519", + "name": "DonnellJacobs MrEttieLakin", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "740e9322-d303-4d7a-b018-5a7ce6f228cf", + "name": "MrTrevorBauch MsTadMante", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ad014131-4ca9-4738-ab04-0abb21988925", + "name": "GoldaLeannon KevinBogisich", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b88a29c3-7d53-40db-a4cd-c74cfa383535", + "name": "MissPrincessStokes EstaHarris", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1047c75a-07f7-464f-9d68-abbe928721d8", + "name": "MissValeriePagac UniqueLowe", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "912d8c9c-ebc4-4c90-939d-a0022fac592f", + "name": "CarolyneYost KhalidHagenes", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "71df5db0-1b97-451e-8d4b-158780ce89b5", + "name": "TraceLarson PercyRempel", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "070fe31e-b2b9-4c40-ba0f-47bd2dea8bed", + "name": "DomenicaHeller MaryHamill", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1c6a4318-74dc-4978-9a6a-cf5218158d09", + "name": "LauraSchumm DomenicWindler", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "1e10de58-6426-48c9-b32a-4068181cc902", + "name": "CristalFahey DrTheodoraAuer", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fca4da6e-6307-4239-8369-4c823da291ea", + "name": "ElizaSatterfield JeramyThiel", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "c2007c10-50e2-45b2-b0ec-94d78fca7464", + "name": "DevenCruickshankDVM KoreyCollierSr", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "fb63837c-1621-4d5c-ae94-5dd4e966850a", + "name": "AmiyaFadel MonicaHyattPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "16031f9b-929a-4b2e-8dca-32ba9d011871", + "name": "RicoSchmeler YasmineBernier", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "b07623eb-9064-4bab-b3ac-7f9ed56e70c3", + "name": "MittieHirthe DaneRutherford", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0f4074d2-3f60-4afa-b67e-9aeb606fcf12", + "name": "DominiquePurdy TianaSchaefer", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "751d5835-a58c-4b86-a097-03e764d05e53", + "name": "GenevieveLegros ColleenCorwin", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "de428405-5be2-419f-b488-ad9f4c56fed5", + "name": "MallieWeimann MargaretteCarroll", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "0e3574ff-e190-4cc5-8424-d68a32f7814f", + "name": "RobertaKunde LillaKing", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "06d057b1-b13a-4f51-b2dd-02a3a688b414", + "name": "ValentinKoeppSr OlgaCronaPhD", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f1afae38-4740-433c-b2e6-dcd415741052", + "name": "AnyaMorar DrMckenzieVeum", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "079c9ca0-74d3-4a95-9fef-e9e17a123873", + "name": "JasonRempel MrBlancaParisian", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "53c5a997-4dda-423f-a56e-b576b8c5fdb3", + "name": "MsLaverneShanahan GlenHeller", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "faa11323-ee4d-42d0-9400-955723e83d89", + "name": "MissVincenzoGreenholt TheodoraRath", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "94a1c9a4-a44d-4e52-badc-051c4084c193", + "name": "RyleySchusterII MarcelinaHillsI", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ebfcbb8f-5d10-42b8-9260-8a0e5eee8f29", + "name": "MarcelleMaggio MayeParker", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "a0c04c7d-1027-43f7-872b-f6150fb1970d", + "name": "TatumVandervort EarleneJohnson", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e3fbc347-f15c-4bc5-9eb0-c10bf26da2dc", + "name": "MissCitlalliHamill NatalieKundeIV", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "241daa8a-3b79-4213-a17c-f3635e100401", + "name": "EverettSwift AyanaStroman", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "ad2c50a9-0f56-403d-9df0-0edcece0c701", + "name": "RaoulCremin ReannaConsidine", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "187e18f6-32c8-437f-8292-fdbe09427d2b", + "name": "ClarabelleBeer JackieShields", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "e29044fe-45b3-41ae-ab00-eb9913e5daa6", + "name": "BrigitteRenner WillardLabadie", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "bccdc05a-c4d6-4b95-acc6-19f1a6c4abbd", + "name": "DavionJast ChanellePagac", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "67a02f30-f193-4490-9aec-ebf7c6619141", + "name": "FavianMarks EdaKirlin", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "672fc730-8e84-4e9e-97f5-c5dcd93557ba", + "name": "MaximusBatz RyleeMetzDDS", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "f1317729-a366-4c19-9765-9f5b1d156f94", + "name": "ChadrickBergnaum RogersBerge", + "location": "Austin, TX", + "photo_url": null + }, + { + "type": "user", + "id": "8ac936dc-3185-47ab-92ad-5b04e470da9f", + "name": "Mateo Antony", + "location": "Austin, TX", + "photo_url": null + } + ], + "bands": [ + { + "id": "32df51d1-e323-4f02-80ba-63229b4861ed", + "name": "Martine Johnston", + "admin": false, + "photo_url": null, + "logo_url": null, + "genres": [ + { + "id": "country", + "description": "Country" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "techno", + "description": "Techno" + } + ] + }, + { + "id": "74f50a3d-df82-47f5-8053-0281bc27403f", + "name": "JMam", + "admin": false, + "photo_url": null, + "logo_url": null, + "genres": [ + { + "id": "blues", + "description": "Blues" + } + ] + }, + { + "id": "fc24a1e0-f212-4418-98d9-f0514e0cc699", + "name": "Uturn", + "admin": false, + "photo_url": null, + "logo_url": null, + "genres": [ + { + "id": "reggae", + "description": "Reggae" + } + ] + } + ], + "instruments": [], + "genres": [ + { + "description": "A Cappella", + "id": "acapella" + }, + { + "description": "African", + "id": "african" + }, + { + "description": "Alternative Rock", + "id": "alternative rock" + }, + { + "description": "Ambient", + "id": "ambient" + }, + { + "description": "Drum & Bass", + "id": "drum & bass" + }, + { + "description": "Electronic", + "id": "electronic" + }, + { + "description": "Folk", + "id": "folk" + }, + { + "description": "Funk", + "id": "funk" + }, + { + "description": "Psychedelic", + "id": "psychedelic" + }, + { + "description": "Punk", + "id": "punk" + }, + { + "description": "R&B", + "id": "r&b" + }, + { + "description": "Rap", + "id": "rap" + } + ], + "sessions": [ + { + "id": "91de1362-bd56-44b2-a39b-8d7fb4d38fa5", + "description": "Private session set up just to test things out in the session interface by myself.", + "musician_access": false, + "approval_required": false, + "fan_access": false + } + ], + "teacher": { + "id": "5fd55476-320d-4532-8ad8-79f9a7d88e20", + "biography": "A teacher experienced teaching music for students from kindergarten to high school. ", + "created_at": "2022-10-20T13:35:33.210Z", + "introductory_video": null, + "lesson_duration_120": false, + "lesson_duration_30": false, + "lesson_duration_45": false, + "lesson_duration_60": true, + "lesson_duration_90": false, + "price_per_lesson_120_cents": null, + "price_per_lesson_30_cents": null, + "price_per_lesson_45_cents": null, + "price_per_lesson_60_cents": 10000, + "price_per_lesson_90_cents": null, + "price_per_month_120_cents": null, + "price_per_month_30_cents": null, + "price_per_month_45_cents": null, + "price_per_month_60_cents": null, + "price_per_month_90_cents": null, + "prices_per_lesson": true, + "prices_per_month": false, + "teaches_advanced": true, + "teaches_age_lower": 3, + "teaches_age_upper": 20, + "teaches_beginner": true, + "teaches_intermediate": true, + "updated_at": "2022-10-20T13:41:50.521Z", + "website": null, + "years_playing": 15, + "years_teaching": 10, + "teaches_test_drive": true, + "test_drives_per_week": 10, + "errors": {}, + "profile_pct": "87.0", + "school_id": null, + "background_check_at": null, + "is_searchable": true, + "review_summary": null, + "school": null, + "recent_reviews": [], + "profile_pct_summary": { + "name_specified": true, + "experiences_teaching": true, + "experiences_education": true, + "experiences_award": true, + "has_stripe_account": null, + "has_teacher_bio": true, + "intro_video": false, + "years_teaching": true, + "years_playing": true, + "instruments_or_subject": true, + "genres": true, + "languages": true, + "teaches_ages_specified": true, + "teaching_level_specified": true, + "has_pricing_specified": true, + "pct": 87 + }, + "instruments": [ + "acoustic guitar", + "drums", + "keyboard", + "voice", + "flute", + "piano" + ], + "subjects": [ + "music-theory", + "composing", + "site-reading", + "guitar-ring" + ], + "genres": [ + "classical", + "folk", + "jazz" + ], + "languages": [ + "EN", + "FR" + ], + "experiences_teaching": [ + { + "name": "Jr. Music Teacher", + "experience_type": "teaching", + "organization": "St. Peters College", + "start_year": 2005, + "end_year": 2010 + } + ], + "experiences_education": [ + { + "name": "Bacholor in Fine arts ", + "experience_type": "education", + "organization": "London Fine Arts University", + "start_year": 2012, + "end_year": 2015 + } + ], + "experiences_award": [ + { + "name": "Best Folk Music Singer", + "experience_type": "award", + "organization": "University of St. Gorge", + "start_year": 2020, + "end_year": null + } + ], + "has_rated_teacher": false + }, + "owned_school_id": null, + "owned_retailer_id": null, + "geoiplocation": null, + "show_free_jamtrack": false, + "show_jamtrack_guide": true, + "mods": {}, + "has_recurly_account": true, + "is_affiliate_partner": false, + "affiliate_referral_count": null, + "affiliate_earnings": null, + "last_jam_audio_latency": 5 + }, + "timestamp": "2026-01-20T10:15:57.112Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/versioncheck?product=JamClientModern&os=MacOSX-M", + "body": { + "version": "2.0.0.1956", + "uri": "http://d48bcgsnmsm6a.cloudfront.net/artifacts/JamClientModern/MacOSX-M/2.0.0.1956/JamKazam-1770.dmg", + "sha1": "2ca2238f4a21a09c32d4a0b6f5fee78b", + "size": 240820609 + }, + "timestamp": "2026-01-20T10:15:57.123Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/jamtracks/purchased?page=1&per_page=40", + "body": { + "next": null, + "jamtracks": [ + { + "id": "1", + "name": "Back in Black", + "description": "This is a JamTrack audio file for use exclusively with the JamKazam service. This JamTrack is a high quality cover of the AC DC song \"Back in Black\".", + "original_artist": "AC DC", + "version": "0", + "year": null, + "duration": 221, + "allow_free": true, + "genres": [ + { + "id": "pop", + "description": "Pop" + }, + { + "id": "rock", + "description": "Rock" + } + ], + "tracks": [ + { + "id": "103dea4d-f2a3-4414-8efe-d2ca378dda60", + "part": "Master Mix", + "instrument": { + "id": "computer", + "description": "Computer", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Master", + "position": 1000, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Master%20Mix-44100-preview-e9a5a63f34b4d523ee1842fff31f88ce.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Master%20Mix-44100-preview-25fcba7ace7086e3cb6b97d7e33ba72e.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Master%20Mix-44100-preview-9f0b072ed9f4b546e170fcdfb302137e.mp3" + }, + { + "id": "2755cbdd-0476-4f3b-9ba1-e2da561ddb4e", + "part": "Lead", + "instrument": { + "id": "voice", + "description": "Voice", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 1, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Vocal%20-%20Lead-44100-preview-d35c328fc3936dad9a79fe102dc72950.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Vocal%20-%20Lead-44100-preview-b97b37651eae352fae3b3060918c7bcb.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Vocal%20-%20Lead-44100-preview-d35c328fc3936dad9a79fe102dc72950.aac" + }, + { + "id": "0db7c4e1-5e8d-43fe-bd35-98acd8f68b26", + "part": "Drums", + "instrument": { + "id": "drums", + "description": "Drums", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 2, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Drums-44100-preview-03aadceb966caf40b96334bdd00234f6.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Drums-44100-preview-854914e3e0d6fdc5f0794325b0ecaead.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Drums-44100-preview-03aadceb966caf40b96334bdd00234f6.aac" + }, + { + "id": "2cc79ab6-dab8-4905-85e6-0df5f8e087f1", + "part": "Bass", + "instrument": { + "id": "bass guitar", + "description": "Bass Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 3, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Bass-44100-preview-61c334ac87f811bd010ed3a910764c2e.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Bass-44100-preview-4066dafd7b72e9993b0c0fe1dba2b332.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Bass-44100-preview-61c334ac87f811bd010ed3a910764c2e.aac" + }, + { + "id": "ed1d3487-3b32-442f-9c76-8a36fe3bb643", + "part": "Solo", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 4, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Solo-44100-preview-e9fe8572a9ac1022762642cbd92b3c34.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Solo-44100-preview-5fb058042254206cfa9fb4dcb0310b2c.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Solo-44100-preview-e9fe8572a9ac1022762642cbd92b3c34.aac" + }, + { + "id": "f4ce7c91-7542-4e03-8fc2-68b31683d33e", + "part": "Rhythm 1", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 5, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%201-44100-preview-6b498479823d4131a01fa535817d5eab.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%201-44100-preview-f4cbb31dbde3e1a3e6012730a7e0e10f.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%201-44100-preview-6b498479823d4131a01fa535817d5eab.aac" + }, + { + "id": "2d96c7ec-59f1-4d56-8a7f-7f4c75a0ccef", + "part": "Rhythm 2", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 6, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%202-44100-preview-a626d7c632560f6737e1b6024141289e.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%202-44100-preview-06a0e5af451f001f3465992efcd34ec0.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Rhythm%202-44100-preview-a626d7c632560f6737e1b6024141289e.aac" + }, + { + "id": "fce018ca-c897-4137-aa10-ef56a8e1831f", + "part": "Intro Scrapes", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 7, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Intro%20Scrapes-44100-preview-0ddfaa7154e9ba35d05d60477d5dd3e9.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Intro%20Scrapes-44100-preview-f53ce3c5f9dcf81af51560f52635fbb0.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Intro%20Scrapes-44100-preview-0ddfaa7154e9ba35d05d60477d5dd3e9.aac" + }, + { + "id": "c9b3e0a8-4db0-4d0f-9769-398a6d56506e", + "part": "Main", + "instrument": { + "id": "electric guitar", + "description": "Electric Guitar", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 8, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Main-44100-preview-234a224f75a97d7ff8f55442ece6fcde.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Main-44100-preview-828c9691f5435dea1c90182fa2618c9b.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Electric%20Guitar%20-%20Main-44100-preview-234a224f75a97d7ff8f55442ece6fcde.aac" + }, + { + "id": "28c3df07-2a88-45a9-9ae6-3399a5d2eb20", + "part": "Sound FX", + "instrument": { + "id": "computer", + "description": "Computer", + "created_at": "2021-02-02T23:16:46.168Z", + "updated_at": "2021-02-02T23:16:46.168Z", + "popularity": 3 + }, + "track_type": "Track", + "position": 9, + "preview_mp3_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Sound%20Effects-44100-preview-6c859c73036cd55bceb65f19f2d2f2f3.mp3", + "preview_ogg_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Sound%20Effects-44100-preview-f840d8df4c7388f776477139025ee712.ogg", + "preview_aac_url": "https://jamkazam-dev-public.s3.amazonaws.com/jam_track_previews/AC%20DC/Back%20in%20Black/Back%20in%20Black%20Stem%20-%20Sound%20Effects-44100-preview-6c859c73036cd55bceb65f19f2d2f2f3.aac" + } + ], + "jmep": null, + "can_download": true, + "jam_track_right_id": 1428, + "purchased_at": 1752755050, + "last_mixdown_id": null, + "last_stem_id": null, + "mixdowns": [ + { + "id": "5f24403f-3cfa-44f5-b36e-52b2c3c66af8", + "name": "db", + "description": null, + "jam_track_id": "1", + "packages": [ + { + "id": "23b10fa0-195d-4ad5-a5a7-2cba6b8c1451", + "jam_track_mixdown_id": "5f24403f-3cfa-44f5-b36e-52b2c3c66af8", + "file_type": "mp3", + "sample_rate": 48, + "encrypt_type": null, + "error_count": 0, + "error_reason": null, + "error_detail": null, + "signing_state": "SIGNED", + "packaging_steps": 10, + "current_packaging_step": 8, + "version": "1" + } + ], + "created_at": 1753866891, + "settings": { + "count-in": false, + "tracks": [ + { + "id": "2755cbdd-0476-4f3b-9ba1-e2da561ddb4e", + "mute": false + }, + { + "id": "0db7c4e1-5e8d-43fe-bd35-98acd8f68b26", + "mute": true + }, + { + "id": "2cc79ab6-dab8-4905-85e6-0df5f8e087f1", + "mute": true + }, + { + "id": "ed1d3487-3b32-442f-9c76-8a36fe3bb643", + "mute": false + }, + { + "id": "f4ce7c91-7542-4e03-8fc2-68b31683d33e", + "mute": false + }, + { + "id": "2d96c7ec-59f1-4d56-8a7f-7f4c75a0ccef", + "mute": false + }, + { + "id": "fce018ca-c897-4137-aa10-ef56a8e1831f", + "mute": false + }, + { + "id": "c9b3e0a8-4db0-4d0f-9769-398a6d56506e", + "mute": false + }, + { + "id": "28c3df07-2a88-45a9-9ae6-3399a5d2eb20", + "mute": false + } + ] + } + } + ] + } + ] + }, + "timestamp": "2026-01-20T10:15:57.123Z" + }, + { + "type": "request", + "method": "POST", + "url": "http://www.jamkazam.local:3100/api/sessions", + "timestamp": "2026-01-20T10:15:57.295Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/history?includePending=false", + "timestamp": "2026-01-20T10:15:57.677Z" + }, + { + "type": "response", + "status": 201, + "url": "http://www.jamkazam.local:3100/api/sessions", + "body": { + "id": "02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "music_session_id": null, + "name": "Private Test Session", + "description": "Private session set up just to test things out in the session interface by myself.", + "musician_access": false, + "approval_required": false, + "fan_access": false, + "fan_chat": false, + "create_type": "quick-start", + "band_id": null, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "genre_id": "pop", + "created_at": "2026-01-20T10:15:57.311Z", + "like_count": 0, + "comment_count": 0, + "play_count": 0, + "scheduled_duration": "01:00:00", + "language": "eng", + "recurring_mode": "once", + "language_description": "English", + "scheduled_start_date": "Tue 20 January 2026", + "access_description": "Only RSVP musicians may join. Fans may not listen to session.", + "timezone": "Central Time (US & Canada),America/Chicago", + "timezone_id": "America/Chicago", + "timezone_description": "Central Time (US & Canada)", + "musician_access_description": "Only RSVP musicians may join", + "fan_access_description": "Fans may not listen to session", + "session_removed_at": null, + "legal_policy": "Standard", + "open_rsvps": false, + "is_unstructured_rsvp?": false, + "friends_can_join": false, + "use_video_conferencing_server": true, + "creator": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "name": "Nuwan Chaturanga", + "photo_url": null + }, + "band": null, + "users": [], + "comments": [], + "session_info_comments": [], + "music_notations": [], + "invitations": [], + "approved_rsvps": [ + { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "resolved_photo_url": "http://localhost:3000/assets/shared/avatar_generic.png", + "full_score": null, + "audio_latency": 5, + "internet_score": null, + "instrument_list": [ + { + "id": "other", + "desc": "Other", + "level": 1 + } + ], + "rsvp_request_id": "103357a2-f2d9-496b-a52d-40ec50ddc47d" + } + ], + "open_slots": [], + "pending_invitations": [], + "pending_rsvp_requests": [], + "lesson_session": null, + "active_music_session": null, + "can_join": true, + "share_url": "http://www.jamkazam.local:3100/s/YJSXUSG4DW", + "genres": [ + "Pop" + ], + "scheduled_start": "Tue 20 January 2026 15:45:00", + "pretty_scheduled_start_with_timezone": "Wednesday, January 21, 3:15-3:15 AM Asia/Kolkata", + "pretty_scheduled_start_short": "Wednesday, January 21 - 3:15am" + }, + "timestamp": "2026-01-20T10:15:57.680Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/history?includePending=false", + "body": { + "id": "02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "music_session_id": null, + "name": "Private Test Session", + "description": "Private session set up just to test things out in the session interface by myself.", + "musician_access": false, + "approval_required": false, + "fan_access": false, + "fan_chat": false, + "create_type": "quick-start", + "band_id": null, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "genre_id": "pop", + "created_at": "2026-01-20T10:15:57.311Z", + "like_count": 0, + "comment_count": 0, + "play_count": 0, + "scheduled_duration": "01:00:00", + "language": "eng", + "recurring_mode": "once", + "language_description": "English", + "scheduled_start_date": "Tue 20 January 2026", + "access_description": "Only RSVP musicians may join. Fans may not listen to session.", + "timezone": "Central Time (US & Canada),America/Chicago", + "timezone_id": "America/Chicago", + "timezone_description": "Central Time (US & Canada)", + "musician_access_description": "Only RSVP musicians may join", + "fan_access_description": "Fans may not listen to session", + "session_removed_at": null, + "legal_policy": "Standard", + "open_rsvps": false, + "is_unstructured_rsvp?": false, + "friends_can_join": false, + "use_video_conferencing_server": true, + "creator": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "name": "Nuwan Chaturanga", + "photo_url": null + }, + "band": null, + "users": [], + "comments": [], + "session_info_comments": [], + "music_notations": [], + "invitations": [], + "approved_rsvps": [ + { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "resolved_photo_url": "http://localhost:3000/assets/shared/avatar_generic.png", + "full_score": null, + "audio_latency": 5, + "internet_score": null, + "instrument_list": [ + { + "id": "other", + "desc": "Other", + "level": 1 + } + ], + "rsvp_request_id": "103357a2-f2d9-496b-a52d-40ec50ddc47d" + } + ], + "open_slots": [], + "pending_invitations": [], + "pending_rsvp_requests": [], + "lesson_session": null, + "active_music_session": null, + "can_join": true, + "share_url": "http://www.jamkazam.local:3100/s/YJSXUSG4DW", + "genres": [ + "Pop" + ], + "scheduled_start": "Tue 20 January 2026 15:45:00", + "pretty_scheduled_start_with_timezone": "Wednesday, January 21, 3:15-3:15 AM Asia/Kolkata", + "pretty_scheduled_start_short": "Wednesday, January 21 - 3:15am" + }, + "timestamp": "2026-01-20T10:15:57.729Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/config/client?", + "timestamp": "2026-01-20T10:15:57.748Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/config/client?", + "body": { + "top_message": null, + "event_page_top_logo_url": "/assets/event/eventbrite-logo.png" + }, + "timestamp": "2026-01-20T10:15:57.766Z" + }, + { + "type": "request", + "method": "POST", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/participants", + "timestamp": "2026-01-20T10:15:57.929Z" + }, + { + "type": "response", + "status": 201, + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/participants", + "body": { + "id": "02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "name": "Private Test Session", + "description": "Private session set up just to test things out in the session interface by myself.", + "musician_access": false, + "approval_required": false, + "friends_can_join": false, + "fan_access": false, + "fan_chat": false, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "claimed_recording_initiator_id": null, + "track_changes_counter": 0, + "max_score": 0, + "backing_track_path": null, + "metronome_active": false, + "jam_track_initiator_id": null, + "jam_track_id": null, + "music_session_id_int": 3061, + "use_video_conferencing_server": true, + "music_notations": [], + "participants": [ + { + "ip_address": "127.0.0.1", + "client_id": "b39b584a-5249-4065-9fcb-ca21d8e69b0a", + "joined_session_at": "2026-01-20T10:15:57.996Z", + "id": "a37e4a35-f994-4707-bd68-4150ae45bd6a", + "metronome_open": false, + "is_jamblaster": false, + "client_role": "parent", + "parent_client_id": "", + "client_id_int": 93862, + "tracks": [ + { + "id": "2033f806-44b4-40a7-8eb3-4b4470b1ddb9", + "connection_id": "a37e4a35-f994-4707-bd68-4150ae45bd6a", + "instrument_id": "piano", + "sound": "stereo", + "client_track_id": "d4734735-0acb-4e87-9737-320efb024b3f", + "client_resource_id": "0x60000117dab0", + "updated_at": "2026-01-20T10:15:57.999Z", + "instrument": "Piano" + } + ], + "backing_tracks": [], + "user": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "name": "Nuwan Chaturanga", + "is_friend": false, + "connection_state": "connected", + "subscription": "jamsubplatinum" + } + } + ], + "invitations": [], + "lesson_session": null, + "join_requests": [], + "jam_track": null, + "claimed_recording": null, + "subscription": { + "play_time_per_month": null, + "play_time_per_session": null, + "can_record_audio": true, + "can_record_video": true, + "can_use_video": true, + "can_record_wave": true, + "video_resolution": 4, + "audio_max_bitrate": 5, + "can_broadcast": true, + "broadcasting_type": 3, + "max_players": null, + "pro_audio": true, + "has_support": true, + "name": "Platinum", + "rank": 3, + "remaining_month_play_time": null + }, + "session_rules": { + "remaining_session_play_time": null + }, + "can_join": true, + "genres": [ + "Pop" + ], + "recording": null, + "share_url": "http://www.jamkazam.local:3100/s/YJSXUSG4DW", + "session_controller_id": "27bd4a30-d1b8-4eea-8454-01a104d59381" + }, + "timestamp": "2026-01-20T10:15:58.327Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "timestamp": "2026-01-20T10:15:58.794Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/chat?type=CHAT_MESSAGE&limit=20&page=0&channel=session&music_session=02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "timestamp": "2026-01-20T10:15:58.809Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "body": {}, + "timestamp": "2026-01-20T10:15:58.835Z" + }, + { + "type": "request", + "method": "PUT", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "timestamp": "2026-01-20T10:15:58.859Z" + }, + { + "type": "response", + "status": 204, + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "body": null, + "timestamp": "2026-01-20T10:15:58.963Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "timestamp": "2026-01-20T10:15:58.964Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/chat?type=CHAT_MESSAGE&limit=20&page=0&channel=session&music_session=02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "body": { + "next": null, + "chats": [] + }, + "timestamp": "2026-01-20T10:15:58.968Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "body": { + "id": "02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "name": "Private Test Session", + "description": "Private session set up just to test things out in the session interface by myself.", + "musician_access": false, + "approval_required": false, + "friends_can_join": false, + "fan_access": false, + "fan_chat": false, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "claimed_recording_initiator_id": null, + "track_changes_counter": 1, + "max_score": 0, + "backing_track_path": null, + "metronome_active": false, + "jam_track_initiator_id": null, + "jam_track_id": null, + "music_session_id_int": 3061, + "use_video_conferencing_server": true, + "music_notations": [], + "participants": [ + { + "ip_address": "127.0.0.1", + "client_id": "b39b584a-5249-4065-9fcb-ca21d8e69b0a", + "joined_session_at": "2026-01-20T10:15:57.996Z", + "id": "a37e4a35-f994-4707-bd68-4150ae45bd6a", + "metronome_open": true, + "is_jamblaster": false, + "client_role": "parent", + "parent_client_id": "", + "client_id_int": 93862, + "tracks": [ + { + "id": "2033f806-44b4-40a7-8eb3-4b4470b1ddb9", + "connection_id": "a37e4a35-f994-4707-bd68-4150ae45bd6a", + "instrument_id": "piano", + "sound": "stereo", + "client_track_id": "d4734735-0acb-4e87-9737-320efb024b3f", + "client_resource_id": "0x60000117dab0", + "updated_at": "2026-01-20T10:15:57.999Z", + "instrument": "Piano" + } + ], + "backing_tracks": [], + "user": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "name": "Nuwan Chaturanga", + "is_friend": false, + "connection_state": "connected", + "subscription": "jamsubplatinum" + } + } + ], + "invitations": [], + "lesson_session": null, + "join_requests": [], + "jam_track": null, + "claimed_recording": null, + "can_join": true, + "genres": [ + "Pop" + ], + "recording": null, + "share_url": "http://www.jamkazam.local:3100/s/YJSXUSG4DW", + "session_controller_id": "27bd4a30-d1b8-4eea-8454-01a104d59381" + }, + "timestamp": "2026-01-20T10:15:59.052Z" + }, + { + "type": "request", + "method": "PUT", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "timestamp": "2026-01-20T10:15:59.264Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "timestamp": "2026-01-20T10:15:59.317Z" + }, + { + "type": "response", + "status": 204, + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "body": null, + "timestamp": "2026-01-20T10:15:59.318Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "body": { + "id": "02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "name": "Private Test Session", + "description": "Private session set up just to test things out in the session interface by myself.", + "musician_access": false, + "approval_required": false, + "friends_can_join": false, + "fan_access": false, + "fan_chat": false, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "claimed_recording_initiator_id": null, + "track_changes_counter": 2, + "max_score": 0, + "backing_track_path": null, + "metronome_active": false, + "jam_track_initiator_id": null, + "jam_track_id": null, + "music_session_id_int": 3061, + "use_video_conferencing_server": true, + "music_notations": [], + "participants": [ + { + "ip_address": "127.0.0.1", + "client_id": "b39b584a-5249-4065-9fcb-ca21d8e69b0a", + "joined_session_at": "2026-01-20T10:15:57.996Z", + "id": "a37e4a35-f994-4707-bd68-4150ae45bd6a", + "metronome_open": true, + "is_jamblaster": false, + "client_role": "parent", + "parent_client_id": "", + "client_id_int": 93862, + "tracks": [ + { + "id": "2033f806-44b4-40a7-8eb3-4b4470b1ddb9", + "connection_id": "a37e4a35-f994-4707-bd68-4150ae45bd6a", + "instrument_id": "piano", + "sound": "stereo", + "client_track_id": "d4734735-0acb-4e87-9737-320efb024b3f", + "client_resource_id": "0x60000117dab0", + "updated_at": "2026-01-20T10:15:57.999Z", + "instrument": "Piano" + } + ], + "backing_tracks": [], + "user": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "name": "Nuwan Chaturanga", + "is_friend": false, + "connection_state": "connected", + "subscription": "jamsubplatinum" + } + } + ], + "invitations": [], + "lesson_session": null, + "join_requests": [], + "jam_track": null, + "claimed_recording": null, + "can_join": true, + "genres": [ + "Pop" + ], + "recording": null, + "share_url": "http://www.jamkazam.local:3100/s/YJSXUSG4DW", + "session_controller_id": "27bd4a30-d1b8-4eea-8454-01a104d59381" + }, + "timestamp": "2026-01-20T10:15:59.352Z" + }, + { + "type": "request", + "method": "POST", + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/udp_reachable", + "timestamp": "2026-01-20T10:15:59.547Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/udp_reachable", + "body": { + "id": "a37e4a35-f994-4707-bd68-4150ae45bd6a", + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "client_id": "b39b584a-5249-4065-9fcb-ca21d8e69b0a", + "created_at": "2026-01-20T10:15:55.601Z", + "updated_at": "2026-01-20T10:15:58.008Z", + "music_session_id": "02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "ip_address": "127.0.0.1", + "as_musician": true, + "aasm_state": "connected", + "addr": 2130706433, + "locidispid": null, + "joined_session_at": "2026-01-20T10:15:57.996Z", + "client_type": "browser", + "stale_time": 40, + "expire_time": 60, + "last_jam_audio_latency": null, + "channel_id": "cda1cd05-a1e0-4c7e-c7a3-dfa8afe48761", + "udp_reachable": false, + "scoring_timeout": "2026-01-20T10:15:55.601Z", + "scoring_failures": 0, + "scoring_timeout_occurrences": 0, + "scoring_failures_offset": 0, + "gateway": "default-1", + "is_network_testing": false, + "metronome_open": true, + "user_active": true, + "is_jamblaster": false, + "client_role": "parent", + "parent_client_id": "", + "client_id_int": 93862 + }, + "timestamp": "2026-01-20T10:15:59.566Z" + }, + { + "type": "request", + "method": "PUT", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "timestamp": "2026-01-20T10:16:05.013Z" + }, + { + "type": "response", + "status": 204, + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "body": null, + "timestamp": "2026-01-20T10:16:05.045Z" + }, + { + "type": "request", + "method": "GET", + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "timestamp": "2026-01-20T10:16:05.049Z" + }, + { + "type": "response", + "status": 200, + "url": "http://www.jamkazam.local:3100/api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "body": { + "id": "02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "name": "Private Test Session", + "description": "Private session set up just to test things out in the session interface by myself.", + "musician_access": false, + "approval_required": false, + "friends_can_join": false, + "fan_access": false, + "fan_chat": false, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "claimed_recording_initiator_id": null, + "track_changes_counter": 3, + "max_score": 0, + "backing_track_path": null, + "metronome_active": false, + "jam_track_initiator_id": null, + "jam_track_id": null, + "music_session_id_int": 3061, + "use_video_conferencing_server": true, + "music_notations": [], + "participants": [ + { + "ip_address": "127.0.0.1", + "client_id": "b39b584a-5249-4065-9fcb-ca21d8e69b0a", + "joined_session_at": "2026-01-20T10:15:57.996Z", + "id": "a37e4a35-f994-4707-bd68-4150ae45bd6a", + "metronome_open": true, + "is_jamblaster": false, + "client_role": "parent", + "parent_client_id": "", + "client_id_int": 93862, + "tracks": [ + { + "id": "2033f806-44b4-40a7-8eb3-4b4470b1ddb9", + "connection_id": "a37e4a35-f994-4707-bd68-4150ae45bd6a", + "instrument_id": "piano", + "sound": "stereo", + "client_track_id": "d4734735-0acb-4e87-9737-320efb024b3f", + "client_resource_id": "0x60000117dab0", + "updated_at": "2026-01-20T10:15:57.999Z", + "instrument": "Piano" + } + ], + "backing_tracks": [], + "user": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "name": "Nuwan Chaturanga", + "is_friend": false, + "connection_state": "connected", + "subscription": "jamsubplatinum" + } + } + ], + "invitations": [], + "lesson_session": null, + "join_requests": [], + "jam_track": null, + "claimed_recording": null, + "can_join": true, + "genres": [ + "Pop" + ], + "recording": null, + "share_url": "http://www.jamkazam.local:3100/s/YJSXUSG4DW", + "session_controller_id": "27bd4a30-d1b8-4eea-8454-01a104d59381" + }, + "timestamp": "2026-01-20T10:16:05.176Z" + } +] \ No newline at end of file diff --git a/jam-ui/test/fixtures/legacy-sequences/summary.json b/jam-ui/test/fixtures/legacy-sequences/summary.json new file mode 100644 index 000000000..5f77445c3 --- /dev/null +++ b/jam-ui/test/fixtures/legacy-sequences/summary.json @@ -0,0 +1,128 @@ +{ + "totalCalls": 70, + "uniqueEndpoints": 25, + "endpoints": [ + { + "endpoint": "GET /api/genres", + "count": 7 + }, + { + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381", + "count": 4 + }, + { + "endpoint": "GET /api/countries", + "count": 2 + }, + { + "endpoint": "GET /api/shopping_carts", + "count": 2 + }, + { + "endpoint": "GET /api/jamtracks/purchased", + "count": 5 + }, + { + "endpoint": "GET /api/teacher_distributions", + "count": 2 + }, + { + "endpoint": "GET /api/regions", + "count": 2 + }, + { + "endpoint": "POST /xoplatform/logger/api/logger", + "count": 4 + }, + { + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification", + "count": 2 + }, + { + "endpoint": "GET /api/instruments", + "count": 6 + }, + { + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "count": 4 + }, + { + "endpoint": "GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications", + "count": 2 + }, + { + "endpoint": "GET /api/languages", + "count": 2 + }, + { + "endpoint": "GET /api/subjects", + "count": 2 + }, + { + "endpoint": "GET /api/chat", + "count": 3 + }, + { + "endpoint": "GET /api/versioncheck", + "count": 6 + }, + { + "endpoint": "GET /api/healthcheck", + "count": 1 + }, + { + "endpoint": "GET /api/config/client", + "count": 2 + }, + { + "endpoint": "GET /api/sessions/scheduled", + "count": 2 + }, + { + "endpoint": "POST /api/sessions", + "count": 1 + }, + { + "endpoint": "GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/history", + "count": 1 + }, + { + "endpoint": "POST /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/participants", + "count": 1 + }, + { + "endpoint": "PUT /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks", + "count": 3 + }, + { + "endpoint": "GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23", + "count": 3 + }, + { + "endpoint": "POST /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/udp_reachable", + "count": 1 + } + ], + "steps": [ + { + "step": "login", + "callCount": 12 + }, + { + "step": "dashboard", + "callCount": 16 + }, + { + "step": "skip-modal", + "callCount": 1 + }, + { + "step": "navigate-to-session", + "callCount": 3 + }, + { + "step": "session-creation", + "callCount": 38 + } + ] +} \ No newline at end of file diff --git a/jam-ui/test/test-results/api-verification/login-actual-calls.json b/jam-ui/test/test-results/api-verification/login-actual-calls.json new file mode 100644 index 000000000..5ba94316c --- /dev/null +++ b/jam-ui/test/test-results/api-verification/login-actual-calls.json @@ -0,0 +1,1121 @@ +[ + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/app_features?env=development", + "pathname": "/api/app_features", + "timestamp": 1768921509276, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 10351, + "responseStatus": 403, + "responseHeaders": { + "x-runtime": "0.029315", + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "no-cache", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "72bde50f-a973-45f4-b501-64eddd3e4b1e" + }, + "responseBody": { + "message": "not logged in" + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/me", + "pathname": "/api/me", + "timestamp": 1768921509278, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 10416, + "responseStatus": 403, + "responseHeaders": { + "x-runtime": "0.126912", + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "no-cache", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "802a8567-0b81-4fad-86cf-e76c7fa04805" + }, + "responseBody": { + "message": "not logged in" + } + }, + { + "method": "UNKNOWN", + "url": "http://www.jamkazam.local:3000/api/me", + "pathname": "/api/me", + "timestamp": 1768921520102, + "responseStatus": 403, + "responseHeaders": { + "x-runtime": "0.082789", + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "no-cache", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "dd269772-fd50-42dd-ab5d-347f998a16f1" + } + }, + { + "method": "POST", + "url": "http://www.jamkazam.local:3000/api/auths/login", + "pathname": "/api/auths/login", + "timestamp": 1768921520674, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "requestBody": { + "email": "nuwan@jamkazam.com", + "password": "jam123" + }, + "duration": 283, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "c351b9f8-5ed8-4138-bf0a-d15a58b5cefb", + "x-runtime": "0.262727", + "etag": "W/\"4dabf8a16746ec83912e82c5fa748292\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "first_name": "Nuwan", + "last_name": "Chaturanga", + "photo_url": null, + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "email": "nuwan@jamkazam.com" + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/me", + "pathname": "/api/me", + "timestamp": 1768921520986, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 649, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "f8410c08-9e4e-4586-a37b-8219e5d71199", + "x-runtime": "0.061384", + "etag": "W/\"2e8034d03a4995b365b8712aa77099d7\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "email": "nuwan@jamkazam.com", + "photo_url": null, + "show_free_jamtrack": false, + "is_affiliate_partner": false, + "recording_pref": 1 + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/app_features?env=development", + "pathname": "/api/app_features", + "timestamp": 1768921520986, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 653, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "39989fc5-f109-4878-9a75-04555d4574f1", + "x-runtime": "0.098484", + "etag": "W/\"d68f143b6187789a415d622035e65268\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": [] + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/profile", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/profile", + "timestamp": 1768921521963, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 193, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "4b84cb5f-e176-456f-b1bf-70dd03616f17", + "x-runtime": "0.165574", + "etag": "W/\"7abc69d192a226c06196c531c03518c1\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "city": "Dallas", + "state": "TX", + "country": "US", + "location": "Dallas, TX", + "online": true, + "photo_url": null, + "musician": true, + "gender": "M", + "birth_date": null, + "friend_count": 1, + "liker_count": 0, + "follower_count": 77, + "following_count": 130, + "recording_count": 0, + "session_count": 0, + "biography": "This is description with special charact xxxxxxaaaasasasas", + "favorite_count": 0, + "audio_latency": null, + "upcoming_session_count": 0, + "age": null, + "website": "www.nuwanchaturanga.me", + "skill_level": 2, + "concert_count": 1, + "studio_session_count": 1, + "virtual_band": false, + "virtual_band_commitment": 2, + "traditional_band": false, + "traditional_band_commitment": null, + "traditional_band_touring": false, + "paid_sessions": true, + "paid_sessions_hourly_rate": 19900, + "paid_sessions_daily_rate": 200000, + "free_sessions": true, + "cowriting": false, + "cowriting_purpose": 2, + "subscribe_email": false, + "is_a_teacher": true, + "is_a_student": false, + "last_active_timestamp": 1768904367, + "v2_photo_url": "https://cdn.filestackcontent.com/grIRdpVyTgeCF7boVGNJ", + "v2_photo_uploaded": true, + "has_stored_credit_card?": true, + "online_presences": [ + { + "id": "32fb4cd7-2a49-4691-8948-0b90a0f4e004", + "service_type": "soundcloud", + "username": "nuwanc" + }, + { + "id": "ca988152-4f5e-4239-b6d2-a02fe02584f1", + "service_type": "reverbnation", + "username": "nuwanmusic" + }, + { + "id": "7f6c3ace-aba7-4386-8b01-eb89b796d6bd", + "service_type": "bandcamp", + "username": "flutenuwan" + }, + { + "id": "990b14f5-bec6-43a9-974e-fbc720ce5a15", + "service_type": "youtube", + "username": "flute by nuwan" + }, + { + "id": "1a711996-b43a-4c0d-b12e-8777109c6e50", + "service_type": "facebook", + "username": "nuwan.chaturanga" + }, + { + "id": "13f7785f-4625-4e4d-8234-81ad71ed1887", + "service_type": "twitter", + "username": "nchatu" + } + ], + "performance_samples": [], + "genres": [ + { + "genre_id": "acapella", + "player_type": "JamRuby::User", + "genre_type": "paid_sessions" + }, + { + "genre_id": "african", + "player_type": "JamRuby::User", + "genre_type": "paid_sessions" + }, + { + "genre_id": "alternative rock", + "player_type": "JamRuby::User", + "genre_type": "paid_sessions" + }, + { + "genre_id": "ambient", + "player_type": "JamRuby::User", + "genre_type": "paid_sessions" + }, + { + "genre_id": "drum & bass", + "player_type": "JamRuby::User", + "genre_type": "free_sessions" + }, + { + "genre_id": "electronic", + "player_type": "JamRuby::User", + "genre_type": "free_sessions" + }, + { + "genre_id": "folk", + "player_type": "JamRuby::User", + "genre_type": "free_sessions" + }, + { + "genre_id": "funk", + "player_type": "JamRuby::User", + "genre_type": "free_sessions" + }, + { + "genre_id": "psychedelic", + "player_type": "JamRuby::User", + "genre_type": "cowriting" + }, + { + "genre_id": "punk", + "player_type": "JamRuby::User", + "genre_type": "cowriting" + }, + { + "genre_id": "r&b", + "player_type": "JamRuby::User", + "genre_type": "cowriting" + }, + { + "genre_id": "rap", + "player_type": "JamRuby::User", + "genre_type": "cowriting" + } + ], + "bands": [ + { + "id": "32df51d1-e323-4f02-80ba-63229b4861ed", + "name": "Martine Johnston", + "admin": false, + "photo_url": null, + "logo_url": null, + "website": "http://ankundinggraham.net/genoveva", + "genres": [ + { + "id": "country", + "description": "Country" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "techno", + "description": "Techno" + } + ] + }, + { + "id": "74f50a3d-df82-47f5-8053-0281bc27403f", + "name": "JMam", + "admin": false, + "photo_url": null, + "logo_url": null, + "website": null, + "genres": [ + { + "id": "blues", + "description": "Blues" + } + ] + }, + { + "id": "fc24a1e0-f212-4418-98d9-f0514e0cc699", + "name": "Uturn", + "admin": false, + "photo_url": null, + "logo_url": null, + "website": null, + "genres": [ + { + "id": "reggae", + "description": "Reggae" + } + ] + } + ], + "instruments": [], + "has_recurly_account": true, + "created_at_timestamp": 1621620928 + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/my_notifications?offset=0&limit=20", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/my_notifications", + "timestamp": 1768921521963, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 336, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "7e512081-a75d-4b7b-aed8-e573edc6c3b9", + "x-runtime": "0.108055", + "etag": "W/\"f0997f4989ad2873787ec48e4e658357\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "next": null, + "unread_total": 0, + "notifications": [] + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/instruments", + "pathname": "/api/instruments", + "timestamp": 1768921521965, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 518, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "b7a8c4df-af6e-4599-932b-15ea9937b58a", + "x-runtime": "0.220971", + "etag": "W/\"245d036f1b39bdde1206a6671360184a\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": [ + { + "id": "accordion", + "description": "Accordion", + "popularity": 2 + }, + { + "id": "acoustic guitar", + "description": "Acoustic Guitar", + "popularity": 3 + }, + { + "id": "bagpipes", + "description": "Bagpipes", + "popularity": 1 + }, + { + "id": "banjo", + "description": "Banjo", + "popularity": 2 + }, + { + "id": "bass guitar", + "description": "Bass Guitar", + "popularity": 3 + }, + { + "id": "bassoon", + "description": "Bassoon", + "popularity": 1 + }, + { + "id": "cello", + "description": "Cello", + "popularity": 1 + }, + { + "id": "charango", + "description": "Charango", + "popularity": 1 + }, + { + "id": "clarinet", + "description": "Clarinet", + "popularity": 2 + }, + { + "id": "computer", + "description": "Computer", + "popularity": 3 + }, + { + "id": "dobro", + "description": "Dobro", + "popularity": 1 + }, + { + "id": "double bass", + "description": "Double Bass", + "popularity": 2 + }, + { + "id": "drums", + "description": "Drums", + "popularity": 3 + }, + { + "id": "electric guitar", + "description": "Electric Guitar", + "popularity": 3 + }, + { + "id": "euphonium", + "description": "Euphonium", + "popularity": 1 + }, + { + "id": "flugelhorn", + "description": "Flugelhorn", + "popularity": 1 + }, + { + "id": "flute", + "description": "Flute", + "popularity": 2 + }, + { + "id": "french horn", + "description": "French Horn", + "popularity": 1 + }, + { + "id": "glockenspiel", + "description": "Glockenspiel", + "popularity": 1 + }, + { + "id": "harmonica", + "description": "Harmonica", + "popularity": 2 + }, + { + "id": "harp", + "description": "Harp", + "popularity": 1 + }, + { + "id": "keyboard", + "description": "Keyboard", + "popularity": 3 + }, + { + "id": "mandolin", + "description": "Mandolin", + "popularity": 1 + }, + { + "id": "oboe", + "description": "Oboe", + "popularity": 1 + }, + { + "id": "orchestra", + "description": "Orchestra", + "popularity": 1 + }, + { + "id": "other", + "description": "Other", + "popularity": 1 + }, + { + "id": "piano", + "description": "Piano", + "popularity": 2 + }, + { + "id": "piccolo", + "description": "Piccolo", + "popularity": 1 + }, + { + "id": "saxophone", + "description": "Saxophone", + "popularity": 2 + }, + { + "id": "sitar", + "description": "Sitar", + "popularity": 1 + }, + { + "id": "steel guitar", + "description": "Steel Guitar", + "popularity": 1 + }, + { + "id": "theremin", + "description": "Theremin", + "popularity": 1 + }, + { + "id": "timpani", + "description": "Timpani", + "popularity": 1 + }, + { + "id": "trombone", + "description": "Trombone", + "popularity": 2 + }, + { + "id": "trumpet", + "description": "Trumpet", + "popularity": 2 + }, + { + "id": "tuba", + "description": "Tuba", + "popularity": 1 + }, + { + "id": "ukulele", + "description": "Ukulele", + "popularity": 1 + }, + { + "id": "viola", + "description": "Viola", + "popularity": 1 + }, + { + "id": "violin", + "description": "Violin", + "popularity": 2 + }, + { + "id": "vocoder", + "description": "Vocoder", + "popularity": 1 + }, + { + "id": "voice", + "description": "Voice", + "popularity": 3 + } + ] + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/countries", + "pathname": "/api/countries", + "timestamp": 1768921521966, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 546, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "3b492459-bfe6-4430-b6cc-c8cb52d861d1", + "x-runtime": "0.043512", + "etag": "W/\"fec3b6158b06c52c8f631a3d881fd814\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "countriesx": [ + { + "countrycode": "US", + "countryname": "United States" + } + ] + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/genres", + "pathname": "/api/genres", + "timestamp": 1768921521965, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 1129, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "a3e812af-dca8-4e7a-8894-9e4668b32401", + "x-runtime": "0.220261", + "etag": "W/\"c6c75dd9c88ce6b32ec03b52c4905ad0\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": [ + { + "id": "acapella", + "description": "A Cappella" + }, + { + "id": "african", + "description": "African" + }, + { + "id": "alternative rock", + "description": "Alternative Rock" + }, + { + "id": "ambient", + "description": "Ambient" + }, + { + "id": "americana", + "description": "Americana" + }, + { + "id": "asian", + "description": "Asian" + }, + { + "id": "avante-garde", + "description": "Avante-Garde" + }, + { + "id": "bluegrass", + "description": "Bluegrass" + }, + { + "id": "blues", + "description": "Blues" + }, + { + "id": "breakbeat", + "description": "Breakbeat" + }, + { + "id": "celtic", + "description": "Celtic" + }, + { + "id": "classical", + "description": "Classical" + }, + { + "id": "country", + "description": "Country" + }, + { + "id": "creole", + "description": "Creole" + }, + { + "id": "dance", + "description": "Dance" + }, + { + "id": "disco", + "description": "Disco" + }, + { + "id": "downtempo", + "description": "Downtempo" + }, + { + "id": "drum & bass", + "description": "Drum & Bass" + }, + { + "id": "electronic", + "description": "Electronic" + }, + { + "id": "folk", + "description": "Folk" + }, + { + "id": "funk", + "description": "Funk" + }, + { + "id": "hard rock", + "description": "Hard Rock" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "holiday", + "description": "Holiday" + }, + { + "id": "house", + "description": "House" + }, + { + "id": "industrial", + "description": "Industrial" + }, + { + "id": "jazz", + "description": "Jazz" + }, + { + "id": "kids", + "description": "Kids" + }, + { + "id": "latin", + "description": "Latin" + }, + { + "id": "metal", + "description": "Metal" + }, + { + "id": "musical", + "description": "Musical" + }, + { + "id": "oldies", + "description": "Oldies" + }, + { + "id": "other", + "description": "Other" + }, + { + "id": "pop", + "description": "Pop" + }, + { + "id": "psychedelic", + "description": "Psychedelic" + }, + { + "id": "punk", + "description": "Punk" + }, + { + "id": "r&b", + "description": "R&B" + }, + { + "id": "rap", + "description": "Rap" + }, + { + "id": "reggae", + "description": "Reggae" + }, + { + "id": "religious", + "description": "Religious" + }, + { + "id": "rock", + "description": "Rock" + }, + { + "id": "ska", + "description": "Ska" + }, + { + "id": "soft rock", + "description": "Soft Rock" + }, + { + "id": "soul", + "description": "Soul" + }, + { + "id": "tv & movie soundtrack", + "description": "TV & Movie Soundtrack" + }, + { + "id": "techno", + "description": "Techno" + }, + { + "id": "traditional", + "description": "Traditional" + }, + { + "id": "trance", + "description": "Trance" + }, + { + "id": "world", + "description": "World" + } + ] + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/regions?country=US", + "pathname": "/api/regions", + "timestamp": 1768921522332, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 816, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "ece8f5bd-bd0c-4b0f-bcbf-4a648f2bcabd", + "x-runtime": "0.055930", + "etag": "W/\"2e0a392d8e82cb45af2f387a672c8e5e\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "regions": [ + { + "region": "TN", + "name": null + }, + { + "region": "ME", + "name": null + }, + { + "region": "MA", + "name": null + }, + { + "region": "TX", + "name": null + }, + { + "region": "OK", + "name": null + }, + { + "region": "WA", + "name": null + }, + { + "region": "CO", + "name": null + }, + { + "region": "CA", + "name": null + }, + { + "region": "AR", + "name": null + }, + { + "region": "FL", + "name": null + }, + { + "region": "OR", + "name": null + } + ] + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/cities?country=US®ion=TX", + "pathname": "/api/cities", + "timestamp": 1768921522334, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 815, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "0d905a88-6a2a-40f7-9f20-a249e4c53a5e", + "x-runtime": "0.049610", + "etag": "W/\"cdf324acfbe0050f30c89cfc5ffa062c\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "cities": [ + "Austin", + "Dallas", + "Houston", + "San Antonio" + ] + } + } +] \ No newline at end of file diff --git a/jam-ui/test/test-results/api-verification/login-comparison-report.md b/jam-ui/test/test-results/api-verification/login-comparison-report.md new file mode 100644 index 000000000..60da07acf --- /dev/null +++ b/jam-ui/test/test-results/api-verification/login-comparison-report.md @@ -0,0 +1,109 @@ +# API Sequence Comparison Report + +## Summary + +- **Match Status:** āŒ FAIL +- **Total Calls:** 13 +- **Matched Calls:** 3 +- **Match Percentage:** 23.1% + +## āŒ Missing API Calls + +The following expected API calls are missing or called fewer times: + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/shopping_carts** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/jamtracks/purchased** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/teacher_distributions** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **POST /xoplatform/logger/api/logger** + - Expected: 4 call(s) + - Actual: 0 call(s) + - Missing: 4 call(s) + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +## āš ļø Extra API Calls + +The following API calls were made but not expected: + +- **GET /api/app_features** + - Expected: 0 call(s) + - Actual: 2 call(s) + - Extra: 2 call(s) + +- **GET /api/me** + - Expected: 0 call(s) + - Actual: 2 call(s) + - Extra: 2 call(s) + +- **UNKNOWN /api/me** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +- **POST /api/auths/login** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/profile** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/my_notifications** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +- **GET /api/instruments** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +- **GET /api/cities** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +## āš ļø Out of Order Calls + +The following API calls occurred in a different order: + +- **GET /api/genres** + - Expected position: 0 + - Actual position: 10 + - Deviation: 10 positions + +- **GET /api/countries** + - Expected position: 2 + - Actual position: 9 + - Deviation: 7 positions + +- **GET /api/regions** + - Expected position: 6 + - Actual position: 11 + - Deviation: 5 positions + +## āŒ Conclusion + +The API sequence does NOT match the expected baseline. Please review the mismatches above. diff --git a/jam-ui/test/test-results/api-verification/session-creation-actual-calls.json b/jam-ui/test/test-results/api-verification/session-creation-actual-calls.json new file mode 100644 index 000000000..0a7797307 --- /dev/null +++ b/jam-ui/test/test-results/api-verification/session-creation-actual-calls.json @@ -0,0 +1,1134 @@ +[ + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/genres", + "pathname": "/api/genres", + "timestamp": 1768927718744, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 128, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "6b4c336d-9d26-4819-9da0-cdb39c21c71e", + "x-runtime": "0.124489", + "etag": "W/\"7a4947c7d3d991a9bf52fa991b6f957a\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": [ + { + "id": "acapella", + "description": "A Cappella" + }, + { + "id": "african", + "description": "African" + }, + { + "id": "alternative rock", + "description": "Alternative Rock" + }, + { + "id": "ambient", + "description": "Ambient" + }, + { + "id": "americana", + "description": "Americana" + }, + { + "id": "asian", + "description": "Asian" + }, + { + "id": "avante-garde", + "description": "Avante-Garde" + }, + { + "id": "bluegrass", + "description": "Bluegrass" + }, + { + "id": "blues", + "description": "Blues" + }, + { + "id": "breakbeat", + "description": "Breakbeat" + }, + { + "id": "celtic", + "description": "Celtic" + }, + { + "id": "classical", + "description": "Classical" + }, + { + "id": "country", + "description": "Country" + }, + { + "id": "creole", + "description": "Creole" + }, + { + "id": "dance", + "description": "Dance" + }, + { + "id": "disco", + "description": "Disco" + }, + { + "id": "downtempo", + "description": "Downtempo" + }, + { + "id": "drum & bass", + "description": "Drum & Bass" + }, + { + "id": "electronic", + "description": "Electronic" + }, + { + "id": "folk", + "description": "Folk" + }, + { + "id": "funk", + "description": "Funk" + }, + { + "id": "hard rock", + "description": "Hard Rock" + }, + { + "id": "hip hop", + "description": "Hip Hop" + }, + { + "id": "holiday", + "description": "Holiday" + }, + { + "id": "house", + "description": "House" + }, + { + "id": "industrial", + "description": "Industrial" + }, + { + "id": "jazz", + "description": "Jazz" + }, + { + "id": "kids", + "description": "Kids" + }, + { + "id": "latin", + "description": "Latin" + }, + { + "id": "metal", + "description": "Metal" + }, + { + "id": "musical", + "description": "Musical" + }, + { + "id": "oldies", + "description": "Oldies" + }, + { + "id": "other", + "description": "Other" + }, + { + "id": "pop", + "description": "Pop" + }, + { + "id": "psychedelic", + "description": "Psychedelic" + }, + { + "id": "punk", + "description": "Punk" + }, + { + "id": "r&b", + "description": "R&B" + }, + { + "id": "rap", + "description": "Rap" + }, + { + "id": "reggae", + "description": "Reggae" + }, + { + "id": "religious", + "description": "Religious" + }, + { + "id": "rock", + "description": "Rock" + }, + { + "id": "ska", + "description": "Ska" + }, + { + "id": "soft rock", + "description": "Soft Rock" + }, + { + "id": "soul", + "description": "Soul" + }, + { + "id": "tv & movie soundtrack", + "description": "TV & Movie Soundtrack" + }, + { + "id": "techno", + "description": "Techno" + }, + { + "id": "traditional", + "description": "Traditional" + }, + { + "id": "trance", + "description": "Trance" + }, + { + "id": "world", + "description": "World" + } + ] + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/me", + "pathname": "/api/me", + "timestamp": 1768927718745, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 149, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "bfac9b72-c1af-4e69-94e9-42182fbc5f27", + "x-runtime": "0.019539", + "etag": "W/\"594e6f8c8545980d3b4b27fc80d80af7\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "email": "nuwan@jamkazam.com", + "photo_url": null, + "show_free_jamtrack": false, + "is_affiliate_partner": false, + "recording_pref": 1 + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": 1768927718744, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 280, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "afe5245c-6592-4c3d-bc48-cbf39dfbdbcf", + "x-runtime": "0.035659", + "etag": "W/\"234672fd4db3690be252ee51dc848be6\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": [ + { + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "first_name": "Seth", + "last_name": "Call", + "name": "Seth Call", + "location": "Boston, MA", + "city": "Boston", + "state": "MA", + "country": "US", + "musician": true, + "email": "nuwan+6@jamkazam.com", + "online": false, + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + } + ] + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/my_notifications?offset=0&limit=20", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/my_notifications", + "timestamp": 1768927718918, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 144, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "da1107d9-d218-46e7-8125-f4a31adb14a5", + "x-runtime": "0.037747", + "etag": "W/\"7e31ea1778e257d697c025a6328a5d78\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "next": null, + "unread_total": 0, + "notifications": [] + } + }, + { + "method": "POST", + "url": "http://www.jamkazam.local:3000/api/sessions", + "pathname": "/api/sessions", + "timestamp": 1768927722478, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "requestBody": { + "privacy": "1", + "description": "Automated test session", + "inviteeIds": "", + "musician_access": true, + "approval_required": false, + "legal_terms": true, + "start": "Tue Jan 20 2026 10:18 PM", + "duration": "60", + "invitations": [], + "timezone": "Central Time (US & Canada),America/Chicago", + "genres": [ + "acapella" + ], + "friends_can_join": true, + "is_unstructured_rsvp": false, + "fan_chat": false, + "fan_access": false, + "legal_policy": "legal_policy", + "language": "eng", + "name": "my session", + "rsvp_slots": [ + { + "instrument_id": "other", + "proficiency_level": 3, + "approve": true + } + ] + }, + "duration": 578, + "responseStatus": 201, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "e8408e38-f9dd-4c2d-aab6-7d48b9d88132", + "x-runtime": "0.587713", + "etag": "W/\"087d1cf79e0bd3757dd0b165e585dd19\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "6278e6f5-013b-4cd2-8e54-061ea6306d66", + "music_session_id": null, + "name": "my session", + "description": "Automated test session", + "musician_access": true, + "approval_required": false, + "fan_access": false, + "fan_chat": false, + "create_type": null, + "band_id": null, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "genre_id": "acapella", + "created_at": "2026-01-20T16:48:42.754Z", + "like_count": 0, + "comment_count": 0, + "play_count": 0, + "scheduled_duration": "01:00:00", + "language": "eng", + "recurring_mode": "once", + "language_description": "English", + "scheduled_start_date": "Wed 21 January 2026", + "access_description": "Musicians may join at will. Fans may not listen to session.", + "timezone": "Central Time (US & Canada),America/Chicago", + "timezone_id": "America/Chicago", + "timezone_description": "Central Time (US & Canada)", + "musician_access_description": "Musicians may join at will", + "fan_access_description": "Fans may not listen to session", + "session_removed_at": null, + "legal_policy": "legal_policy", + "open_rsvps": false, + "is_unstructured_rsvp?": false, + "friends_can_join": true, + "use_video_conferencing_server": true, + "creator": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "name": "Nuwan Chaturanga", + "photo_url": null + }, + "band": null, + "users": [], + "comments": [], + "session_info_comments": [], + "music_notations": [], + "invitations": [], + "approved_rsvps": [ + { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "resolved_photo_url": "http://localhost:3000/assets/shared/avatar_generic.png", + "full_score": null, + "audio_latency": 5, + "internet_score": null, + "instrument_list": [ + { + "id": "other", + "desc": "Other", + "level": 3 + } + ], + "rsvp_request_id": "b9447b96-431d-48aa-b35a-abe00544590b" + } + ], + "open_slots": [], + "pending_invitations": [], + "pending_rsvp_requests": [], + "lesson_session": null, + "active_music_session": null, + "can_join": true, + "share_url": "http://www.jamkazam.local:3000/s/ENKNHSKEQMC", + "genres": [ + "A Cappella" + ], + "scheduled_start": "Tue 20 January 2026 22:18:00", + "pretty_scheduled_start_with_timezone": "Tuesday, January 20, 10:18-10:18 PM US Central Time", + "pretty_scheduled_start_short": "Tuesday, January 20 - 10:18pm" + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/me", + "pathname": "/api/me", + "timestamp": 1768927723154, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 41, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "ed73cffb-5edd-4c5a-baca-f323fc4ebb3d", + "x-runtime": "0.024595", + "etag": "W/\"560927ed10a8d78794da9584ba5f58f3\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "email": "nuwan@jamkazam.com", + "photo_url": null, + "show_free_jamtrack": false, + "is_affiliate_partner": false, + "recording_pref": 1 + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/app_features?env=development", + "pathname": "/api/app_features", + "timestamp": 1768927723154, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 92, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "41ee7ec5-89c5-4046-afb5-ea6265200af4", + "x-runtime": "0.032665", + "etag": "W/\"264c649084c29d56da2f9dc7d49b47e9\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": [] + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/my_notifications?offset=0&limit=20", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/my_notifications", + "timestamp": 1768927723285, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 59, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "01f61269-8492-48f2-a96d-ebac749226a3", + "x-runtime": "0.043336", + "etag": "W/\"1df9d0fca0b40ab27122935bceca9413\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "next": null, + "unread_total": 0, + "notifications": [] + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": 1768927723299, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 54, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "7dcccf13-5196-42db-94b3-b9fce6ac6e48", + "x-runtime": "0.045822", + "etag": "W/\"e1867853da6714e4b5229f107f19c75e\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": [ + { + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "first_name": "Seth", + "last_name": "Call", + "name": "Seth Call", + "location": "Boston, MA", + "city": "Boston", + "state": "MA", + "country": "US", + "musician": true, + "email": "nuwan+6@jamkazam.com", + "online": false, + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + } + ] + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/sessions/6278e6f5-013b-4cd2-8e54-061ea6306d66/history?includePending=false", + "pathname": "/api/sessions/6278e6f5-013b-4cd2-8e54-061ea6306d66/history", + "timestamp": 1768927723299, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 268, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "d21b4e3c-16b5-4a7b-8b65-22c360586a1d", + "x-runtime": "0.217620", + "etag": "W/\"087d1cf79e0bd3757dd0b165e585dd19\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "6278e6f5-013b-4cd2-8e54-061ea6306d66", + "music_session_id": null, + "name": "my session", + "description": "Automated test session", + "musician_access": true, + "approval_required": false, + "fan_access": false, + "fan_chat": false, + "create_type": null, + "band_id": null, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "genre_id": "acapella", + "created_at": "2026-01-20T16:48:42.754Z", + "like_count": 0, + "comment_count": 0, + "play_count": 0, + "scheduled_duration": "01:00:00", + "language": "eng", + "recurring_mode": "once", + "language_description": "English", + "scheduled_start_date": "Wed 21 January 2026", + "access_description": "Musicians may join at will. Fans may not listen to session.", + "timezone": "Central Time (US & Canada),America/Chicago", + "timezone_id": "America/Chicago", + "timezone_description": "Central Time (US & Canada)", + "musician_access_description": "Musicians may join at will", + "fan_access_description": "Fans may not listen to session", + "session_removed_at": null, + "legal_policy": "legal_policy", + "open_rsvps": false, + "is_unstructured_rsvp?": false, + "friends_can_join": true, + "use_video_conferencing_server": true, + "creator": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "name": "Nuwan Chaturanga", + "photo_url": null + }, + "band": null, + "users": [], + "comments": [], + "session_info_comments": [], + "music_notations": [], + "invitations": [], + "approved_rsvps": [ + { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "resolved_photo_url": "http://localhost:3000/assets/shared/avatar_generic.png", + "full_score": null, + "audio_latency": 5, + "internet_score": null, + "instrument_list": [ + { + "id": "other", + "desc": "Other", + "level": 3 + } + ], + "rsvp_request_id": "b9447b96-431d-48aa-b35a-abe00544590b" + } + ], + "open_slots": [], + "pending_invitations": [], + "pending_rsvp_requests": [], + "lesson_session": null, + "active_music_session": null, + "can_join": true, + "share_url": "http://www.jamkazam.local:3000/s/ENKNHSKEQMC", + "genres": [ + "A Cappella" + ], + "scheduled_start": "Tue 20 January 2026 22:18:00", + "pretty_scheduled_start_with_timezone": "Tuesday, January 20, 10:18-10:18 PM US Central Time", + "pretty_scheduled_start_short": "Tuesday, January 20 - 10:18pm" + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/sessions/6278e6f5-013b-4cd2-8e54-061ea6306d66/history?includePending=false", + "pathname": "/api/sessions/6278e6f5-013b-4cd2-8e54-061ea6306d66/history", + "timestamp": 1768927723662, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 91, + "responseStatus": 200, + "responseHeaders": { + "x-runtime": "0.090907", + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "etag": "W/\"087d1cf79e0bd3757dd0b165e585dd19\"", + "vary": "Accept-Encoding, Origin", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "cache-control": "max-age=0, private, must-revalidate", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "x-frame-options": "SAMEORIGIN", + "x-xss-protection": "1; mode=block", + "x-request-id": "9b6abe7f-6cde-4239-b6da-e6645f6c4945" + }, + "responseBody": { + "id": "6278e6f5-013b-4cd2-8e54-061ea6306d66", + "music_session_id": null, + "name": "my session", + "description": "Automated test session", + "musician_access": true, + "approval_required": false, + "fan_access": false, + "fan_chat": false, + "create_type": null, + "band_id": null, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "genre_id": "acapella", + "created_at": "2026-01-20T16:48:42.754Z", + "like_count": 0, + "comment_count": 0, + "play_count": 0, + "scheduled_duration": "01:00:00", + "language": "eng", + "recurring_mode": "once", + "language_description": "English", + "scheduled_start_date": "Wed 21 January 2026", + "access_description": "Musicians may join at will. Fans may not listen to session.", + "timezone": "Central Time (US & Canada),America/Chicago", + "timezone_id": "America/Chicago", + "timezone_description": "Central Time (US & Canada)", + "musician_access_description": "Musicians may join at will", + "fan_access_description": "Fans may not listen to session", + "session_removed_at": null, + "legal_policy": "legal_policy", + "open_rsvps": false, + "is_unstructured_rsvp?": false, + "friends_can_join": true, + "use_video_conferencing_server": true, + "creator": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "name": "Nuwan Chaturanga", + "photo_url": null + }, + "band": null, + "users": [], + "comments": [], + "session_info_comments": [], + "music_notations": [], + "invitations": [], + "approved_rsvps": [ + { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "resolved_photo_url": "http://localhost:3000/assets/shared/avatar_generic.png", + "full_score": null, + "audio_latency": 5, + "internet_score": null, + "instrument_list": [ + { + "id": "other", + "desc": "Other", + "level": 3 + } + ], + "rsvp_request_id": "b9447b96-431d-48aa-b35a-abe00544590b" + } + ], + "open_slots": [], + "pending_invitations": [], + "pending_rsvp_requests": [], + "lesson_session": null, + "active_music_session": null, + "can_join": true, + "share_url": "http://www.jamkazam.local:3000/s/ENKNHSKEQMC", + "genres": [ + "A Cappella" + ], + "scheduled_start": "Tue 20 January 2026 22:18:00", + "pretty_scheduled_start_with_timezone": "Tuesday, January 20, 10:18-10:18 PM US Central Time", + "pretty_scheduled_start_short": "Tuesday, January 20 - 10:18pm" + } + }, + { + "method": "POST", + "url": "http://www.jamkazam.local:3000/api/sessions/6278e6f5-013b-4cd2-8e54-061ea6306d66/participants", + "pathname": "/api/sessions/6278e6f5-013b-4cd2-8e54-061ea6306d66/participants", + "timestamp": 1768927723797, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "requestBody": { + "client_id": "af30a870-1d86-404c-8333-027f3cc6db14", + "as_musician": true, + "tracks": [ + { + "client_track_id": "d4734735-0acb-4e87-9737-320efb024b3f", + "client_resource_id": "0x60000117dab0", + "instrument_id": "piano", + "sound": "stereo" + } + ], + "client_role": "parent", + "parent_client_id": "" + }, + "duration": 524, + "responseStatus": 201, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "0f9c6f22-0541-4c0e-a338-a24bb471bf81", + "x-runtime": "0.519323", + "etag": "W/\"83e77a295d4cd7b73e81313a0065f8f8\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "location": "http://www.jamkazam.local:3000/api/sessions/6278e6f5-013b-4cd2-8e54-061ea6306d66", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "6278e6f5-013b-4cd2-8e54-061ea6306d66", + "name": "my session", + "description": "Automated test session", + "musician_access": true, + "approval_required": false, + "friends_can_join": true, + "fan_access": false, + "fan_chat": false, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "claimed_recording_initiator_id": null, + "track_changes_counter": 0, + "max_score": 0, + "backing_track_path": null, + "metronome_active": false, + "jam_track_initiator_id": null, + "jam_track_id": null, + "music_session_id_int": 3062, + "use_video_conferencing_server": true, + "created_at": "2026-01-20T16:48:43.865Z", + "music_notations": [], + "participants": [ + { + "ip_address": "127.0.0.1", + "client_id": "af30a870-1d86-404c-8333-027f3cc6db14", + "joined_session_at": "2026-01-20T16:48:44.007Z", + "id": "0babbfb7-48b0-4513-b2bd-f05ca2c6091f", + "metronome_open": false, + "is_jamblaster": false, + "client_role": "parent", + "parent_client_id": "", + "client_id_int": 93863, + "tracks": [ + { + "id": "67fcceb8-fb5e-4516-abb0-37b8966f2f6e", + "connection_id": "0babbfb7-48b0-4513-b2bd-f05ca2c6091f", + "instrument_id": "piano", + "sound": "stereo", + "client_track_id": "d4734735-0acb-4e87-9737-320efb024b3f", + "client_resource_id": "0x60000117dab0", + "updated_at": "2026-01-20T16:48:44.018Z", + "instrument": "Piano" + } + ], + "backing_tracks": [], + "user": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "name": "Nuwan Chaturanga", + "is_friend": false, + "connection_state": "connected", + "subscription": "jamsubplatinum" + } + } + ], + "invitations": [], + "lesson_session": null, + "join_requests": [], + "jam_track": null, + "claimed_recording": null, + "subscription": { + "play_time_per_month": null, + "play_time_per_session": null, + "can_record_audio": true, + "can_record_video": true, + "can_use_video": true, + "can_record_wave": true, + "video_resolution": 4, + "audio_max_bitrate": 5, + "can_broadcast": true, + "broadcasting_type": 3, + "max_players": null, + "pro_audio": true, + "has_support": true, + "name": "Platinum", + "rank": 3, + "remaining_month_play_time": null + }, + "session_rules": { + "remaining_session_play_time": null + }, + "can_join": true, + "genres": [ + "A Cappella" + ], + "recording": null, + "share_url": "http://www.jamkazam.local:3000/s/ENKNHSKEQMC", + "session_controller_id": "27bd4a30-d1b8-4eea-8454-01a104d59381" + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/sessions/6278e6f5-013b-4cd2-8e54-061ea6306d66", + "pathname": "/api/sessions/6278e6f5-013b-4cd2-8e54-061ea6306d66", + "timestamp": 1768927724502, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 42, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "14c784fb-6d13-47ac-8bdb-22b1d816a6ab", + "x-runtime": "0.045840", + "etag": "W/\"656eb8e8d6e810fdd3194954919c3f24\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "6278e6f5-013b-4cd2-8e54-061ea6306d66", + "name": "my session", + "description": "Automated test session", + "musician_access": true, + "approval_required": false, + "friends_can_join": true, + "fan_access": false, + "fan_chat": false, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "claimed_recording_initiator_id": null, + "track_changes_counter": 0, + "max_score": 0, + "backing_track_path": null, + "metronome_active": false, + "jam_track_initiator_id": null, + "jam_track_id": null, + "music_session_id_int": 3062, + "use_video_conferencing_server": true, + "created_at": "2026-01-20T16:48:43.865Z", + "music_notations": [], + "participants": [ + { + "ip_address": "127.0.0.1", + "client_id": "af30a870-1d86-404c-8333-027f3cc6db14", + "joined_session_at": "2026-01-20T16:48:44.007Z", + "id": "0babbfb7-48b0-4513-b2bd-f05ca2c6091f", + "metronome_open": false, + "is_jamblaster": false, + "client_role": "parent", + "parent_client_id": "", + "client_id_int": 93863, + "tracks": [ + { + "id": "67fcceb8-fb5e-4516-abb0-37b8966f2f6e", + "connection_id": "0babbfb7-48b0-4513-b2bd-f05ca2c6091f", + "instrument_id": "piano", + "sound": "stereo", + "client_track_id": "d4734735-0acb-4e87-9737-320efb024b3f", + "client_resource_id": "0x60000117dab0", + "updated_at": "2026-01-20T16:48:44.018Z", + "instrument": "Piano" + } + ], + "backing_tracks": [], + "user": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "name": "Nuwan Chaturanga", + "is_friend": false, + "connection_state": "connected", + "subscription": "jamsubplatinum" + } + } + ], + "invitations": [], + "lesson_session": null, + "join_requests": [], + "jam_track": null, + "claimed_recording": null, + "can_join": true, + "genres": [ + "A Cappella" + ], + "recording": null, + "share_url": "http://www.jamkazam.local:3000/s/ENKNHSKEQMC", + "session_controller_id": "27bd4a30-d1b8-4eea-8454-01a104d59381" + } + } +] \ No newline at end of file diff --git a/jam-ui/test/test-results/api-verification/session-creation-comparison-report.md b/jam-ui/test/test-results/api-verification/session-creation-comparison-report.md new file mode 100644 index 000000000..4870e661a --- /dev/null +++ b/jam-ui/test/test-results/api-verification/session-creation-comparison-report.md @@ -0,0 +1,184 @@ +# API Sequence Comparison Report + +## Summary + +- **Match Status:** āŒ FAIL +- **Total Calls:** 13 +- **Matched Calls:** 4 +- **Match Percentage:** 30.8% + +## āŒ Missing API Calls + +The following expected API calls are missing or called fewer times: + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381** + - Expected: 2 call(s) + - Actual: 0 call(s) + - Missing: 2 call(s) + +- **GET /api/countries** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/shopping_carts** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/genres** + - Expected: 3 call(s) + - Actual: 1 call(s) + - Missing: 2 call(s) + +- **GET /api/instruments** + - Expected: 3 call(s) + - Actual: 0 call(s) + - Missing: 3 call(s) + +- **GET /api/jamtracks/purchased** + - Expected: 3 call(s) + - Actual: 0 call(s) + - Missing: 3 call(s) + +- **GET /api/languages** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/subjects** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/chat** + - Expected: 2 call(s) + - Actual: 0 call(s) + - Missing: 2 call(s) + +- **GET /api/sessions/scheduled** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/regions** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/teacher_distributions** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/versioncheck** + - Expected: 3 call(s) + - Actual: 0 call(s) + - Missing: 3 call(s) + +- **GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/history** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/config/client** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **POST /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/participants** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **PUT /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks** + - Expected: 3 call(s) + - Actual: 0 call(s) + - Missing: 3 call(s) + +- **GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23** + - Expected: 3 call(s) + - Actual: 0 call(s) + - Missing: 3 call(s) + +- **POST /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/udp_reachable** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +## āš ļø Extra API Calls + +The following API calls were made but not expected: + +- **GET /api/me** + - Expected: 0 call(s) + - Actual: 2 call(s) + - Extra: 2 call(s) + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/my_notifications** + - Expected: 0 call(s) + - Actual: 2 call(s) + - Extra: 2 call(s) + +- **GET /api/app_features** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +- **GET /api/sessions/6278e6f5-013b-4cd2-8e54-061ea6306d66/history** + - Expected: 0 call(s) + - Actual: 2 call(s) + - Extra: 2 call(s) + +- **POST /api/sessions/6278e6f5-013b-4cd2-8e54-061ea6306d66/participants** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +- **GET /api/sessions/6278e6f5-013b-4cd2-8e54-061ea6306d66** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +## āš ļø Out of Order Calls + +The following API calls occurred in a different order: + +- **GET /api/genres** + - Expected position: 4 + - Actual position: 0 + - Deviation: 4 positions + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends** + - Expected position: 7 + - Actual position: 2 + - Deviation: 5 positions + +- **GET /api/genres** + - Expected position: 11 + - Actual position: 0 + - Deviation: 11 positions + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends** + - Expected position: 16 + - Actual position: 2 + - Deviation: 14 positions + +- **POST /api/sessions** + - Expected position: 25 + - Actual position: 4 + - Deviation: 21 positions + +## āŒ Conclusion + +The API sequence does NOT match the expected baseline. Please review the mismatches above. diff --git a/jam-ui/test/test-results/e2e/complete-flow-api-calls.json b/jam-ui/test/test-results/e2e/complete-flow-api-calls.json new file mode 100644 index 000000000..4157004ad --- /dev/null +++ b/jam-ui/test/test-results/e2e/complete-flow-api-calls.json @@ -0,0 +1,772 @@ +[ + { + "method": "POST", + "url": "http://www.jamkazam.local:3000/api/sessions", + "pathname": "/api/sessions", + "timestamp": 1768927894879, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "requestBody": { + "privacy": "1", + "description": "Automated test session", + "inviteeIds": "", + "musician_access": true, + "approval_required": false, + "legal_terms": true, + "start": "Tue Jan 20 2026 10:21 PM", + "duration": "60", + "invitations": [], + "timezone": "Central Time (US & Canada),America/Chicago", + "genres": [ + "acapella" + ], + "friends_can_join": true, + "is_unstructured_rsvp": false, + "fan_chat": false, + "fan_access": false, + "legal_policy": "legal_policy", + "language": "eng", + "name": "my session", + "rsvp_slots": [ + { + "instrument_id": "other", + "proficiency_level": 3, + "approve": true + } + ] + }, + "duration": 139, + "responseStatus": 201, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "ed02c69a-ca9c-4223-a4ce-1e7ef63ad112", + "x-runtime": "0.142518", + "etag": "W/\"1c90918fc0af71c877f432af9fddbff0\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "c2682005-d64f-4f2e-9e72-b9017c0097fc", + "music_session_id": null, + "name": "my session", + "description": "Automated test session", + "musician_access": true, + "approval_required": false, + "fan_access": false, + "fan_chat": false, + "create_type": null, + "band_id": null, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "genre_id": "acapella", + "created_at": "2026-01-20T16:51:34.911Z", + "like_count": 0, + "comment_count": 0, + "play_count": 0, + "scheduled_duration": "01:00:00", + "language": "eng", + "recurring_mode": "once", + "language_description": "English", + "scheduled_start_date": "Wed 21 January 2026", + "access_description": "Musicians may join at will. Fans may not listen to session.", + "timezone": "Central Time (US & Canada),America/Chicago", + "timezone_id": "America/Chicago", + "timezone_description": "Central Time (US & Canada)", + "musician_access_description": "Musicians may join at will", + "fan_access_description": "Fans may not listen to session", + "session_removed_at": null, + "legal_policy": "legal_policy", + "open_rsvps": false, + "is_unstructured_rsvp?": false, + "friends_can_join": true, + "use_video_conferencing_server": true, + "creator": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "name": "Nuwan Chaturanga", + "photo_url": null + }, + "band": null, + "users": [], + "comments": [], + "session_info_comments": [], + "music_notations": [], + "invitations": [], + "approved_rsvps": [ + { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "resolved_photo_url": "http://localhost:3000/assets/shared/avatar_generic.png", + "full_score": null, + "audio_latency": 5, + "internet_score": null, + "instrument_list": [ + { + "id": "other", + "desc": "Other", + "level": 3 + } + ], + "rsvp_request_id": "3b57a648-3858-44a0-8650-45555a6dd33b" + } + ], + "open_slots": [], + "pending_invitations": [], + "pending_rsvp_requests": [], + "lesson_session": null, + "active_music_session": null, + "can_join": true, + "share_url": "http://www.jamkazam.local:3000/s/ZAPOFY0FCPM", + "genres": [ + "A Cappella" + ], + "scheduled_start": "Tue 20 January 2026 22:21:00", + "pretty_scheduled_start_with_timezone": "Tuesday, January 20, 10:21-10:21 PM US Central Time", + "pretty_scheduled_start_short": "Tuesday, January 20 - 10:21pm" + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/app_features?env=development", + "pathname": "/api/app_features", + "timestamp": 1768927895119, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 50, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "cdd88fd7-8a3f-4ae9-bf68-f2b9b772f29a", + "x-runtime": "0.046358", + "etag": "W/\"b7b5ed7616e7f6ac80c7b989a95ff930\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": [] + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/me", + "pathname": "/api/me", + "timestamp": 1768927895119, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 66, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "d56f8566-0db9-432f-b346-fdde8316de03", + "x-runtime": "0.020159", + "etag": "W/\"39d0929eb10af68175337821ac59ae6c\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "email": "nuwan@jamkazam.com", + "photo_url": null, + "show_free_jamtrack": false, + "is_affiliate_partner": false, + "recording_pref": 1 + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/my_notifications?offset=0&limit=20", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/my_notifications", + "timestamp": 1768927895217, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 43, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "fa2daac0-4c35-401d-9fb3-24bde47fdffd", + "x-runtime": "0.053999", + "etag": "W/\"0457d24107947f8d0d88d3831e84f366\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "next": null, + "unread_total": 0, + "notifications": [] + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "pathname": "/api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends", + "timestamp": 1768927895224, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 62, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "d00334f0-917d-4e65-9fd7-44a1e0f57996", + "x-runtime": "0.032089", + "etag": "W/\"733a82e20cbe8c7635b4fd37017e97c1\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": [ + { + "id": "a09f9a7e-afb7-489d-870d-e13a336e0b97", + "first_name": "Seth", + "last_name": "Call", + "name": "Seth Call", + "location": "Boston, MA", + "city": "Boston", + "state": "MA", + "country": "US", + "musician": true, + "email": "nuwan+6@jamkazam.com", + "online": false, + "photo_url": "https://s3.amazonaws.com/jamkazam-dev-public/avatars/a09f9a7e-afb7-489d-870d-e13a336e0b97/8EfyNy2cQPaxEsypRviW_IMG_20231224_133203_HDR.jpg" + } + ] + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/sessions/c2682005-d64f-4f2e-9e72-b9017c0097fc/history?includePending=false", + "pathname": "/api/sessions/c2682005-d64f-4f2e-9e72-b9017c0097fc/history", + "timestamp": 1768927895224, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 208, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "aaa0508c-b4d8-4d24-8890-ec9266b1d4a8", + "x-runtime": "0.110980", + "etag": "W/\"1c90918fc0af71c877f432af9fddbff0\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "c2682005-d64f-4f2e-9e72-b9017c0097fc", + "music_session_id": null, + "name": "my session", + "description": "Automated test session", + "musician_access": true, + "approval_required": false, + "fan_access": false, + "fan_chat": false, + "create_type": null, + "band_id": null, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "genre_id": "acapella", + "created_at": "2026-01-20T16:51:34.911Z", + "like_count": 0, + "comment_count": 0, + "play_count": 0, + "scheduled_duration": "01:00:00", + "language": "eng", + "recurring_mode": "once", + "language_description": "English", + "scheduled_start_date": "Wed 21 January 2026", + "access_description": "Musicians may join at will. Fans may not listen to session.", + "timezone": "Central Time (US & Canada),America/Chicago", + "timezone_id": "America/Chicago", + "timezone_description": "Central Time (US & Canada)", + "musician_access_description": "Musicians may join at will", + "fan_access_description": "Fans may not listen to session", + "session_removed_at": null, + "legal_policy": "legal_policy", + "open_rsvps": false, + "is_unstructured_rsvp?": false, + "friends_can_join": true, + "use_video_conferencing_server": true, + "creator": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "name": "Nuwan Chaturanga", + "photo_url": null + }, + "band": null, + "users": [], + "comments": [], + "session_info_comments": [], + "music_notations": [], + "invitations": [], + "approved_rsvps": [ + { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "resolved_photo_url": "http://localhost:3000/assets/shared/avatar_generic.png", + "full_score": null, + "audio_latency": 5, + "internet_score": null, + "instrument_list": [ + { + "id": "other", + "desc": "Other", + "level": 3 + } + ], + "rsvp_request_id": "3b57a648-3858-44a0-8650-45555a6dd33b" + } + ], + "open_slots": [], + "pending_invitations": [], + "pending_rsvp_requests": [], + "lesson_session": null, + "active_music_session": null, + "can_join": true, + "share_url": "http://www.jamkazam.local:3000/s/ZAPOFY0FCPM", + "genres": [ + "A Cappella" + ], + "scheduled_start": "Tue 20 January 2026 22:21:00", + "pretty_scheduled_start_with_timezone": "Tuesday, January 20, 10:21-10:21 PM US Central Time", + "pretty_scheduled_start_short": "Tuesday, January 20 - 10:21pm" + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/sessions/c2682005-d64f-4f2e-9e72-b9017c0097fc/history?includePending=false", + "pathname": "/api/sessions/c2682005-d64f-4f2e-9e72-b9017c0097fc/history", + "timestamp": 1768927895444, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 97, + "responseStatus": 200, + "responseHeaders": { + "x-runtime": "0.096440", + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "etag": "W/\"1c90918fc0af71c877f432af9fddbff0\"", + "vary": "Accept-Encoding, Origin", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "cache-control": "max-age=0, private, must-revalidate", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "x-frame-options": "SAMEORIGIN", + "x-xss-protection": "1; mode=block", + "x-request-id": "2c056ad2-8e49-4443-b0e2-04b5836dce4c" + }, + "responseBody": { + "id": "c2682005-d64f-4f2e-9e72-b9017c0097fc", + "music_session_id": null, + "name": "my session", + "description": "Automated test session", + "musician_access": true, + "approval_required": false, + "fan_access": false, + "fan_chat": false, + "create_type": null, + "band_id": null, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "genre_id": "acapella", + "created_at": "2026-01-20T16:51:34.911Z", + "like_count": 0, + "comment_count": 0, + "play_count": 0, + "scheduled_duration": "01:00:00", + "language": "eng", + "recurring_mode": "once", + "language_description": "English", + "scheduled_start_date": "Wed 21 January 2026", + "access_description": "Musicians may join at will. Fans may not listen to session.", + "timezone": "Central Time (US & Canada),America/Chicago", + "timezone_id": "America/Chicago", + "timezone_description": "Central Time (US & Canada)", + "musician_access_description": "Musicians may join at will", + "fan_access_description": "Fans may not listen to session", + "session_removed_at": null, + "legal_policy": "legal_policy", + "open_rsvps": false, + "is_unstructured_rsvp?": false, + "friends_can_join": true, + "use_video_conferencing_server": true, + "creator": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "name": "Nuwan Chaturanga", + "photo_url": null + }, + "band": null, + "users": [], + "comments": [], + "session_info_comments": [], + "music_notations": [], + "invitations": [], + "approved_rsvps": [ + { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "first_name": "Nuwan", + "last_name": "Chaturanga", + "name": "Nuwan Chaturanga", + "resolved_photo_url": "http://localhost:3000/assets/shared/avatar_generic.png", + "full_score": null, + "audio_latency": 5, + "internet_score": null, + "instrument_list": [ + { + "id": "other", + "desc": "Other", + "level": 3 + } + ], + "rsvp_request_id": "3b57a648-3858-44a0-8650-45555a6dd33b" + } + ], + "open_slots": [], + "pending_invitations": [], + "pending_rsvp_requests": [], + "lesson_session": null, + "active_music_session": null, + "can_join": true, + "share_url": "http://www.jamkazam.local:3000/s/ZAPOFY0FCPM", + "genres": [ + "A Cappella" + ], + "scheduled_start": "Tue 20 January 2026 22:21:00", + "pretty_scheduled_start_with_timezone": "Tuesday, January 20, 10:21-10:21 PM US Central Time", + "pretty_scheduled_start_short": "Tuesday, January 20 - 10:21pm" + } + }, + { + "method": "POST", + "url": "http://www.jamkazam.local:3000/api/sessions/c2682005-d64f-4f2e-9e72-b9017c0097fc/participants", + "pathname": "/api/sessions/c2682005-d64f-4f2e-9e72-b9017c0097fc/participants", + "timestamp": 1768927895579, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "requestBody": { + "client_id": "8d64a3b0-2f34-48c1-8199-74766ad6b1ac", + "as_musician": true, + "tracks": [ + { + "client_track_id": "d4734735-0acb-4e87-9737-320efb024b3f", + "client_resource_id": "0x60000117dab0", + "instrument_id": "piano", + "sound": "stereo" + } + ], + "client_role": "parent", + "parent_client_id": "" + }, + "duration": 444, + "responseStatus": 201, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "74ae651d-b619-436b-bf23-0a101b498f10", + "x-runtime": "0.440659", + "etag": "W/\"511bac56d5816bf59cf165f3ab9f9289\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "location": "http://www.jamkazam.local:3000/api/sessions/c2682005-d64f-4f2e-9e72-b9017c0097fc", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "c2682005-d64f-4f2e-9e72-b9017c0097fc", + "name": "my session", + "description": "Automated test session", + "musician_access": true, + "approval_required": false, + "friends_can_join": true, + "fan_access": false, + "fan_chat": false, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "claimed_recording_initiator_id": null, + "track_changes_counter": 0, + "max_score": 0, + "backing_track_path": null, + "metronome_active": false, + "jam_track_initiator_id": null, + "jam_track_id": null, + "music_session_id_int": 3065, + "use_video_conferencing_server": true, + "created_at": "2026-01-20T16:51:35.602Z", + "music_notations": [], + "participants": [ + { + "ip_address": "127.0.0.1", + "client_id": "8d64a3b0-2f34-48c1-8199-74766ad6b1ac", + "joined_session_at": "2026-01-20T16:51:35.654Z", + "id": "2a4bf89d-6da3-4e80-b253-deb796ebb489", + "metronome_open": false, + "is_jamblaster": false, + "client_role": "parent", + "parent_client_id": "", + "client_id_int": 93868, + "tracks": [ + { + "id": "662bdeb9-3dfe-4753-98e4-3902b5a10534", + "connection_id": "2a4bf89d-6da3-4e80-b253-deb796ebb489", + "instrument_id": "piano", + "sound": "stereo", + "client_track_id": "d4734735-0acb-4e87-9737-320efb024b3f", + "client_resource_id": "0x60000117dab0", + "updated_at": "2026-01-20T16:51:35.657Z", + "instrument": "Piano" + } + ], + "backing_tracks": [], + "user": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "name": "Nuwan Chaturanga", + "is_friend": false, + "connection_state": "connected", + "subscription": "jamsubplatinum" + } + } + ], + "invitations": [], + "lesson_session": null, + "join_requests": [], + "jam_track": null, + "claimed_recording": null, + "subscription": { + "play_time_per_month": null, + "play_time_per_session": null, + "can_record_audio": true, + "can_record_video": true, + "can_use_video": true, + "can_record_wave": true, + "video_resolution": 4, + "audio_max_bitrate": 5, + "can_broadcast": true, + "broadcasting_type": 3, + "max_players": null, + "pro_audio": true, + "has_support": true, + "name": "Platinum", + "rank": 3, + "remaining_month_play_time": null + }, + "session_rules": { + "remaining_session_play_time": null + }, + "can_join": true, + "genres": [ + "A Cappella" + ], + "recording": null, + "share_url": "http://www.jamkazam.local:3000/s/ZAPOFY0FCPM", + "session_controller_id": "27bd4a30-d1b8-4eea-8454-01a104d59381" + } + }, + { + "method": "GET", + "url": "http://www.jamkazam.local:3000/api/sessions/c2682005-d64f-4f2e-9e72-b9017c0097fc", + "pathname": "/api/sessions/c2682005-d64f-4f2e-9e72-b9017c0097fc", + "timestamp": 1768927896184, + "requestHeaders": { + "accept": "application/json", + "referer": "http://beta.jamkazam.local:4000/", + "accept-language": "en-US", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "content-type": "application/json" + }, + "duration": 182, + "responseStatus": 200, + "responseHeaders": { + "content-encoding": "gzip", + "x-content-type-options": "nosniff", + "transfer-encoding": "chunked", + "x-xss-protection": "1; mode=block", + "x-request-id": "320d63a4-cd6e-45c2-affb-dc16a4908dd8", + "x-runtime": "0.075026", + "etag": "W/\"1140a03eccac397577d88aa4add338ae\"", + "x-frame-options": "SAMEORIGIN", + "access-control-max-age": "7200", + "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS", + "access-control-allow-origin": "http://beta.jamkazam.local:4000", + "access-control-expose-headers": "", + "vary": "Accept-Encoding, Origin", + "access-control-allow-credentials": "true", + "content-type": "application/json; charset=utf-8", + "cache-control": "max-age=0, private, must-revalidate" + }, + "responseBody": { + "id": "c2682005-d64f-4f2e-9e72-b9017c0097fc", + "name": "my session", + "description": "Automated test session", + "musician_access": true, + "approval_required": false, + "friends_can_join": true, + "fan_access": false, + "fan_chat": false, + "user_id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "claimed_recording_initiator_id": null, + "track_changes_counter": 0, + "max_score": 0, + "backing_track_path": null, + "metronome_active": false, + "jam_track_initiator_id": null, + "jam_track_id": null, + "music_session_id_int": 3065, + "use_video_conferencing_server": true, + "created_at": "2026-01-20T16:51:35.602Z", + "music_notations": [], + "participants": [ + { + "ip_address": "127.0.0.1", + "client_id": "8d64a3b0-2f34-48c1-8199-74766ad6b1ac", + "joined_session_at": "2026-01-20T16:51:35.654Z", + "id": "2a4bf89d-6da3-4e80-b253-deb796ebb489", + "metronome_open": false, + "is_jamblaster": false, + "client_role": "parent", + "parent_client_id": "", + "client_id_int": 93868, + "tracks": [ + { + "id": "662bdeb9-3dfe-4753-98e4-3902b5a10534", + "connection_id": "2a4bf89d-6da3-4e80-b253-deb796ebb489", + "instrument_id": "piano", + "sound": "stereo", + "client_track_id": "d4734735-0acb-4e87-9737-320efb024b3f", + "client_resource_id": "0x60000117dab0", + "updated_at": "2026-01-20T16:51:35.657Z", + "instrument": "Piano" + } + ], + "backing_tracks": [], + "user": { + "id": "27bd4a30-d1b8-4eea-8454-01a104d59381", + "photo_url": null, + "name": "Nuwan Chaturanga", + "is_friend": false, + "connection_state": "connected", + "subscription": "jamsubplatinum" + } + } + ], + "invitations": [], + "lesson_session": null, + "join_requests": [], + "jam_track": null, + "claimed_recording": null, + "can_join": true, + "genres": [ + "A Cappella" + ], + "recording": null, + "share_url": "http://www.jamkazam.local:3000/s/ZAPOFY0FCPM", + "session_controller_id": "27bd4a30-d1b8-4eea-8454-01a104d59381" + } + } +] \ No newline at end of file diff --git a/jam-ui/test/test-results/e2e/complete-flow-comparison.md b/jam-ui/test/test-results/e2e/complete-flow-comparison.md new file mode 100644 index 000000000..6ac71226d --- /dev/null +++ b/jam-ui/test/test-results/e2e/complete-flow-comparison.md @@ -0,0 +1,199 @@ +# API Sequence Comparison Report + +## Summary + +- **Match Status:** āŒ FAIL +- **Total Calls:** 9 +- **Matched Calls:** 2 +- **Match Percentage:** 22.2% + +## āŒ Missing API Calls + +The following expected API calls are missing or called fewer times: + +- **GET /api/genres** + - Expected: 7 call(s) + - Actual: 0 call(s) + - Missing: 7 call(s) + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381** + - Expected: 4 call(s) + - Actual: 0 call(s) + - Missing: 4 call(s) + +- **GET /api/countries** + - Expected: 2 call(s) + - Actual: 0 call(s) + - Missing: 2 call(s) + +- **GET /api/shopping_carts** + - Expected: 2 call(s) + - Actual: 0 call(s) + - Missing: 2 call(s) + +- **GET /api/jamtracks/purchased** + - Expected: 5 call(s) + - Actual: 0 call(s) + - Missing: 5 call(s) + +- **GET /api/teacher_distributions** + - Expected: 2 call(s) + - Actual: 0 call(s) + - Missing: 2 call(s) + +- **GET /api/regions** + - Expected: 2 call(s) + - Actual: 0 call(s) + - Missing: 2 call(s) + +- **POST /xoplatform/logger/api/logger** + - Expected: 4 call(s) + - Actual: 0 call(s) + - Missing: 4 call(s) + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/broadcast_notification** + - Expected: 2 call(s) + - Actual: 0 call(s) + - Missing: 2 call(s) + +- **GET /api/instruments** + - Expected: 6 call(s) + - Actual: 0 call(s) + - Missing: 6 call(s) + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends** + - Expected: 4 call(s) + - Actual: 1 call(s) + - Missing: 3 call(s) + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/notifications** + - Expected: 2 call(s) + - Actual: 0 call(s) + - Missing: 2 call(s) + +- **GET /api/languages** + - Expected: 2 call(s) + - Actual: 0 call(s) + - Missing: 2 call(s) + +- **GET /api/subjects** + - Expected: 2 call(s) + - Actual: 0 call(s) + - Missing: 2 call(s) + +- **GET /api/chat** + - Expected: 3 call(s) + - Actual: 0 call(s) + - Missing: 3 call(s) + +- **GET /api/versioncheck** + - Expected: 6 call(s) + - Actual: 0 call(s) + - Missing: 6 call(s) + +- **GET /api/healthcheck** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **GET /api/config/client** + - Expected: 2 call(s) + - Actual: 0 call(s) + - Missing: 2 call(s) + +- **GET /api/sessions/scheduled** + - Expected: 2 call(s) + - Actual: 0 call(s) + - Missing: 2 call(s) + +- **GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/history** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **POST /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/participants** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +- **PUT /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23/tracks** + - Expected: 3 call(s) + - Actual: 0 call(s) + - Missing: 3 call(s) + +- **GET /api/sessions/02d4846c-eb02-40d5-ab2d-fe56e6c84d23** + - Expected: 3 call(s) + - Actual: 0 call(s) + - Missing: 3 call(s) + +- **POST /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/udp_reachable** + - Expected: 1 call(s) + - Actual: 0 call(s) + - Missing: 1 call(s) + +## āš ļø Extra API Calls + +The following API calls were made but not expected: + +- **GET /api/app_features** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +- **GET /api/me** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/my_notifications** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +- **GET /api/sessions/c2682005-d64f-4f2e-9e72-b9017c0097fc/history** + - Expected: 0 call(s) + - Actual: 2 call(s) + - Extra: 2 call(s) + +- **POST /api/sessions/c2682005-d64f-4f2e-9e72-b9017c0097fc/participants** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +- **GET /api/sessions/c2682005-d64f-4f2e-9e72-b9017c0097fc** + - Expected: 0 call(s) + - Actual: 1 call(s) + - Extra: 1 call(s) + +## āš ļø Out of Order Calls + +The following API calls occurred in a different order: + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends** + - Expected position: 15 + - Actual position: 4 + - Deviation: 11 positions + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends** + - Expected position: 18 + - Actual position: 4 + - Deviation: 14 positions + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends** + - Expected position: 39 + - Actual position: 4 + - Deviation: 35 positions + +- **GET /api/users/27bd4a30-d1b8-4eea-8454-01a104d59381/friends** + - Expected position: 48 + - Actual position: 4 + - Deviation: 44 positions + +- **POST /api/sessions** + - Expected position: 57 + - Actual position: 0 + - Deviation: 57 positions + +## āŒ Conclusion + +The API sequence does NOT match the expected baseline. Please review the mismatches above. diff --git a/jam-ui/test/test-results/e2e/complete-flow-websockets.json b/jam-ui/test/test-results/e2e/complete-flow-websockets.json new file mode 100644 index 000000000..ca1bf16ab --- /dev/null +++ b/jam-ui/test/test-results/e2e/complete-flow-websockets.json @@ -0,0 +1,2564 @@ +[ + { + "url": "ws://beta.jamkazam.local:4000/sockjs-node", + "timestamp": 1768927876672, + "isNativeClient": false, + "isServerConnection": false, + "messages": [ + { + "direction": "received", + "payload": "{\"type\":\"log-level\",\"data\":\"none\"}", + "timestamp": 1768927876679, + "size": 34 + }, + { + "direction": "received", + "payload": "{\"type\":\"hot\"}", + "timestamp": 1768927876679, + "size": 14 + }, + { + "direction": "received", + "payload": "{\"type\":\"liveReload\"}", + "timestamp": 1768927876679, + "size": 21 + }, + { + "direction": "received", + "payload": "{\"type\":\"hash\",\"data\":\"8fcec829639a752b457d\"}", + "timestamp": 1768927876679, + "size": 45 + }, + { + "direction": "received", + "payload": "{\"type\":\"warnings\",\"data\":[\"./src/helpers/MessageFactory.js\\nModule Warning (from ./node_modules/eslint-loader/dist/cjs.js):\\n\\n \\u001b[1mLine 103:7:\\u001b[22m 'getCookie' is assigned a value but ne...", + "timestamp": 1768927876691, + "size": 206417 + } + ], + "closed": false + }, + { + "url": "ws://localhost:3060/", + "timestamp": 1768927895119, + "isNativeClient": true, + "isServerConnection": false, + "messages": [ + { + "direction": "sent", + "payload": "{\"type\":3,\"id\":0}", + "timestamp": 1768927895121, + "size": 17 + }, + { + "direction": "received", + "payload": "{\"data\":{\"jkfrontendchannel\":{\"enums\":{\"JKAppMessage\":{\"AbortRecording\":1001,\"BringVideoWindowToFront\":1004,\"ClientJoinedSession\":1008,\"ClientLeftSession\":1009,\"ClientUpdateStartDownload\":1010,\"Client...", + "timestamp": 1768927895168, + "size": 11852 + }, + { + "direction": "sent", + "payload": "{\"type\":7,\"object\":\"jkfrontendchannel\",\"signal\":5}", + "timestamp": 1768927895168, + "size": 50 + }, + { + "direction": "sent", + "payload": "{\"type\":4}", + "timestamp": 1768927895168, + "size": 10 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927895168, + "size": 2732 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":2,\\\"arguments\\\":[],\\\"method\\\":1401}\"],\"id\":1}", + "timestamp": 1768927895218, + "size": 132 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1401,\\\"method_name\\\":\\\"GetAudioRecordingPreference\\\",\\\"request_id\\\":2,\\\"response\\\":2}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895258, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":1,\"type\":10}", + "timestamp": 1768927895262, + "size": 30 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":3,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":2}", + "timestamp": 1768927895305, + "size": 129 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":4,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":3}", + "timestamp": 1768927895305, + "size": 129 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":5,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":4}", + "timestamp": 1768927895305, + "size": 129 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":6,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":5}", + "timestamp": 1768927895305, + "size": 129 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":7,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":6}", + "timestamp": 1768927895305, + "size": 129 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":8,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":7}", + "timestamp": 1768927895305, + "size": 129 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":9,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":8}", + "timestamp": 1768927895305, + "size": 129 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":10,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":9}", + "timestamp": 1768927895306, + "size": 130 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":3,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895307, + "size": 161 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":2,\"type\":10}", + "timestamp": 1768927895307, + "size": 30 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":4,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895307, + "size": 161 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":3,\"type\":10}", + "timestamp": 1768927895307, + "size": 30 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":5,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895307, + "size": 161 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":4,\"type\":10}", + "timestamp": 1768927895307, + "size": 30 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":6,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895307, + "size": 161 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":5,\"type\":10}", + "timestamp": 1768927895307, + "size": 30 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":7,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895307, + "size": 161 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":6,\"type\":10}", + "timestamp": 1768927895307, + "size": 30 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":8,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895307, + "size": 161 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":7,\"type\":10}", + "timestamp": 1768927895307, + "size": 30 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":9,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895308, + "size": 161 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":8,\"type\":10}", + "timestamp": 1768927895308, + "size": 30 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":10,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895308, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":9,\"type\":10}", + "timestamp": 1768927895308, + "size": 30 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":11,\\\"arguments\\\":[],\\\"method\\\":1151}\"],\"id\":10}", + "timestamp": 1768927895316, + "size": 134 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":12,\\\"arguments\\\":[\\\"JK.HandleMetronomeCallback2\\\"],\\\"method\\\":1328}\"],\"id\":11}", + "timestamp": 1768927895316, + "size": 165 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1151,\\\"method_name\\\":\\\"getOperatingMode\\\",\\\"request_id\\\":11,\\\"response\\\":\\\"client\\\"}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895317, + "size": 161 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":13,\\\"arguments\\\":[],\\\"method\\\":1261}\"],\"id\":12}", + "timestamp": 1768927895317, + "size": 134 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":10,\"type\":10}", + "timestamp": 1768927895317, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1328,\\\"method_name\\\":\\\"setMetronomeOpenCallback\\\",\\\"request_id\\\":12,\\\"response\\\":{\\\"process_status\\\":\\\"Success\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895317, + "size": 191 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":11,\"type\":10}", + "timestamp": 1768927895317, + "size": 31 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":14,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":13}", + "timestamp": 1768927895319, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":15,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":14}", + "timestamp": 1768927895319, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":16,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":15}", + "timestamp": 1768927895319, + "size": 131 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1261,\\\"method_name\\\":\\\"SessionGetMacHash\\\",\\\"request_id\\\":13,\\\"response\\\":{\\\"1b4d0ddbf9c1d7cd0a311465676d86a5892a36ea\\\":{\\\"ipaddr_0\\\":\\\"fe80::1c92:1083:c1e6:8f02%en0\\\",\\\"ipadd...", + "timestamp": 1768927895319, + "size": 1715 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":17,\\\"arguments\\\":[],\\\"method\\\":1125}\"],\"id\":16}", + "timestamp": 1768927895319, + "size": 134 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":18,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":17}", + "timestamp": 1768927895319, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":19,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":18}", + "timestamp": 1768927895320, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":20,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":19}", + "timestamp": 1768927895320, + "size": 131 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":12,\"type\":10}", + "timestamp": 1768927895320, + "size": 31 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":21,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":20}", + "timestamp": 1768927895320, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":22,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":21}", + "timestamp": 1768927895320, + "size": 131 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":14,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895320, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":13,\"type\":10}", + "timestamp": 1768927895320, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":15,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895320, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":14,\"type\":10}", + "timestamp": 1768927895320, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":16,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895320, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":15,\"type\":10}", + "timestamp": 1768927895320, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1125,\\\"method_name\\\":\\\"GetDetailedOS\\\",\\\"request_id\\\":17,\\\"response\\\":\\\"MacOSX-M\\\"}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895321, + "size": 160 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":23,\\\"arguments\\\":[],\\\"method\\\":1203}\"],\"id\":22}", + "timestamp": 1768927895322, + "size": 134 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":16,\"type\":10}", + "timestamp": 1768927895322, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":18,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895322, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":17,\"type\":10}", + "timestamp": 1768927895322, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":19,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895323, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":18,\"type\":10}", + "timestamp": 1768927895323, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":20,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895323, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":19,\"type\":10}", + "timestamp": 1768927895323, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":21,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895323, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":20,\"type\":10}", + "timestamp": 1768927895323, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":22,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895323, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":21,\"type\":10}", + "timestamp": 1768927895323, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1203,\\\"method_name\\\":\\\"NetworkTestResult\\\",\\\"request_id\\\":23,\\\"response\\\":{\\\"preserve_port\\\":false,\\\"public_ip\\\":\\\"112.134.221.38\\\",\\\"remote_udp_blocked\\\":false,\\\"stun_failed\\...", + "timestamp": 1768927895323, + "size": 287 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":22,\"type\":10}", + "timestamp": 1768927895324, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927895350, + "size": 2732 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":24,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":23}", + "timestamp": 1768927895434, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":25,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":24}", + "timestamp": 1768927895434, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":26,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":25}", + "timestamp": 1768927895434, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":27,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":26}", + "timestamp": 1768927895434, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":28,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":27}", + "timestamp": 1768927895434, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":29,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":28}", + "timestamp": 1768927895434, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":30,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":29}", + "timestamp": 1768927895434, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":31,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":30}", + "timestamp": 1768927895434, + "size": 131 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":24,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895434, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":23,\"type\":10}", + "timestamp": 1768927895434, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":25,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895434, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":24,\"type\":10}", + "timestamp": 1768927895434, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":26,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895434, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":25,\"type\":10}", + "timestamp": 1768927895434, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":27,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895434, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":26,\"type\":10}", + "timestamp": 1768927895434, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":28,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895434, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":27,\"type\":10}", + "timestamp": 1768927895434, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":29,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895434, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":28,\"type\":10}", + "timestamp": 1768927895434, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":30,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895434, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":29,\"type\":10}", + "timestamp": 1768927895434, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":31,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895434, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":30,\"type\":10}", + "timestamp": 1768927895434, + "size": 31 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":32,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":31}", + "timestamp": 1768927895436, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":33,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":32}", + "timestamp": 1768927895437, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":34,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":33}", + "timestamp": 1768927895437, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":35,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":34}", + "timestamp": 1768927895437, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":36,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":35}", + "timestamp": 1768927895437, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":37,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":36}", + "timestamp": 1768927895437, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":38,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":37}", + "timestamp": 1768927895437, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":39,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":38}", + "timestamp": 1768927895437, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":40,\\\"arguments\\\":[{\\\"user_id\\\":\\\"27bd4a30-d1b8-4eea-8454-01a104d59381\\\",\\\"token\\\":\\\"CKXGCTBxfdGG12oXACOEYA\\\",\\\"us...", + "timestamp": 1768927895455, + "size": 537 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":32,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895455, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":31,\"type\":10}", + "timestamp": 1768927895457, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":33,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895457, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":32,\"type\":10}", + "timestamp": 1768927895457, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":34,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895457, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":33,\"type\":10}", + "timestamp": 1768927895457, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":35,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895457, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":34,\"type\":10}", + "timestamp": 1768927895457, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":36,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895458, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":35,\"type\":10}", + "timestamp": 1768927895458, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":37,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895458, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":36,\"type\":10}", + "timestamp": 1768927895458, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":38,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895458, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":37,\"type\":10}", + "timestamp": 1768927895458, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":39,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895458, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":38,\"type\":10}", + "timestamp": 1768927895458, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3007,\\\"response\\\":{\\\"message\\\":\\\"Y0dsdVoxOXlaWEY4ZkRJd05qa3dNRFl5TWpKOGZERTFmSHd4T2pFM05qZzVNamM0T1RVNk5USTFNakk0Zkh3eE5qTXhNamszTlRjNWZId3hOak14TWprM05UYzVmSHhPZFhkaGJpQkRhR0Y...", + "timestamp": 1768927895459, + "size": 321 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleAlertCallback(28, \\\\\\\"\\\\\\\")\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895459, + "size": 156 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1205,\\\"method_name\\\":\\\"OnLoggedIn\\\",\\\"request_id\\\":40,\\\"response\\\":{\\\"CustomUrl\\\":\\\"\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895459, + "size": 165 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":39,\"type\":10}", + "timestamp": 1768927895459, + "size": 31 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":41,\\\"arguments\\\":[{\\\"user_id\\\":\\\"27bd4a30-d1b8-4eea-8454-01a104d59381\\\",\\\"token\\\":\\\"CKXGCTBxfdGG12oXACOEYA\\\",\\\"us...", + "timestamp": 1768927895463, + "size": 537 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3007,\\\"response\\\":{\\\"message\\\":\\\"Y0dsdVoxOXlaWEY4ZkRFeE5Ea3hNVFkzTVh4OE1UVjhmREU2TVRjMk9Ea3lOemc1TlRvMU5EQXdORFo4ZkRFeE1ESXdNelE0TXpaOGZERXhNREl3TXpRNE16WjhmRTUxZDJGdUlFTm9ZWFI...", + "timestamp": 1768927895465, + "size": 313 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1205,\\\"method_name\\\":\\\"OnLoggedIn\\\",\\\"request_id\\\":41,\\\"response\\\":{\\\"CustomUrl\\\":\\\"\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895465, + "size": 165 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":40,\"type\":10}", + "timestamp": 1768927895465, + "size": 31 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":42,\\\"arguments\\\":[],\\\"method\\\":1121}\"],\"id\":41}", + "timestamp": 1768927895544, + "size": 134 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1121,\\\"method_name\\\":\\\"getClientParentChildRole\\\",\\\"request_id\\\":42,\\\"response\\\":1}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895545, + "size": 160 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":43,\\\"arguments\\\":[],\\\"method\\\":1025}\"],\"id\":42}", + "timestamp": 1768927895546, + "size": 134 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":41,\"type\":10}", + "timestamp": 1768927895546, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1025,\\\"method_name\\\":\\\"FTUEGetAllAudioConfigurations\\\",\\\"request_id\\\":43,\\\"response\\\":[\\\"In/Out: Scarlett 2i2 USB\\\",\\\"In: MacBook Pro Microphone, Out: MacBook Pro Speakers\\\",\\...", + "timestamp": 1768927895547, + "size": 287 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":44,\\\"arguments\\\":[],\\\"method\\\":1149}\"],\"id\":43}", + "timestamp": 1768927895547, + "size": 134 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":45,\\\"arguments\\\":[],\\\"method\\\":1269}\"],\"id\":44}", + "timestamp": 1768927895547, + "size": 134 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":42,\"type\":10}", + "timestamp": 1768927895547, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1149,\\\"method_name\\\":\\\"GetNetworkTestScore\\\",\\\"request_id\\\":44,\\\"response\\\":0}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895547, + "size": 155 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":43,\"type\":10}", + "timestamp": 1768927895548, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1269,\\\"method_name\\\":\\\"SessionPageEnter\\\",\\\"request_id\\\":45,\\\"response\\\":{\\\"reason\\\":\\\"already_started\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895548, + "size": 183 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":46,\\\"arguments\\\":[true],\\\"method\\\":1256}\"],\"id\":45}", + "timestamp": 1768927895551, + "size": 138 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":44,\"type\":10}", + "timestamp": 1768927895552, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927895552, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1256,\\\"method_name\\\":\\\"SessionGetAllControlState\\\",\\\"request_id\\\":46,\\\"response\\\":[{\\\"_id\\\":10000,\\\"client_id\\\":\\\"\\\",\\\"group_id\\\":0,\\\"id\\\":\\\"1e329e9a-6aba-4449-8a3e-25d65bfb61...", + "timestamp": 1768927895554, + "size": 6295 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":47,\\\"arguments\\\":[true],\\\"method\\\":1256}\"],\"id\":46}", + "timestamp": 1768927895554, + "size": 138 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":45,\"type\":10}", + "timestamp": 1768927895554, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1256,\\\"method_name\\\":\\\"SessionGetAllControlState\\\",\\\"request_id\\\":47,\\\"response\\\":[{\\\"_id\\\":10000,\\\"client_id\\\":\\\"\\\",\\\"group_id\\\":0,\\\"id\\\":\\\"1e329e9a-6aba-4449-8a3e-25d65bfb61...", + "timestamp": 1768927895557, + "size": 6295 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":48,\\\"arguments\\\":[],\\\"method\\\":1198}\"],\"id\":47}", + "timestamp": 1768927895557, + "size": 134 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":46,\"type\":10}", + "timestamp": 1768927895557, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1198,\\\"method_name\\\":\\\"LastUsedProfileName\\\",\\\"request_id\\\":48,\\\"response\\\":\\\"In/Out: Scarlett 2i2 USB\\\"}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895557, + "size": 182 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":49,\\\"arguments\\\":[],\\\"method\\\":1198}\"],\"id\":48}", + "timestamp": 1768927895565, + "size": 134 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":47,\"type\":10}", + "timestamp": 1768927895565, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1198,\\\"method_name\\\":\\\"LastUsedProfileName\\\",\\\"request_id\\\":49,\\\"response\\\":\\\"In/Out: Scarlett 2i2 USB\\\"}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895565, + "size": 182 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":50,\\\"arguments\\\":[],\\\"method\\\":1044}\"],\"id\":49}", + "timestamp": 1768927895565, + "size": 134 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":48,\"type\":10}", + "timestamp": 1768927895565, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1044,\\\"method_name\\\":\\\"FTUEGetExpectedLatency\\\",\\\"request_id\\\":50,\\\"response\\\":{\\\"latency\\\":11.270833969116211,\\\"latencyknown\\\":true,\\\"latencyvar\\\":1}}\"],\"object\":\"jkfrontendc...", + "timestamp": 1768927895566, + "size": 228 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":51,\\\"arguments\\\":[],\\\"method\\\":1149}\"],\"id\":50}", + "timestamp": 1768927895566, + "size": 134 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":49,\"type\":10}", + "timestamp": 1768927895566, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1149,\\\"method_name\\\":\\\"GetNetworkTestScore\\\",\\\"request_id\\\":51,\\\"response\\\":0}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895566, + "size": 155 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":52,\\\"arguments\\\":[\\\"JK.HandleBridgeCallback2\\\"],\\\"method\\\":1272}\"],\"id\":51}", + "timestamp": 1768927895572, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":50,\"type\":10}", + "timestamp": 1768927895573, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1272,\\\"method_name\\\":\\\"SessionRegisterCallback\\\",\\\"request_id\\\":52,\\\"response\\\":{\\\"process_status\\\":\\\"Success\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895573, + "size": 190 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":53,\\\"arguments\\\":[\\\"JK.HandleAlertCallback\\\"],\\\"method\\\":1277}\"],\"id\":52}", + "timestamp": 1768927895573, + "size": 160 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":51,\"type\":10}", + "timestamp": 1768927895573, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1277,\\\"method_name\\\":\\\"SessionSetAlertCallback\\\",\\\"request_id\\\":53,\\\"response\\\":{\\\"process_status\\\":\\\"Success\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895574, + "size": 190 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":54,\\\"arguments\\\":[\\\"JK.HandleRecordingStartResult\\\",\\\"JK.HandleRecordingStopResult\\\",\\\"JK.HandleRecordingStarted\\...", + "timestamp": 1768927895574, + "size": 290 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":52,\"type\":10}", + "timestamp": 1768927895574, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1227,\\\"method_name\\\":\\\"RegisterRecordingCallbacks\\\",\\\"request_id\\\":54,\\\"response\\\":{\\\"process_status\\\":\\\"Success\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895574, + "size": 193 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":55,\\\"arguments\\\":[1000],\\\"method\\\":1279}\"],\"id\":54}", + "timestamp": 1768927895574, + "size": 138 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":53,\"type\":10}", + "timestamp": 1768927895574, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1279,\\\"method_name\\\":\\\"SessionSetConnectionStatusRefreshRate\\\",\\\"request_id\\\":55,\\\"response\\\":{\\\"process_status\\\":\\\"Success\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type...", + "timestamp": 1768927895575, + "size": 204 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":56,\\\"arguments\\\":[],\\\"method\\\":1121}\"],\"id\":55}", + "timestamp": 1768927895575, + "size": 134 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":54,\"type\":10}", + "timestamp": 1768927895575, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1121,\\\"method_name\\\":\\\"getClientParentChildRole\\\",\\\"request_id\\\":56,\\\"response\\\":1}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895575, + "size": 160 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":57,\\\"arguments\\\":[],\\\"method\\\":1154}\"],\"id\":56}", + "timestamp": 1768927895576, + "size": 134 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":55,\"type\":10}", + "timestamp": 1768927895576, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1154,\\\"method_name\\\":\\\"getParentClientId\\\",\\\"request_id\\\":57,\\\"response\\\":\\\"\\\"}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895576, + "size": 156 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":58,\\\"arguments\\\":[],\\\"method\\\":1044}\"],\"id\":57}", + "timestamp": 1768927895577, + "size": 134 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":56,\"type\":10}", + "timestamp": 1768927895579, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1044,\\\"method_name\\\":\\\"FTUEGetExpectedLatency\\\",\\\"request_id\\\":58,\\\"response\\\":{\\\"latency\\\":11.270833969116211,\\\"latencyknown\\\":true,\\\"latencyvar\\\":1}}\"],\"object\":\"jkfrontendc...", + "timestamp": 1768927895579, + "size": 228 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":57,\"type\":10}", + "timestamp": 1768927895579, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1008,\\\"method_name\\\":\\\"ClientJoinedSession\\\",\\\"request_id\\\":43606,\\\"response\\\":{\\\"AudioFormat\\\":\\\"mp3\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895748, + "size": 182 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1121,\\\"method_name\\\":\\\"getClientParentChildRole\\\",\\\"request_id\\\":43607,\\\"response\\\":1}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895748, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1404,\\\"method_name\\\":\\\"GetCurrentRecordingId\\\",\\\"request_id\\\":43608,\\\"response\\\":\\\"\\\"}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895748, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927895750, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1256,\\\"method_name\\\":\\\"SessionGetAllControlState\\\",\\\"request_id\\\":43609,\\\"response\\\":[{\\\"_id\\\":10000,\\\"client_id\\\":\\\"\\\",\\\"group_id\\\":0,\\\"id\\\":\\\"1e329e9a-6aba-4449-8a3e-25d65bf...", + "timestamp": 1768927895751, + "size": 6298 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1401,\\\"method_name\\\":\\\"GetAudioRecordingPreference\\\",\\\"request_id\\\":43610,\\\"response\\\":2}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895758, + "size": 166 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1401,\\\"method_name\\\":\\\"GetAudioRecordingPreference\\\",\\\"request_id\\\":43611,\\\"response\\\":2}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895777, + "size": 166 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1378,\\\"method_name\\\":\\\"UpdateSessionInfo\\\",\\\"request_id\\\":43612,\\\"response\\\":{\\\"process_status\\\":\\\"Success\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895783, + "size": 187 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1256,\\\"method_name\\\":\\\"SessionGetAllControlState\\\",\\\"request_id\\\":43613,\\\"response\\\":[{\\\"_id\\\":10100,\\\"client_id\\\":\\\"\\\",\\\"group_id\\\":1,\\\"id\\\":\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356...", + "timestamp": 1768927895789, + "size": 6323 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1256,\\\"method_name\\\":\\\"SessionGetAllControlState\\\",\\\"request_id\\\":43614,\\\"response\\\":[{\\\"_id\\\":10000,\\\"client_id\\\":\\\"\\\",\\\"group_id\\\":0,\\\"id\\\":\\\"1e329e9a-6aba-4449-8a3e-25d65bf...", + "timestamp": 1768927895802, + "size": 6298 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1034,\\\"method_name\\\":\\\"FTUEGetChannels\\\",\\\"request_id\\\":43615,\\\"response\\\":{\\\"inputs\\\":[],\\\"outputs\\\":[]}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895811, + "size": 183 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1401,\\\"method_name\\\":\\\"GetAudioRecordingPreference\\\",\\\"request_id\\\":43616,\\\"response\\\":2}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895815, + "size": 166 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1256,\\\"method_name\\\":\\\"SessionGetAllControlState\\\",\\\"request_id\\\":43617,\\\"response\\\":[{\\\"_id\\\":10100,\\\"client_id\\\":\\\"\\\",\\\"group_id\\\":1,\\\"id\\\":\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356...", + "timestamp": 1768927895829, + "size": 6323 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1034,\\\"method_name\\\":\\\"FTUEGetChannels\\\",\\\"request_id\\\":43618,\\\"response\\\":{\\\"inputs\\\":[],\\\"outputs\\\":[]}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895856, + "size": 183 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1401,\\\"method_name\\\":\\\"GetAudioRecordingPreference\\\",\\\"request_id\\\":43619,\\\"response\\\":2}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927895859, + "size": 166 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927895950, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1122,\\\"method_name\\\":\\\"getConnectionDetail\\\",\\\"request_id\\\":43620,\\\"response\\\":[{\\\"audio\\\":{\\\"acpu\\\":2.061195135116577,\\\"audio_chat_in\\\":\\\"MacBook Pro Microphone\\\",\\\"audio_cha...", + "timestamp": 1768927895979, + "size": 1229 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1122,\\\"method_name\\\":\\\"getConnectionDetail\\\",\\\"request_id\\\":43621,\\\"response\\\":[{\\\"audio\\\":{\\\"acpu\\\":2.061195135116577,\\\"audio_chat_in\\\":\\\"MacBook Pro Microphone\\\",\\\"audio_cha...", + "timestamp": 1768927895980, + "size": 1229 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":59,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":58}", + "timestamp": 1768927896026, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":60,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":59}", + "timestamp": 1768927896026, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":61,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":60}", + "timestamp": 1768927896026, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":62,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":61}", + "timestamp": 1768927896026, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":63,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":62}", + "timestamp": 1768927896026, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":64,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":63}", + "timestamp": 1768927896026, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":65,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":64}", + "timestamp": 1768927896026, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":66,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":65}", + "timestamp": 1768927896026, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":67,\\\"arguments\\\":[true],\\\"method\\\":1256}\"],\"id\":66}", + "timestamp": 1768927896037, + "size": 138 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":68,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":67}", + "timestamp": 1768927896037, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":69,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":68}", + "timestamp": 1768927896037, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":70,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":69}", + "timestamp": 1768927896037, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":71,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":70}", + "timestamp": 1768927896037, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":72,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":71}", + "timestamp": 1768927896037, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":73,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":72}", + "timestamp": 1768927896037, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":74,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":73}", + "timestamp": 1768927896037, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":75,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":74}", + "timestamp": 1768927896037, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":76,\\\"arguments\\\":[{\\\"sessionID\\\":\\\"c2682005-d64f-4f2e-9e72-b9017c0097fc\\\"}],\\\"method\\\":1197}\"],\"id\":75}", + "timestamp": 1768927896044, + "size": 190 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":59,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896044, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":58,\"type\":10}", + "timestamp": 1768927896044, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":60,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896044, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":59,\"type\":10}", + "timestamp": 1768927896044, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":61,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896045, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":60,\"type\":10}", + "timestamp": 1768927896045, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":62,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896045, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":61,\"type\":10}", + "timestamp": 1768927896045, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":63,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896045, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":62,\"type\":10}", + "timestamp": 1768927896045, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":64,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896045, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":63,\"type\":10}", + "timestamp": 1768927896045, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":65,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896046, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":64,\"type\":10}", + "timestamp": 1768927896046, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":66,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896046, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":65,\"type\":10}", + "timestamp": 1768927896046, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1256,\\\"method_name\\\":\\\"SessionGetAllControlState\\\",\\\"request_id\\\":67,\\\"response\\\":[{\\\"_id\\\":10000,\\\"client_id\\\":\\\"\\\",\\\"group_id\\\":0,\\\"id\\\":\\\"1e329e9a-6aba-4449-8a3e-25d65bfb61...", + "timestamp": 1768927896046, + "size": 6295 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":77,\\\"arguments\\\":[false],\\\"method\\\":1256}\"],\"id\":76}", + "timestamp": 1768927896047, + "size": 139 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":66,\"type\":10}", + "timestamp": 1768927896047, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":68,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896047, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":67,\"type\":10}", + "timestamp": 1768927896047, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":69,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896047, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":68,\"type\":10}", + "timestamp": 1768927896047, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":70,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896047, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":69,\"type\":10}", + "timestamp": 1768927896047, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":71,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896047, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":70,\"type\":10}", + "timestamp": 1768927896047, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":72,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896048, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":71,\"type\":10}", + "timestamp": 1768927896048, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":73,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896048, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":72,\"type\":10}", + "timestamp": 1768927896048, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":74,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896048, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":73,\"type\":10}", + "timestamp": 1768927896048, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":75,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896048, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":74,\"type\":10}", + "timestamp": 1768927896048, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleAlertCallback(2, \\\\\\\"Mode change\\\\\\\")\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896083, + "size": 166 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleAlertCallback(2, \\\\\\\"Local Peer Stream Mixer Mode\\\\\\\")\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896084, + "size": 183 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1197,\\\"method_name\\\":\\\"JoinSession\\\",\\\"request_id\\\":76,\\\"response\\\":{\\\"process_status\\\":\\\"Success\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896085, + "size": 178 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":75,\"type\":10}", + "timestamp": 1768927896096, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleAlertCallback(2, \\\\\\\"RebuildRemoteUserControl\\\\\\\")\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896096, + "size": 179 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":78,\\\"arguments\\\":[true],\\\"method\\\":1256}\"],\"id\":77}", + "timestamp": 1768927896097, + "size": 138 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1256,\\\"method_name\\\":\\\"SessionGetAllControlState\\\",\\\"request_id\\\":77,\\\"response\\\":[{\\\"_id\\\":10100,\\\"client_id\\\":\\\"\\\",\\\"group_id\\\":1,\\\"id\\\":\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c68...", + "timestamp": 1768927896099, + "size": 6320 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":79,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":78}", + "timestamp": 1768927896105, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":80,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":79}", + "timestamp": 1768927896113, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":81,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":80}", + "timestamp": 1768927896113, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":82,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":81}", + "timestamp": 1768927896114, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":83,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":82}", + "timestamp": 1768927896114, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":84,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":83}", + "timestamp": 1768927896114, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":85,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":84}", + "timestamp": 1768927896114, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":86,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":85}", + "timestamp": 1768927896114, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":87,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":86}", + "timestamp": 1768927896128, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":88,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":87}", + "timestamp": 1768927896128, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":89,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":88}", + "timestamp": 1768927896128, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":90,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":89}", + "timestamp": 1768927896128, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":91,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":90}", + "timestamp": 1768927896128, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":92,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":91}", + "timestamp": 1768927896128, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":93,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":92}", + "timestamp": 1768927896128, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":94,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":93}", + "timestamp": 1768927896128, + "size": 131 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":76,\"type\":10}", + "timestamp": 1768927896133, + "size": 31 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":95,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":94}", + "timestamp": 1768927896141, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":96,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":95}", + "timestamp": 1768927896141, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":97,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":96}", + "timestamp": 1768927896141, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":98,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":97}", + "timestamp": 1768927896141, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":99,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":98}", + "timestamp": 1768927896141, + "size": 131 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":100,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":99}", + "timestamp": 1768927896141, + "size": 132 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":101,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":100}", + "timestamp": 1768927896141, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":102,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":101}", + "timestamp": 1768927896141, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":103,\\\"arguments\\\":[],\\\"method\\\":1385}\"],\"id\":102}", + "timestamp": 1768927896155, + "size": 136 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1256,\\\"method_name\\\":\\\"SessionGetAllControlState\\\",\\\"request_id\\\":78,\\\"response\\\":[{\\\"_id\\\":10000,\\\"client_id\\\":\\\"\\\",\\\"group_id\\\":0,\\\"id\\\":\\\"1e329e9a-6aba-4449-8a3e-25d65bfb61...", + "timestamp": 1768927896162, + "size": 6295 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":77,\"type\":10}", + "timestamp": 1768927896184, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":79,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896184, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":78,\"type\":10}", + "timestamp": 1768927896184, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":80,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896184, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":79,\"type\":10}", + "timestamp": 1768927896184, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":81,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896184, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":80,\"type\":10}", + "timestamp": 1768927896184, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":82,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896184, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":81,\"type\":10}", + "timestamp": 1768927896184, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":83,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896184, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":82,\"type\":10}", + "timestamp": 1768927896184, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":84,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896184, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":83,\"type\":10}", + "timestamp": 1768927896184, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":85,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896184, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":84,\"type\":10}", + "timestamp": 1768927896185, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":86,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896185, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":85,\"type\":10}", + "timestamp": 1768927896185, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":87,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896185, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":86,\"type\":10}", + "timestamp": 1768927896185, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":88,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896185, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":87,\"type\":10}", + "timestamp": 1768927896185, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":89,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896185, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":88,\"type\":10}", + "timestamp": 1768927896185, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":90,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896185, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":89,\"type\":10}", + "timestamp": 1768927896185, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":91,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896185, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":90,\"type\":10}", + "timestamp": 1768927896186, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":92,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896186, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":91,\"type\":10}", + "timestamp": 1768927896186, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":93,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896186, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":92,\"type\":10}", + "timestamp": 1768927896186, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":94,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896186, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":93,\"type\":10}", + "timestamp": 1768927896186, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":95,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896189, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":94,\"type\":10}", + "timestamp": 1768927896189, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":96,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896189, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":95,\"type\":10}", + "timestamp": 1768927896189, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":97,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896189, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":96,\"type\":10}", + "timestamp": 1768927896190, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":98,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896190, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":97,\"type\":10}", + "timestamp": 1768927896190, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":99,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896190, + "size": 162 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":98,\"type\":10}", + "timestamp": 1768927896190, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":100,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896190, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":99,\"type\":10}", + "timestamp": 1768927896190, + "size": 31 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":101,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896190, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":100,\"type\":10}", + "timestamp": 1768927896190, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":102,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896190, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":101,\"type\":10}", + "timestamp": 1768927896191, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1385,\\\"method_name\\\":\\\"VSTListTrackAssignments\\\",\\\"request_id\\\":103,\\\"response\\\":{\\\"vsts\\\":[]}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896191, + "size": 172 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":102,\"type\":10}", + "timestamp": 1768927896191, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927896357, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927896514, + "size": 2732 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":104,\\\"arguments\\\":[],\\\"method\\\":1207}\"],\"id\":103}", + "timestamp": 1768927896524, + "size": 136 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":105,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":104}", + "timestamp": 1768927896536, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":106,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":105}", + "timestamp": 1768927896536, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":107,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":106}", + "timestamp": 1768927896536, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":108,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":107}", + "timestamp": 1768927896536, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":109,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":108}", + "timestamp": 1768927896536, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":110,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":109}", + "timestamp": 1768927896536, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":111,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":110}", + "timestamp": 1768927896536, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":112,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":111}", + "timestamp": 1768927896536, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":113,\\\"arguments\\\":[],\\\"method\\\":1385}\"],\"id\":112}", + "timestamp": 1768927896549, + "size": 136 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":114,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":113}", + "timestamp": 1768927896549, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":115,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":114}", + "timestamp": 1768927896549, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":116,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":115}", + "timestamp": 1768927896549, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":117,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":116}", + "timestamp": 1768927896549, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":118,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":117}", + "timestamp": 1768927896549, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":119,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":118}", + "timestamp": 1768927896549, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":120,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":119}", + "timestamp": 1768927896549, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":121,\\\"arguments\\\":[\\\"jamClient\\\"]}\"],\"id\":120}", + "timestamp": 1768927896549, + "size": 133 + }, + { + "direction": "sent", + "payload": "{\"type\":6,\"object\":\"jkfrontendchannel\",\"method\":\"receiveText\",\"args\":[\"{\\\"request_id\\\":122,\\\"arguments\\\":[],\\\"method\\\":1385}\"],\"id\":121}", + "timestamp": 1768927896557, + "size": 136 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1207,\\\"method_name\\\":\\\"OnLoggedOut\\\",\\\"request_id\\\":104,\\\"response\\\":{\\\"process_status\\\":\\\"Success\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896587, + "size": 179 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":103,\"type\":10}", + "timestamp": 1768927896589, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":105,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896589, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":104,\"type\":10}", + "timestamp": 1768927896589, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":106,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896589, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":105,\"type\":10}", + "timestamp": 1768927896589, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":107,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896589, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":106,\"type\":10}", + "timestamp": 1768927896589, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":108,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896589, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":107,\"type\":10}", + "timestamp": 1768927896589, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":109,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896589, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":108,\"type\":10}", + "timestamp": 1768927896589, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":110,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896590, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":109,\"type\":10}", + "timestamp": 1768927896590, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":111,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896590, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":110,\"type\":10}", + "timestamp": 1768927896590, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":112,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896590, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":111,\"type\":10}", + "timestamp": 1768927896590, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1385,\\\"method_name\\\":\\\"VSTListTrackAssignments\\\",\\\"request_id\\\":113,\\\"response\\\":{\\\"vsts\\\":[]}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896590, + "size": 172 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":112,\"type\":10}", + "timestamp": 1768927896590, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":114,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896590, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":113,\"type\":10}", + "timestamp": 1768927896590, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":115,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896591, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":114,\"type\":10}", + "timestamp": 1768927896591, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":116,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896591, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":115,\"type\":10}", + "timestamp": 1768927896591, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":117,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896591, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":116,\"type\":10}", + "timestamp": 1768927896591, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":118,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896591, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":117,\"type\":10}", + "timestamp": 1768927896591, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":119,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896591, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":118,\"type\":10}", + "timestamp": 1768927896591, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":120,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896592, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":119,\"type\":10}", + "timestamp": 1768927896592, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":0,\\\"method_name\\\":\\\"\\\",\\\"request_id\\\":121,\\\"response\\\":{\\\"0\\\":\\\"Not a valid method\\\"}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896593, + "size": 163 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":120,\"type\":10}", + "timestamp": 1768927896593, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927896707, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1385,\\\"method_name\\\":\\\"VSTListTrackAssignments\\\",\\\"request_id\\\":122,\\\"response\\\":{\\\"vsts\\\":[]}}\"],\"object\":\"jkfrontendchannel\",\"signal\":5,\"type\":1}", + "timestamp": 1768927896708, + "size": 172 + }, + { + "direction": "received", + "payload": "{\"data\":null,\"id\":121,\"type\":10}", + "timestamp": 1768927896708, + "size": 32 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927896848, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927897028, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1122,\\\"method_name\\\":\\\"getConnectionDetail\\\",\\\"request_id\\\":43622,\\\"response\\\":[{\\\"audio\\\":{\\\"acpu\\\":3.257441520690918,\\\"audio_chat_in\\\":\\\"MacBook Pro Microphone\\\",\\\"audio_cha...", + "timestamp": 1768927897032, + "size": 1256 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1122,\\\"method_name\\\":\\\"getConnectionDetail\\\",\\\"request_id\\\":43623,\\\"response\\\":[{\\\"audio\\\":{\\\"acpu\\\":3.257441520690918,\\\"audio_chat_in\\\":\\\"MacBook Pro Microphone\\\",\\\"audio_cha...", + "timestamp": 1768927897032, + "size": 1256 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927897250, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927897440, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927897641, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927897838, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927898040, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1122,\\\"method_name\\\":\\\"getConnectionDetail\\\",\\\"request_id\\\":43624,\\\"response\\\":[{\\\"audio\\\":{\\\"acpu\\\":2.1440341472625732,\\\"audio_chat_in\\\":\\\"MacBook Pro Microphone\\\",\\\"audio_ch...", + "timestamp": 1768927898042, + "size": 1257 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"method_id\\\":1122,\\\"method_name\\\":\\\"getConnectionDetail\\\",\\\"request_id\\\":43625,\\\"response\\\":[{\\\"audio\\\":{\\\"acpu\\\":2.1440341472625732,\\\"audio_chat_in\\\":\\\"MacBook Pro Microphone\\\",\\\"audio_ch...", + "timestamp": 1768927898042, + "size": 1257 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927898231, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927898428, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927898625, + "size": 2732 + }, + { + "direction": "received", + "payload": "{\"args\":[\"{\\\"event_id\\\":3006,\\\"response\\\":{\\\"execute_script\\\":\\\"JK.HandleBridgeCallback2([\\\\n [\\\\n \\\\\\\"vu\\\\\\\",\\\\n \\\\\\\"7fe6542c-5da3-4bd0-b3cf-4bbf356c682b\\\\\\\",\\\\n false,\\\\n ...", + "timestamp": 1768927898953, + "size": 2732 + } + ], + "closed": false + }, + { + "url": "ws://localhost:6767/?channel_id=96b32dc5-15ab-4ff6-dcaa-5922d2708ed6&token=CKXGCTBxfdGG12oXACOEYA&client_type=client&client_id=8d64a3b0-2f34-48c1-8199-74766ad6b1ac&machine=1b4d0ddbf9c1d7cd0a311465676d86a5892a36ea&os=MacOSX-M&product=JamClientModern&udp_reachable=false", + "timestamp": 1768927895325, + "isNativeClient": false, + "isServerConnection": false, + "messages": [ + { + "direction": "sent", + "payload": "{\"type\":\"LOGIN\",\"route_to\":\"server\",\"login\":{\"token\":\"CKXGCTBxfdGG12oXACOEYA\",\"client_id\":\"8d64a3b0-2f34-48c1-8199-74766ad6b1ac\",\"client_type\":\"browser\"}}", + "timestamp": 1768927895444, + "size": 154 + }, + { + "direction": "received", + "payload": "{\"type\":\"LOGIN_ACK\",\"route_to\":\"client\",\"login_ack\":{\"public_ip\":\"127.0.0.1\",\"client_id\":\"8d64a3b0-2f34-48c1-8199-74766ad6b1ac\",\"token\":\"CKXGCTBxfdGG12oXACOEYA\",\"heartbeat_interval\":20,\"reconnected\":f...", + "timestamp": 1768927895445, + "size": 565 + }, + { + "direction": "received", + "payload": "{\"type\":\"LOGIN_ACK\",\"route_to\":\"client\",\"login_ack\":{\"public_ip\":\"127.0.0.1\",\"client_id\":\"8d64a3b0-2f34-48c1-8199-74766ad6b1ac\",\"token\":\"CKXGCTBxfdGG12oXACOEYA\",\"heartbeat_interval\":20,\"reconnected\":f...", + "timestamp": 1768927895460, + "size": 565 + }, + { + "direction": "received", + "payload": "{\"type\":\"SESSION_JOIN\",\"route_to\":\"user:27bd4a30-d1b8-4eea-8454-01a104d59381\",\"session_join\":{\"session_id\":\"c2682005-d64f-4f2e-9e72-b9017c0097fc\",\"msg\":\"Nuwan Chaturanga has joined the session.\",\"trac...", + "timestamp": 1768927895725, + "size": 329 + } + ], + "closed": false + }, + { + "url": "ws://www.jamkazam.local:6767/websocket?channel_id=c8b6b7c5-b0d6-49d9-d058-08ae47c8ff7f&token=CKXGCTBxfdGG12oXACOEYA&client_type=browser&client_id=&machine=&os=MacOSX&udp_reachable=", + "timestamp": 1768927896521, + "isNativeClient": false, + "isServerConnection": true, + "messages": [], + "closed": true, + "closedAt": 1768927896586 + } +] \ No newline at end of file diff --git a/jam-ui/test/test-results/e2e/session-interface.png b/jam-ui/test/test-results/e2e/session-interface.png new file mode 100644 index 0000000000000000000000000000000000000000..14e1631232288dc1310959a845e222abfa8aff42 GIT binary patch literal 70675 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
-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

Kip{dY@uoa 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 + requestBody?: any; + responseStatus?: number; + responseHeaders?: Record; + responseBody?: any; + duration?: number; +} + +export class APIInterceptor { + private calls: APICall[] = []; + private pendingRequests: Map = new Map(); + + /** + * Start intercepting API calls on the given page + */ + intercept(page: Page) { + page.on('request', (request: Request) => { + this.recordRequest(request); + }); + + page.on('response', async (response: Response) => { + await this.recordResponse(response); + }); + } + + /** + * Record an API request + */ + private recordRequest(request: Request) { + const url = request.url(); + + // Only capture API calls + if (!url.includes('/api/')) { + return; + } + + const parsedUrl = new URL(url); + const call: APICall = { + method: request.method(), + url: url, + pathname: parsedUrl.pathname, + timestamp: Date.now(), + requestHeaders: request.headers(), + }; + + // Try to capture request body + try { + const postData = request.postData(); + if (postData) { + try { + call.requestBody = JSON.parse(postData); + } catch { + call.requestBody = postData; + } + } + } catch { + // Ignore if we can't get post data + } + + // Store as pending until we get the response + this.pendingRequests.set(url, call); + } + + /** + * Record an API response and merge with request data + */ + private async recordResponse(response: Response) { + const url = response.url(); + + // Only capture API calls + if (!url.includes('/api/')) { + return; + } + + const pendingCall = this.pendingRequests.get(url); + + if (pendingCall) { + // Calculate duration + pendingCall.duration = Date.now() - pendingCall.timestamp; + pendingCall.responseStatus = response.status(); + pendingCall.responseHeaders = response.headers(); + + // Try to capture response body + try { + const contentType = response.headers()['content-type'] || ''; + if (contentType.includes('application/json')) { + pendingCall.responseBody = await response.json(); + } + } catch { + // Ignore if we can't parse response + } + + this.calls.push(pendingCall); + this.pendingRequests.delete(url); + } else { + // Response without matching request - create minimal record + const parsedUrl = new URL(url); + this.calls.push({ + method: 'UNKNOWN', + url: url, + pathname: parsedUrl.pathname, + timestamp: Date.now(), + responseStatus: response.status(), + responseHeaders: response.headers(), + }); + } + } + + /** + * Get all captured API calls + */ + getCalls(): APICall[] { + return this.calls; + } + + /** + * Get calls filtered by method + */ + getCallsByMethod(method: string): APICall[] { + return this.calls.filter(call => call.method === method); + } + + /** + * Get calls filtered by pathname pattern + */ + getCallsByPath(pattern: string | RegExp): APICall[] { + if (typeof pattern === 'string') { + return this.calls.filter(call => call.pathname.includes(pattern)); + } else { + return this.calls.filter(call => pattern.test(call.pathname)); + } + } + + /** + * Get unique endpoints called + */ + getUniqueEndpoints(): string[] { + const endpoints = new Set(); + for (const call of this.calls) { + endpoints.add(`${call.method} ${call.pathname}`); + } + return Array.from(endpoints); + } + + /** + * Reset the interceptor + */ + reset() { + this.calls = []; + this.pendingRequests.clear(); + } + + /** + * Export calls to JSON + */ + toJSON(): string { + return JSON.stringify(this.calls, null, 2); + } +} diff --git a/jam-ui/test/utils/sequence-comparator.ts b/jam-ui/test/utils/sequence-comparator.ts new file mode 100644 index 000000000..740af5aba --- /dev/null +++ b/jam-ui/test/utils/sequence-comparator.ts @@ -0,0 +1,293 @@ +import { APICall } from './api-interceptor'; + +export interface ComparisonResult { + matches: boolean; + totalCalls: number; + matchedCalls: number; + missingCalls: EndpointMismatch[]; + extraCalls: EndpointMismatch[]; + outOfOrderCalls: OrderMismatch[]; + timingVariances: TimingVariance[]; + report: string; +} + +export interface EndpointMismatch { + endpoint: string; + expectedCount: number; + actualCount: number; +} + +export interface OrderMismatch { + endpoint: string; + expectedPosition: number; + actualPosition: number; + deviation: number; +} + +export interface TimingVariance { + endpoint: string; + expectedTiming: number; + actualTiming: number; + variance: number; +} + +/** + * Compare two API call sequences + */ +export function compareAPISequences( + actual: APICall[], + expected: APICall[] +): ComparisonResult { + const missing: EndpointMismatch[] = []; + const extra: EndpointMismatch[] = []; + const outOfOrder: OrderMismatch[] = []; + const timingVariances: TimingVariance[] = []; + + // Build endpoint maps + const actualEndpoints = buildEndpointMap(actual); + const expectedEndpoints = buildEndpointMap(expected); + + // Find missing calls (in expected but not in actual) + for (const [endpoint, expectedCalls] of expectedEndpoints.entries()) { + const actualCalls = actualEndpoints.get(endpoint) || []; + if (actualCalls.length === 0) { + missing.push({ + endpoint, + expectedCount: expectedCalls.length, + actualCount: 0, + }); + } else if (actualCalls.length < expectedCalls.length) { + missing.push({ + endpoint, + expectedCount: expectedCalls.length, + actualCount: actualCalls.length, + }); + } + } + + // Find extra calls (in actual but not in expected) + for (const [endpoint, actualCalls] of actualEndpoints.entries()) { + const expectedCalls = expectedEndpoints.get(endpoint) || []; + if (expectedCalls.length === 0) { + extra.push({ + endpoint, + expectedCount: 0, + actualCount: actualCalls.length, + }); + } else if (actualCalls.length > expectedCalls.length) { + extra.push({ + endpoint, + expectedCount: expectedCalls.length, + actualCount: actualCalls.length, + }); + } + } + + // Check order + const orderMismatches = checkOrder(actual, expected); + outOfOrder.push(...orderMismatches); + + // Check timing + const timings = checkTimingVariance(actual, expected); + timingVariances.push(...timings); + + // Calculate match percentage + const totalExpected = expected.length; + const matched = totalExpected - missing.reduce((sum, m) => sum + (m.expectedCount - m.actualCount), 0); + const matchPercentage = totalExpected > 0 ? (matched / totalExpected) * 100 : 0; + + // Generate report + const report = generateReport({ + matches: matchPercentage >= 95, + totalCalls: actual.length, + matchedCalls: matched, + missingCalls: missing, + extraCalls: extra, + outOfOrderCalls: outOfOrder, + timingVariances: timingVariances, + report: '', + }); + + return { + matches: matchPercentage >= 95, + totalCalls: actual.length, + matchedCalls: matched, + missingCalls: missing, + extraCalls: extra, + outOfOrderCalls: outOfOrder, + timingVariances: timingVariances, + report, + }; +} + +/** + * Build a map of endpoint -> calls + */ +function buildEndpointMap(calls: APICall[]): Map { + const map = new Map(); + for (const call of calls) { + const endpoint = `${call.method} ${call.pathname}`; + if (!map.has(endpoint)) { + map.set(endpoint, []); + } + map.get(endpoint)!.push(call); + } + return map; +} + +/** + * Check if calls are in the same order + */ +function checkOrder(actual: APICall[], expected: APICall[]): OrderMismatch[] { + const mismatches: OrderMismatch[] = []; + + // Create a sequence of endpoints for both + const actualSequence = actual.map(c => `${c.method} ${c.pathname}`); + const expectedSequence = expected.map(c => `${c.method} ${c.pathname}`); + + // For each expected endpoint, find its position in actual + for (let i = 0; i < expectedSequence.length; i++) { + const endpoint = expectedSequence[i]; + const actualIndex = actualSequence.indexOf(endpoint); + + if (actualIndex !== -1) { + const deviation = Math.abs(actualIndex - i); + // Only report if deviation is significant (more than 3 positions) + if (deviation > 3) { + mismatches.push({ + endpoint, + expectedPosition: i, + actualPosition: actualIndex, + deviation, + }); + } + } + } + + return mismatches; +} + +/** + * Check timing variance between calls + */ +function checkTimingVariance(actual: APICall[], expected: APICall[]): TimingVariance[] { + const variances: TimingVariance[] = []; + + if (actual.length === 0 || expected.length === 0) { + return variances; + } + + // Calculate relative timings (time from first call) + const actualStartTime = actual[0].timestamp; + const expectedStartTime = expected[0].timestamp; + + const actualTimings = new Map(); + const expectedTimings = new Map(); + + for (const call of actual) { + const endpoint = `${call.method} ${call.pathname}`; + const relativeTime = call.timestamp - actualStartTime; + if (!actualTimings.has(endpoint)) { + actualTimings.set(endpoint, []); + } + actualTimings.get(endpoint)!.push(relativeTime); + } + + for (const call of expected) { + const endpoint = `${call.method} ${call.pathname}`; + const relativeTime = call.timestamp - expectedStartTime; + if (!expectedTimings.has(endpoint)) { + expectedTimings.set(endpoint, []); + } + expectedTimings.get(endpoint)!.push(relativeTime); + } + + // Compare average timings + for (const [endpoint, expectedTimes] of expectedTimings.entries()) { + const actualTimes = actualTimings.get(endpoint); + if (actualTimes && actualTimes.length > 0) { + const avgExpected = expectedTimes.reduce((a, b) => a + b, 0) / expectedTimes.length; + const avgActual = actualTimes.reduce((a, b) => a + b, 0) / actualTimes.length; + const variance = Math.abs(avgActual - avgExpected); + + // Only report if variance is significant (more than 500ms) + if (variance > 500) { + variances.push({ + endpoint, + expectedTiming: avgExpected, + actualTiming: avgActual, + variance, + }); + } + } + } + + return variances; +} + +/** + * Generate a human-readable comparison report + */ +function generateReport(result: ComparisonResult): string { + let report = '# API Sequence Comparison Report\n\n'; + + report += `## Summary\n\n`; + report += `- **Match Status:** ${result.matches ? 'āœ… PASS' : 'āŒ FAIL'}\n`; + report += `- **Total Calls:** ${result.totalCalls}\n`; + report += `- **Matched Calls:** ${result.matchedCalls}\n`; + report += `- **Match Percentage:** ${((result.matchedCalls / result.totalCalls) * 100).toFixed(1)}%\n\n`; + + if (result.missingCalls.length > 0) { + report += `## āŒ Missing API Calls\n\n`; + report += `The following expected API calls are missing or called fewer times:\n\n`; + for (const missing of result.missingCalls) { + report += `- **${missing.endpoint}**\n`; + report += ` - Expected: ${missing.expectedCount} call(s)\n`; + report += ` - Actual: ${missing.actualCount} call(s)\n`; + report += ` - Missing: ${missing.expectedCount - missing.actualCount} call(s)\n\n`; + } + } + + if (result.extraCalls.length > 0) { + report += `## āš ļø Extra API Calls\n\n`; + report += `The following API calls were made but not expected:\n\n`; + for (const extra of result.extraCalls) { + report += `- **${extra.endpoint}**\n`; + report += ` - Expected: ${extra.expectedCount} call(s)\n`; + report += ` - Actual: ${extra.actualCount} call(s)\n`; + report += ` - Extra: ${extra.actualCount - extra.expectedCount} call(s)\n\n`; + } + } + + if (result.outOfOrderCalls.length > 0) { + report += `## āš ļø Out of Order Calls\n\n`; + report += `The following API calls occurred in a different order:\n\n`; + for (const order of result.outOfOrderCalls) { + report += `- **${order.endpoint}**\n`; + report += ` - Expected position: ${order.expectedPosition}\n`; + report += ` - Actual position: ${order.actualPosition}\n`; + report += ` - Deviation: ${order.deviation} positions\n\n`; + } + } + + if (result.timingVariances.length > 0) { + report += `## ā±ļø Timing Variances\n\n`; + report += `The following API calls have significant timing differences:\n\n`; + for (const timing of result.timingVariances) { + report += `- **${timing.endpoint}**\n`; + report += ` - Expected timing: ${timing.expectedTiming.toFixed(0)}ms\n`; + report += ` - Actual timing: ${timing.actualTiming.toFixed(0)}ms\n`; + report += ` - Variance: ${timing.variance.toFixed(0)}ms\n\n`; + } + } + + if (result.matches) { + report += `## āœ… Conclusion\n\n`; + report += `The API sequence matches the expected baseline with acceptable variance.\n`; + } else { + report += `## āŒ Conclusion\n\n`; + report += `The API sequence does NOT match the expected baseline. Please review the mismatches above.\n`; + } + + return report; +} diff --git a/jam-ui/test/utils/test-helpers.ts b/jam-ui/test/utils/test-helpers.ts new file mode 100644 index 000000000..031030282 --- /dev/null +++ b/jam-ui/test/utils/test-helpers.ts @@ -0,0 +1,387 @@ +import { Page, expect } from '@playwright/test'; + +export interface LoginCredentials { + email: string; + password: string; +} + +export interface SessionFormData { + sessionName?: string; + sessionType?: 'private' | 'public' | 'friends'; + description?: string; +} + +/** + * Login to jam-ui application + */ +export async function loginToJamUI( + page: Page, + credentials: LoginCredentials = { + email: 'nuwan@jamkazam.com', + password: 'jam123', + } +): Promise { + await page.goto('http://beta.jamkazam.local:4000/'); + + // Wait for login form to be visible + await page.waitForSelector('input[name="email"], input[type="email"], #email', { + timeout: 10000, + }); + + // Fill in credentials - try multiple selectors + const emailSelectors = ['input[name="email"]', 'input[type="email"]', '#email', '[placeholder*="email" i]']; + for (const selector of emailSelectors) { + try { + const element = await page.$(selector); + if (element) { + await page.fill(selector, credentials.email); + break; + } + } catch { + continue; + } + } + + const passwordSelectors = ['input[name="password"]', 'input[type="password"]', '#password']; + for (const selector of passwordSelectors) { + try { + const element = await page.$(selector); + if (element) { + await page.fill(selector, credentials.password); + break; + } + } catch { + continue; + } + } + + // Submit form + const submitSelectors = [ + 'button[type="submit"]', + 'input[type="submit"]', + 'button:has-text("Sign In")', + 'button:has-text("Login")', + ]; + for (const selector of submitSelectors) { + try { + const element = await page.$(selector); + if (element) { + await page.click(selector); + break; + } + } catch { + continue; + } + } + + // Wait for navigation after login + await page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => {}); + await page.waitForTimeout(2000); +} + +/** + * Navigate to session creation page + */ +export async function navigateToSessionCreation(page: Page): Promise { + // Try multiple selectors for the create session link + const createSessionSelectors = [ + 'text=create session', + 'text=Create Session', + 'a:has-text("create session")', + 'a:has-text("Create Session")', + '[href*="session"][href*="create"]', + '[data-testid="create-session"]', + ]; + + let clicked = false; + for (const selector of createSessionSelectors) { + try { + const element = await page.$(selector); + if (element) { + await page.click(selector); + clicked = true; + break; + } + } catch { + continue; + } + } + + if (!clicked) { + throw new Error('Could not find "Create Session" link'); + } + + await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {}); + await page.waitForTimeout(1000); +} + +/** + * Fill and submit session creation form (jam-ui uses form-based creation) + */ +export async function fillSessionForm(page: Page, formData: SessionFormData = {}): Promise { + const { + sessionName = 'Test Session ' + Date.now(), + sessionType = 'private', + description = 'Automated test session', + } = formData; + + console.log('Filling session creation form...'); + + // Wait for form to be visible + await page.waitForTimeout(1000); + + // Fill session name - try multiple selectors + const nameSelectors = [ + 'input[name="session_name"]', + 'input[name="name"]', + 'input[name="sessionName"]', + '#session_name', + '#name', + '#sessionName', + 'input[placeholder*="name" i]', + ]; + + let nameFilled = false; + for (const selector of nameSelectors) { + try { + const element = await page.$(selector); + if (element && await element.isVisible()) { + await page.fill(selector, sessionName); + console.log(` Filled session name using: ${selector}`); + nameFilled = true; + break; + } + } catch { + continue; + } + } + + if (!nameFilled) { + console.log(' Warning: Could not find session name field'); + } + + // Select session type if there's a dropdown + const typeSelectors = [ + 'select[name="session_type"]', + 'select[name="type"]', + 'select[name="sessionType"]', + '#session_type', + '#type', + '#sessionType', + ]; + + for (const selector of typeSelectors) { + try { + const element = await page.$(selector); + if (element && await element.isVisible()) { + await page.selectOption(selector, sessionType); + console.log(` Selected session type: ${sessionType}`); + break; + } + } catch { + continue; + } + } + + // Try clicking radio buttons for session type + const radioSelectors = [ + `input[type="radio"][value="${sessionType}"]`, + `input[type="radio"][id*="${sessionType}" i]`, + `label:has-text("${sessionType}") input[type="radio"]`, + ]; + + for (const selector of radioSelectors) { + try { + const element = await page.$(selector); + if (element && await element.isVisible()) { + await page.click(selector); + console.log(` Clicked radio for: ${sessionType}`); + break; + } + } catch { + continue; + } + } + + // Fill description if field exists + const descSelectors = [ + 'textarea[name="description"]', + 'input[name="description"]', + 'textarea[name="notes"]', + '#description', + '#notes', + ]; + + for (const selector of descSelectors) { + try { + const element = await page.$(selector); + if (element && await element.isVisible()) { + await page.fill(selector, description); + console.log(` Filled description`); + break; + } + } catch { + continue; + } + } + + await page.waitForTimeout(500); + + // Submit form + console.log('Submitting form...'); + const submitSelectors = [ + 'button[type="submit"]', + 'input[type="submit"]', + 'button:has-text("Create Session")', + 'button:has-text("Create")', + 'button:has-text("Submit")', + 'button:has-text("Start Session")', + ]; + + let submitted = false; + for (const selector of submitSelectors) { + try { + const element = await page.$(selector); + if (element && await element.isVisible()) { + await page.click(selector); + console.log(` Clicked submit button: ${selector}`); + submitted = true; + break; + } + } catch { + continue; + } + } + + if (!submitted) { + throw new Error('Could not find submit button for session creation form'); + } + + await page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => {}); + await page.waitForTimeout(3000); + + console.log('Form submitted, waiting for session to load...'); +} + +/** + * Create and join session using jam-ui's form-based approach + * (jam-ui doesn't have Quick Start buttons - it uses a form) + */ +export async function createAndJoinSession( + page: Page, + sessionData: SessionFormData = {} +): Promise { + console.log('\nCreating session using jam-ui form...'); + + // Navigate to Create Session if not already there + const currentUrl = page.url(); + if (!currentUrl.includes('session') || !currentUrl.includes('create')) { + console.log('Navigating to Create Session page...'); + await navigateToSessionCreation(page); + } + + // Fill and submit the session creation form + await fillSessionForm(page, { + sessionType: 'private', + ...sessionData, + }); + + console.log('Session creation complete, should be in session interface now'); +} + +/** + * Legacy function for compatibility - jam-ui uses form-based creation + * @deprecated Use createAndJoinSession instead + */ +export async function clickQuickStart(page: Page, type: 'private' | 'public' | 'friends' = 'private'): Promise { + console.log('Note: jam-ui uses form-based session creation, not Quick Start buttons'); + await createAndJoinSession(page, { sessionType: type }); +} + +/** + * Verify session interface is loaded + */ +export async function verifySessionInterfaceLoaded(page: Page): Promise { + // Check for key session interface elements + const requiredElements = [ + { name: 'audio inputs', selectors: ['text=audio inputs', 'text=Audio Inputs', '[data-testid="audio-inputs"]'] }, + { name: 'personal mix', selectors: ['text=personal mix', 'text=Personal Mix', '[data-testid="personal-mix"]'] }, + { name: 'LEAVE button', selectors: ['text=LEAVE', 'button:has-text("LEAVE")', '[data-testid="leave-button"]'] }, + ]; + + for (const element of requiredElements) { + let found = false; + for (const selector of element.selectors) { + try { + const el = await page.$(selector); + if (el) { + found = true; + break; + } + } catch { + continue; + } + } + + if (!found) { + console.warn(`Expected element not found: ${element.name}`); + } + } +} + +/** + * Wait for API calls to settle + */ +export async function waitForAPICalls(page: Page, timeout: number = 3000): Promise { + await page.waitForLoadState('networkidle', { timeout }).catch(() => {}); + await page.waitForTimeout(1000); +} + +/** + * Dismiss any modals or overlays + */ +export async function dismissModals(page: Page): Promise { + // Try pressing Escape + await page.keyboard.press('Escape'); + await page.waitForTimeout(500); + + // Try to remove dialog overlays + await page.evaluate(() => { + const overlays = document.querySelectorAll('.dialog-overlay, .modal-overlay, [role="dialog"]'); + overlays.forEach(overlay => { + (overlay as HTMLElement).remove(); + }); + }); + + await page.waitForTimeout(500); +} + +/** + * Extract session ID from current URL or page content + */ +export async function extractSessionId(page: Page): Promise { + // Try to extract from URL + const url = page.url(); + const urlMatch = url.match(/session[s]?\/([a-f0-9-]{36})/i); + if (urlMatch) { + return urlMatch[1]; + } + + // Try to extract from page content + const sessionId = await page.evaluate(() => { + // Look for session ID in data attributes + const sessionEl = document.querySelector('[data-session-id]'); + if (sessionEl) { + return sessionEl.getAttribute('data-session-id'); + } + + // Look for session ID in window object + if ((window as any).sessionId) { + return (window as any).sessionId; + } + + return null; + }); + + return sessionId; +} diff --git a/jam-ui/test/utils/websocket-monitor.ts b/jam-ui/test/utils/websocket-monitor.ts new file mode 100644 index 000000000..79148262a --- /dev/null +++ b/jam-ui/test/utils/websocket-monitor.ts @@ -0,0 +1,179 @@ +import { Page, WebSocket } from '@playwright/test'; + +export interface WSConnection { + url: string; + timestamp: number; + isNativeClient: boolean; + isServerConnection: boolean; + messages: WSMessage[]; + closed: boolean; + closedAt?: number; +} + +export interface WSMessage { + direction: 'sent' | 'received'; + payload: string; + timestamp: number; + size: number; +} + +export class WebSocketMonitor { + private connections: WSConnection[] = []; + private activeConnections: Map = new Map(); + + /** + * Start monitoring WebSocket connections on the given page + */ + monitor(page: Page) { + page.on('websocket', (ws: WebSocket) => { + this.recordConnection(ws); + }); + } + + /** + * Record a WebSocket connection and its messages + */ + private recordConnection(ws: WebSocket) { + const url = ws.url(); + const timestamp = Date.now(); + + const connection: WSConnection = { + url: url, + timestamp: timestamp, + isNativeClient: url.includes('localhost:3060'), + isServerConnection: url.includes('jamkazam.local:6767') || url.includes('jamkazam.com:6767'), + messages: [], + closed: false, + }; + + console.log(`[WebSocket Monitor] Connection opened: ${url}`); + + // Listen for sent messages + ws.on('framesent', frame => { + const payload = frame.payload.toString(); + const message: WSMessage = { + direction: 'sent', + payload: payload, + timestamp: Date.now(), + size: payload.length, + }; + connection.messages.push(message); + }); + + // Listen for received messages + ws.on('framereceived', frame => { + const payload = frame.payload.toString(); + const message: WSMessage = { + direction: 'received', + payload: payload, + timestamp: Date.now(), + size: payload.length, + }; + connection.messages.push(message); + }); + + // Listen for close + ws.on('close', () => { + connection.closed = true; + connection.closedAt = Date.now(); + console.log(`[WebSocket Monitor] Connection closed: ${url}`); + }); + + this.connections.push(connection); + this.activeConnections.set(url, connection); + } + + /** + * Get all connections + */ + getConnections(): WSConnection[] { + return this.connections; + } + + /** + * Get active (non-closed) connections + */ + getActiveConnections(): WSConnection[] { + return this.connections.filter(conn => !conn.closed); + } + + /** + * Get native client connection (ws://localhost:3060/) + */ + getNativeClientConnection(): WSConnection | undefined { + return this.connections.find(conn => conn.isNativeClient); + } + + /** + * Get server connection (ws://jamkazam.local:6767/websocket) + */ + getServerConnection(): WSConnection | undefined { + return this.connections.find(conn => conn.isServerConnection); + } + + /** + * Get connection count + */ + getConnectionCount(): number { + return this.connections.length; + } + + /** + * Get total message count across all connections + */ + getTotalMessageCount(): number { + return this.connections.reduce((sum, conn) => sum + conn.messages.length, 0); + } + + /** + * Get messages from a specific connection + */ + getMessagesFromConnection(url: string): WSMessage[] { + const conn = this.connections.find(c => c.url === url); + return conn ? conn.messages : []; + } + + /** + * Verify dual WebSocket connections are established + */ + verifyDualConnections(): { + hasNativeClient: boolean; + hasServerConnection: boolean; + bothEstablished: boolean; + } { + const hasNativeClient = this.getNativeClientConnection() !== undefined; + const hasServerConnection = this.getServerConnection() !== undefined; + + return { + hasNativeClient, + hasServerConnection, + bothEstablished: hasNativeClient && hasServerConnection, + }; + } + + /** + * Reset the monitor + */ + reset() { + this.connections = []; + this.activeConnections.clear(); + } + + /** + * Export connections to JSON + */ + toJSON(): string { + return JSON.stringify( + this.connections.map(conn => ({ + ...conn, + // Truncate messages for readability + messages: conn.messages.map(msg => ({ + ...msg, + payload: msg.payload.length > 200 ? msg.payload.substring(0, 200) + '...' : msg.payload, + })), + })), + null, + 2 + ); + } +} diff --git a/jam-ui/test/verify-session-flow-steps.spec.ts b/jam-ui/test/verify-session-flow-steps.spec.ts new file mode 100644 index 000000000..57dbaee65 --- /dev/null +++ b/jam-ui/test/verify-session-flow-steps.spec.ts @@ -0,0 +1,497 @@ +import { chromium } from '@playwright/test'; +import * as fs from 'fs'; +import * as path from 'path'; + +/** + * Detailed step-by-step verification of the session join flow + * This script goes through each step individually and captures API calls at each stage + */ + +interface StepCapture { + stepNumber: number; + stepName: string; + apiCalls: any[]; + wsMessages: any[]; + screenshots: string[]; + timestamp: string; +} + +async function verifySessionFlow() { + console.log('='.repeat(80)); + console.log('SESSION FLOW STEP-BY-STEP VERIFICATION'); + console.log('='.repeat(80)); + console.log(); + + const browser = await chromium.launch({ + headless: false, + slowMo: 800, + }); + + const testResultsDir = path.join(__dirname, '../test-results/step-verification'); + if (!fs.existsSync(testResultsDir)) { + fs.mkdirSync(testResultsDir, { recursive: true }); + } + + const context = await browser.newContext({ + ignoreHTTPSErrors: true, + }); + + const page = await context.newPage(); + + const stepCaptures: StepCapture[] = []; + let currentStepApiCalls: any[] = []; + let currentStepWsMessages: any[] = []; + + // Listen to all network activity + page.on('request', request => { + const url = request.url(); + if (url.includes('/api/')) { + currentStepApiCalls.push({ + type: 'request', + method: request.method(), + url: url, + timestamp: new Date().toISOString(), + }); + console.log(` [API] ${request.method()} ${url}`); + } + }); + + page.on('response', async response => { + const url = response.url(); + if (url.includes('/api/')) { + let body = null; + try { + const contentType = response.headers()['content-type'] || ''; + if (contentType.includes('application/json')) { + body = await response.json(); + } + } catch (e) { + // Ignore + } + + currentStepApiCalls.push({ + type: 'response', + status: response.status(), + url: url, + body: body, + timestamp: new Date().toISOString(), + }); + } + }); + + page.on('websocket', ws => { + console.log(` [WebSocket] Connected: ${ws.url()}`); + currentStepWsMessages.push({ + event: 'open', + url: ws.url(), + timestamp: new Date().toISOString(), + }); + + ws.on('framesent', frame => { + currentStepWsMessages.push({ + event: 'sent', + payload: frame.payload.toString().substring(0, 200), + timestamp: new Date().toISOString(), + }); + }); + + ws.on('framereceived', frame => { + currentStepWsMessages.push({ + event: 'received', + payload: frame.payload.toString().substring(0, 200), + timestamp: new Date().toISOString(), + }); + }); + }); + + function saveStepCapture(stepNumber: number, stepName: string) { + const capture: StepCapture = { + stepNumber, + stepName, + apiCalls: [...currentStepApiCalls], + wsMessages: [...currentStepWsMessages], + screenshots: [], + timestamp: new Date().toISOString(), + }; + + stepCaptures.push(capture); + + // Save individual step data + const stepDir = path.join(testResultsDir, `step-${stepNumber}`); + if (!fs.existsSync(stepDir)) { + fs.mkdirSync(stepDir, { recursive: true }); + } + + fs.writeFileSync( + path.join(stepDir, 'api-calls.json'), + JSON.stringify(currentStepApiCalls, null, 2) + ); + + fs.writeFileSync( + path.join(stepDir, 'ws-messages.json'), + JSON.stringify(currentStepWsMessages, null, 2) + ); + + console.log(` āœ“ Captured ${currentStepApiCalls.length} API calls`); + console.log(` āœ“ Captured ${currentStepWsMessages.length} WebSocket messages`); + + // Reset for next step + currentStepApiCalls = []; + currentStepWsMessages = []; + } + + try { + // STEP 1: User Authentication + console.log('\n' + '='.repeat(80)); + console.log('STEP 1: USER AUTHENTICATION'); + console.log('='.repeat(80)); + + console.log('Navigating to signin page...'); + await page.goto('http://www.jamkazam.local:3100/signin', { + waitUntil: 'networkidle', + timeout: 30000, + }); + + await page.screenshot({ + path: path.join(testResultsDir, 'step-1-signin-page.png'), + fullPage: true, + }); + + console.log('Filling in credentials...'); + await page.fill('input#session_email', 'nuwan@jamkazam.com'); + await page.fill('input#session_password', 'jam123'); + + console.log('Clicking sign in...'); + await page.click('input[type="submit"]'); + + console.log('Waiting for login to complete...'); + await page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => {}); + await page.waitForTimeout(3000); + + await page.screenshot({ + path: path.join(testResultsDir, 'step-1-after-login.png'), + fullPage: true, + }); + + saveStepCapture(1, 'User Authentication'); + + // STEP 2: Dashboard Load + console.log('\n' + '='.repeat(80)); + console.log('STEP 2: DASHBOARD LOAD'); + console.log('='.repeat(80)); + + console.log('Dashboard is loading (WebSocket connection should establish)...'); + await page.waitForTimeout(5000); // Wait for all dashboard data to load + + await page.screenshot({ + path: path.join(testResultsDir, 'step-2-dashboard-loaded.png'), + fullPage: true, + }); + + saveStepCapture(2, 'Dashboard Load'); + + // STEP 3: Skip Upgrade Modal + console.log('\n' + '='.repeat(80)); + console.log('STEP 3: SKIP UPGRADE MODAL'); + console.log('='.repeat(80)); + + console.log('Pressing Cmd+Shift+0 to dismiss upgrade modal...'); + await page.keyboard.press('Meta+Shift+Digit0'); + await page.waitForTimeout(2000); + + // Check if overlay still exists and try to dismiss it + const overlay = await page.$('.dialog-overlay'); + if (overlay) { + console.log('Overlay still present, trying to click it or escape...'); + await page.keyboard.press('Escape'); + await page.waitForTimeout(1000); + + // If still there, try clicking outside + const overlayStill = await page.$('.dialog-overlay'); + if (overlayStill) { + console.log('Trying to force-remove overlay...'); + await page.evaluate(() => { + const overlays = document.querySelectorAll('.dialog-overlay'); + overlays.forEach(o => o.remove()); + }); + await page.waitForTimeout(500); + } + } + + await page.screenshot({ + path: path.join(testResultsDir, 'step-3-modal-dismissed.png'), + fullPage: true, + }); + + saveStepCapture(3, 'Skip Upgrade Modal'); + + // STEP 4: Navigate to Create Session + console.log('\n' + '='.repeat(80)); + console.log('STEP 4: NAVIGATE TO CREATE SESSION'); + console.log('='.repeat(80)); + + console.log('Looking for Create Session button...'); + + // Remove any remaining overlays + await page.evaluate(() => { + const overlays = document.querySelectorAll('.dialog-overlay'); + overlays.forEach(o => o.remove()); + }); + await page.waitForTimeout(500); + + // Try multiple selectors + const createSessionSelectors = [ + 'text=create session', + 'h2:has-text("create session")', + '[data-testid="create-session"]', + 'button:has-text("Create Session")', + 'a:has-text("Create Session")', + 'div:has-text("Create Session")', + '.tile:has-text("Create Session")', + '[title*="Create Session"]', + ]; + + let sessionClicked = false; + for (const selector of createSessionSelectors) { + try { + const element = await page.$(selector); + if (element) { + console.log(`Found Create Session using: ${selector}`); + // Use force click to bypass any remaining overlays + await page.click(selector, { force: true }); + sessionClicked = true; + break; + } + } catch (e) { + console.log(`Selector ${selector} failed: ${e.message}`); + continue; + } + } + + if (!sessionClicked) { + console.warn('Could not find "Create Session" button - saving partial results...'); + } + + await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {}); + await page.waitForTimeout(2000); + + await page.screenshot({ + path: path.join(testResultsDir, 'step-4-session-page.png'), + fullPage: true, + }); + + saveStepCapture(4, 'Navigate to Create Session'); + + // STEP 5: Create Quick Start Session + console.log('\n' + '='.repeat(80)); + console.log('STEP 5: CREATE QUICK START SESSION'); + console.log('='.repeat(80)); + + console.log('Pressing Ctrl+Shift+0 to enable native client features...'); + await page.keyboard.press('Control+Shift+Digit0'); + await page.waitForTimeout(2000); + + await page.screenshot({ + path: path.join(testResultsDir, 'step-5-before-quickstart.png'), + fullPage: true, + }); + + console.log('Looking for Quick Start button...'); + const quickStartSelectors = [ + 'text=QUICK START PRIVATE', + 'text=QUICK START PUBLIC', + 'text=QUICK START FRIENDS', + 'button:has-text("QUICK START")', + 'button:has-text("Quick Start")', + '[data-testid="quick-start"]', + ]; + + let quickStartClicked = false; + for (const selector of quickStartSelectors) { + try { + const element = await page.$(selector); + if (element) { + console.log(`Found Quick Start button using: ${selector}`); + await page.click(selector, { force: true }); + quickStartClicked = true; + console.log('Quick Start button clicked!'); + break; + } + } catch (e) { + console.log(`Selector ${selector} failed: ${e.message}`); + continue; + } + } + + if (!quickStartClicked) { + console.warn('Could not find Quick Start button - trying generic button click'); + // Try to click any button with "QUICK START" text + try { + await page.evaluate(() => { + const buttons = Array.from(document.querySelectorAll('button')); + const quickStartBtn = buttons.find(btn => btn.textContent?.includes('QUICK START')); + if (quickStartBtn) { + (quickStartBtn as HTMLElement).click(); + return true; + } + return false; + }); + console.log('Clicked Quick Start via evaluate'); + quickStartClicked = true; + } catch (e) { + console.error('Failed to click Quick Start button'); + } + } + + console.log('Waiting for session to initialize...'); + await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {}); + await page.waitForTimeout(5000); // Wait for WebSocket messages + + await page.screenshot({ + path: path.join(testResultsDir, 'step-5-session-joined.png'), + fullPage: true, + }); + + saveStepCapture(5, 'Create Quick Start Session'); + + // Generate summary report + console.log('\n' + '='.repeat(80)); + console.log('GENERATING SUMMARY REPORT'); + console.log('='.repeat(80)); + + const report = generateReport(stepCaptures); + fs.writeFileSync(path.join(testResultsDir, 'VERIFICATION_REPORT.md'), report); + console.log(`āœ“ Report saved to: ${testResultsDir}/VERIFICATION_REPORT.md`); + + // Save complete capture + fs.writeFileSync( + path.join(testResultsDir, 'complete-capture.json'), + JSON.stringify(stepCaptures, null, 2) + ); + + console.log('\nKeeping browser open for 10 seconds for inspection...'); + await page.waitForTimeout(10000); + + } catch (error) { + console.error('\nāŒ Error during verification:', error); + await page.screenshot({ + path: path.join(testResultsDir, 'error-screenshot.png'), + fullPage: true, + }); + throw error; + } finally { + await context.close(); + await browser.close(); + } +} + +function generateReport(stepCaptures: StepCapture[]): string { + let report = `# Session Flow Verification Report + +**Generated:** ${new Date().toLocaleString()} + +## Summary + +This report documents the exact API calls and WebSocket messages that occur at each step of the session join flow. + +`; + + for (const step of stepCaptures) { + const apiRequests = step.apiCalls.filter(c => c.type === 'request'); + const uniqueEndpoints = new Set( + apiRequests.map(c => `${c.method} ${new URL(c.url).pathname}`) + ); + + report += ` +## Step ${step.stepNumber}: ${step.stepName} + +**Timestamp:** ${step.timestamp} + +### API Calls Made (${apiRequests.length} requests) + +`; + + if (uniqueEndpoints.size > 0) { + report += 'Unique endpoints called:\n'; + for (const endpoint of Array.from(uniqueEndpoints)) { + const count = apiRequests.filter( + c => `${c.method} ${new URL(c.url).pathname}` === endpoint + ).length; + report += `- ${endpoint}${count > 1 ? ` (${count} times)` : ''}\n`; + } + } else { + report += 'No API calls made during this step.\n'; + } + + report += ` +### WebSocket Activity + +- Total messages sent/received: ${step.wsMessages.length} +- WebSocket connection events: ${step.wsMessages.filter(m => m.event === 'open').length} + +`; + + report += ` +### Screenshots + +- Available at: \`step-${step.stepNumber}/\` + +--- + +`; + } + + // Add comparison section + report += ` +## Key Findings + +### Step-by-Step API Call Summary + +`; + + for (const step of stepCaptures) { + const apiRequests = step.apiCalls.filter(c => c.type === 'request'); + report += `**Step ${step.stepNumber} (${step.stepName}):** ${apiRequests.length} API calls\n`; + } + + report += ` + +### WebSocket Message Summary + +`; + + for (const step of stepCaptures) { + report += `**Step ${step.stepNumber} (${step.stepName}):** ${step.wsMessages.length} messages\n`; + } + + report += ` + +## Recommendations + +Based on this verification: + +1. Review the API calls at each step to ensure the migration plan accurately reflects them +2. Pay special attention to Step 5 (Create Quick Start Session) - this is where session creation happens +3. Verify WebSocket message sequences match between legacy and new implementation +4. Check if removing the separate "trick browser" step changed any API behavior + +## Next Steps + +1. Compare this capture with the original capture to identify any differences +2. Update the migration plan if any discrepancies are found +3. Use these findings to create more accurate Playwright tests +`; + + return report; +} + +// Run the verification +verifySessionFlow() + .then(() => { + console.log('\nāœ… Verification completed successfully!'); + process.exit(0); + }) + .catch(error => { + console.error('\nāŒ Verification failed:', error); + process.exit(1); + }); diff --git a/jam-ui/test/websocket-verification/ws-connection.spec.ts b/jam-ui/test/websocket-verification/ws-connection.spec.ts new file mode 100644 index 000000000..96cc6b819 --- /dev/null +++ b/jam-ui/test/websocket-verification/ws-connection.spec.ts @@ -0,0 +1,174 @@ +import { test, expect } from '@playwright/test'; +import { WebSocketMonitor } from '../utils/websocket-monitor'; +import { loginToJamUI, navigateToSessionCreation, fillSessionForm, waitForAPICalls } from '../utils/test-helpers'; +import * as fs from 'fs'; +import * as path from 'path'; + +test.describe('WebSocket Connection Verification', () => { + test('dual WebSocket connections are established during session join', async ({ page }) => { + const wsMonitor = new WebSocketMonitor(); + wsMonitor.monitor(page); + + // Login + await loginToJamUI(page); + await waitForAPICalls(page); + + // Navigate to session creation + await navigateToSessionCreation(page); + await waitForAPICalls(page); + + // Create session using form + await fillSessionForm(page); + await waitForAPICalls(page, 5000); + + // Verify connections + const verification = wsMonitor.verifyDualConnections(); + + console.log('\nWebSocket Connection Verification:'); + console.log(` Native client connection: ${verification.hasNativeClient ? 'YES' : 'NO'}`); + console.log(` Server connection: ${verification.hasServerConnection ? 'YES' : 'NO'}`); + console.log(` Both established: ${verification.bothEstablished ? 'YES' : 'NO'}`); + + const connections = wsMonitor.getConnections(); + console.log(`\nTotal connections: ${connections.length}`); + connections.forEach((conn, idx) => { + console.log(` ${idx + 1}. ${conn.url}`); + console.log(` Messages: ${conn.messages.length}`); + console.log(` Type: ${conn.isNativeClient ? 'Native Client' : conn.isServerConnection ? 'Server' : 'Unknown'}`); + }); + + // Save results + const resultsDir = path.join(__dirname, '../test-results/websocket-verification'); + if (!fs.existsSync(resultsDir)) { + fs.mkdirSync(resultsDir, { recursive: true }); + } + + fs.writeFileSync( + path.join(resultsDir, 'connections.json'), + wsMonitor.toJSON() + ); + + // Assertions + expect(verification.bothEstablished).toBe(true); + expect(wsMonitor.getConnectionCount()).toBeGreaterThanOrEqual(2); + }); + + test('native client connection is to localhost:3060', async ({ page }) => { + const wsMonitor = new WebSocketMonitor(); + wsMonitor.monitor(page); + + await loginToJamUI(page); + await navigateToSessionCreation(page); + await page.keyboard.press('Control+Shift+Digit0'); + await waitForAPICalls(page, 3000); + await clickQuickStart(page); + await waitForAPICalls(page, 5000); + + const nativeClient = wsMonitor.getNativeClientConnection(); + + expect(nativeClient).toBeDefined(); + expect(nativeClient?.url).toContain('localhost:3060'); + expect(nativeClient?.url).toContain('ws://'); + + console.log(`\nNative client connection URL: ${nativeClient?.url}`); + console.log(`Messages sent/received: ${nativeClient?.messages.length || 0}`); + }); + + test('server connection is to jamkazam.local:6767', async ({ page }) => { + const wsMonitor = new WebSocketMonitor(); + wsMonitor.monitor(page); + + await loginToJamUI(page); + await navigateToSessionCreation(page); + await page.keyboard.press('Control+Shift+Digit0'); + await waitForAPICalls(page, 3000); + await clickQuickStart(page); + await waitForAPICalls(page, 5000); + + const serverConn = wsMonitor.getServerConnection(); + + expect(serverConn).toBeDefined(); + expect(serverConn?.url).toMatch(/jamkazam\.(local|com):6767/); + expect(serverConn?.url).toContain('ws://'); + expect(serverConn?.url).toContain('/websocket'); + + console.log(`\nServer connection URL: ${serverConn?.url}`); + console.log(`Messages sent/received: ${serverConn?.messages.length || 0}`); + + // Check URL parameters + if (serverConn) { + const url = new URL(serverConn.url); + console.log('\nServer connection parameters:'); + console.log(` channel_id: ${url.searchParams.get('channel_id') || 'N/A'}`); + console.log(` client_type: ${url.searchParams.get('client_type') || 'N/A'}`); + console.log(` client_id: ${url.searchParams.get('client_id') || 'N/A'}`); + console.log(` product: ${url.searchParams.get('product') || 'N/A'}`); + + // Verify expected parameters + expect(url.searchParams.get('client_type')).toBe('browser'); + expect(url.searchParams.get('product')).toBe('JamClientModern'); + } + }); + + test('WebSocket connections send and receive messages', async ({ page }) => { + const wsMonitor = new WebSocketMonitor(); + wsMonitor.monitor(page); + + await loginToJamUI(page); + await navigateToSessionCreation(page); + await page.keyboard.press('Control+Shift+Digit0'); + await waitForAPICalls(page, 3000); + await clickQuickStart(page); + await waitForAPICalls(page, 10000); // Wait longer for messages + + const totalMessages = wsMonitor.getTotalMessageCount(); + + console.log(`\nTotal WebSocket messages: ${totalMessages}`); + + const connections = wsMonitor.getConnections(); + for (const conn of connections) { + const sentCount = conn.messages.filter(m => m.direction === 'sent').length; + const receivedCount = conn.messages.filter(m => m.direction === 'received').length; + + console.log(`\n${conn.isNativeClient ? 'Native Client' : 'Server'} (${conn.url}):`); + console.log(` Sent: ${sentCount}`); + console.log(` Received: ${receivedCount}`); + console.log(` Total: ${conn.messages.length}`); + } + + // Should have substantial message traffic + expect(totalMessages).toBeGreaterThan(100); + }); + + test('WebSocket connections remain active during session', async ({ page }) => { + const wsMonitor = new WebSocketMonitor(); + wsMonitor.monitor(page); + + await loginToJamUI(page); + await navigateToSessionCreation(page); + await page.keyboard.press('Control+Shift+Digit0'); + await waitForAPICalls(page, 3000); + await clickQuickStart(page); + await waitForAPICalls(page, 5000); + + // Wait a bit longer + await page.waitForTimeout(3000); + + const activeConnections = wsMonitor.getActiveConnections(); + + console.log(`\nActive WebSocket connections: ${activeConnections.length}`); + activeConnections.forEach(conn => { + console.log(` ${conn.isNativeClient ? 'Native Client' : 'Server'}: OPEN`); + }); + + // Both connections should still be active + expect(activeConnections.length).toBeGreaterThanOrEqual(2); + + // Verify neither connection is closed + const nativeClient = wsMonitor.getNativeClientConnection(); + const server = wsMonitor.getServerConnection(); + + expect(nativeClient?.closed).toBe(false); + expect(server?.closed).toBe(false); + }); +});