Ctrl K
ComunidadGuías…

test/devin-backend-usage.test.js

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/**
 * H0 dashboard read path: org resolution and GET-only reads.
 *
 * This file used to exercise `getBillingUsage` from the devin-backend stub. The
 * dashboard now owns its read path (`src/dashboard/devin-read.js`) and the stub
 * function is gone; the same wire assertions live here against the new reader.
 */
import { afterEach, describe, it } from 'node:test';
import assert from 'node:assert/strict';
import {
  ReadError,
  readDevinJson,
  resolveOrgId,
  __resetReadCache,
  __setFetchImplForTest,
} from '../src/dashboard/devin-read.js';

function jsonResponse(value, { status = 200 } = {}) {
  return {
    ok: status >= 200 && status < 300,
    status,
    headers: { get: () => null },
    text: async () => JSON.stringify(value),
  };
}

function errorResponse(status) {
  return jsonResponse({}, { status });
}

const originalOrg = process.env.DEVIN_BACKEND_ORG_ID;

afterEach(() => {
  __setFetchImplForTest(null);
  __resetReadCache();
  if (originalOrg === undefined) delete process.env.DEVIN_BACKEND_ORG_ID;
  else process.env.DEVIN_BACKEND_ORG_ID = originalOrg;
});

describe('dashboard read path org resolution', () => {
  it('resolves the org through GET current-membership, never post-auth', async () => {
    const calls = [];
    const fetchImpl = async (url, init) => {
      calls.push({ url, method: init.method });
      if (url.endsWith('/users/current-membership')) return jsonResponse({ org: { org_id: 'org-test' } });
      throw new Error(`unexpected ${url}`);
    };

    const org = await resolveOrgId({ token: 'tok', fetchImpl });
    assert.equal(org, 'org-test');
    assert.equal(calls.length, 1);
    assert.equal(calls[0].method, 'GET');
    assert.ok(calls.every((c) => !c.url.includes('/users/post-auth')));
    assert.ok(calls.every((c) => c.method === 'GET'));
  });

  it('falls back to GET /organizations and picks the primary org', async () => {
    const calls = [];
    const fetchImpl = async (url) => {
      calls.push(url);
      if (url.endsWith('/users/current-membership')) return errorResponse(404);
      if (url.endsWith('/organizations')) {
        return jsonResponse([{ org_id: 'org-a' }, { org_id: 'org-b', is_primary_org: true }]);
      }
      throw new Error(`unexpected ${url}`);
    };
    const org = await resolveOrgId({ token: 'tok', fetchImpl });
    assert.equal(org, 'org-b');
    assert.equal(calls.length, 2);
    assert.ok(calls.some((url) => url.endsWith('/organizations')));
  });

  it('rejects when neither GET endpoint returns a usable org id', async () => {
    const fetchImpl = async (url) => {
      if (url.endsWith('/users/current-membership')) return errorResponse(404);
      if (url.endsWith('/organizations')) return jsonResponse([]);
      throw new Error(`unexpected ${url}`);
    };
    await assert.rejects(
      resolveOrgId({ token: 'tok', fetchImpl }),
      (err) => err instanceof ReadError && err.kind === 'org_unresolved',
    );
  });

  it('does not fall back when the token is rejected', async () => {
    const calls = [];
    const fetchImpl = async (url) => { calls.push(url); return errorResponse(401); };
    await assert.rejects(
      resolveOrgId({ token: 'tok', fetchImpl }),
      (err) => err.kind === 'unauthorized',
    );
    assert.equal(calls.length, 1);
  });

  it('never puts orgId, accountId or keyPrefix in the reader output', async () => {
    const out = await readDevinJson({
      token: 'tok',
      path: '/org-test/billing/status',
      orgId: 'org-test',
      fetchImpl: async () => jsonResponse({ plan_slug: 'pro' }),
    });
    assert.equal(out.orgId, undefined);
    assert.equal(out.accountId, undefined);
    assert.equal(out.keyPrefix, undefined);
    assert.equal(out.plan_slug, 'pro');
  });
});