Docs/Skills and code/tests/
tests/channel-metric-features.test.js
import test from "node:test";
import assert from "node:assert/strict";
import { calculateChannelMetrics, median, percentile, subscriberBand, catalogueBand, ageBand, evidenceBand, csvCell } from "../src/analysis/channel-metric-features.js";
test("median and percentile are robust to ordering and empty input", () => {
assert.equal(median([9, 1, 5]), 5);
assert.equal(median([9, 1, 5, 7]), 6);
assert.equal(median([]), null);
assert.equal(percentile([1, 2, 3, 4, 5], 0.9), 5);
assert.equal(percentile([], 0.9), null);
});
test("bands create cohorts without imposing a quality verdict", () => {
assert.equal(subscriberBand(999), "under_1k");
assert.equal(subscriberBand(1000), "1k_9k");
assert.equal(subscriberBand(null), "unknown");
assert.equal(catalogueBand(1000), "1000_plus");
assert.equal(ageBand(365 * 4), "3_7y");
assert.equal(evidenceBand(4), "under_5");
assert.equal(evidenceBand(20), "20_plus");
});
test("channel metrics compute efficiency, coverage, view distribution and warnings", () => {
const channel = {
channel_url: "https://youtube.com/@sample", name: "Sample", ecosystem_classification: "core",
subscriber_count: 10000, subscriber_count_precision: "abbreviated",
video_count: 100, video_count_precision: "exact_displayed",
total_view_count: 500000, total_view_count_precision: "exact_displayed",
joined_date: "2020-01-01", channel_id: "UC123", description: "Technology channel", country: "IN", handle: "@sample", thumbnail_url: "https://img"
};
const videos = [
{ video_id: "a", view_count: 100, published_at: "2025-01-01", published_at_precision: "exact_day" },
{ video_id: "b", view_count: 200, published_at: "2025-02-01", published_at_precision: "exact_day" },
{ video_id: "c", view_count: 300, published_at: "2025-03-01", published_at_precision: "estimated_month" },
{ video_id: "a", view_count: 100, published_at: "2025-01-01", published_at_precision: "exact_day" }
];
const result = calculateChannelMetrics(channel, videos, { nowMs: Date.parse("2026-01-01T00:00:00Z") });
assert.equal(result.linked_video_count, 3, "duplicate video IDs should be deduplicated");
assert.equal(result.subscribers_per_upload, 100);
assert.equal(result.lifetime_views_per_upload, 5000);
assert.equal(result.lifetime_views_per_subscriber, 50);
assert.equal(result.video_median_views, 200);
assert.equal(result.video_count_with_views, 3);
assert.equal(result.exact_dated_video_count_for_age_adjusted_views, 2, "estimated month must not be treated as exact date");
assert.equal(result.corpus_coverage_percent, 3);
assert.ok(result.warnings.includes("subscriber_count_is_abbreviated_approximation"));
});
test("zero denominators return null instead of infinity", () => {
const result = calculateChannelMetrics({ channel_url: "x", name: "x", subscriber_count: 5, video_count: 0, total_view_count: 10 }, []);
assert.equal(result.subscribers_per_upload, null);
assert.equal(result.lifetime_views_per_upload, null);
assert.equal(result.lifetime_views_per_subscriber, 2);
});
test("CSV output escapes commas, quotes, and newlines", () => {
assert.equal(csvCell('A,"B"'), '"A,""B"""');
assert.equal(csvCell("line1\nline2"), '"line1\nline2"');
assert.equal(csvCell(null), "");
});
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.