import * as fse from "fs-extra" ; import { expect } from "chai" ; import path from "./assert_path" ; import helper from "./helper" ; import * as jetpack from ".." ; import { FSJetpack } from "../types" ; describe ( "file" , ( ) => { beforeEach ( helper . setCleanTestCwd ) ; afterEach ( helper . switchBackToCorrectCwd ) ; describe ( "creates file if it doesn't exist" , ( ) => { const expectations = ( ) => { path ( "file.txt" ) . shouldBeFileWithContent ( "" ) ; } ; it ( "sync" , ( ) => { jetpack . file ( "file.txt" ) ; expectations ( ) ; } ) ; it ( "async" , done => { jetpack . fileAsync ( "file.txt" ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; describe ( "leaves file intact if it already exists" , ( ) => { const preparations = ( ) => { fse . outputFileSync ( "file.txt" , "abc" ) ; } ; const expectations = ( ) => { path ( "file.txt" ) . shouldBeFileWithContent ( "abc" ) ; } ; it ( "sync" , ( ) => { preparations ( ) ; jetpack . file ( "file.txt" ) ; expectations ( ) ; } ) ; it ( "async" , done => { preparations ( ) ; jetpack . fileAsync ( "file.txt" ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; describe ( "can save file content given as string" , ( ) => { const expectations = ( ) => { path ( "file.txt" ) . shouldBeFileWithContent ( "ąbć" ) ; } ; it ( "sync" , ( ) => { jetpack . file ( "file.txt" , { content : "ąbć" } ) ; expectations ( ) ; } ) ; it ( "async" , done => { jetpack . fileAsync ( "file.txt" , { content : "ąbć" } ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; describe ( "can save file content given as buffer" , ( ) => { const expectations = ( ) => { path ( "file" ) . shouldBeFileWithContent ( new Buffer ( [ 11 , 22 ] ) ) ; } ; it ( "sync" , ( ) => { jetpack . file ( "file" , { content : new Buffer ( [ 11 , 22 ] ) } ) ; expectations ( ) ; } ) ; it ( "async" , done => { jetpack . fileAsync ( "file" , { content : new Buffer ( [ 11 , 22 ] ) } ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; describe ( "can save file content given as plain JS object (will be saved as JSON)" , ( ) => { const obj = { a : "abc" , b : 123 } ; const expectations = ( ) => { const data = JSON . parse ( fse . readFileSync ( "file.txt" , "utf8" ) ) ; expect ( data ) . to . eql ( obj ) ; } ; it ( "sync" , ( ) => { jetpack . file ( "file.txt" , { content : obj } ) ; expectations ( ) ; } ) ; it ( "async" , done => { jetpack . fileAsync ( "file.txt" , { content : obj } ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; describe ( "written JSON data can be indented" , ( ) => { const obj = { a : "abc" , b : 123 } ; const expectations = ( ) => { const sizeA = fse . statSync ( "a.json" ) . size ; const sizeB = fse . statSync ( "b.json" ) . size ; const sizeC = fse . statSync ( "c.json" ) . size ; expect ( sizeB ) . to . be . above ( sizeA ) ; expect ( sizeC ) . to . be . above ( sizeB ) ; } ; it ( "sync" , ( ) => { jetpack . file ( "a.json" , { content : obj , jsonIndent : 0 } ) ; jetpack . file ( "b.json" , { content : obj } ) ; jetpack . file ( "c.json" , { content : obj , jsonIndent : 4 } ) ; expectations ( ) ; } ) ; it ( "async" , done => { jetpack . fileAsync ( "a.json" , { content : obj , jsonIndent : 0 } ) . then ( ( ) => { return jetpack . fileAsync ( "b.json" , { content : obj } ) ; } ) . then ( ( ) => { return jetpack . fileAsync ( "c.json" , { content : obj , jsonIndent : 4 } ) ; } ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; describe ( "replaces content of already existing file" , ( ) => { const preparations = ( ) => { fse . writeFileSync ( "file.txt" , "abc" ) ; } ; const expectations = ( ) => { path ( "file.txt" ) . shouldBeFileWithContent ( "123" ) ; } ; it ( "sync" , ( ) => { preparations ( ) ; jetpack . file ( "file.txt" , { content : "123" } ) ; expectations ( ) ; } ) ; it ( "async" , done => { preparations ( ) ; jetpack . fileAsync ( "file.txt" , { content : "123" } ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; describe ( "throws if given path is not a file" , ( ) => { const preparations = ( ) => { fse . mkdirsSync ( "a" ) ; } ; const expectations = ( err ) => { expect ( err . message ) . to . have . string ( "exists but is not a file." ) ; } ; it ( "sync" , ( ) => { preparations ( ) ; try { jetpack . file ( "a" ) ; throw new Error ( "Expected error to be thrown" ) ; } catch ( err ) { expectations ( err ) ; } } ) ; it ( "async" , done => { preparations ( ) ; jetpack . fileAsync ( "a" ) . catch ( err => { expectations ( err ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; describe ( "if directory for file doesn't exist creates it as well" , ( ) => { const expectations = ( ) => { path ( "a/b/c.txt" ) . shouldBeFileWithContent ( "" ) ; } ; it ( "sync" , ( ) => { jetpack . file ( "a/b/c.txt" ) ; expectations ( ) ; } ) ; it ( "async" , done => { jetpack . fileAsync ( "a/b/c.txt" ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; describe ( "returns currently used jetpack instance" , ( ) => { const expectations = ( jetpackContext ) => { expect ( jetpackContext ) . to . equal ( jetpack ) ; } ; it ( "sync" , ( ) => { expectations ( jetpack . file ( "file.txt" ) ) ; } ) ; it ( "async" , done => { jetpack . fileAsync ( "file.txt" ) . then ( jetpackContext => { expectations ( jetpackContext ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; describe ( "respects internal CWD of jetpack instance" , ( ) => { const expectations = ( ) => { path ( "a/b.txt" ) . shouldBeFileWithContent ( "" ) ; } ; it ( "sync" , ( ) => { const jetContext = jetpack . cwd ( "a" ) ; jetContext . file ( "b.txt" ) ; expectations ( ) ; } ) ; it ( "async" , done => { const jetContext = jetpack . cwd ( "a" ) ; jetContext . fileAsync ( "b.txt" ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; if ( process . platform !== "win32" ) { describe ( "sets mode of newly created file (unix only)" , ( ) => { const expectations = ( ) => { path ( "file.txt" ) . shouldHaveMode ( "711" ) ; } ; it ( "sync, mode passed as string" , ( ) => { jetpack . file ( "file.txt" , { mode : "711" } ) ; expectations ( ) ; } ) ; it ( "sync, mode passed as number" , ( ) => { jetpack . file ( "file.txt" , { mode : 0o711 } ) ; expectations ( ) ; } ) ; it ( "async, mode passed as string" , done => { jetpack . fileAsync ( "file.txt" , { mode : "711" } ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; it ( "async, mode passed as number" , done => { jetpack . fileAsync ( "file.txt" , { mode : 0o711 } ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; describe ( "changes mode of existing file if it doesn't match (unix only)" , ( ) => { const preparations = ( ) => { fse . writeFileSync ( "file.txt" , "abc" , { mode : "700" } ) ; } ; const expectations = ( ) => { path ( "file.txt" ) . shouldHaveMode ( "511" ) ; } ; it ( "sync" , ( ) => { preparations ( ) ; jetpack . file ( "file.txt" , { mode : "511" } ) ; expectations ( ) ; } ) ; it ( "async" , done => { preparations ( ) ; jetpack . fileAsync ( "file.txt" , { mode : "511" } ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; describe ( "leaves mode of file intact if not explicitly specified (unix only)" , ( ) => { const preparations = ( ) => { fse . writeFileSync ( "file.txt" , "abc" , { mode : "700" } ) ; } ; const expectations = ( ) => { path ( "file.txt" ) . shouldHaveMode ( "700" ) ; } ; it ( "sync, ensure exists" , ( ) => { preparations ( ) ; jetpack . file ( "file.txt" ) ; expectations ( ) ; } ) ; it ( "sync, ensure content" , ( ) => { preparations ( ) ; jetpack . file ( "file.txt" , { content : "abc" } ) ; expectations ( ) ; } ) ; it ( "async, ensure exists" , done => { preparations ( ) ; jetpack . fileAsync ( "file.txt" ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; it ( "async, ensure content" , done => { preparations ( ) ; jetpack . fileAsync ( "file.txt" , { content : "abc" } ) . then ( ( ) => { expectations ( ) ; done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; } else { describe ( "specyfying mode have no effect and throws no error (windows only)" , ( ) => { it ( "sync" , ( ) => { jetpack . file ( "file.txt" , { mode : "711" } ) ; } ) ; it ( "async" , done => { jetpack . fileAsync ( "file.txt" , { mode : "711" } ) . then ( ( ) => { done ( ) ; } ) . catch ( done ) ; } ) ; } ) ; } describe ( "input validation" , ( ) => { const tests = [ { type : "sync" , method : jetpack . file as any , methodName : "file" } , { type : "async" , method : jetpack . fileAsync as any , methodName : "fileAsync" } ] ; describe ( '"path" argument' , ( ) => { tests . forEach ( test => { it ( test . type , ( ) => { expect ( ( ) => { test . method ( undefined ) ; } ) . to . throw ( `Argument "path" passed to ${ test . methodName }(path, [criteria]) must be a string. Received undefined` ) ; } ) ; } ) ; } ) ; describe ( '"criteria" object' , ( ) => { describe ( '"content" argument' , ( ) => { tests . forEach ( test => { it ( test . type , ( ) => { expect ( ( ) => { test . method ( "abc" , { content : 1 } ) ; } ) . to . throw ( `Argument "criteria.content" passed to ${ test . methodName }(path, [criteria]) must be a string or a buffer or an object or an array. Received number` ) ; } ) ; } ) ; } ) ; describe ( '"jsonIndent" argument' , ( ) => { tests . forEach ( test => { it ( test . type , ( ) => { expect ( ( ) => { test . method ( "abc" , { jsonIndent : true } ) ; } ) . to . throw ( `Argument "criteria.jsonIndent" passed to ${ test . methodName }(path, [criteria]) must be a number. Received boolean` ) ; } ) ; } ) ; } ) ; describe ( '"mode" argument' , ( ) => { tests . forEach ( test => { it ( test . type , ( ) => { expect ( ( ) => { test . method ( "abc" , { mode : true } ) ; } ) . to . throw ( `Argument "criteria.mode" passed to ${ test . methodName }(path, [criteria]) must be a string or a number. Received boolean` ) ; } ) ; } ) ; } ) ; } ) ; } ) ; } ) ;