Преглед изворни кода

Refactoring of JavaSriptObfuscatorCLI class

sanex3339 пре 7 година
родитељ
комит
bdb5aaebd8

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
dist/index.js


+ 2 - 2
package.json

@@ -57,12 +57,12 @@
     "babel-loader": "7.1.1",
     "babel-loader": "7.1.1",
     "babel-plugin-array-includes": "2.0.3",
     "babel-plugin-array-includes": "2.0.3",
     "babel-preset-es2015": "6.24.1",
     "babel-preset-es2015": "6.24.1",
-    "chai": "4.1.0",
+    "chai": "4.1.1",
     "coveralls": "2.13.1",
     "coveralls": "2.13.1",
     "istanbul": "1.1.0-alpha.1",
     "istanbul": "1.1.0-alpha.1",
     "mocha": "3.5.0",
     "mocha": "3.5.0",
     "pre-commit": "1.2.2",
     "pre-commit": "1.2.2",
-    "sinon": "2.4.1",
+    "sinon": "3.0.0",
     "ts-node": "3.3.0",
     "ts-node": "3.3.0",
     "tslint": "5.5.0",
     "tslint": "5.5.0",
     "tslint-eslint-rules": "4.1.1",
     "tslint-eslint-rules": "4.1.1",

+ 4 - 1
src/JavaScriptObfuscator.ts

@@ -35,6 +35,9 @@ export class JavaScriptObfuscator {
      * @param {string[]} argv
      * @param {string[]} argv
      */
      */
     public static runCLI (argv: string[]): void {
     public static runCLI (argv: string[]): void {
-        new JavaScriptObfuscatorCLI(argv).run();
+        const javaScriptObfuscatorCLI: JavaScriptObfuscatorCLI = new JavaScriptObfuscatorCLI(argv);
+
+        javaScriptObfuscatorCLI.initialize();
+        javaScriptObfuscatorCLI.run();
     }
     }
 }
 }

+ 48 - 37
src/cli/JavaScriptObfuscatorCLI.ts

@@ -1,13 +1,18 @@
 import * as commander from 'commander';
 import * as commander from 'commander';
 import * as path from 'path';
 import * as path from 'path';
 
 
+import { TInputCLIOptions } from '../types/options/TInputCLIOptions';
 import { TInputOptions } from '../types/options/TInputOptions';
 import { TInputOptions } from '../types/options/TInputOptions';
 import { TObject } from '../types/TObject';
 import { TObject } from '../types/TObject';
 
 
+import { IInitializable } from '../interfaces/IInitializable';
 import { IObfuscationResult } from '../interfaces/IObfuscationResult';
 import { IObfuscationResult } from '../interfaces/IObfuscationResult';
 
 
+import { initializable } from '../decorators/Initializable';
+
 import { DEFAULT_PRESET } from '../options/presets/Default';
 import { DEFAULT_PRESET } from '../options/presets/Default';
 
 
+import { ArraySanitizer } from './sanitizers/ArraySanitizer';
 import { BooleanSanitizer } from './sanitizers/BooleanSanitizer';
 import { BooleanSanitizer } from './sanitizers/BooleanSanitizer';
 import { SourceMapModeSanitizer } from './sanitizers/SourceMapModeSanitizer';
 import { SourceMapModeSanitizer } from './sanitizers/SourceMapModeSanitizer';
 import { StringArrayEncodingSanitizer } from './sanitizers/StringArrayEncodingSanitizer';
 import { StringArrayEncodingSanitizer } from './sanitizers/StringArrayEncodingSanitizer';
@@ -15,7 +20,7 @@ import { StringArrayEncodingSanitizer } from './sanitizers/StringArrayEncodingSa
 import { CLIUtils } from './utils/CLIUtils';
 import { CLIUtils } from './utils/CLIUtils';
 import { JavaScriptObfuscator } from '../JavaScriptObfuscator';
 import { JavaScriptObfuscator } from '../JavaScriptObfuscator';
 
 
