import { describe, beforeEach, afterEach, test, expect, jest, } from '@jest/globals'; import { Knifecycle, constant } from 'knifecycle'; import initJSArch, { JSARCH_PREFIX, type JSArchService } from './jsarch.js'; import initParser from './parser.js'; import { DEFAULT_CONFIG } from './CONFIG.js'; import initPackageJSON from './packageJSON.js'; import { initImporter } from 'common-services'; import { type FSService } from './fs.js'; import { type GlobService } from './glob.js'; describe('jsArch service', () => { const log = jest.fn(); const glob = jest.fn(); const readFileAsync = jest.fn(); let $: Knifecycle; beforeEach(() => { $ = new Knifecycle(); $.register(constant('EOL', '\n')); $.register(constant('ENV', {})); $.register(constant('CONFIG', DEFAULT_CONFIG)); $.register(constant('log', log)); $.register(constant('glob', glob)); $.register(constant('fs', { readFileAsync })); $.register(initParser); $.register(initPackageJSON); $.register(initImporter); $.register(initJSArch); }); afterEach(() => { log.mockReset(); glob.mockReset(); readFileAsync.mockReset(); }); test('with no architecture notes', async () => { glob.mockResolvedValueOnce([ '/home/me/project/bar.js', '/home/me/project/foo.js', ]); readFileAsync.mockResolvedValue( Buffer.from(` console.log('test'); `), ); const { jsArch } = (await $.run(['jsArch'])) as { jsArch: JSArchService }; const content = await jsArch({ patterns: ['**/*.js'], base: './blob/master', cwd: '/home/me/project', }); expect(readFileAsync.mock.calls).toEqual([ ['/home/me/project/bar.js'], ['/home/me/project/foo.js'], ]); expect(content).toEqual(''); }); test('with some architecture notes in a file', async () => { glob.mockResolvedValueOnce(['/home/me/project/foo.js']); readFileAsync.mockResolvedValueOnce( Buffer.from(` /* Architecture Note #1: Title Some content ! */ console.log('test'); `), ); const { jsArch } = (await $.run(['jsArch'])) as { jsArch: JSArchService }; const content = await jsArch({ patterns: ['**/*.js'], base: './blob/master', cwd: '/home/me/project', }); expect(readFileAsync.mock.calls).toEqual([['/home/me/project/foo.js']]); expect(content).toEqual( `${JSARCH_PREFIX}# Architecture Notes ## Summary 1. [Title](#1-title) ## 1. Title Some content ! [See in context](./blob/master/foo.js#L3-L6) `, ); }); test('with some architecture notes containing a $', async () => { glob.mockResolvedValueOnce(['/home/me/project/foo.js']); readFileAsync.mockResolvedValueOnce( Buffer.from(` /* Architecture Note #1: \`$autoload\` Some content ! */ console.log('test'); `), ); const { jsArch } = (await $.run(['jsArch'])) as { jsArch: JSArchService }; const content = await jsArch({ patterns: ['**/*.js'], base: './blob/master', cwd: '/home/me/project', }); expect(readFileAsync.mock.calls).toEqual([['/home/me/project/foo.js']]); expect(content).toEqual( `${JSARCH_PREFIX}# Architecture Notes ## Summary 1. [\`$autoload\`](#1-\`$autoload\`) ## 1. \`$autoload\` Some content ! [See in context](./blob/master/foo.js#L3-L6) `, ); }); test('with some architecture notes in a TypeScript file', async () => { $.register( constant('CONFIG', { ...DEFAULT_CONFIG, parserOptions: { ...DEFAULT_CONFIG.parserOptions, plugins: ['typescript'], }, }), ); glob.mockResolvedValueOnce(['/home/me/project/foo.js']); readFileAsync.mockResolvedValueOnce( Buffer.from(` interface lol { lol : string; } /* Architecture Note #1: Title Some content ! */ console.log('test'); `), ); const { jsArch } = (await $.run(['jsArch'])) as { jsArch: JSArchService }; const content = await jsArch({ patterns: ['**/*.js'], base: './blob/master', cwd: '/home/me/project', }); expect(readFileAsync.mock.calls).toEqual([['/home/me/project/foo.js']]); expect(content).toEqual( `${JSARCH_PREFIX}# Architecture Notes ## Summary 1. [Title](#1-title) ## 1. Title Some content ! [See in context](./blob/master/foo.js#L7-L10) `, ); }); test('with some architecture notes in a file and bitbucket links', async () => { $.register( constant('CONFIG', { ...DEFAULT_CONFIG, gitProvider: 'bitbucket', }), ); glob.mockResolvedValueOnce(['/home/me/project/foo.js']); readFileAsync.mockResolvedValueOnce( Buffer.from(` /* Architecture Note #1: Title Some content ! */ console.log('test'); `), ); const { jsArch } = (await $.run(['jsArch'])) as { jsArch: JSArchService }; const content = await jsArch({ patterns: ['**/*.js'], base: './blob/master', cwd: '/home/me/project', }); expect(readFileAsync.mock.calls).toEqual([['/home/me/project/foo.js']]); expect(content).toEqual( `${JSARCH_PREFIX}# Architecture Notes ## Summary 1. [Title](#1-title) ## 1. Title Some content ! [See in context](./blob/master/foo.js#foo.js-3:6) `, ); }); test('with some indented architecture notes in a file', async () => { glob.mockResolvedValueOnce(['/home/me/project/foo.js']); readFileAsync.mockResolvedValueOnce( Buffer.from(` /* Architecture Note #1: Title Some content ! Nice! */ console.log('test'); `), ); const { jsArch } = (await $.run(['jsArch'])) as { jsArch: JSArchService }; const content = await jsArch({ patterns: ['**/*.js'], base: './blob/master', cwd: '/home/me/project', }); expect(readFileAsync.mock.calls).toEqual([['/home/me/project/foo.js']]); expect(content).toEqual( `${JSARCH_PREFIX}# Architecture Notes ## Summary 1. [Title](#1-title) ## 1. Title Some content ! Nice! [See in context](./blob/master/foo.js#L3-L7) `, ); }); test('with architecture notes in several files', async () => { glob.mockResolvedValueOnce([ '/home/me/project/bar.js', '/home/me/project/foo.js', ]); readFileAsync.mockResolvedValueOnce( Buffer.from(` /* Architecture Note #1.1: Title Some content ! */ console.log('test'); /* Architecture Note #1: Title Some content ! */ `), ); readFileAsync.mockResolvedValueOnce( Buffer.from(` /* Architecture Note #1.3: Title Some content ! */ console.log('test'); /* Architecture Note #2: Title Some content ! */ `), ); const { jsArch } = (await $.run(['jsArch'])) as { jsArch: JSArchService }; const content = await jsArch({ patterns: ['**/*.js'], base: './blob/master', cwd: '/home/me/project', }); expect(readFileAsync.mock.calls).toEqual([ ['/home/me/project/bar.js'], ['/home/me/project/foo.js'], ]); expect(content).toEqual( `${JSARCH_PREFIX}# Architecture Notes ## Summary 1. [Title](#1-title) 1. [Title](#11-title) 3. [Title](#13-title) 2. [Title](#2-title) ## 1. Title Some content ! [See in context](./blob/master/bar.js#L8-L11) ### 1.1. Title Some content ! [See in context](./blob/master/bar.js#L2-L5) ### 1.3. Title Some content ! [See in context](./blob/master/foo.js#L2-L5) ## 2. Title Some content ! [See in context](./blob/master/foo.js#L8-L11) `, ); }); });