/** * Weighing a repository's files into the shares the language bar paints. */ import { describe, expect, it } from 'vitest'; import { languageOf, languageShares, percent } from '../src/lib/languages.js'; /** @param {string} path @param {number} size */ const file = (path, size) => ({ path, size }); describe('languageOf', () => { it('reads the language from the extension', () => { expect(languageOf('src/app.tsx')).toBe('TypeScript'); expect(languageOf('src/app.jsx')).toBe('JavaScript'); expect(languageOf('main.go')).toBe('Go'); expect(languageOf('style.scss')).toBe('SCSS'); }); it('reads the language from the name where there is no extension', () => { expect(languageOf('Dockerfile')).toBe('Dockerfile'); expect(languageOf('docker/Containerfile')).toBe('Dockerfile'); expect(languageOf('Makefile.am')).toBe('Makefile'); expect(languageOf('justfile')).toBe('Just'); }); it('gives data and prose files no language', () => { expect(languageOf('package.json')).toBe(''); expect(languageOf('README.md')).toBe(''); expect(languageOf('.github/workflows/ci.yml')).toBe(''); expect(languageOf('LICENSE')).toBe(''); }); it('gives vendored and generated paths no language', () => { expect(languageOf('node_modules/left-pad/index.js')).toBe(''); expect(languageOf('packages/app/dist/bundle.js')).toBe(''); expect(languageOf('public/vendor.min.js')).toBe(''); expect(languageOf('vendor/github.com/pkg/errors.go')).toBe(''); // A directory whose name only starts with an ignored one still counts. expect(languageOf('distributed/worker.js')).toBe('JavaScript'); }); }); describe('languageShares', () => { it('ranks languages by bytes and shares out the languaged bytes', () => { const shares = languageShares([ file('src/app.ts', 700), file('src/util.ts', 100), file('src/app.css', 200), file('package-lock.json', 100000), ]); expect(shares.map((row) => row.name)).toEqual(['TypeScript', 'CSS']); expect(shares[0].share).toBeCloseTo(80); expect(shares[1].share).toBeCloseTo(20); expect(shares[0].color).toBe('#3178c6'); }); it('adds everything past the sixth language together as Other', () => { const shares = languageShares([ file('a.ts', 100), file('b.js', 90), file('c.py', 80), file('d.go', 70), file('e.rs', 60), file('f.rb', 50), file('g.lua', 40), file('h.php', 30), ]); expect(shares).toHaveLength(7); expect(shares[6].name).toBe('Other'); expect(shares[6].bytes).toBe(70); expect(shares.reduce((sum, row) => sum + row.share, 0)).toBeCloseTo(100); }); it('reports nothing for a repository with no languaged file', () => { expect(languageShares([file('README.md', 500)])).toEqual([]); expect(languageShares([])).toEqual([]); }); }); describe('percent', () => { it('prints one decimal, and a floor for a share below it', () => { expect(percent(98.34)).toBe('98.3%'); expect(percent(0.1)).toBe('0.1%'); expect(percent(0.02)).toBe('<0.1%'); }); });