Return

All tests / src/constants nextCoverage.ts

100% Statements 6/6
100% Branches 0/0
100% Functions 0/0
100% Lines 4/4

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127                                                            34x   1x                                                                   1x               208x                                                                                                        
/**
 * Data behind /next-coverage. Same contract as `nextLeak.ts`: every figure is copied from a real run
 * of the published CLI on `checkedAt`, never rounded, never extrapolated. A reader has the repo, the
 * commit and the version, so they can reproduce the whole page in about a minute.
 *
 * The tool is 0.x and its own CHANGELOG says the CLI and the JSON may change between minors, so this
 * file and its date move together with the version above them.
 *
 * Bucket names, finding text and file paths are data, not copy: they stay in English in every locale,
 * the way the CLI prints them, and never enter the message catalogues.
 */
 
export type Bucket = 'used' | 'wouldApply' | 'notApplicable' | 'notEvaluated';
 
export type Finding = {
    /** The API entry the finding hangs off, as the report labels it. */
    api: string;
    group: string;
    /** The report's own sentence, verbatim. */
    what: string;
    /** The one-line reason the report prints under it. */
    why: string;
    docs: string;
    /** Files named by the report; `more` is how many it summarised as "and N more". */
    files: string[];
    more?: number;
    /** Present only on the finding the page leads with. */
    detail?: string;
};
 
export const BUCKETS: Bucket[] = ['used', 'wouldApply', 'notApplicable', 'notEvaluated'];
 
const findings: Finding[] = [
    {
        api: 'cacheTag',
        group: 'functions',
        what: 'declared here, and no invalidation names them anywhere in the project',
        why: 'a tag lets revalidateTag drop exactly these scopes, so a change reaches the page without waiting out the profile',
        docs: 'https://nextjs.org/docs/app/api-reference/functions/cacheTag',
        files: ['features/product/product-queries.ts'],
        detail: 'products',
    },
    {
        api: 'cacheLife',
        group: 'functions',
        what: 'these cache scopes inherit the default profile because they never set one',
        why: 'a profile sets how long the scope is fresh and how long it may be served stale, instead of the framework’s default',
        docs: 'https://nextjs.org/docs/app/api-reference/functions/cacheLife',
        files: [
            'features/category/components/Categories.tsx',
            'features/category/components/CategoryFilters.tsx',
            'features/category/components/FeaturedCategories.tsx',
        ],
        more: 8,
    },
    {
        api: 'sitemap.xml',
        group: 'file-conventions',
        what: 'the project serves 7 pages and declares no sitemap',
        why: 'a sitemap file generates the XML from the routes, so crawlers find every page rather than the ones something links to',
        docs: 'https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap',
        files: ['app'],
    },
];
 
/** Modules on the client side of the boundary, per route, from the same run. */
const clientWeight = [
    { route: '/all', modules: 20 },
    { route: '/', modules: 16 },
    { route: '/product/[id]', modules: 15 },
    { route: '/cart', modules: 12 },
    { route: '/user', modules: 12 },
];
 
export const nextCoverage = {
    version: '0.1.0',
    /** The run below, and the hand check under it, were made on this date. */
    checkedAt: '2026-09-20',
    install: 'npx next-coverage',
    strict: 'npx next-coverage --strict --findings',
    requirements: 'Node.js 20.19+, Next.js 16.2+, App Router',
    repository: 'https://github.com/xabierlameiro/next-coverage',
    npm: 'https://www.npmjs.com/package/next-coverage',
    npmx: 'https://npmx.dev/package/next-coverage',
    newIssue: 'https://github.com/xabierlameiro/next-coverage/issues',
    exampleRun: {
        project: 'aurorascharff/next16-commerce',
        projectUrl: 'https://github.com/aurorascharff/next16-commerce',
        commit: '13d17c0f21ee742cec914078480d4a008c51f782',
        commitShort: '13d17c0f',
        commitUrl: 'https://github.com/aurorascharff/next16-commerce/tree/13d17c0f21ee742cec914078480d4a008c51f782',
        nextVersion: '16.3.0-preview.10',
        header: 'next-coverage · Next.js 16.3.0-preview.10 · ~/next16-commerce',
        seconds: 1.2,
        entries: 151,
        evaluated: 30,
        summary: '29 of 30 evaluated APIs are in use.',
        counts: { used: 29, wouldApply: 1, notApplicable: 8, notEvaluated: 113 },
        /** The report breaks its own silence down, which is the point of showing it. */
        notEvaluatedBreakdown: [
            { count: 32, what: 'abstained' },
            { count: 5, what: 'suggested on another entry' },
            { count: 72, what: 'evaluated and unmatched' },
        ],
        findings,
        findingsInStrict: 14,
        withheld: 65,
        constraintsChecked: 13,
        clientWeight,
        clientWeightMoreRoutes: 2,
        /** No build was present, and the report says so rather than guessing. */
        buildContrast: 'nothing contrasted: no production build found at .next',
    },
    /**
     * The lead finding, checked by reading the project rather than by trusting the tool. Line numbers
     * are from the pinned commit.
     */
    verification: {
        declares:
            "features/product/product-queries.ts:47 — getProducts declares 'use cache', cacheLife('minutes') and cacheTag('products')",
        alsoDeclares: "features/product/components/{Product,ProductDetails}.tsx — cacheTag('product-' + productId)",
        invalidates:
            "features/product/product-actions.ts:54 — setFeaturedProduct changes the featured product and calls revalidateTag('featured-product', 'max')",
        conclusion: 'Nothing in the project ever names products or product-<id>.',
    },
} as const;