Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: CI

on:
push:
branches:
- '**'
pull_request:
branches:
- '**'

jobs:
ci:
name: Lint, Build, and Test
runs-on: ubuntu-latest

steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20

- name: Setup pnpm
uses: pnpm/action-setup@v3

- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

- name: Cache pnpm dependencies
uses: actions/cache@v4
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-

- name: Install Dependencies
run: pnpm install --frozen-lockfile

- name: Run Linter
run: pnpm lint

- name: Build Projects
run: pnpm build

- name: Run Tests
run: pnpm test
16 changes: 10 additions & 6 deletions apps/dashboard/src/app/compare/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,22 @@ function ComparePageInner() {
const exampleSlug = searchParams.get('example');
if (exampleSlug && EXAMPLES_BY_SLUG[exampleSlug]) {
const ex = EXAMPLES_BY_SLUG[exampleSlug];
setSdp1Raw(ex.sdp1);
setSdp2Raw(ex.sdp2);
runCompare(ex.sdp1, ex.sdp2);
setTimeout(() => {
setSdp1Raw(ex.sdp1);
setSdp2Raw(ex.sdp2);
runCompare(ex.sdp1, ex.sdp2);
}, 0);
return;
}

// 2. Fall back to URL hash
const saved = loadFromHash();
if (saved) {
setSdp1Raw(saved.sdp1);
setSdp2Raw(saved.sdp2);
runCompare(saved.sdp1, saved.sdp2);
setTimeout(() => {
setSdp1Raw(saved.sdp1);
setSdp2Raw(saved.sdp2);
runCompare(saved.sdp1, saved.sdp2);
}, 0);
}
}, [runCompare, searchParams]);

Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export default function HomePage() {
<br />
{' '}<span className="text-white">if</span> (desc?.sdp) {'{'}
<br />
{' '}console.log(<span className="text-white">"%c[SignalFlow] "</span> + desc.type.toUpperCase(), <span className="text-white">"color: #34d399; font-weight: bold"</span>);
{' '}console.log(<span className="text-white">{'"%c[SignalFlow] "'}</span> + desc.type.toUpperCase(), <span className="text-white">{'"color: #34d399; font-weight: bold"'}</span>);
<br />
{' '}console.log(desc.sdp);
<br />
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
"deploy": "pnpm --filter dashboard build && wrangler pages deploy apps/dashboard/out --project-name signalflow",
"start": "pnpm --filter dashboard start",
"lint": "pnpm -r lint",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "pnpm -r --if-present test"
},
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "pnpm@10.32.1"
"packageManager": "pnpm@10.32.1",
"devDependencies": {
"wrangler": "^4.97.0"
}
}
2 changes: 1 addition & 1 deletion packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "src/index.ts",
"scripts": {
"build": "tsc",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "pnpm build && node test-parser.mjs && node test-detector.mjs && node test-diff.mjs && node test-diagnostics.mjs"
},
"keywords": [],
"author": "",
Expand Down
11 changes: 9 additions & 2 deletions packages/shared/test-detector.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,15 @@ try {
const livekit = parseSDP(livekitSDP);
console.log('LiveKit detection:', livekit.source); // expect 'LiveKit'

console.log(chrome.source === 'Chrome' ? '✅ Chrome detected' : '❌ Chrome FAILED');
console.log(livekit.source === 'LiveKit' ? '✅ LiveKit detected' : '❌ LiveKit FAILED');
const chromeSuccess = chrome.source === 'Chrome';
const livekitSuccess = livekit.source === 'LiveKit';
console.log(chromeSuccess ? '✅ Chrome detected' : '❌ Chrome FAILED');
console.log(livekitSuccess ? '✅ LiveKit detected' : '❌ LiveKit FAILED');

if (!chromeSuccess || !livekitSuccess) {
process.exit(1);
}
} catch(e) {
console.error('❌ Error:', e.message);
process.exit(1);
}
6 changes: 6 additions & 0 deletions packages/shared/test-diagnostics.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,17 @@ const checks = [
['codec-missing-rtx', 'warning'],
];

let failed = false;
checks.forEach(([id, expectedSeverity]) => {
const found = issues.find(i => i.id === id);
if (found && found.severity === expectedSeverity) {
console.log(`✅ ${id}`);
} else {
console.log(`❌ ${id} — expected severity ${expectedSeverity}, got: ${found?.severity || 'NOT FOUND'}`);
failed = true;
}
});

if (failed) {
process.exit(1);
}
5 changes: 5 additions & 0 deletions packages/shared/test-diff.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ try {
console.log(fpChange ? '✅ Fingerprint change detected' : '❌ Fingerprint change NOT detected');

console.log('Media changes count:', result.mediaChanges.length); // expect 2

if (!av1Removed || !fpChange || result.mediaChanges.length !== 2) {
process.exit(1);
}
} catch(e) {
console.error('❌ Error:', e.message, e.stack);
process.exit(1);
}
35 changes: 29 additions & 6 deletions packages/shared/test-parser.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,44 @@ a=rtpmap:96 VP8/90000
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96`;

let failed = false;

try {
const result = parseSDP(testSDP);
console.log('✅ Parsed OK');
console.log('Media sections:', result.media.length); // expect 2
console.log('Audio codecs:', result.media[0].codecs.map(c => c.name)); // expect ['opus']
console.log('Video codecs:', result.media[1].codecs.map(c => c.name)); // expect ['VP8']
console.log('VP8 has RTX:', result.media[1].codecs[0].rtx); // expect 97
console.log('ICE ufrag:', result.media[0].iceUfrag); // expect 'abc123'
if (result.media.length !== 2) {
console.error('❌ Media sections count is not 2, got:', result.media.length);
failed = true;
}
if (!result.media[0].codecs.map(c => c.name).includes('opus')) {
console.error('❌ Expected audio codec opus, got:', result.media[0].codecs.map(c => c.name));
failed = true;
}
if (!result.media[1].codecs.map(c => c.name).includes('VP8')) {
console.error('❌ Expected video codec VP8, got:', result.media[1].codecs.map(c => c.name));
failed = true;
}
if (result.media[1].codecs[0].rtx !== 97) {
console.error('❌ Expected VP8 RTX map 97, got:', result.media[1].codecs[0].rtx);
failed = true;
}
if (result.media[0].iceUfrag !== 'abc123') {
console.error('❌ Expected ICE ufrag abc123, got:', result.media[0].iceUfrag);
failed = true;
}
} catch(e) {
console.error('❌ FAILED:', e.message);
failed = true;
}

try {
parseSDP('not an sdp');
console.error('❌ Should have thrown');
console.error('❌ Should have thrown on invalid SDP');
failed = true;
} catch(e) {
console.log('✅ Correctly threw on invalid SDP:', e.message);
}

if (failed) {
process.exit(1);
}
Loading
Loading