Docs/Skills and code/tests/

tests/video-info-fetch.test.js

Code77 lines3.0 KBtests/

import test from "node:test";
import assert from "node:assert/strict";
import { fetchVideoInfo, normalizeVideoInfoPayload } from "../src/video-info-fetch.js";

const basicPayload = {
  basic_info: {
    id: "3U2CtXLSbZY",
    title: "How Database Indexes Work (Explained in 5 Minutes)",
    author: "Example Channel",
    channel_id: "UC123",
    duration: 305,
    view_count: 123456,
    like_count: 2400,
    category: "Education",
    short_description: "A short explanation of database indexing.",
    publish_date: "2026-09-28",
    thumbnail: [{ url: "https://example.test/thumb.jpg", width: 1280, height: 720 }]
  },
  playability_status: { status: "OK" }
};

test("default fetch uses getBasicInfo and never invokes getInfo", async () => {
  let basicCalls = 0;
  let fullCalls = 0;
  const fake = {
    async getBasicInfo(id) { basicCalls++; assert.equal(id, "3U2CtXLSbZY"); return basicPayload; },
    async getInfo() { fullCalls++; throw new Error("must not call full info by default"); }
  };
  const result = await fetchVideoInfo(fake, "3U2CtXLSbZY");
  assert.equal(basicCalls, 1);
  assert.equal(fullCalls, 0);
  assert.equal(result.metadata_source, "youtubei_get_basic_info");
  assert.equal(result.title, basicPayload.basic_info.title);
  assert.equal(result.view_count, 123456);
  assert.equal(result.likes_count, 2400);
  assert.equal(result.duration_seconds, 305);
  assert.equal(result.published_at, "2026-09-28");
  assert.equal(result.video_channel_id, "UC123");
  assert.equal(result.thumbnail_url, "https://example.test/thumb.jpg");
  assert.match(result.description, /database indexing/);
});

test("full-info mode explicitly calls getInfo and merges secondary fields", async () => {
  let basicCalls = 0;
  let fullCalls = 0;
  const fake = {
    async getBasicInfo() { basicCalls++; throw new Error("not expected"); },
    async getInfo(id) {
      fullCalls++;
      return {
        ...basicPayload,
        primary_info: { published: "Published Sep 28, 2026", view_count: { view_count: "123K views" } },
        secondary_info: { owner: { title: "Owner title", author: { id: "UC-owner" } } }
      };
    }
  };
  const result = await fetchVideoInfo(fake, "3U2CtXLSbZY", { fullInfo: true });
  assert.equal(basicCalls, 0);
  assert.equal(fullCalls, 1);
  assert.equal(result.metadata_source, "youtubei_get_info");
  assert.equal(result.published_at, "2026-09-28");
  assert.equal(result.view_count_text, "123K views");
});

test("normalizer preserves unknown fields as null and refuses payload without a title", () => {
  const result = normalizeVideoInfoPayload({ basic_info: { id: "x", title: "Example" } }, "x");
  assert.equal(result.view_count, null);
  assert.equal(result.likes_count, null);
  assert.equal(result.duration_seconds, null);
  assert.equal(result.published_at, null);
  assert.equal(result.published_at_precision, "unknown");
  assert.throws(
    () => normalizeVideoInfoPayload({ basic_info: {}, playability_status: { status: "ERROR" } }, "private-id"),
    /no usable video title.*playability_status=ERROR/i
  );
});

Shown as it is in the repository at build time (2026-11-03); the home directory appears as <home>. If this page and the file differ, the file is right. Back to the catalogue.