/* eslint-env mocha */

'use strict';

const assert = require('assert');
const proxyquire = require('proxyquire');

let readFileMock;
let writeFileArgs;
let writeFileMock;
let writeFileSyncArgs;
const makeArt =
proxyquire
(
    '../make-art',
    {
        fs:
        {
            readFile(...args)
            {
                readFileMock.apply(this, args);
            },
            writeFile(...args)
            {
                writeFileArgs = args;
                if (writeFileMock)
                    writeFileMock();
            },
            writeFileSync(...args)
            {
                writeFileSyncArgs = args;
            },
        },
    },
);

afterEach
(
    () =>
    {
        readFileMock = writeFileArgs = writeFileMock = writeFileSyncArgs = undefined;
    },
);

describe
(
    'makeArt',
    () =>
    {
        it
        (
            'creates art.js',
            () =>
            {
                const expectedPath = 'test';
                makeArt(expectedPath);
                const [actualPath, actualData] = writeFileSyncArgs;
                assert.strictEqual(actualPath, expectedPath);
                assert.equal(typeof actualData, 'string');
            },
        );
        it
        (
            'fails for missing path',
            () =>
            {
                assert.throws(makeArt, isMissingPathError);
                assert(!writeFileSyncArgs);
            },
        );
    },
);

describe
(
    'makeArt.async',
    () =>
    {
        it
        (
            'creates art.js',
            done =>
            {
                const expectedPath = 'test';
                const expectedCallback = Function();
                readFileMock = (file, callback) => callback(null, 'DATA');
                writeFileMock =
                () =>
                {
                    const [actualPath, actualData, actualCallback] = writeFileArgs;
                    assert.strictEqual(actualPath, expectedPath);
                    assert.equal(typeof actualData, 'string');
                    assert.strictEqual(actualCallback, expectedCallback);
                    done();
                };
                makeArt.async(expectedPath, null, expectedCallback);
            },
        );
        it
        (
            'fails for missing path',
            () =>
            {
                assert.throws(makeArt.async, isMissingPathError);
                assert(!writeFileArgs);
            },
        );
        it
        (
            'fails on read error',
            done =>
            {
                const expectedError = Error();
                readFileMock = (file, callback) => callback(expectedError);
                makeArt.async
                (
                    'test',
                    null,
                    actualError =>
                    {
                        assert.strictEqual(actualError, expectedError);
                        done();
                    },
                );
            },
        );
        it
        (
            'fails on write error',
            done =>
            {
                const expectedError = Error();
                readFileMock = (file, callback) => callback(null, 'DATA');
                writeFileMock =
                () =>
                {
                    throw expectedError;
                };
                makeArt.async
                (
                    'test',
                    null,
                    actualError =>
                    {
                        assert.strictEqual(actualError, expectedError);
                        done();
                    },
                );
            },
        );
    },
);

describe
(
    'processCommandLine',
    () =>
    {
        function callProcessCommandLine(newProcessArgv)
        {
            process.argv = newProcessArgv;
            makeArt.processCommandLine();
        }

        let consoleErrorArgs;
        let consoleError;
        let processArgv;

        beforeEach
        (
            () =>
            {
                consoleError = console.error;
                console.error =
                (...args) =>
                {
                    consoleErrorArgs = args;
                };
                processArgv = process.argv;
            },
        );

        afterEach
        (
            () =>
            {
                process.argv = processArgv;
                console.error = consoleError;
                consoleErrorArgs = undefined;
            },
        );

        it
        (
            'creates art.js',
            () =>
            {
                const expectedPath = 'test';
                callProcessCommandLine([, , expectedPath, 'foo', 'bar.baz', 'bar']);
                const [actualPath, data] = writeFileSyncArgs;
                assert.strictEqual(actualPath, expectedPath);
                assert.equal(typeof data, 'string');
                assert.deepStrictEqual(consoleErrorArgs, undefined);
            },
        );
        it
        (
            'fails for missing path',
            () =>
            {
                callProcessCommandLine([]);
                assert.strictEqual(writeFileSyncArgs, undefined);
                assert.deepStrictEqual(consoleErrorArgs, ['missing path']);
            },
        );
    },
);

function isMissingPathError(obj)
{
    const result = Object.getPrototypeOf(obj) === Error.prototype && obj.message === 'missing path';
    return result;
}

@@ -107,16 +107,55 @@
 quire');
+%0Aconst %7B promisify %7D = require('util');
 %0A%0Alet re
@@ -562,16 +562,23 @@
 ileMock(
+...args
 );%0A     
@@ -1584,32 +1584,49 @@
  'creates art.js
+ with 2 arguments
 ',%0A            d
@@ -1616,36 +1616,40 @@
 s',%0A            
-done
+async ()
  =%3E%0A            
@@ -1715,42 +1715,56 @@
     
-const expectedC
+readFileMock = (file, c
 allback
+)
  =
- Function(
+%3E callback(null
 );%0A 
@@ -1770,36 +1770,37 @@
                 
-read
+write
 FileMock = (file
@@ -1792,32 +1792,38 @@
 ileMock = (file,
+ data,
  callback) =%3E ca
@@ -1829,32 +1829,24 @@
 allback(null
-, 'DATA'
 );%0A         
@@ -1856,68 +1856,54 @@
     
-writeFileMock =%0A                () =%3E%0A                %7B%0A    
+await promisify(makeArt.async)(expectedPath);%0A
     
@@ -1947,24 +1947,8 @@
 Data
-, actualCallback
 %5D = 
@@ -1958,28 +1958,24 @@
 teFileArgs;%0A
-    
             
@@ -2032,36 +2032,32 @@
                 
-    
 assert.equal(typ
@@ -2091,32 +2091,35 @@
             
+%7D,%0A
         
 assert.stric
@@ -2110,107 +2110,301 @@
     
-assert.strictEqual(actualCallback, expectedCallback);%0A                    done();%0A                %7D
+);%0A        it%0A        (%0A            'creates art.js with 3 arguments',%0A            async () =%3E%0A            %7B%0A                const expectedPath = 'test';%0A                readFileMock = (file, callback) =%3E callback(null);%0A                writeFileMock = (file, data, callback) =%3E callback(null)
 ;%0A  
@@ -2409,32 +2409,48 @@
                 
+await promisify(
 makeArt.async(ex
@@ -2446,16 +2446,17 @@
 rt.async
+)
 (expecte
@@ -2470,26 +2470,193 @@
 null
-, expectedCallback
+);%0A                const %5BactualPath, actualData%5D = writeFileArgs;%0A                assert.strictEqual(actualPath, expectedPath);%0A                assert.equal(typeof actualData, 'string'
 );%0A 

Update make-art.spec.js