voluptasvelit
Version:
JavaScript obfuscator
860 lines (698 loc) • 35.4 kB
text/typescript
import * as fs from 'fs';
import * as mkdirp from 'mkdirp';
import * as path from 'path';
import * as rimraf from 'rimraf';
import * as sinon from 'sinon';
import { assert } from 'chai';
import { StdoutWriteMock } from '../../mocks/StdoutWriteMock';
import { JavaScriptObfuscatorCLI } from '../../../src/JavaScriptObfuscatorCLIFacade';
describe('JavaScriptObfuscatorCLI', function (): void {
this.timeout(100000);
const expectedError: RegExp = /Given input path must be a valid/;
const fixturesDirName: string = 'test/fixtures';
const fixtureFileName: string = 'sample.js';
const fixtureFilePath: string = `${fixturesDirName}/${fixtureFileName}`;
const outputDirName: string = 'test/tmp';
const outputFileName: string = 'sample-obfuscated.js';
const outputFilePath: string = `${outputDirName}/${outputFileName}`;
const configDirName: string = 'test/fixtures';
const configFileName: string = 'config.js';
const configFilePath: string = `${configDirName}/${configFileName}`;
describe('run', () => {
before(() => {
mkdirp.sync(outputDirName);
});
describe('Variant #1: obfuscation of single file', () => {
describe('`--output` option is set', () => {
let isFileExist: boolean;
before(() => {
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--compact',
'true',
'--self-defending',
'0'
]);
isFileExist = fs.existsSync(outputFilePath);
});
it('should create file with obfuscated code in `--output` directory', () => {
assert.equal(isFileExist, true);
});
after(() => {
fs.unlinkSync(outputFilePath);
});
});
describe('`--output` option isn\'t set', () => {
describe('Variant #1: default behaviour', () => {
let outputFixturesFilePath: string,
isFileExist: boolean;
before(() => {
outputFixturesFilePath = `${fixturesDirName}/${outputFileName}`;
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
fixtureFilePath
]);
isFileExist = fs.existsSync(outputFixturesFilePath);
});
it(`should create file \`${outputFileName}\` with obfuscated code in \`${fixturesDirName}\` directory`, () => {
assert.equal(isFileExist, true);
});
after(() => {
fs.unlinkSync(outputFixturesFilePath);
});
});
describe('Variant #2: invalid input file path', () => {
let testFunc: () => void;
before(() => {
testFunc = () => JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
'wrong/file/path'
]);
});
it(`should throw an error`, () => {
assert.throws(testFunc, expectedError);
});
});
describe('Variant #3: input file extension isn\'t `.js`', () => {
const expectedError: RegExp = /Given input path must be a valid/;
const outputFileName: string = 'sample-obfuscated.ts';
const outputFilePath: string = `${outputDirName}/${outputFileName}`;
let testFunc: () => void;
before(() => {
fs.writeFileSync(outputFilePath, 'data');
testFunc = () => JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
outputFilePath
]);
});
it(`should throw an error`, () => {
assert.throws(testFunc, expectedError);
});
after(() => {
fs.unlinkSync(outputFilePath);
});
});
});
describe('--exclude option', () => {
describe('Variant #1: --exclude option is pointed on different file', () => {
let isFileExist: boolean;
before(() => {
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--exclude',
'**/foo.js'
]);
isFileExist = fs.existsSync(outputFilePath);
});
it('should create file with obfuscated code in `--output` directory', () => {
assert.equal(isFileExist, true);
});
});
describe('Variant #2: --exclude option is pointed on input file', () => {
let testFunc: () => void;
before(() => {
testFunc = () => JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--exclude',
'**/sample.js'
]);
});
it('should throw an error', () => {
assert.throws(testFunc, expectedError);
});
after(() => {
fs.unlinkSync(outputFilePath);
});
});
});
});
describe('Variant #2: obfuscation of directory', () => {
describe(`Variant #1: default behaviour`, () => {
const directoryPath: string = `${fixturesDirName}/directory-obfuscation`;
const outputFileName1: string = 'foo-obfuscated.js';
const outputFileName2: string = 'bar-obfuscated.js';
const outputFileName3: string = 'baz-obfuscated.js';
const readFileEncoding: string = 'utf8';
const regExp1: RegExp = /^var *a1_0x(\w){4,6} *= *0x1;$/;
const regExp2: RegExp = /^var *a0_0x(\w){4,6} *= *0x2;$/;
let outputFixturesFilePath1: string,
outputFixturesFilePath2: string,
outputFixturesFilePath3: string,
isFileExist1: boolean,
isFileExist2: boolean,
isFileExist3: boolean,
fileContent1: string,
fileContent2: string;
before(() => {
outputFixturesFilePath1 = `${directoryPath}/${outputFileName1}`;
outputFixturesFilePath2 = `${directoryPath}/${outputFileName2}`;
outputFixturesFilePath3 = `${directoryPath}/${outputFileName3}`;
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
directoryPath,
'--rename-globals',
'true'
]);
isFileExist1 = fs.existsSync(outputFixturesFilePath1);
isFileExist2 = fs.existsSync(outputFixturesFilePath2);
isFileExist3 = fs.existsSync(outputFixturesFilePath3);
fileContent1 = fs.readFileSync(outputFixturesFilePath1, readFileEncoding);
fileContent2 = fs.readFileSync(outputFixturesFilePath2, readFileEncoding);
});
it(`should create file \`${outputFileName1}\` with obfuscated code in \`${fixturesDirName}\` directory`, () => {
assert.equal(isFileExist1, true);
});
it(`should create file \`${outputFileName2}\` with obfuscated code in \`${fixturesDirName}\` directory`, () => {
assert.equal(isFileExist2, true);
});
it(`shouldn't create file \`${outputFileName3}\` in \`${fixturesDirName}\` directory`, () => {
assert.equal(isFileExist3, false);
});
it(`match #1: should create file with obfuscated code with prefixed identifier`, () => {
assert.match(fileContent1, regExp1);
});
it(`match #2: should create file with obfuscated code with prefixed identifier`, () => {
assert.match(fileContent2, regExp2);
});
after(() => {
rimraf.sync(outputFixturesFilePath1);
rimraf.sync(outputFixturesFilePath2);
});
});
describe('Variant #2: obfuscation of directory with `identifiersPrefix` option value', () => {
const directoryPath: string = `${fixturesDirName}/directory-obfuscation`;
const identifiersPrefix: string = 'foo';
const outputFileName1: string = 'foo-obfuscated.js';
const outputFileName2: string = 'bar-obfuscated.js';
const readFileEncoding: string = 'utf8';
const regExp1: RegExp = /^var *foo1_0x(\w){4,6} *= *0x1;$/;
const regExp2: RegExp = /^var *foo0_0x(\w){4,6} *= *0x2;$/;
let outputFixturesFilePath1: string,
outputFixturesFilePath2: string,
isFileExist1: boolean,
isFileExist2: boolean,
fileContent1: string,
fileContent2: string;
before(() => {
outputFixturesFilePath1 = `${directoryPath}/${outputFileName1}`;
outputFixturesFilePath2 = `${directoryPath}/${outputFileName2}`;
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
directoryPath,
'--identifiers-prefix',
identifiersPrefix,
'--rename-globals',
'true'
]);
isFileExist1 = fs.existsSync(outputFixturesFilePath1);
isFileExist2 = fs.existsSync(outputFixturesFilePath2);
fileContent1 = fs.readFileSync(outputFixturesFilePath1, readFileEncoding);
fileContent2 = fs.readFileSync(outputFixturesFilePath2, readFileEncoding);
});
it(`should create file \`${outputFileName1}\` with obfuscated code in \`${fixturesDirName}\` directory`, () => {
assert.equal(isFileExist1, true);
});
it(`should create file \`${outputFileName2}\` with obfuscated code in \`${fixturesDirName}\` directory`, () => {
assert.equal(isFileExist2, true);
});
it(`match #1: should create file with obfuscated code with prefixed identifier`, () => {
assert.match(fileContent1, regExp1);
});
it(`match #2: should create file with obfuscated code with prefixed identifier`, () => {
assert.match(fileContent2, regExp2);
});
after(() => {
rimraf.sync(outputFixturesFilePath1);
rimraf.sync(outputFixturesFilePath2);
});
});
describe('Variant #3: obfuscation of directory with `output` option', () => {
const directoryPath: string = `${fixturesDirName}/directory-obfuscation`;
const outputDirectoryName: string = 'obfuscated';
const outputDirectoryPath: string = `${directoryPath}/${outputDirectoryName}`;
const outputFileName1: string = 'foo.js';
const outputFileName2: string = 'bar.js';
const outputFileName3: string = 'baz.js';
let outputFixturesFilePath1: string,
outputFixturesFilePath2: string,
outputFixturesFilePath3: string,
isFileExist1: boolean,
isFileExist2: boolean,
isFileExist3: boolean;
before(() => {
outputFixturesFilePath1 = `${outputDirectoryPath}/${directoryPath}/${outputFileName1}`;
outputFixturesFilePath2 = `${outputDirectoryPath}/${directoryPath}/${outputFileName2}`;
outputFixturesFilePath3 = `${outputDirectoryPath}/${directoryPath}/${outputFileName3}`;
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
directoryPath,
'--output',
outputDirectoryPath
]);
isFileExist1 = fs.existsSync(outputFixturesFilePath1);
isFileExist2 = fs.existsSync(outputFixturesFilePath2);
isFileExist3 = fs.existsSync(outputFixturesFilePath3);
});
it(
`should create file \`${outputFileName1}\` with obfuscated code in ` +
`\`${fixturesDirName}/${outputDirectoryName}\` directory`,
() => {
assert.equal(isFileExist1, true);
}
);
it(
`should create file \`${outputFileName2}\` with obfuscated code in ` +
`\`${fixturesDirName}/${outputDirectoryName}\` directory`,
() => {
assert.equal(isFileExist2, true);
}
);
it(
`shouldn't create file \`${outputFileName3}\` in ` +
`\`${fixturesDirName}/${outputDirectoryName}\` directory`,
() => {
assert.equal(isFileExist3, false);
}
);
after(() => {
rimraf.sync(outputDirectoryPath);
});
});
describe('Variant #4: --exclude option', () => {
describe('Variant #1: --exclude option is pointed on different file', () => {
const directoryPath: string = `${fixturesDirName}/directory-obfuscation`;
const outputFileName1: string = 'foo-obfuscated.js';
const outputFileName2: string = 'bar-obfuscated.js';
const outputFileName3: string = 'baz-obfuscated.js';
const readFileEncoding: string = 'utf8';
const regExp1: RegExp = /^var *a1_0x(\w){4,6} *= *0x1;$/;
const regExp2: RegExp = /^var *a0_0x(\w){4,6} *= *0x2;$/;
let outputFixturesFilePath1: string,
outputFixturesFilePath2: string,
outputFixturesFilePath3: string,
isFileExist1: boolean,
isFileExist2: boolean,
isFileExist3: boolean,
fileContent1: string,
fileContent2: string;
before(() => {
outputFixturesFilePath1 = `${directoryPath}/${outputFileName1}`;
outputFixturesFilePath2 = `${directoryPath}/${outputFileName2}`;
outputFixturesFilePath3 = `${directoryPath}/${outputFileName3}`;
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
directoryPath,
'--exclude',
'**/bark.js',
'--rename-globals',
'true'
]);
isFileExist1 = fs.existsSync(outputFixturesFilePath1);
isFileExist2 = fs.existsSync(outputFixturesFilePath2);
isFileExist3 = fs.existsSync(outputFixturesFilePath3);
fileContent1 = fs.readFileSync(outputFixturesFilePath1, readFileEncoding);
fileContent2 = fs.readFileSync(outputFixturesFilePath2, readFileEncoding);
});
it(`should create file \`${outputFileName1}\` with obfuscated code in \`${fixturesDirName}\` directory`, () => {
assert.equal(isFileExist1, true);
});
it(`should create file \`${outputFileName2}\` with obfuscated code in \`${fixturesDirName}\` directory`, () => {
assert.equal(isFileExist2, true);
});
it(`shouldn't create file \`${outputFileName3}\` in \`${fixturesDirName}\` directory`, () => {
assert.equal(isFileExist3, false);
});
it(`match #1: should create file with obfuscated code with prefixed identifier`, () => {
assert.match(fileContent1, regExp1);
});
it(`match #2: should create file with obfuscated code with prefixed identifier`, () => {
assert.match(fileContent2, regExp2);
});
after(() => {
rimraf.sync(outputFixturesFilePath1);
rimraf.sync(outputFixturesFilePath2);
});
});
describe('Variant #2: --exclude option is pointed on file under obfuscating directory', () => {
const directoryPath: string = `${fixturesDirName}/directory-obfuscation`;
const outputFileName1: string = 'foo-obfuscated.js';
const outputFileName2: string = 'bar-obfuscated.js';
const outputFileName3: string = 'baz-obfuscated.js';
const readFileEncoding: string = 'utf8';
const regExp1: RegExp = /^var *a0_0x(\w){4,6} *= *0x2;$/;
let outputFixturesFilePath1: string,
outputFixturesFilePath2: string,
outputFixturesFilePath3: string,
isFileExist1: boolean,
isFileExist2: boolean,
isFileExist3: boolean,
fileContent1: string;
before(() => {
outputFixturesFilePath1 = `${directoryPath}/${outputFileName1}`;
outputFixturesFilePath2 = `${directoryPath}/${outputFileName2}`;
outputFixturesFilePath3 = `${directoryPath}/${outputFileName3}`;
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
directoryPath,
'--exclude',
'**/foo.js',
'--rename-globals',
'true'
]);
isFileExist1 = fs.existsSync(outputFixturesFilePath1);
isFileExist2 = fs.existsSync(outputFixturesFilePath2);
isFileExist3 = fs.existsSync(outputFixturesFilePath3);
fileContent1 = fs.readFileSync(outputFixturesFilePath2, readFileEncoding);
});
it(`shouldn't create file \`${outputFileName1}\` in \`${fixturesDirName}\` directory`, () => {
assert.equal(isFileExist1, false);
});
it(`should create file \`${outputFileName2}\` with obfuscated code in \`${fixturesDirName}\` directory`, () => {
assert.equal(isFileExist2, true);
});
it(`shouldn't create file \`${outputFileName3}\` in \`${fixturesDirName}\` directory`, () => {
assert.equal(isFileExist3, false);
});
it(`match #1: should create file with obfuscated code with prefixed identifier`, () => {
assert.match(fileContent1, regExp1);
});
after(() => {
rimraf.sync(outputFixturesFilePath1);
rimraf.sync(outputFixturesFilePath2);
});
});
});
});
describe('`--sourceMap` option is set', () => {
const outputSourceMapPath: string = `${outputFilePath}.map`;
describe('Variant #1: `--sourceMapMode` option value is `separate`', () => {
describe('Variant #1: default behaviour', () => {
const expectedSourceMapSourceName: string = path.basename(fixtureFileName);
let isFileExist: boolean,
sourceMapObject: any;
before(() => {
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--compact',
'true',
'--self-defending',
'0',
'--source-map',
'true'
]);
try {
const content: string = fs.readFileSync(outputSourceMapPath, { encoding: 'utf8' });
isFileExist = true;
sourceMapObject = JSON.parse(content);
} catch (e) {
isFileExist = false;
}
});
it('should create file with source map in the same directory as output file', () => {
assert.equal(isFileExist, true);
});
it('source map from created file should contains property `version`', () => {
assert.property(sourceMapObject, 'version');
});
it('source map from created file should contains property `sources`', () => {
assert.property(sourceMapObject, 'sources');
});
it('source map source should has correct name', () => {
assert.equal(sourceMapObject.sources[0], expectedSourceMapSourceName);
});
it('source map from created file should contains property `names`', () => {
assert.property(sourceMapObject, 'names');
});
after(() => {
rimraf.sync(outputFilePath);
rimraf.sync(outputSourceMapPath);
});
});
describe('Variant #2: `sourceMapBaseUrl` option is set', () => {
const expectedSourceMapSourceName: string = path.basename(fixtureFileName);
let isFileExist: boolean,
sourceMapObject: any;
before(() => {
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--compact',
'true',
'--self-defending',
'0',
'--source-map',
'true',
'--source-map-base-url',
'http://localhost:9000/'
]);
try {
const content: string = fs.readFileSync(outputSourceMapPath, { encoding: 'utf8' });
isFileExist = true;
sourceMapObject = JSON.parse(content);
} catch (e) {
isFileExist = false;
}
});
it('should create file with source map in the same directory as output file', () => {
assert.equal(isFileExist, true);
});
it('source map from created file should contains property `version`', () => {
assert.property(sourceMapObject, 'version');
});
it('source map from created file should contains property `sources`', () => {
assert.property(sourceMapObject, 'sources');
});
it('source map source should has correct name', () => {
assert.equal(sourceMapObject.sources[0], expectedSourceMapSourceName);
});
it('source map from created file should contains property `names`', () => {
assert.property(sourceMapObject, 'names');
});
after(() => {
fs.unlinkSync(outputFilePath);
fs.unlinkSync(outputSourceMapPath);
});
});
describe('Variant #3: `--sourceMapFileName` option is set', () => {
const expectedSourceMapSourceName: string = path.basename(fixtureFileName);
const sourceMapFileName: string = 'test';
const sourceMapFilePath: string = `${sourceMapFileName}.js.map`;
const outputSourceMapFilePath: string = `${outputDirName}/${sourceMapFilePath}`;
let isFileExist: boolean,
sourceMapObject: any;
before(() => {
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--compact',
'true',
'--self-defending',
'0',
'--source-map',
'true',
'--source-map-file-name',
sourceMapFileName
]);
try {
const content: string = fs.readFileSync(outputSourceMapFilePath, { encoding: 'utf8' });
isFileExist = true;
sourceMapObject = JSON.parse(content);
} catch (e) {
isFileExist = false;
}
});
it('should create source map file with given name in the same directory as output file', () => {
assert.equal(isFileExist, true);
});
it('source map from created file should contains property `version`', () => {
assert.property(sourceMapObject, 'version');
});
it('source map from created file should contains property `sources`', () => {
assert.property(sourceMapObject, 'sources');
});
it('source map source should has correct name', () => {
assert.equal(sourceMapObject.sources[0], expectedSourceMapSourceName);
});
it('source map from created file should contains property `names`', () => {
assert.property(sourceMapObject, 'names');
});
after(() => {
fs.unlinkSync(outputFilePath);
fs.unlinkSync(outputSourceMapFilePath);
});
});
});
describe('Variant #2: `--sourceMapMode` option is `inline`', () => {
let isFileExist: boolean;
before(() => {
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--compact',
'true',
'--self-defending',
'0',
'--source-map',
'true',
'--source-map-mode',
'inline'
]);
isFileExist = fs.existsSync(outputSourceMapPath);
});
it('shouldn\'t create file with source map', () => {
assert.equal(isFileExist, false);
});
after(() => {
fs.unlinkSync(outputFilePath);
});
});
});
describe('help output', () => {
let callback: sinon.SinonSpy<any, void>,
stdoutWriteMock: StdoutWriteMock;
beforeEach(() => {
callback = sinon.spy(console, 'log');
stdoutWriteMock = new StdoutWriteMock(process.stdout.write);
});
describe('`--help` option is set', () => {
let isConsoleLogCalled: boolean;
beforeEach(() => {
stdoutWriteMock.mute();
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--help'
]);
stdoutWriteMock.restore();
isConsoleLogCalled = callback.called;
});
it('should print `console.log` help', () => {
assert.equal(isConsoleLogCalled, true);
});
});
describe('no arguments passed', () => {
let isConsoleLogCalled: boolean;
beforeEach(() => {
stdoutWriteMock.mute();
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator'
]);
stdoutWriteMock.restore();
isConsoleLogCalled = callback.called;
});
it('should print `console.log` help', () => {
assert.equal(isConsoleLogCalled, true);
});
});
afterEach(() => {
callback.restore();
});
});
describe('`--config` option is set', () => {
const outputSourceMapPath: string = `${outputFilePath}.map`;
let isFileExist: boolean,
sourceMapObject: any;
before(() => {
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--config',
configFilePath
]);
try {
const content: string = fs.readFileSync(outputSourceMapPath, {encoding: 'utf8'});
isFileExist = true;
sourceMapObject = JSON.parse(content);
} catch (e) {
isFileExist = false;
}
});
it('should create file with source map in the same directory as output file', () => {
assert.equal(isFileExist, true);
});
it('source map from created file should contains property `version`', () => {
assert.property(sourceMapObject, 'version');
});
it('source map from created file should contains property `sources`', () => {
assert.property(sourceMapObject, 'sources');
});
it('source map from created file should contains property `names`', () => {
assert.property(sourceMapObject, 'names');
});
after(() => {
fs.unlinkSync(outputFilePath);
fs.unlinkSync(outputSourceMapPath);
});
});
describe('`--config` option is set but overridden by CLI option', () => {
const outputSourceMapPath: string = `${outputFilePath}.map`;
let isFileExist: boolean;
before(() => {
JavaScriptObfuscatorCLI.obfuscate([
'node',
'javascript-obfuscator',
fixtureFilePath,
'--output',
outputFilePath,
'--config',
configFilePath,
'--source-map',
'false',
]);
try {
fs.readFileSync(outputSourceMapPath, {encoding: 'utf8'});
isFileExist = true;
} catch (e) {
isFileExist = false;
}
});
it('should create file without source map in the same directory as output file', () => {
assert.equal(isFileExist, false);
});
after(() => {
fs.unlinkSync(outputFilePath);
});
});
after(() => {
rimraf.sync(outputDirName);
});
});
});