Skip to main content
Module

std/path/glob_test.ts

Deno standard library
Go to Latest
File
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.import { assert, assertEquals } from "../testing/asserts.ts";import { GlobToRegExpOptions, globToRegExp, isGlob, joinGlobs, normalizeGlob,} from "./glob.ts";import { SEP } from "./mod.ts";
function match( glob: string, path: string, opts: GlobToRegExpOptions = {},): boolean { if (opts.os == null) { const matchDarwin = path.match( globToRegExp(glob, { ...opts, os: "darwin" }), ); if (matchDarwin) { assertEquals(matchDarwin.length, 1); } const matchLinux = path.match(globToRegExp(glob, { ...opts, os: "linux" })); if (matchLinux) { assertEquals(matchLinux.length, 1); } const matchWindows = path.match( globToRegExp(glob, { ...opts, os: "windows" }), ); if (matchWindows) { assertEquals(matchWindows.length, 1); } return !!matchDarwin && !!matchLinux && !!matchWindows; } else { const match = path.match(globToRegExp(glob, opts)); if (match) { assertEquals(match.length, 1); } return !!match; }}
Deno.test({ name: "[path] globToRegExp() Basic RegExp", fn(): void { assertEquals(globToRegExp(""), /^$/); assertEquals(globToRegExp("*.js", { os: "linux" }), /^[^/]*\.js\/*$/); },});
Deno.test({ name: "[path] globToRegExp() * (wildcard)", fn(): void { assert(match("*", "foo", { extended: false, globstar: false })); assert(match("*", "foo", { extended: false, globstar: false })); assert(match("f*", "foo", { extended: false, globstar: false })); assert(match("f*", "foo", { extended: false, globstar: false })); assert(match("*o", "foo", { extended: false, globstar: false })); assert(match("*o", "foo", { extended: false, globstar: false })); assert(match("u*orn", "unicorn", { extended: false, globstar: false })); assert(match("u*orn", "unicorn", { extended: false, globstar: false })); assert(!match("ico", "unicorn", { extended: false, globstar: false })); assert(match("u*nicorn", "unicorn", { extended: false, globstar: false })); assert(match("u*nicorn", "unicorn", { extended: false, globstar: false })); },});
Deno.test({ name: "[path] globToRegExp() ? (match one character)", fn(): void { assert(match("f?o", "foo", { extended: false, globstar: false })); assert(match("f?o?", "fooo", { extended: false, globstar: false })); assert(!match("f?oo", "foo", { extended: false, globstar: false })); assert(!match("?fo", "fooo", { extended: false, globstar: false })); assert(!match("f?oo", "foo", { extended: false, globstar: false })); assert(!match("foo?", "foo", { extended: false, globstar: false })); },});
Deno.test({ name: "[path] globToRegExp() [seq] (character range)", fn(): void { assert(match("fo[oz]", "foo", { extended: false, globstar: false })); assert(match("fo[oz]", "foz", { extended: false, globstar: false })); assert(!match("fo[oz]", "fog", { extended: false, globstar: false })); assert(match("fo[a-z]", "fob", { extended: false, globstar: false })); assert(!match("fo[a-d]", "fot", { extended: false, globstar: false })); assert(!match("fo[!tz]", "fot", { extended: false, globstar: false })); assert(match("fo[!tz]", "fob", { extended: false, globstar: false })); },});
Deno.test({ name: "[path] globToRegExp() [[:alnum:]] (character class in range)", fn(): void { assert( match( "[[:alnum:]]/bar.txt", "a/bar.txt", { extended: false, globstar: false }, ), ); assert( match( "[[:alnum:]abc]/bar.txt", "1/bar.txt", { extended: false, globstar: false }, ), ); assert( match( "[[:digit:]]/bar.txt", "1/bar.txt", { extended: false, globstar: false }, ), ); assert( match( "[[:digit:]b]/bar.txt", "b/bar.txt", { extended: false, globstar: false }, ), ); assert( match( "[![:digit:]b]/bar.txt", "a/bar.txt", { extended: false, globstar: false }, ), ); assert( !match( "[[:alnum:]]/bar.txt", "!/bar.txt", { extended: false, globstar: false }, ), ); assert( !match( "[[:digit:]]/bar.txt", "a/bar.txt", { extended: false, globstar: false }, ), ); assert( !match( "[[:digit:]b]/bar.txt", "a/bar.txt", { extended: false, globstar: false }, ), ); },});
Deno.test({ name: "[path] globToRegExp() {} (brace expansion)", fn(): void { assert( match("foo{bar,baaz}", "foobaaz", { extended: false, globstar: false }), ); assert( match("foo{bar,baaz}", "foobar", { extended: false, globstar: false }), ); assert( !match("foo{bar,baaz}", "foobuzz", { extended: false, globstar: false }), ); assert( match("foo{bar,b*z}", "foobuzz", { extended: false, globstar: false }), ); },});
Deno.test({ name: "[path] globToRegExp() Complex matches", fn(): void { assert( match( "http://?o[oz].b*z.com/{*.js,*.html}", "http://foo.baaz.com/jquery.min.js", { extended: false, globstar: false }, ), ); assert( match( "http://?o[oz].b*z.com/{*.js,*.html}", "http://moz.buzz.com/index.html", { extended: false, globstar: false }, ), ); assert( !match( "http://?o[oz].b*z.com/{*.js,*.html}", "http://moz.buzz.com/index.htm", { extended: false, globstar: false }, ), ); assert( !match( "http://?o[oz].b*z.com/{*.js,*.html}", "http://moz.bar.com/index.html", { extended: false, globstar: false }, ), ); assert( !match( "http://?o[oz].b*z.com/{*.js,*.html}", "http://flozz.buzz.com/index.html", { extended: false, globstar: false }, ), ); },});
Deno.test({ name: "[path] globToRegExp() ** (globstar)", fn(): void { assert(match("/foo/**", "/foo/bar.txt")); assert(match("/foo/**", "/foo/bar/baz.txt")); assert(!match("/foo/**", "/foo/bar/baz.txt", { globstar: false })); assert(match("/foo/**", "/foo/bar", { globstar: false })); assert(match("/foo/**/*.txt", "/foo/bar/baz.txt")); assert(match("/foo/**/*.txt", "/foo/bar/baz/qux.txt")); assert(match("/foo/**/bar.txt", "/foo/bar.txt")); assert(match("/foo/**/**/bar.txt", "/foo/bar.txt")); assert(match("/foo/**/*/baz.txt", "/foo/bar/baz.txt")); assert(match("/foo/**/*.txt", "/foo/bar.txt")); assert(match("/foo/**/**/*.txt", "/foo/bar.txt")); assert(match("/foo/**/*/*.txt", "/foo/bar/baz.txt")); assert(match("**/*.txt", "/foo/bar/baz/qux.txt")); assert(match("**/foo.txt", "foo.txt")); assert(match("**/*.txt", "foo.txt")); assert(!match("/foo/**.txt", "/foo/bar/baz/qux.txt")); assert( !match("/foo/bar**/*.txt", "/foo/bar/baz/qux.txt"), ); assert(!match("/foo/bar**", "/foo/bar/baz.txt")); assert(!match("**/.txt", "/foo/bar/baz/qux.txt")); assert( !match( "http://foo.com/*", "http://foo.com/bar/baz/jquery.min.js", ), ); assert( !match("http://foo.com/*", "http://foo.com/bar/baz/jquery.min.js"), ); assert( match("http://foo.com/**", "http://foo.com/bar/baz/jquery.min.js"), ); assert( match( "http://foo.com/**/jquery.min.js", "http://foo.com/bar/baz/jquery.min.js", ), ); assert( !match( "http://foo.com/*/jquery.min.js", "http://foo.com/bar/baz/jquery.min.js", ), ); },});
Deno.test({ name: "[path] globToRegExp() ?(pattern-list) (extended: match zero or one)", fn(): void { assert(match("?(foo).txt", "foo.txt")); assert(!match("?(foo).txt", "foo.txt", { extended: false })); assert(match("?(foo).txt", "a(foo).txt", { extended: false })); assert(match("?(foo).txt", ".txt")); assert(match("?(foo|bar)baz.txt", "foobaz.txt")); assert(match("?(ba[zr]|qux)baz.txt", "bazbaz.txt")); assert(match("?(ba[zr]|qux)baz.txt", "barbaz.txt")); assert(match("?(ba[zr]|qux)baz.txt", "quxbaz.txt")); assert(match("?(ba[!zr]|qux)baz.txt", "batbaz.txt")); assert(match("?(ba*|qux)baz.txt", "batbaz.txt")); assert(match("?(ba*|qux)baz.txt", "batttbaz.txt")); assert(match("?(ba*|qux)baz.txt", "quxbaz.txt")); assert(match("?(ba?(z|r)|qux)baz.txt", "bazbaz.txt")); assert(match("?(ba?(z|?(r))|qux)baz.txt", "bazbaz.txt")); assert(!match("?(foo|bar)baz.txt", "foobarbaz.txt")); assert(!match("?(ba[zr]|qux)baz.txt", "bazquxbaz.txt")); assert(!match("?(ba[!zr]|qux)baz.txt", "bazbaz.txt")); },});
Deno.test({ name: "[path] globToRegExp() *(pattern-list) (extended: match zero or more)", fn(): void { assert(match("*(foo).txt", "foo.txt")); assert(!match("*(foo).txt", "foo.txt", { extended: false })); assert(match("*(foo).txt", "bar(foo).txt", { extended: false })); assert(match("*(foo).txt", "foofoo.txt")); assert(match("*(foo).txt", ".txt")); assert(match("*(fooo).txt", ".txt")); assert(!match("*(fooo).txt", "foo.txt")); assert(match("*(foo|bar).txt", "foobar.txt")); assert(match("*(foo|bar).txt", "barbar.txt")); assert(match("*(foo|bar).txt", "barfoobar.txt")); assert(match("*(foo|bar).txt", ".txt")); assert(match("*(foo|ba[rt]).txt", "bat.txt")); assert(match("*(foo|b*[rt]).txt", "blat.txt")); assert(!match("*(foo|b*[rt]).txt", "tlat.txt")); assert(match("*(*).txt", "whatever.txt")); assert(match("*(foo|bar)/**/*.txt", "foo/hello/world/bar.txt")); assert(match("*(foo|bar)/**/*.txt", "foo/world/bar.txt")); },});
Deno.test({ name: "[path] globToRegExp() +(pattern-list) (extended: match 1 or more)", fn(): void { assert(match("+(foo).txt", "foo.txt")); assert(!match("+(foo).txt", "foo.txt", { extended: false })); assert(match("+(foo).txt", "+(foo).txt", { extended: false })); assert(!match("+(foo).txt", ".txt")); assert(match("+(foo|bar).txt", "foobar.txt")); },});
Deno.test({ name: "[path] globToRegExp() @(pattern-list) (extended: match one)", fn(): void { assert(match("@(foo).txt", "foo.txt")); assert(!match("@(foo).txt", "foo.txt", { extended: false })); assert(match("@(foo).txt", "@(foo).txt", { extended: false })); assert(match("@(foo|baz)bar.txt", "foobar.txt")); assert(!match("@(foo|baz)bar.txt", "foobazbar.txt")); assert(!match("@(foo|baz)bar.txt", "foofoobar.txt")); assert(!match("@(foo|baz)bar.txt", "toofoobar.txt")); },});
Deno.test({ name: "[path] globToRegExp() !(pattern-list) (extended: match any except)", fn(): void { assert(match("!(boo).txt", "foo.txt")); assert(!match("!(boo).txt", "foo.txt", { extended: false })); assert(match("!(boo).txt", "!(boo).txt", { extended: false })); assert(match("!(foo|baz)bar.txt", "buzbar.txt")); assert(match("!({foo,bar})baz.txt", "notbaz.txt")); assert(!match("!({foo,bar})baz.txt", "foobaz.txt")); },});
Deno.test({ name: "[path] globToRegExp() Special extended characters should match themselves", fn(): void { const glob = "\\/$^+.()=!|,.*"; assert(match(glob, glob)); assert(match(glob, glob, { extended: false })); },});
Deno.test({ name: "[path] globToRegExp() Special extended characters in range", fn(): void { assertEquals(globToRegExp("[?*+@!|]", { os: "linux" }), /^[?*+@!|]\/*$/); assertEquals(globToRegExp("[!?*+@!|]", { os: "linux" }), /^[^?*+@!|]\/*$/); },});
Deno.test({ name: "[path] globToRegExp() Special RegExp characters in range", fn(): void { // Excluding characters checked in the previous test. assertEquals(globToRegExp("[\\$^.=]", { os: "linux" }), /^[\\$^.=]\/*$/); assertEquals(globToRegExp("[!\\$^.=]", { os: "linux" }), /^[^\\$^.=]\/*$/); assertEquals(globToRegExp("[^^]", { os: "linux" }), /^[\^^]\/*$/); },});
Deno.test({ name: "[path] globToRegExp() Repeating separators", fn() { assert(match("foo/bar", "foo//bar")); assert(match("foo//bar", "foo/bar")); assert(match("foo//bar", "foo//bar")); assert(match("**/bar", "foo//bar")); assert(match("**//bar", "foo/bar")); assert(match("**//bar", "foo//bar")); },});
Deno.test({ name: "[path] globToRegExp() Trailing separators", fn() { assert(match("foo", "foo/")); assert(match("foo/", "foo")); assert(match("foo/", "foo/")); assert(match("**", "foo/")); assert(match("**/", "foo")); assert(match("**/", "foo/")); },});
Deno.test({ name: "[path] globToRegExp() Backslashes on Windows", fn() { assert(match("foo/bar", "foo\\bar", { os: "windows" })); assert(match("foo\\bar", "foo/bar", { os: "windows" })); assert(match("foo\\bar", "foo\\bar", { os: "windows" })); assert(match("**/bar", "foo\\bar", { os: "windows" })); assert(match("**\\bar", "foo/bar", { os: "windows" })); assert(match("**\\bar", "foo\\bar", { os: "windows" })); },});
Deno.test({ name: "[path] GlobToRegExpOptions::extended", fn() { const pattern1 = globToRegExp("?(foo|bar)"); assertEquals("foo".match(pattern1)?.[0], "foo"); assertEquals("bar".match(pattern1)?.[0], "bar");
const pattern2 = globToRegExp("?(foo|bar)", { extended: false }); assertEquals("foo".match(pattern2)?.[0], undefined); assertEquals("bar".match(pattern2)?.[0], undefined); assertEquals("?(foo|bar)".match(pattern2)?.[0], "?(foo|bar)"); },});
Deno.test({ name: "[path] GlobToRegExpOptions::globstar", fn() { const pattern1 = globToRegExp("**/foo"); assertEquals("foo".match(pattern1)?.[0], "foo"); assertEquals("path/to/foo".match(pattern1)?.[0], "path/to/foo");
const pattern2 = globToRegExp("**/foo", { globstar: false }); assertEquals("foo".match(pattern2)?.[0], undefined); assertEquals("path/to/foo".match(pattern2)?.[0], undefined); assertEquals("path-to/foo".match(pattern2)?.[0], "path-to/foo"); },});
Deno.test({ name: "[path] GlobToRegExpOptions::os", fn() { const pattern1 = globToRegExp("foo/bar", { os: "linux" }); assertEquals("foo/bar".match(pattern1)?.[0], "foo/bar"); assertEquals("foo\\bar".match(pattern1)?.[0], undefined);
const pattern2 = globToRegExp("foo/bar", { os: "windows" }); assertEquals("foo/bar".match(pattern2)?.[0], "foo/bar"); assertEquals("foo\\bar".match(pattern2)?.[0], "foo\\bar"); },});
Deno.test({ name: "[path] isGlob()", fn(): void { // should be true if valid glob pattern assert(isGlob("!foo.js")); assert(isGlob("*.js")); assert(isGlob("!*.js")); assert(isGlob("!foo")); assert(isGlob("!foo.js")); assert(isGlob("**/abc.js")); assert(isGlob("abc/*.js")); assert(isGlob("@.(?:abc)")); assert(isGlob("@.(?!abc)"));
// should be false if invalid glob pattern assert(!isGlob("")); assert(!isGlob("~/abc")); assert(!isGlob("~/abc")); assert(!isGlob("~/(abc)")); assert(!isGlob("+~(abc)")); assert(!isGlob(".")); assert(!isGlob("@.(abc)")); assert(!isGlob("aa")); assert(!isGlob("who?")); assert(!isGlob("why!?")); assert(!isGlob("where???")); assert(!isGlob("abc!/def/!ghi.js")); assert(!isGlob("abc.js")); assert(!isGlob("abc/def/!ghi.js")); assert(!isGlob("abc/def/ghi.js"));
// Should be true if path has regex capture group assert(isGlob("abc/(?!foo).js")); assert(isGlob("abc/(?:foo).js")); assert(isGlob("abc/(?=foo).js")); assert(isGlob("abc/(a|b).js")); assert(isGlob("abc/(a|b|c).js")); assert(isGlob("abc/(foo bar)/*.js"));
// Should be false if the path has parens but is not a valid capture group assert(!isGlob("abc/(?foo).js")); assert(!isGlob("abc/(a b c).js")); assert(!isGlob("abc/(ab).js")); assert(!isGlob("abc/(abc).js")); assert(!isGlob("abc/(foo bar).js"));
// should be false if the capture group is imbalanced assert(!isGlob("abc/(?ab.js")); assert(!isGlob("abc/(ab.js")); assert(!isGlob("abc/(a|b.js")); assert(!isGlob("abc/(a|b|c.js"));
// should be true if the path has a regex character class assert(isGlob("abc/[abc].js")); assert(isGlob("abc/[^abc].js")); assert(isGlob("abc/[1-3].js"));
// should be false if the character class is not balanced assert(!isGlob("abc/[abc.js")); assert(!isGlob("abc/[^abc.js")); assert(!isGlob("abc/[1-3.js"));
// should be false if the character class is escaped assert(!isGlob("abc/\\[abc].js")); assert(!isGlob("abc/\\[^abc].js")); assert(!isGlob("abc/\\[1-3].js"));
// should be true if the path has brace characters assert(isGlob("abc/{a,b}.js")); assert(isGlob("abc/{a..z}.js")); assert(isGlob("abc/{a..z..2}.js"));
// should be false if (basic) braces are not balanced assert(!isGlob("abc/\\{a,b}.js")); assert(!isGlob("abc/\\{a..z}.js")); assert(!isGlob("abc/\\{a..z..2}.js"));
// should be true if the path has regex characters assert(isGlob("!&(abc)")); assert(isGlob("!*.js")); assert(isGlob("!foo")); assert(isGlob("!foo.js")); assert(isGlob("**/abc.js")); assert(isGlob("*.js")); assert(isGlob("*z(abc)")); assert(isGlob("[1-10].js")); assert(isGlob("[^abc].js")); assert(isGlob("[a-j]*[^c]b/c")); assert(isGlob("[abc].js")); assert(isGlob("a/b/c/[a-z].js")); assert(isGlob("abc/(aaa|bbb).js")); assert(isGlob("abc/*.js")); assert(isGlob("abc/{a,b}.js")); assert(isGlob("abc/{a..z..2}.js")); assert(isGlob("abc/{a..z}.js"));
assert(!isGlob("$(abc)")); assert(!isGlob("&(abc)")); assert(!isGlob("Who?.js")); assert(!isGlob("? (abc)")); assert(!isGlob("?.js")); assert(!isGlob("abc/?.js"));
// should be false if regex characters are escaped assert(!isGlob("\\?.js")); assert(!isGlob("\\[1-10\\].js")); assert(!isGlob("\\[^abc\\].js")); assert(!isGlob("\\[a-j\\]\\*\\[^c\\]b/c")); assert(!isGlob("\\[abc\\].js")); assert(!isGlob("\\a/b/c/\\[a-z\\].js")); assert(!isGlob("abc/\\(aaa|bbb).js")); assert(!isGlob("abc/\\?.js")); },});
Deno.test("[path] normalizeGlob() Globstar", function (): void { assertEquals(normalizeGlob(`**${SEP}..`, { globstar: true }), `**${SEP}..`);});
Deno.test("[path] joinGlobs() Globstar", function (): void { assertEquals(joinGlobs(["**", ".."], { globstar: true }), `**${SEP}..`);});