1111
1212'use strict' ;
1313
14+ const asyncify = require ( 'async/asyncify' ) ;
1415const { EventEmitter} = require ( 'events' ) ;
1516const { dirname} = require . requireActual ( 'path' ) ;
1617const fs = jest . genMockFromModule ( 'fs' ) ;
18+ const invariant = require ( 'fbjs/lib/invariant' ) ;
1719const path = require ( 'path' ) ;
1820const stream = require . requireActual ( 'stream' ) ;
1921
@@ -74,8 +76,7 @@ fs.readFile.mockImplementation(function(filepath, encoding, callback) {
7476 let node ;
7577 try {
7678 node = getToNode ( filepath ) ;
77- // dir check
78- if ( node && typeof node === 'object' && node . SYMLINK == null ) {
79+ if ( isDirNode ( node ) ) {
7980 callback ( new Error ( 'Error readFile a dir: ' + filepath ) ) ;
8081 }
8182 if ( node == null ) {
@@ -90,13 +91,51 @@ fs.readFile.mockImplementation(function(filepath, encoding, callback) {
9091
9192fs . readFileSync . mockImplementation ( function ( filepath , encoding ) {
9293 const node = getToNode ( filepath ) ;
93- // dir check
94- if ( node && typeof node === 'object' && node . SYMLINK == null ) {
94+ if ( isDirNode ( node ) ) {
9595 throw new Error ( 'Error readFileSync a dir: ' + filepath ) ;
9696 }
9797 return node ;
9898} ) ;
9999
100+ fs . writeFile . mockImplementation ( asyncify ( fs . writeFileSync ) ) ;
101+
102+ fs . writeFileSync . mockImplementation ( ( filePath , content , options ) => {
103+ if ( options == null || typeof options === 'string' ) {
104+ options = { encoding : options } ;
105+ }
106+ invariant (
107+ options . encoding == null || options . encoding === 'utf8' ,
108+ '`options` argument supports only `null` or `"utf8"`' ,
109+ ) ;
110+ const dirPath = path . dirname ( filePath ) ;
111+ const node = getToNode ( dirPath ) ;
112+ if ( ! isDirNode ( node ) ) {
113+ throw fsError ( 'ENOTDIR' , 'not a directory: ' + dirPath ) ;
114+ }
115+ node [ path . basename ( filePath ) ] = content ;
116+ } ) ;
117+
118+ fs . mkdir . mockImplementation ( asyncify ( fs . mkdirSync ) ) ;
119+
120+ fs . mkdirSync . mockImplementation ( ( dirPath , mode ) => {
121+ const parentPath = path . dirname ( dirPath ) ;
122+ const node = getToNode ( parentPath ) ;
123+ if ( ! isDirNode ( node ) ) {
124+ throw fsError ( 'ENOTDIR' , 'not a directory: ' + parentPath ) ;
125+ }
126+ node [ path . basename ( dirPath ) ] = { } ;
127+ } ) ;
128+
129+ function fsError ( code , message ) {
130+ const error = new Error ( code + ': ' + message ) ;
131+ error . code = code ;
132+ return error ;
133+ }
134+
135+ function isDirNode ( node ) {
136+ return node && typeof node === 'object' && node . SYMLINK == null ;
137+ }
138+
100139function readlinkSync ( filepath ) {
101140 const node = getToNode ( filepath ) ;
102141 if ( node !== null && typeof node === 'object' && ! ! node . SYMLINK ) {
@@ -250,7 +289,7 @@ fs.close.mockImplementation((fd, callback = noop) => {
250289 callback ( null ) ;
251290} ) ;
252291
253- let filesystem ;
292+ let filesystem = { } ;
254293
255294fs . createReadStream . mockImplementation ( filepath => {
256295 if ( ! filepath . startsWith ( '/' ) ) {
0 commit comments