ai-research-survey

Systematic scan of agentic development research. What's signal, what's noise.
git clone https://git.shiptheloop.com/ai-research-survey.git
Log | Files | Refs

explorer.spec.ts (11480B)


      1 import { test, expect } from '@playwright/test';
      2 
      3 test.describe('Dashboard', () => {
      4   test('loads and shows headline stats', async ({ page }) => {
      5     await page.goto('/');
      6     await expect(page.locator('.card .value').first()).toBeVisible({ timeout: 10000 });
      7     const cards = page.locator('.card');
      8     await expect(cards).toHaveCount(4);
      9     await expect(cards.nth(0).locator('.value')).toHaveText('1047');
     10     await expect(cards.nth(1).locator('.value')).toHaveText('47.2%');
     11   });
     12 
     13   test('shows spinner then content', async ({ page }) => {
     14     await page.goto('/');
     15     // Spinner should appear briefly (may be too fast to catch, but structure exists)
     16     await expect(page.locator('.card .value').first()).toBeVisible({ timeout: 10000 });
     17   });
     18 
     19   test('shows histogram', async ({ page }) => {
     20     await page.goto('/');
     21     await expect(page.locator('.card .value').first()).toBeVisible({ timeout: 10000 });
     22     const bars = page.locator('svg .bar');
     23     expect(await bars.count()).toBeGreaterThan(5);
     24     await expect(page.locator('svg .bar[height]:not([height="0"])')).not.toHaveCount(0);
     25   });
     26 
     27   test('shows category pass rates', async ({ page }) => {
     28     await page.goto('/');
     29     await expect(page.locator('.card .value').first()).toBeVisible({ timeout: 10000 });
     30     const hbars = page.locator('.hbar');
     31     expect(await hbars.count()).toBeGreaterThan(5);
     32   });
     33 
     34   test('shows year trends chart', async ({ page }) => {
     35     await page.goto('/');
     36     await expect(page.locator('.card .value').first()).toBeVisible({ timeout: 10000 });
     37     await expect(page.locator('.trend-chart')).toBeVisible();
     38   });
     39 
     40   test('shows pipeline progress bar', async ({ page }) => {
     41     await page.goto('/');
     42     await expect(page.locator('.pipeline-bar')).toBeVisible({ timeout: 10000 });
     43     await expect(page.locator('.pipeline-stat')).toContainText('of');
     44     await expect(page.locator('.pipeline-seg.deprecated')).toBeVisible();
     45   });
     46 
     47   test('shows named games', async ({ page }) => {
     48     await page.goto('/');
     49     await expect(page.locator('.card .value').first()).toBeVisible({ timeout: 10000 });
     50     const games = page.locator('.game-row');
     51     expect(await games.count()).toBeGreaterThan(2);
     52   });
     53 });
     54 
     55 test.describe('Papers Browser', () => {
     56   test('shows paper table', async ({ page }) => {
     57     await page.goto('/#/papers');
     58     await expect(page.locator('table tbody tr').first()).toBeVisible({ timeout: 10000 });
     59     expect(await page.locator('table tbody tr').count()).toBe(2688);
     60     await expect(page.locator('#f-count')).toHaveText('2688 / 2688');
     61   });
     62 
     63   test('text search filters papers', async ({ page }) => {
     64     await page.goto('/#/papers');
     65     await expect(page.locator('table tbody tr').first()).toBeVisible({ timeout: 10000 });
     66     await page.fill('#f-search', 'metr');
     67     const count = await page.locator('table tbody tr').count();
     68     expect(count).toBeGreaterThan(0);
     69     expect(count).toBeLessThan(2688);
     70   });
     71 
     72   test('archetype filter works', async ({ page }) => {
     73     await page.goto('/#/papers');
     74     await expect(page.locator('table tbody tr').first()).toBeVisible({ timeout: 10000 });
     75     await page.selectOption('#f-archetype', 'Complete');
     76     const count = await page.locator('table tbody tr').count();
     77     expect(count).toBeGreaterThan(0);
     78     expect(count).toBeLessThan(2688);
     79   });
     80 
     81   test('clicking row navigates to paper detail', async ({ page }) => {
     82     await page.goto('/#/papers');
     83     await expect(page.locator('table tbody tr').first()).toBeVisible({ timeout: 10000 });
     84     await page.locator('table tbody tr').first().click();
     85     await expect(page.locator('.paper-header h2')).toBeVisible({ timeout: 10000 });
     86   });
     87 
     88   test('sort by score works', async ({ page }) => {
     89     await page.goto('/#/papers');
     90     await expect(page.locator('table tbody tr').first()).toBeVisible({ timeout: 10000 });
     91     await page.locator('thead th', { hasText: 'Score' }).click();
     92     const firstScore = await page.locator('table tbody tr').first().locator('td.score').textContent();
     93     // First entry is "--" (unscanned) or a low score
     94     expect(firstScore!.trim()).toMatch(/^--|^\d/);
     95   });
     96 });
     97 
     98 test.describe('Paper Detail', () => {
     99   test('shows METR paper detail with links', async ({ page }) => {
    100     await page.goto('/#/paper/metr-rct-2025');
    101     await expect(page.locator('.paper-header h2')).toBeVisible({ timeout: 10000 });
    102     await expect(page.locator('.paper-header h2')).toContainText('Measuring the Impact');
    103     await expect(page.locator('.paper-meta')).toContainText('69.8%');
    104     // Should have arXiv link
    105     await expect(page.locator('.paper-links a', { hasText: 'arXiv' })).toBeVisible();
    106   });
    107 
    108   test('shows checklist items', async ({ page }) => {
    109     await page.goto('/#/paper/metr-rct-2025');
    110     await expect(page.locator('.checklist-category').first()).toBeVisible({ timeout: 10000 });
    111     const items = page.locator('.checklist-item');
    112     expect(await items.count()).toBeGreaterThan(30);
    113   });
    114 
    115   test('shows claims', async ({ page }) => {
    116     await page.goto('/#/paper/metr-rct-2025');
    117     await expect(page.locator('.claim').first()).toBeVisible({ timeout: 10000 });
    118     expect(await page.locator('.claim').count()).toBeGreaterThan(3);
    119   });
    120 
    121   test('shows red flags', async ({ page }) => {
    122     await page.goto('/#/paper/metr-rct-2025');
    123     await expect(page.locator('.red-flag').first()).toBeVisible({ timeout: 10000 });
    124     expect(await page.locator('.red-flag').count()).toBeGreaterThan(2);
    125   });
    126 
    127   test('back link works', async ({ page }) => {
    128     await page.goto('/#/paper/metr-rct-2025');
    129     await expect(page.locator('.back-link')).toBeVisible({ timeout: 10000 });
    130     await page.locator('.back-link').click();
    131     await expect(page.locator('table tbody tr').first()).toBeVisible({ timeout: 10000 });
    132   });
    133 
    134   test('shows 404 for unknown paper', async ({ page }) => {
    135     await page.goto('/#/paper/nonexistent-paper-9999');
    136     await expect(page.locator('text=Paper not found')).toBeVisible({ timeout: 10000 });
    137   });
    138 });
    139 
    140 test.describe('Citation Network', () => {
    141   test('renders canvas', async ({ page }) => {
    142     await page.goto('/#/network');
    143     await expect(page.locator('#network-canvas')).toBeVisible({ timeout: 10000 });
    144   });
    145 
    146   test('shows node count', async ({ page }) => {
    147     await page.goto('/#/network');
    148     await expect(page.locator('#net-count')).toBeVisible({ timeout: 10000 });
    149     const text = await page.locator('#net-count').textContent();
    150     expect(text).toMatch(/\d+ nodes/);
    151   });
    152 
    153   test('min connections filter works', async ({ page }) => {
    154     await page.goto('/#/network');
    155     await expect(page.locator('#net-count')).toBeVisible({ timeout: 10000 });
    156     const before = await page.locator('#net-count').textContent();
    157     await page.fill('#net-min-conn', '5');
    158     await page.waitForTimeout(500);
    159     const after = await page.locator('#net-count').textContent();
    160     const beforeNodes = parseInt(before!.match(/(\d+) nodes/)![1]);
    161     const afterNodes = parseInt(after!.match(/(\d+) nodes/)![1]);
    162     expect(afterNodes).toBeLessThan(beforeNodes);
    163   });
    164 });
    165 
    166 test.describe('Tensions', () => {
    167   test('shows three tension groups', async ({ page }) => {
    168     await page.goto('/#/tensions');
    169     await expect(page.locator('.tension-group').first()).toBeVisible({ timeout: 10000 });
    170     expect(await page.locator('.tension-group').count()).toBe(6);
    171   });
    172 
    173   test('shows tension claims', async ({ page }) => {
    174     await page.goto('/#/tensions');
    175     await expect(page.locator('.tension-claim').first()).toBeVisible({ timeout: 10000 });
    176     expect(await page.locator('.tension-claim').count()).toBeGreaterThan(5);
    177   });
    178 });
    179 
    180 test.describe('Navigation', () => {
    181   test('nav links work', async ({ page }) => {
    182     await page.goto('/');
    183     await expect(page.locator('.card .value').first()).toBeVisible({ timeout: 10000 });
    184 
    185     await page.locator('nav a', { hasText: 'Papers' }).click();
    186     await expect(page.locator('table')).toBeVisible({ timeout: 10000 });
    187 
    188     await page.locator('nav a', { hasText: 'Network' }).click();
    189     await expect(page.locator('#network-canvas')).toBeVisible({ timeout: 10000 });
    190 
    191     await page.locator('nav a', { hasText: 'Tensions' }).click();
    192     await expect(page.locator('.tension-group').first()).toBeVisible({ timeout: 10000 });
    193 
    194     await page.locator('nav a', { hasText: 'Dashboard' }).click();
    195     await expect(page.locator('.card .value').first()).toBeVisible({ timeout: 10000 });
    196   });
    197 
    198   test('active nav state updates', async ({ page }) => {
    199     await page.goto('/#/papers');
    200     await expect(page.locator('table tbody tr').first()).toBeVisible({ timeout: 10000 });
    201     await expect(page.locator('nav a.active')).toHaveText('Papers');
    202   });
    203 });
    204 
    205 test.describe('Findings', () => {
    206   test('loads and shows all sections', async ({ page }) => {
    207     await page.goto('/#/findings');
    208     await expect(page.locator('.section').first()).toBeVisible({ timeout: 10000 });
    209     // Should have 17 sections
    210     expect(await page.locator('.section').count()).toBe(17);
    211   });
    212 
    213   test('shows per-question pass rates', async ({ page }) => {
    214     await page.goto('/#/findings');
    215     await expect(page.locator('.section').first()).toBeVisible({ timeout: 10000 });
    216     await expect(page.locator('h2', { hasText: 'Per-Question Pass Rates' })).toBeVisible();
    217     // Should have horizontal bars
    218     expect(await page.locator('.section').first().locator('.hbar').count()).toBeGreaterThan(10);
    219   });
    220 
    221   test('shows year category trends with toggles', async ({ page }) => {
    222     await page.goto('/#/findings');
    223     await expect(page.locator('#cat-toggles')).toBeVisible({ timeout: 10000 });
    224     const activeToggles = page.locator('.toggle-btn.active');
    225     expect(await activeToggles.count()).toBe(4);
    226     // Click a toggle to deactivate
    227     await activeToggles.first().click();
    228     expect(await page.locator('.toggle-btn.active').count()).toBe(3);
    229   });
    230 
    231   test('shows funding gap', async ({ page }) => {
    232     await page.goto('/#/findings');
    233     await expect(page.locator('h2', { hasText: 'Funding Disclosure Gap' })).toBeVisible({ timeout: 10000 });
    234     await expect(page.locator('text=pp gap')).toBeVisible();
    235   });
    236 
    237   test('shows reproducibility drill-down', async ({ page }) => {
    238     await page.goto('/#/findings');
    239     await expect(page.locator('h2', { hasText: 'Reproducibility Drill-Down' })).toBeVisible({ timeout: 10000 });
    240     await expect(page.locator('text=fully reproducible')).toBeVisible();
    241   });
    242 
    243   test('shows 6 named games', async ({ page }) => {
    244     await page.goto('/#/findings');
    245     const gamesSection = page.locator('.section', { has: page.locator('h2', { hasText: 'Named Games' }) });
    246     await expect(gamesSection).toBeVisible({ timeout: 10000 });
    247     expect(await gamesSection.locator('.game-row').count()).toBe(10);
    248   });
    249 });
    250 
    251 test.describe('Theme', () => {
    252   test('toggle switches theme', async ({ page }) => {
    253     await page.goto('/');
    254     await expect(page.locator('.card .value').first()).toBeVisible({ timeout: 10000 });
    255     const themeBefore = await page.locator('html').getAttribute('data-theme');
    256     expect(themeBefore).toMatch(/^(dark|light)$/);
    257     // Click toggle — should switch
    258     await page.click('#theme-toggle');
    259     const themeAfter = await page.locator('html').getAttribute('data-theme');
    260     expect(themeAfter).not.toBe(themeBefore);
    261     // Toggle back
    262     await page.click('#theme-toggle');
    263     const themeBack = await page.locator('html').getAttribute('data-theme');
    264     expect(themeBack).toBe(themeBefore);
    265   });
    266 });

Impressum · Datenschutz