diff --git a/index.d.ts b/index.d.ts index b9571a6..6a84d28 100644 --- a/index.d.ts +++ b/index.d.ts @@ -4,7 +4,7 @@ import {Options as FastGlobOptions, Entry} from 'fast-glob'; export type GlobEntry = Entry; export interface GlobTask { - readonly pattern: string; + readonly patterns: string[]; readonly options: Options; } @@ -141,6 +141,16 @@ Note that you should avoid running the same tasks multiple times as they contain export function generateGlobTasks( patterns: string | readonly string[], options?: Options +): Promise; + +/** +@see generateGlobTasks + +@returns An object in the format `{pattern: string, options: object}`, which can be passed as arguments to [`fast-glob`](https://github.com/mrmlnc/fast-glob). This is useful for other globbing-related packages. +*/ +export function generateGlobTasksSync( + patterns: string | readonly string[], + options?: Options ): GlobTask[]; /** diff --git a/index.js b/index.js index 75a6092..26630a2 100644 --- a/index.js +++ b/index.js @@ -49,7 +49,8 @@ const normalizeOptions = (options = {}) => { return options; }; -const normalizeArguments = fn => (patterns, options) => fn(toPatternsArray(patterns), normalizeOptions(options)); +const normalizeArguments = fn => async (patterns, options) => fn(toPatternsArray(patterns), normalizeOptions(options)); +const normalizeArgumentsSync = fn => (patterns, options) => fn(toPatternsArray(patterns), normalizeOptions(options)); const getFilter = async options => createFilterFunction( options.gitignore && await isGitIgnored({cwd: options.cwd, ignore: options.ignore}), @@ -71,7 +72,7 @@ const createFilterFunction = isIgnored => { const unionFastGlobResults = (results, filter) => results.flat().filter(fastGlobResult => filter(fastGlobResult)); const unionFastGlobStreams = (streams, filter) => merge2(streams).pipe(new FilterStream(fastGlobResult => filter(fastGlobResult))); -const generateGlobTasksInternal = (patterns, taskOptions) => { +const convertNegativePatterns = (patterns, taskOptions) => { const globTasks = []; for (const [index, pattern] of patterns.entries()) { if (isNegative(pattern)) { @@ -88,7 +89,7 @@ const generateGlobTasksInternal = (patterns, taskOptions) => { ignore: [...taskOptions.ignore, ...ignore], }; - globTasks.push({pattern, options}); + globTasks.push({patterns: [pattern], options}); } return globTasks; @@ -100,7 +101,7 @@ const getDirGlobOptions = (options, cwd) => ({ }); const generateTasks = async (patterns, options) => { - const globTasks = generateGlobTasksInternal(patterns, options); + const globTasks = convertNegativePatterns(patterns, options); const {cwd, expandDirectories} = options; @@ -113,24 +114,23 @@ const generateTasks = async (patterns, options) => { return Promise.all( globTasks.map(async task => { - const {pattern, options} = task; + let {patterns, options} = task; - const [ + [ patterns, - ignore, + options.ignore, ] = await Promise.all([ - dirGlob(pattern, patternExpandOptions), + dirGlob(patterns, patternExpandOptions), dirGlob(options.ignore, ignoreExpandOptions), ]); - options.ignore = ignore; - return {pattern: patterns, options}; + return {patterns, options}; }), ); }; const generateTasksSync = (patterns, options) => { - const globTasks = generateGlobTasksInternal(patterns, options); + const globTasks = convertNegativePatterns(patterns, options); const {cwd, expandDirectories} = options; @@ -142,17 +142,14 @@ const generateTasksSync = (patterns, options) => { const ignoreExpandOptions = cwd ? {cwd} : undefined; return globTasks.map(task => { - const {pattern, options} = task; - const patterns = dirGlob.sync(pattern, patternExpandOptions); + let {patterns, options} = task; + patterns = dirGlob.sync(patterns, patternExpandOptions); options.ignore = dirGlob.sync(options.ignore, ignoreExpandOptions); - return {pattern: patterns, options}; + return {patterns, options}; }); }; -export const globby = async (patterns, options) => { - patterns = toPatternsArray(patterns); - options = normalizeOptions(options); - +export const globby = normalizeArguments(async (patterns, options) => { const [ tasks, filter, @@ -160,32 +157,33 @@ export const globby = async (patterns, options) => { generateTasks(patterns, options), getFilter(options), ]); - const results = await Promise.all(tasks.map(task => fastGlob(task.pattern, task.options))); + const results = await Promise.all(tasks.map(task => fastGlob(task.patterns, task.options))); return unionFastGlobResults(results, filter); -}; +}); -export const globbySync = normalizeArguments((patterns, options) => { +export const globbySync = normalizeArgumentsSync((patterns, options) => { const tasks = generateTasksSync(patterns, options); const filter = getFilterSync(options); - const results = tasks.map(task => fastGlob.sync(task.pattern, task.options)); + const results = tasks.map(task => fastGlob.sync(task.patterns, task.options)); return unionFastGlobResults(results, filter); }); -export const globbyStream = normalizeArguments((patterns, options) => { +export const globbyStream = normalizeArgumentsSync((patterns, options) => { const tasks = generateTasksSync(patterns, options); const filter = getFilterSync(options); - const streams = tasks.map(task => fastGlob.stream(task.pattern, task.options)); + const streams = tasks.map(task => fastGlob.stream(task.patterns, task.options)); return unionFastGlobStreams(streams, filter); }); -export const isDynamicPattern = normalizeArguments( +export const isDynamicPattern = normalizeArgumentsSync( (patterns, options) => patterns.some(pattern => fastGlob.isDynamicPattern(pattern, options)), ); -export const generateGlobTasks = normalizeArguments(generateGlobTasksInternal); +export const generateGlobTasks = normalizeArguments(generateTasks); +export const generateGlobTasksSync = normalizeArgumentsSync(generateTasksSync); export { isGitIgnored, diff --git a/index.test-d.ts b/index.test-d.ts index c3b0c86..e6bc5f5 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -9,6 +9,7 @@ import { globbySync, globbyStream, generateGlobTasks, + generateGlobTasksSync, isDynamicPattern, isGitIgnored, isGitIgnoredSync, @@ -83,14 +84,14 @@ expectType(globbyStream('*.tmp', {ignore: ['**/b.tmp']})) })(); // GenerateGlobTasks -expectType(generateGlobTasks('*.tmp')); -expectType(generateGlobTasks(['a.tmp', '*.tmp', '!{c,d,e}.tmp'])); +expectType>(generateGlobTasks('*.tmp')); +expectType>(generateGlobTasks(['a.tmp', '*.tmp', '!{c,d,e}.tmp'])); -expectType(generateGlobTasks('*.tmp', {expandDirectories: false})); -expectType( +expectType>(generateGlobTasks('*.tmp', {expandDirectories: false})); +expectType>( generateGlobTasks('*.tmp', {expandDirectories: ['a*', 'b*']}), ); -expectType( +expectType>( generateGlobTasks('*.tmp', { expandDirectories: { files: ['a', 'b'], @@ -98,8 +99,27 @@ expectType( }, }), ); -expectType(generateGlobTasks('*.tmp', {gitignore: true})); -expectType(generateGlobTasks('*.tmp', {ignore: ['**/b.tmp']})); +expectType>(generateGlobTasks('*.tmp', {gitignore: true})); +expectType>(generateGlobTasks('*.tmp', {ignore: ['**/b.tmp']})); + +// GenerateGlobTasksSync +expectType(generateGlobTasksSync('*.tmp')); +expectType(generateGlobTasksSync(['a.tmp', '*.tmp', '!{c,d,e}.tmp'])); + +expectType(generateGlobTasksSync('*.tmp', {expandDirectories: false})); +expectType( + generateGlobTasksSync('*.tmp', {expandDirectories: ['a*', 'b*']}), +); +expectType( + generateGlobTasksSync('*.tmp', { + expandDirectories: { + files: ['a', 'b'], + extensions: ['tmp'], + }, + }), +); +expectType(generateGlobTasksSync('*.tmp', {gitignore: true})); +expectType(generateGlobTasksSync('*.tmp', {ignore: ['**/b.tmp']})); // IsDynamicPattern expectType(isDynamicPattern('**')); diff --git a/package.json b/package.json index 7c51dbe..791ea12 100644 --- a/package.json +++ b/package.json @@ -81,5 +81,10 @@ "ignores": [ "fixtures" ] + }, + "ava": { + "files": [ + "!tests/utilities.js" + ] } } diff --git a/readme.md b/readme.md index 315a53b..32d76ed 100644 --- a/readme.md +++ b/readme.md @@ -110,10 +110,16 @@ import {globbyStream} from 'globby'; ### generateGlobTasks(patterns, options?) -Returns an `object[]` in the format `{pattern: string, options: Object}`, which can be passed as arguments to [`fast-glob`](https://github.com/mrmlnc/fast-glob). This is useful for other globbing-related packages. +Returns an `Promise` in the format `{patterns: string[], options: Object}`, which can be passed as arguments to [`fast-glob`](https://github.com/mrmlnc/fast-glob). This is useful for other globbing-related packages. Note that you should avoid running the same tasks multiple times as they contain a file system cache. Instead, run this method each time to ensure file system changes are taken into consideration. +### generateGlobTasksSync(patterns, options?) + +Returns an `object[]` in the format `{patterns: string[], options: Object}`, which can be passed as arguments to [`fast-glob`](https://github.com/mrmlnc/fast-glob). This is useful for other globbing-related packages. + +Takes the same arguments as `generateGlobTasks`. + ### isDynamicPattern(patterns, options?) Returns a `boolean` of whether there are any special glob characters in the `patterns`. diff --git a/tests/generate-glob-tasks.js b/tests/generate-glob-tasks.js new file mode 100644 index 0000000..738c4f7 --- /dev/null +++ b/tests/generate-glob-tasks.js @@ -0,0 +1,101 @@ +import util from 'node:util'; +import process from 'node:process'; +import path from 'node:path'; +import test from 'ava'; +import { + generateGlobTasks, + generateGlobTasksSync, +} from '../index.js'; +import { + invalidPatterns, + getPathValues, +} from './utilities.js'; + +const runGenerateGlobTasks = async (t, patterns, options) => { + const promiseResult = await generateGlobTasks(patterns, options); + const syncResult = generateGlobTasksSync(patterns, options); + + t.deepEqual( + promiseResult, + syncResult, + 'generateGlobTasksSync() result is different than generateGlobTasks()', + ); + + return promiseResult; +}; + +test('generateGlobTasks', async t => { + const tasks = await runGenerateGlobTasks(t, ['*.tmp', '!b.tmp'], {ignore: ['c.tmp']}); + + t.is(tasks.length, 1); + t.deepEqual(tasks[0].patterns, ['*.tmp']); + t.deepEqual(tasks[0].options.ignore, ['c.tmp', 'b.tmp']); + await t.notThrowsAsync(generateGlobTasks('*')); + t.notThrows(() => generateGlobTasksSync('*')); +}); + +// Rejected for being an invalid pattern +for (const value of invalidPatterns) { + const valueString = util.format(value); + const message = 'Patterns must be a string or an array of strings'; + + test(`throws for invalid patterns input: ${valueString}`, async t => { + await t.throwsAsync(generateGlobTasks(value), {instanceOf: TypeError, message}); + t.throws(() => generateGlobTasksSync(value), {instanceOf: TypeError, message}); + }); +} + +test('throws when specifying a file as cwd', async t => { + const error = {message: 'The `cwd` option must be a path to a directory'}; + + for (const file of getPathValues(path.resolve('fixtures/gitignore/bar.js'))) { + // eslint-disable-next-line no-await-in-loop + await t.throwsAsync(generateGlobTasks('*', {cwd: file}), error); + t.throws(() => generateGlobTasksSync('*', {cwd: file}), error); + } +}); + +test('cwd', async t => { + const cwd = process.cwd(); + for (const cwdDirectory of getPathValues(cwd)) { + // eslint-disable-next-line no-await-in-loop + const [task] = await runGenerateGlobTasks(t, ['*'], {cwd: cwdDirectory}); + t.is(task.options.cwd, cwd); + } +}); + +test('expandDirectories option', async t => { + { + const tasks = await runGenerateGlobTasks(t, ['fixtures'], {ignore: ['fixtures/negative']}); + t.is(tasks.length, 1); + t.deepEqual(tasks[0].patterns, ['fixtures/**']); + t.deepEqual(tasks[0].options.ignore, ['fixtures/negative/**']); + } + + { + const tasks = await runGenerateGlobTasks(t, ['fixtures'], {ignore: ['fixtures/negative'], expandDirectories: false}); + t.is(tasks.length, 1); + t.deepEqual(tasks[0].patterns, ['fixtures']); + t.deepEqual(tasks[0].options.ignore, ['fixtures/negative']); + } + + { + const tasks = await runGenerateGlobTasks(t, ['fixtures'], {expandDirectories: ['a*', 'b*']}); + t.is(tasks.length, 1); + t.deepEqual(tasks[0].patterns, ['fixtures/**/a*', 'fixtures/**/b*']); + t.deepEqual(tasks[0].options.ignore, []); + } + + { + const tasks = await runGenerateGlobTasks(t, ['fixtures'], { + expandDirectories: { + files: ['a', 'b*'], + extensions: ['tmp', 'txt'], + }, + ignore: ['**/b.tmp'], + }); + t.is(tasks.length, 1); + t.deepEqual(tasks[0].patterns, ['fixtures/**/a.{tmp,txt}', 'fixtures/**/b*.{tmp,txt}']); + t.deepEqual(tasks[0].options.ignore, ['**/b.tmp']); + } +}); diff --git a/gitignore.test.js b/tests/gitignore.js similarity index 75% rename from gitignore.test.js rename to tests/gitignore.js index 1baaba3..5fc8c00 100644 --- a/gitignore.test.js +++ b/tests/gitignore.js @@ -1,14 +1,14 @@ import path from 'node:path'; -import {fileURLToPath, pathToFileURL} from 'node:url'; import test from 'ava'; import slash from 'slash'; -import {isGitIgnored, isGitIgnoredSync} from './gitignore.js'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const getPathValues = cwd => [cwd, pathToFileURL(cwd)]; +import {isGitIgnored, isGitIgnoredSync} from '../gitignore.js'; +import { + PROJECT_ROOT, + getPathValues, +} from './utilities.js'; test('gitignore', async t => { - for (const cwd of getPathValues(path.join(__dirname, 'fixtures/gitignore'))) { + for (const cwd of getPathValues(path.join(PROJECT_ROOT, 'fixtures/gitignore'))) { // eslint-disable-next-line no-await-in-loop const isIgnored = await isGitIgnored({cwd}); const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file)); @@ -18,7 +18,7 @@ test('gitignore', async t => { }); test('gitignore - mixed path styles', async t => { - const directory = path.join(__dirname, 'fixtures/gitignore'); + const directory = path.join(PROJECT_ROOT, 'fixtures/gitignore'); for (const cwd of getPathValues(directory)) { // eslint-disable-next-line no-await-in-loop const isIgnored = await isGitIgnored({cwd}); @@ -27,7 +27,7 @@ test('gitignore - mixed path styles', async t => { }); test('gitignore - os paths', async t => { - const directory = path.join(__dirname, 'fixtures/gitignore'); + const directory = path.join(PROJECT_ROOT, 'fixtures/gitignore'); for (const cwd of getPathValues(directory)) { // eslint-disable-next-line no-await-in-loop const isIgnored = await isGitIgnored({cwd}); @@ -36,7 +36,7 @@ test('gitignore - os paths', async t => { }); test('gitignore - sync', t => { - for (const cwd of getPathValues(path.join(__dirname, 'fixtures/gitignore'))) { + for (const cwd of getPathValues(path.join(PROJECT_ROOT, 'fixtures/gitignore'))) { const isIgnored = isGitIgnoredSync({cwd}); const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file)); const expected = ['bar.js']; @@ -47,7 +47,7 @@ test('gitignore - sync', t => { test('ignore ignored .gitignore', async t => { const ignore = ['**/.gitignore']; - for (const cwd of getPathValues(path.join(__dirname, 'fixtures/gitignore'))) { + for (const cwd of getPathValues(path.join(PROJECT_ROOT, 'fixtures/gitignore'))) { // eslint-disable-next-line no-await-in-loop const isIgnored = await isGitIgnored({cwd, ignore}); const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file)); @@ -59,7 +59,7 @@ test('ignore ignored .gitignore', async t => { test('ignore ignored .gitignore - sync', t => { const ignore = ['**/.gitignore']; - for (const cwd of getPathValues(path.join(__dirname, 'fixtures/gitignore'))) { + for (const cwd of getPathValues(path.join(PROJECT_ROOT, 'fixtures/gitignore'))) { const isIgnored = isGitIgnoredSync({cwd, ignore}); const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file)); const expected = ['foo.js', 'bar.js']; @@ -68,7 +68,7 @@ test('ignore ignored .gitignore - sync', t => { }); test('negative gitignore', async t => { - for (const cwd of getPathValues(path.join(__dirname, 'fixtures/negative'))) { + for (const cwd of getPathValues(path.join(PROJECT_ROOT, 'fixtures/negative'))) { // eslint-disable-next-line no-await-in-loop const isIgnored = await isGitIgnored({cwd}); const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file)); @@ -78,7 +78,7 @@ test('negative gitignore', async t => { }); test('negative gitignore - sync', t => { - for (const cwd of getPathValues(path.join(__dirname, 'fixtures/negative'))) { + for (const cwd of getPathValues(path.join(PROJECT_ROOT, 'fixtures/negative'))) { const isIgnored = isGitIgnoredSync({cwd}); const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file)); const expected = ['foo.js']; @@ -87,7 +87,7 @@ test('negative gitignore - sync', t => { }); test('multiple negation', async t => { - for (const cwd of getPathValues(path.join(__dirname, 'fixtures/multiple-negation'))) { + for (const cwd of getPathValues(path.join(PROJECT_ROOT, 'fixtures/multiple-negation'))) { // eslint-disable-next-line no-await-in-loop const isIgnored = await isGitIgnored({cwd}); @@ -104,7 +104,7 @@ test('multiple negation', async t => { }); test('multiple negation - sync', t => { - for (const cwd of getPathValues(path.join(__dirname, 'fixtures/multiple-negation'))) { + for (const cwd of getPathValues(path.join(PROJECT_ROOT, 'fixtures/multiple-negation'))) { const isIgnored = isGitIgnoredSync({cwd}); const actual = [ @@ -120,7 +120,7 @@ test('multiple negation - sync', t => { }); test('check file', async t => { - const directory = path.join(__dirname, 'fixtures/gitignore'); + const directory = path.join(PROJECT_ROOT, 'fixtures/gitignore'); const ignoredFile = path.join(directory, 'foo.js'); const isIgnored = await isGitIgnored({cwd: directory}); const isIgnoredSync = isGitIgnoredSync({cwd: directory}); diff --git a/test.js b/tests/globby.js similarity index 86% rename from test.js rename to tests/globby.js index 18ea844..29ab1bd 100644 --- a/test.js +++ b/tests/globby.js @@ -2,7 +2,6 @@ import process from 'node:process'; import fs from 'node:fs'; import path from 'node:path'; import util from 'node:util'; -import {fileURLToPath, pathToFileURL} from 'node:url'; import test from 'ava'; import getStream from 'get-stream'; import { @@ -10,10 +9,13 @@ import { globbySync, globbyStream, isDynamicPattern, - generateGlobTasks, -} from './index.js'; +} from '../index.js'; +import { + PROJECT_ROOT, + getPathValues, + invalidPatterns, +} from './utilities.js'; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); const cwd = process.cwd(); const temporary = 'tmp'; @@ -25,8 +27,6 @@ const fixture = [ 'e.tmp', ]; -const getCwdValues = cwd => [cwd, pathToFileURL(cwd)]; - const stabilizeResult = result => result .map(fastGlobResult => { // In `objectMode`, `fastGlobResult.dirent` contains a function that makes `t.deepEqual` assertion fail. @@ -68,14 +68,14 @@ test.before(() => { for (const element of fixture) { fs.writeFileSync(element, ''); - fs.writeFileSync(path.join(__dirname, temporary, element), ''); + fs.writeFileSync(path.join(PROJECT_ROOT, temporary, element), ''); } }); test.after(() => { for (const element of fixture) { fs.unlinkSync(element); - fs.unlinkSync(path.join(__dirname, temporary, element)); + fs.unlinkSync(path.join(PROJECT_ROOT, temporary, element)); } fs.rmdirSync(temporary); @@ -123,28 +123,19 @@ test('don\'t mutate the options object - async', async t => { t.pass(); }); -test('expose generateGlobTasks', t => { - const tasks = generateGlobTasks(['*.tmp', '!b.tmp'], {ignore: ['c.tmp']}); - - t.is(tasks.length, 1); - t.is(tasks[0].pattern, '*.tmp'); - t.deepEqual(tasks[0].options.ignore, ['c.tmp', 'b.tmp']); - t.notThrows(() => generateGlobTasks('*')); -}); - test('expose isDynamicPattern', t => { t.true(isDynamicPattern('**')); t.true(isDynamicPattern(['**', 'path1', 'path2'])); t.false(isDynamicPattern(['path1', 'path2'])); - for (const cwdDirectory of getCwdValues(cwd)) { + for (const cwdDirectory of getPathValues(cwd)) { t.true(isDynamicPattern('**', {cwd: cwdDirectory})); } }); test('expandDirectories option', async t => { t.deepEqual(await runGlobby(t, temporary), ['tmp/a.tmp', 'tmp/b.tmp', 'tmp/c.tmp', 'tmp/d.tmp', 'tmp/e.tmp']); - for (const temporaryDirectory of getCwdValues(temporary)) { + for (const temporaryDirectory of getPathValues(temporary)) { // eslint-disable-next-line no-await-in-loop t.deepEqual(await runGlobby(t, '**', {cwd: temporaryDirectory}), ['a.tmp', 'b.tmp', 'c.tmp', 'd.tmp', 'e.tmp']); } @@ -189,7 +180,7 @@ test('expandDirectories and ignores option', async t => { test.serial.failing('relative paths and ignores option', async t => { process.chdir(temporary); - for (const cwd of getCwdValues(process.cwd())) { + for (const cwd of getPathValues(process.cwd())) { // eslint-disable-next-line no-await-in-loop t.deepEqual(await runGlobby(t, '../tmp', { cwd, @@ -201,32 +192,14 @@ test.serial.failing('relative paths and ignores option', async t => { }); // Rejected for being an invalid pattern -for (const value of [ - {}, - [{}], - true, - [true], - false, - [false], - null, - [null], - undefined, - [undefined], - Number.NaN, - [Number.NaN], - 5, - [5], - function () {}, - [function () {}], -]) { +for (const value of invalidPatterns) { const valueString = util.format(value); const message = 'Patterns must be a string or an array of strings'; test(`throws for invalid patterns input: ${valueString}`, async t => { - await t.throwsAsync(globby(t, value), {instanceOf: TypeError, message}); + await t.throwsAsync(globby(value), {instanceOf: TypeError, message}); t.throws(() => globbySync(value), {instanceOf: TypeError, message}); t.throws(() => globbyStream(value), {instanceOf: TypeError, message}); - t.throws(() => generateGlobTasks(value), {instanceOf: TypeError, message}); t.throws(() => isDynamicPattern(value), {instanceOf: TypeError, message}); }); } @@ -264,7 +237,7 @@ test('gitignore option and objectMode option', async t => { }); test('`{extension: false}` and `expandDirectories.extensions` option', async t => { - for (const temporaryDirectory of getCwdValues(temporary)) { + for (const temporaryDirectory of getPathValues(temporary)) { t.deepEqual( // eslint-disable-next-line no-await-in-loop await runGlobby(t, '*', { @@ -291,7 +264,7 @@ test('`{extension: false}` and `expandDirectories.extensions` option', async t = test('throws when specifying a file as cwd', async t => { const error = {message: 'The `cwd` option must be a path to a directory'}; - for (const file of getCwdValues(path.resolve('fixtures/gitignore/bar.js'))) { + for (const file of getPathValues(path.resolve('fixtures/gitignore/bar.js'))) { // eslint-disable-next-line no-await-in-loop await t.throwsAsync(globby('.', {cwd: file}), error); // eslint-disable-next-line no-await-in-loop @@ -304,7 +277,7 @@ test('throws when specifying a file as cwd', async t => { }); test('throws when specifying a file as cwd - isDynamicPattern', t => { - for (const file of getCwdValues(path.resolve('fixtures/gitignore/bar.js'))) { + for (const file of getPathValues(path.resolve('fixtures/gitignore/bar.js'))) { t.throws(() => { isDynamicPattern('.', {cwd: file}); }, {message: 'The `cwd` option must be a path to a directory'}); @@ -316,7 +289,7 @@ test('throws when specifying a file as cwd - isDynamicPattern', t => { }); test('don\'t throw when specifying a non-existing cwd directory', async t => { - for (const cwd of getCwdValues('/unknown')) { + for (const cwd of getPathValues('/unknown')) { // eslint-disable-next-line no-await-in-loop const actual = await runGlobby(t, '.', {cwd}); t.is(actual.length, 0); diff --git a/tests/utilities.js b/tests/utilities.js new file mode 100644 index 0000000..d50a054 --- /dev/null +++ b/tests/utilities.js @@ -0,0 +1,22 @@ +import {fileURLToPath, pathToFileURL} from 'node:url'; + +export const PROJECT_ROOT = fileURLToPath(new URL('../', import.meta.url)); +export const getPathValues = path => [path, pathToFileURL(path)]; +export const invalidPatterns = [ + {}, + [{}], + true, + [true], + false, + [false], + null, + [null], + undefined, + [undefined], + Number.NaN, + [Number.NaN], + 5, + [5], + function () {}, + [function () {}], +];