import path from "path" ; import { TextDecoder } from "util" ; import { addAll , base64Decode , base64Encode , globsToMatcher , kebabCase , nonCircularClone , resolveStoragePersist , sanitisePath , spaceCase , titleCase , viewToArray , viewToBuffer , } from "@miniflare/shared" ; import { useTmp } from "@miniflare/shared-test" ; import test from "ava" ; test ( "nonCircularClone: creates copy of data" , ( t ) => { const original = { a : 1 , b : { c : "2" } } ; const clone = nonCircularClone ( original ) ; t . not ( original , clone ) ; t . not ( original . b , clone . b ) ; t . deepEqual ( original , clone ) ; } ) ; test ( "addAll: adds all elements to set" , ( t ) => { const set = new Set < string > ( ) ; addAll ( set , [ "a" , "b" , "c" ] ) ; t . true ( set . has ( "a" ) ) ; t . true ( set . has ( "b" ) ) ; t . true ( set . has ( "c" ) ) ; } ) ; test ( "viewToArray: converts ArrayBufferView to Uint8Array" , ( t ) => { const array = viewToArray ( Buffer . from ( "test" ) ) ; t . is ( new TextDecoder ( ) . decode ( array ) , "test" ) ; } ) ; test ( "viewToBuffer: converts ArrayBufferView to ArrayBuffer" , ( t ) => { const buffer = viewToBuffer ( Buffer . from ( "test" ) ) ; t . is ( new TextDecoder ( ) . decode ( buffer ) , "test" ) ; } ) ; test ( "base64Encode: encodes base64 string" , ( t ) => { t . is ( base64Encode ( "test ✅" ) , "dGVzdCDinIU=" ) ; } ) ; test ( "base64Decode: decodes base64 string" , ( t ) => { t . is ( base64Decode ( "dGVzdCDinIU=" ) , "test ✅" ) ; } ) ; test ( "globsToMatcher: converts globs to string matcher" , ( t ) => { const globs = [ "*.txt" , "src/**/*.js" , "!src/bad.js" ] ; const matcher = globsToMatcher ( globs ) ; t . true ( matcher . test ( "test.txt" ) ) ; t . true ( matcher . test ( "dist/test.txt" ) ) ; t . true ( matcher . test ( "src/index.js" ) ) ; t . true ( matcher . test ( "src/lib/add.js" ) ) ; t . false ( matcher . test ( "src/bad.js" ) ) ; t . is ( matcher . toString ( ) , globs . join ( ", " ) ) ; } ) ; test ( "globsToMatcher: returns matcher that matches nothing on undefined globs" , ( t ) => { const matcher = globsToMatcher ( ) ; t . false ( matcher . test ( "test.txt" ) ) ; t . is ( matcher . toString ( ) , "" ) ; } ) ; test ( "kebabCase: converts string from camelCase to kebab-case" , ( t ) => { t . is ( kebabCase ( "optionOneName" ) , "option-one-name" ) ; } ) ; test ( "spaceCase: converts string from PascalCase or camelCase to space case" , ( t ) => { t . is ( spaceCase ( "HTTPPlugin" ) , "HTTP Plugin" ) ; t . is ( spaceCase ( "optionOneName" ) , "option One Name" ) ; } ) ; test ( "titleCase: converts string from PascalCase or camelCase to Title Case" , ( t ) => { t . is ( titleCase ( "HTTPPlugin" ) , "HTTP Plugin" ) ; t . is ( titleCase ( "optionOneName" ) , "Option One Name" ) ; } ) ; test ( "resolveStoragePersist: resolves file system paths relative to root" , async ( t ) => { const tmp = await useTmp ( t ) ; const tmp2 = await useTmp ( t ) ; t . is ( resolveStoragePersist ( tmp , "data" ) , path . resolve ( tmp , "data" ) ) ; t . is ( resolveStoragePersist ( tmp , tmp2 ) , tmp2 ) ; } ) ; test ( "resolveStoragePersist: leaves other paths untouched" , ( t ) => { t . is ( resolveStoragePersist ( "/root" ) , undefined ) ; t . is ( resolveStoragePersist ( "/root" , false ) , false ) ; t . is ( resolveStoragePersist ( "/root" , true ) , true ) ; t . is ( resolveStoragePersist ( "/root" , "redis://localhost:6379" ) , "redis://localhost:6379" ) ; } ) ; test ( "sanitisePath: doesn't change safe paths" , ( t ) => { t . is ( sanitisePath ( "test file.txt" ) , "test file.txt" ) ; t . is ( sanitisePath ( "tést filé.txt" ) , "tést filé.txt" ) ; } ) ; test ( "sanitisePath: sanitises namespace separators" , ( t ) => { const s = path . sep ; t . is ( sanitisePath ( "a/b\\c:d|e" ) , `a${ s }b${ s }c${ s }d${ s }e` ) ; } ) ; test ( "sanitisePath: sanitises relative paths" , ( t ) => { const s = path . sep ; t . is ( sanitisePath ( "." ) , "_" ) ; t . is ( sanitisePath ( ".." ) , "__" ) ; t . is ( sanitisePath ( "./" ) , "__" ) ; t . is ( sanitisePath ( "../" ) , "___" ) ; t . is ( sanitisePath ( "./.." ) , `_${ s }__` ) ; t . is ( sanitisePath ( "./../" ) , `_${ s }___` ) ; t . is ( sanitisePath ( "..\\./.../..\\..../.a./." ) , `__${ s }_${ s }___${ s }__${ s }____${ s }.a.${ s }_` ) ; t . is ( sanitisePath ( "dir/../test.txt" ) , `dir${ s }__${ s }test.txt` ) ; } ) ; test ( "sanitisePath: sanitises illegal characters" , ( t ) => { t . is ( sanitisePath ( "?.text" ) , "_.text" ) ; t . is ( sanitisePath ( "h<ll*.txt" ) , "h_ll_.txt" ) ; t . is ( sanitisePath ( ">\"'^new\nline" ) , "____new_line" ) ; } ) ; test ( "sanitisePath: sanitises reserved filenames" , ( t ) => { t . is ( sanitisePath ( "CON" ) , "_" ) ; t . is ( sanitisePath ( "com4" ) , "_" ) ; t . is ( sanitisePath ( "PRN." ) , "_" ) ; t . is ( sanitisePath ( "aux.txt" ) , "_" ) ; t . is ( sanitisePath ( "LpT9.text" ) , "_" ) ; t . is ( sanitisePath ( "LPT10" ) , "LPT10" ) ; } ) ; test ( "sanitisePath: sanitises leading and trailing characters" , ( t ) => { t . is ( sanitisePath ( " /test" ) , "__test" ) ; t . is ( sanitisePath ( "hello   " ) , "hello___" ) ; t . is ( sanitisePath ( "file/ /" ) , "file___" ) ; } ) ; test ( "sanitisePath: truncates to 255 characters" , ( t ) => { const base = "" . padStart ( 254 , "x" ) ; t . is ( base . length , 254 ) ; t . is ( sanitisePath ( base ) , base ) ; t . is ( sanitisePath ( base + "x" ) , base + "x" ) ; t . is ( sanitisePath ( base + "xx" ) , base + "x" ) ; } ) ;