-export class JavaScriptObfuscatorCLI {
+export class JavaScriptObfuscatorCLI implements IInitializable {
     /**
     /**
      * @type {string[]}
      * @type {string[]}
      */
      */
@@ -29,16 +34,25 @@ export class JavaScriptObfuscatorCLI {
     /**
     /**
      * @type {commander.CommanderStatic}
      * @type {commander.CommanderStatic}
      */
      */
+    @initializable()
     private commands: commander.CommanderStatic;
     private commands: commander.CommanderStatic;
 
 
+    /**
+     * @type {TInputCLIOptions}
+     */
+    @initializable()
+    private inputCLIOptions: TInputCLIOptions;
+
     /**
     /**
      * @type {string}
      * @type {string}
      */
      */
+    @initializable()
     private inputPath: string;
     private inputPath: string;
 
 
     /**
     /**
      * @type {string}
      * @type {string}
      */
      */
+    @initializable()
     private sourceCode: string = '';
     private sourceCode: string = '';
 
 
     /**
     /**
@@ -46,21 +60,18 @@ export class JavaScriptObfuscatorCLI {
      */
      */
     constructor (argv: string[]) {
     constructor (argv: string[]) {
         this.rawArguments = argv;
         this.rawArguments = argv;
-        this.arguments = this.rawArguments.slice(2);
-
-        this.commands = <commander.CommanderStatic>(new commander.Command());
+        this.arguments = argv.slice(2);
     }
     }
 
 
     /**
     /**
      * @param {TObject} options
      * @param {TObject} options
      * @returns {TInputOptions}
      * @returns {TInputOptions}
      */
      */
-    private static sanitizeOptions (options: TObject): TInputOptions {
+    private static filterOptions (options: TObject): TInputOptions {
         const filteredOptions: TInputOptions = {};
         const filteredOptions: TInputOptions = {};
-        const availableOptions: string[] = Object.keys(DEFAULT_PRESET);
 
 
         for (const option in options) {
         for (const option in options) {
-            if (!options.hasOwnProperty(option) || !availableOptions.includes(option)) {
+            if (!options.hasOwnProperty(option) || options[option] === undefined) {
                 continue;
                 continue;
             }
             }
 
 
@@ -70,46 +81,50 @@ export class JavaScriptObfuscatorCLI {
         return filteredOptions;
         return filteredOptions;
     }
     }
 
 
-    public run (): void {
+    public initialize (): void {
+        this.inputPath = this.arguments[0] || '';
+        this.commands = <commander.CommanderStatic>(new commander.Command());
+
         this.configureCommands();
         this.configureCommands();
         this.configureHelp();
         this.configureHelp();
 
 
-        if (!this.arguments.length || this.arguments.includes('--help')) {
-            this.commands.outputHelp();
+        this.inputCLIOptions = this.commands.opts();
+    }
 
 
-            return;
-        }
+    public run (): void {
+        const canShowHelp: boolean = !this.arguments.length || this.arguments.includes('--help');
 
 
-        this.inputPath = this.arguments[0];
-        CLIUtils.validateInputPath(this.inputPath);
+        if (canShowHelp) {
+            return this.commands.outputHelp();
+        }
 
 
-        this.getData();
-        this.processData();
+        this.sourceCode = CLIUtils.readSourceCode(this.inputPath);
+        this.processSourceCode();
     }
     }
 
 
     /**
     /**
      * @returns {TInputOptions}
      * @returns {TInputOptions}
      */
      */
     private buildOptions (): TInputOptions {
     private buildOptions (): TInputOptions {
-        const inputOptions: TInputOptions = JavaScriptObfuscatorCLI.sanitizeOptions(this.commands);
-        const configFileLocation: string = this.commands.config
-            ? path.resolve(this.commands.config, '.')
-            : '';
-        const configFileOptions: TInputOptions = configFileLocation
-            ? JavaScriptObfuscatorCLI.sanitizeOptions(CLIUtils.getUserConfig(configFileLocation))
-            : {};
+        const inputCLIOptions: TInputOptions = JavaScriptObfuscatorCLI.filterOptions(this.inputCLIOptions);
+        const configFilePath: string|undefined = this.inputCLIOptions.config;
+        const configFileLocation: string = configFilePath ? path.resolve(configFilePath, '.') : '';
+        const configFileOptions: TInputOptions = configFileLocation ? CLIUtils.getUserConfig(configFileLocation) : {};
 
 
         return {
         return {
             ...DEFAULT_PRESET,
             ...DEFAULT_PRESET,
             ...configFileOptions,
             ...configFileOptions,
-            ...inputOptions
+            ...inputCLIOptions
         };
         };
     }
     }
 
 
     private configureCommands (): void {
     private configureCommands (): void {
         this.commands
         this.commands
-            .version(CLIUtils.getPackageConfig().version, '-v, --version')
             .usage('<inputPath> [options]')
             .usage('<inputPath> [options]')
+            .version(
+                CLIUtils.getPackageConfig().version,
+                '-v, --version'
+            )
             .option(
             .option(
                 '-o, --output <path>',
                 '-o, --output <path>',
                 'Output path for obfuscated code'
                 'Output path for obfuscated code'
@@ -161,7 +176,7 @@ export class JavaScriptObfuscatorCLI {
             .option(
             .option(
                 '--domainLock <list>',
                 '--domainLock <list>',
                 'Blocks the execution of the code in domains that do not match the passed RegExp patterns (comma separated)',
                 'Blocks the execution of the code in domains that do not match the passed RegExp patterns (comma separated)',
-                (value: string) => value.split(',')
+                ArraySanitizer
             )
             )
             .option(
             .option(
                 '--log <boolean>', 'Enables logging of the information to the console',
                 '--log <boolean>', 'Enables logging of the information to the console',
@@ -174,7 +189,7 @@ export class JavaScriptObfuscatorCLI {
             .option(
             .option(
                 '--reservedNames <list>',
                 '--reservedNames <list>',
                 'Disable obfuscation of variable names, function names and names of function parameters that match the passed RegExp patterns (comma separated)',
                 'Disable obfuscation of variable names, function names and names of function parameters that match the passed RegExp patterns (comma separated)',
-                (value: string) => value.split(',')
+                ArraySanitizer
             )
             )
             .option(
             .option(
                 '--renameGlobals <boolean>', 'Allows to enable obfuscation of global variable and function names with declaration.',
                 '--renameGlobals <boolean>', 'Allows to enable obfuscation of global variable and function names with declaration.',
@@ -244,18 +259,14 @@ export class JavaScriptObfuscatorCLI {
         });
         });
     }
     }
 
 
-    private getData (): void {
-        this.sourceCode = CLIUtils.readFile(this.inputPath);
-    }
-
-    private processData (): void {
+    private processSourceCode (): void {
         const options: TInputOptions = this.buildOptions();
         const options: TInputOptions = this.buildOptions();
-        const outputCodePath: string = CLIUtils.getOutputCodePath(this.commands.output, this.inputPath);
+        const outputCodePath: string = CLIUtils.getOutputCodePath(this.inputCLIOptions.output, this.inputPath);
 
 
         if (options.sourceMap) {
         if (options.sourceMap) {
-            this.processDataWithSourceMap(outputCodePath, options);
+            this.processSourceCodeWithSourceMap(outputCodePath, options);
         } else {
         } else {
-            this.processDataWithoutSourceMap(outputCodePath, options);
+            this.processSourceCodeWithoutSourceMap(outputCodePath, options);
         }
         }
     }
     }
 
 
@@ -263,7 +274,7 @@ export class JavaScriptObfuscatorCLI {
      * @param {string} outputCodePath
      * @param {string} outputCodePath
      * @param {TInputOptions} options
      * @param {TInputOptions} options
      */
      */
-    private processDataWithoutSourceMap (outputCodePath: string, options: TInputOptions): void {
+    private processSourceCodeWithoutSourceMap (outputCodePath: string, options: TInputOptions): void {
         const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(this.sourceCode, options).getObfuscatedCode();
         const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(this.sourceCode, options).getObfuscatedCode();
 
 
         CLIUtils.writeFile(outputCodePath, obfuscatedCode);
         CLIUtils.writeFile(outputCodePath, obfuscatedCode);
@@ -273,7 +284,7 @@ export class JavaScriptObfuscatorCLI {
      * @param {string} outputCodePath
      * @param {string} outputCodePath
      * @param {TInputOptions} options
      * @param {TInputOptions} options
      */
      */
-    private processDataWithSourceMap (outputCodePath: string, options: TInputOptions): void {
+    private processSourceCodeWithSourceMap (outputCodePath: string, options: TInputOptions): void {
         const outputSourceMapPath: string = CLIUtils.getOutputSourceMapPath(
         const outputSourceMapPath: string = CLIUtils.getOutputSourceMapPath(
             outputCodePath,
             outputCodePath,
             options.sourceMapFileName || ''
             options.sourceMapFileName || ''

+ 9 - 0
src/cli/sanitizers/ArraySanitizer.ts

@@ -0,0 +1,9 @@
+import { TCLISanitizer } from '../../types/cli/TCLISanitizer';
+
+/**
+ * @param {string} value
+ * @returns {string[]}
+ */
+export const ArraySanitizer: TCLISanitizer = (value: string): string[] => {
+    return value.split(',').map((string: string) => string.trim());
+};

+ 2 - 2
src/cli/sanitizers/SourceMapModeSanitizer.ts

@@ -9,8 +9,8 @@ import { SourceMapMode } from '../../enums/SourceMapMode';
 export const SourceMapModeSanitizer: TCLISanitizer = (value: string): string => {
 export const SourceMapModeSanitizer: TCLISanitizer = (value: string): string => {
     const availableMode: boolean = Object
     const availableMode: boolean = Object
         .keys(SourceMapMode)
         .keys(SourceMapMode)
-        .some((key: string): boolean => {
-            return SourceMapMode[<any>key] === value;
+        .some((key: any): boolean => {
+            return SourceMapMode[key] === value;
         });
         });
 
 
     if (!availableMode) {
     if (!availableMode) {

+ 6 - 11
src/cli/utils/CLIUtils.ts

@@ -24,14 +24,14 @@ export class CLIUtils {
      * @param {string} inputPath
      * @param {string} inputPath
      * @returns {string}
      * @returns {string}
      */
      */
-    public static getOutputCodePath (outputPath: string, inputPath: string): string {
+    public static getOutputCodePath (outputPath: string|undefined, inputPath: string): string {
         if (outputPath) {
         if (outputPath) {
             return outputPath;
             return outputPath;
         }
         }
 
 
         return inputPath
         return inputPath
             .split('.')
             .split('.')
-            .map<string>((value: string, index: number) => {
+            .map((value: string, index: number) => {
                 return index === 0 ? `${value}-obfuscated` : value;
                 return index === 0 ? `${value}-obfuscated` : value;
             })
             })
             .join('.');
             .join('.');
@@ -62,7 +62,7 @@ export class CLIUtils {
      * @returns {IPackageConfig}
      * @returns {IPackageConfig}
      */
      */
     public static getPackageConfig (): IPackageConfig {
     public static getPackageConfig (): IPackageConfig {
-        return <IPackageConfig>JSON.parse(
+        return JSON.parse(
             fs.readFileSync(
             fs.readFileSync(
                 path.join(
                 path.join(
                     path.dirname(
                     path.dirname(
@@ -111,14 +111,7 @@ export class CLIUtils {
      * @param {string} inputPath
      * @param {string} inputPath
      * @returns {string}
      * @returns {string}
      */
      */
-    public static readFile (inputPath: string): string {
-        return fs.readFileSync(inputPath, CLIUtils.encoding);
-    }
-
-    /**
-     * @param {string} inputPath
-     */
-    public static validateInputPath (inputPath: string): void {
+    public static readSourceCode (inputPath: string): string {
         if (!CLIUtils.isFilePath(inputPath)) {
         if (!CLIUtils.isFilePath(inputPath)) {
             throw new ReferenceError(`Given input path must be a valid file path`);
             throw new ReferenceError(`Given input path must be a valid file path`);
         }
         }
@@ -126,6 +119,8 @@ export class CLIUtils {
         if (!CLIUtils.availableInputExtensions.includes(path.extname(inputPath))) {
         if (!CLIUtils.availableInputExtensions.includes(path.extname(inputPath))) {
             throw new ReferenceError(`Input file must have .js extension`);
             throw new ReferenceError(`Input file must have .js extension`);
         }
         }
+
+        return fs.readFileSync(inputPath, CLIUtils.encoding);
     }
     }
 
 
     /**
     /**

+ 7 - 0
src/interfaces/options/ICLIOptions.d.ts

@@ -0,0 +1,7 @@
+import { IOptions } from './IOptions';
+
+export interface ICLIOptions extends IOptions {
+    readonly config: string;
+    readonly output: string;
+    readonly version: string;
+}

+ 5 - 0
src/types/options/TInputCLIOptions.d.ts

@@ -0,0 +1,5 @@
+import { TObject } from '../TObject';
+
+import { ICLIOptions } from '../../interfaces/options/ICLIOptions';
+
+export type TInputCLIOptions = Partial<Pick<ICLIOptions, keyof ICLIOptions>> & TObject;

+ 1 - 0
test/index.spec.ts

@@ -5,6 +5,7 @@ require('source-map-support').install();
 /**
 /**
  * Unit tests
  * Unit tests
  */
  */
+import './unit-tests/cli/sanitizers/ArraySanitizer.spec';
 import './unit-tests/cli/sanitizers/BooleanSanitizer.spec';
 import './unit-tests/cli/sanitizers/BooleanSanitizer.spec';
 import './unit-tests/cli/sanitizers/SourceMapModeSanitizer.spec';
 import './unit-tests/cli/sanitizers/SourceMapModeSanitizer.spec';
 import './unit-tests/cli/sanitizers/StringArrayEncodingSanitizer.spec';
 import './unit-tests/cli/sanitizers/StringArrayEncodingSanitizer.spec';

+ 38 - 0
test/unit-tests/cli/sanitizers/ArraySanitizer.spec.ts

@@ -0,0 +1,38 @@
+import { assert } from 'chai';
+
+import { ArraySanitizer } from '../../../../src/cli/sanitizers/ArraySanitizer';
+
+
+describe('ArraySanitizer', () => {
+    describe('ArraySanitizer: TCLISanitizer = (value: string): string[]', () => {
+        describe('variant #1: input value `foo`', () => {
+            const inputValue: string = 'foo';
+            const expectedValue: string[] = ['foo'];
+
+            let value: string[];
+
+            before(() => {
+                value = ArraySanitizer(inputValue);
+            });
+
+            it('should sanitize value', () => {
+                assert.deepEqual(value, expectedValue);
+            });
+        });
+
+        describe('variant #2: input value `foo, bar`', () => {
+            const inputValue: string = 'foo, bar';
+            const expectedValue: string[] = ['foo', 'bar'];
+
+            let value: string[];
+
+            before(() => {
+                value = ArraySanitizer(inputValue);
+            });
+
+            it('should sanitize value', () => {
+                assert.deepEqual(value, expectedValue);
+            });
+        });
+    });
+});

+ 7 - 7
test/unit-tests/cli/utils/CLIUtils.spec.ts

@@ -87,20 +87,20 @@ describe('CLIUtils', () => {
         });
         });
     });
     });
 
 
-    describe('validateInputPath (inputPath: string): void', () => {
+    describe('readSourceCode (inputPath: string): void', () => {
         describe('`inputPath` is a valid path', () => {
         describe('`inputPath` is a valid path', () => {
             const tmpFileName: string = 'test.js';
             const tmpFileName: string = 'test.js';
             const inputPath: string = `${tmpDir}/${tmpFileName}`;
             const inputPath: string = `${tmpDir}/${tmpFileName}`;
 
 
-            let testFunc: () => void;
+            let result: string;
 
 
             before(() => {
             before(() => {
                 fs.writeFileSync(inputPath, fileContent);
                 fs.writeFileSync(inputPath, fileContent);
-                testFunc = () => CLIUtils.validateInputPath(inputPath);
+                result = CLIUtils.readSourceCode(inputPath);
             });
             });
 
 
-            it('shouldn\'t throw an error if `inputPath` is a valid path', () => {
-                assert.doesNotThrow(testFunc, ReferenceError);
+            it('should return content of file', () => {
+                assert.equal(result, fileContent);
             });
             });
 
 
             after(() => {
             after(() => {
@@ -115,7 +115,7 @@ describe('CLIUtils', () => {
             let testFunc: () => void;
             let testFunc: () => void;
 
 
             before(() => {
             before(() => {
-                testFunc = () => CLIUtils.validateInputPath(inputPath);
+                testFunc = () => CLIUtils.readSourceCode(inputPath);
             });
             });
 
 
             it('should throw an error if `inputPath` is not a valid path', () => {
             it('should throw an error if `inputPath` is not a valid path', () => {
@@ -131,7 +131,7 @@ describe('CLIUtils', () => {
 
 
             before(() => {
             before(() => {
                 fs.writeFileSync(inputPath, fileContent);
                 fs.writeFileSync(inputPath, fileContent);
-                testFunc = () => CLIUtils.validateInputPath(inputPath);
+                testFunc = () => CLIUtils.readSourceCode(inputPath);
             });
             });
 
 
             it('should throw an error if `inputPath` is a file name has invalid extension', () => {
             it('should throw an error if `inputPath` is a file name has invalid extension', () => {

+ 27 - 13
yarn.lock

@@ -56,11 +56,7 @@
   version "2.2.41"
   version "2.2.41"
   resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.41.tgz#e27cf0817153eb9f2713b2d3f6c68f1e1c3ca608"
   resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.41.tgz#e27cf0817153eb9f2713b2d3f6c68f1e1c3ca608"
 
 
-"@types/node@*":
-  version "8.0.17"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.17.tgz#677bc8c118cfb76013febb62ede1f31d2c7222a1"
-
-"@types/[email protected]":
+"@types/node@*", "@types/[email protected]":
   version "8.0.19"
   version "8.0.19"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.19.tgz#e46e2b0243de7d03f15b26b45c59ebb84f657a4e"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.19.tgz#e46e2b0243de7d03f15b26b45c59ebb84f657a4e"
 
 
@@ -920,9 +916,9 @@ center-align@^0.1.1:
     align-text "^0.1.3"
     align-text "^0.1.3"
     lazy-cache "^1.0.3"
     lazy-cache "^1.0.3"
 
 
[email protected].0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.0.tgz#331a0391b55c3af8740ae9c3b7458bc1c3805e6d"
[email protected].1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.1.tgz#66e21279e6f3c6415ff8231878227900e2171b39"
   dependencies:
   dependencies:
     assertion-error "^1.0.1"
     assertion-error "^1.0.1"
     check-error "^1.0.1"
     check-error "^1.0.1"
@@ -1693,7 +1689,7 @@ form-data@~2.1.1:
     combined-stream "^1.0.5"
     combined-stream "^1.0.5"
     mime-types "^2.1.12"
     mime-types "^2.1.12"
 
 
[email protected]:
[email protected], formatio@^1.2.0:
   version "1.2.0"
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb"
   resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb"
   dependencies:
   dependencies:
@@ -2353,6 +2349,10 @@ jsprim@^1.2.2:
     json-schema "0.2.3"
     json-schema "0.2.3"
     verror "1.3.6"
     verror "1.3.6"
 
 
+just-extend@^1.1.22:
+  version "1.1.22"
+  resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.22.tgz#3330af756cab6a542700c64b2e4e4aa062d52fff"
+
 kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
 kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
   version "3.2.2"
   version "3.2.2"
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
@@ -2490,6 +2490,10 @@ lolex@^1.6.0:
   version "1.6.0"
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6"
   resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6"
 
 
+lolex@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.1.2.tgz#2694b953c9ea4d013e5b8bfba891c991025b2629"
+
 longest@^1.0.1:
 longest@^1.0.1:
   version "1.0.1"
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
   resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
@@ -2690,6 +2694,15 @@ native-promise-only@^0.8.1:
   version "0.8.1"
   version "0.8.1"
   resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11"
   resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11"
 
 
+nise@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/nise/-/nise-1.0.1.tgz#0da92b10a854e97c0f496f6c2845a301280b3eef"
+  dependencies:
+    formatio "^1.2.0"
+    just-extend "^1.1.22"
+    lolex "^1.6.0"
+    path-to-regexp "^1.7.0"
+
 [email protected]:
 [email protected]:
   version "1.6.3"
   version "1.6.3"
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
@@ -3406,14 +3419,15 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
   version "3.0.2"
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
 
 
-sinon@2.4.1:
-  version "2.4.1"
-  resolved "https://registry.yarnpkg.com/sinon/-/sinon-2.4.1.tgz#021fd64b54cb77d9d2fb0d43cdedfae7629c3a36"
+sinon@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/sinon/-/sinon-3.0.0.tgz#f6919755c8c705e0b4ae977e8351bbcbaf6d91de"
   dependencies:
   dependencies:
     diff "^3.1.0"
     diff "^3.1.0"
     formatio "1.2.0"
     formatio "1.2.0"
-    lolex "^1.6.0"
+    lolex "^2.1.2"
     native-promise-only "^0.8.1"
     native-promise-only "^0.8.1"
+    nise "^1.0.1"
     path-to-regexp "^1.7.0"
     path-to-regexp "^1.7.0"
     samsam "^1.1.3"
     samsam "^1.1.3"
     text-encoding "0.6.4"
     text-encoding "0.6.4"

Неке датотеке нису приказане због велике количине промена