mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
591 lines
24 KiB
TypeScript
591 lines
24 KiB
TypeScript
import * as fs from 'fs';
|
|
import * as mkdirp from 'mkdirp';
|
|
import * as rimraf from 'rimraf';
|
|
|
|
import { assert } from 'chai';
|
|
import * as sinon from 'sinon';
|
|
|
|
import { IFileData } from '../../../../src/interfaces/cli/IFileData';
|
|
|
|
import { SourceCodeReader } from '../../../../src/cli/utils/SourceCodeReader';
|
|
|
|
describe('SourceCodeReader', () => {
|
|
const expectedError: RegExp = /Given input path must be a valid/;
|
|
const fileContent: string = 'test';
|
|
const tmpDirectoryPath: string = 'test/tmp';
|
|
|
|
before(() => {
|
|
mkdirp.sync(tmpDirectoryPath);
|
|
});
|
|
|
|
describe('readSourceCode', () => {
|
|
describe('Variant #1: input path is a file path', () => {
|
|
describe('Variant #1: `inputPath` is a valid path', () => {
|
|
const tmpFileName: string = 'test.js';
|
|
const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
|
|
const expectedFilesData: IFileData[] = [{
|
|
content: fileContent,
|
|
filePath: inputPath
|
|
}];
|
|
|
|
let filesData: IFileData[];
|
|
|
|
before(() => {
|
|
fs.writeFileSync(inputPath, fileContent);
|
|
filesData = new SourceCodeReader(inputPath, {}).readSourceCode();
|
|
});
|
|
|
|
it('should return valid files data', () => {
|
|
assert.deepEqual(filesData, expectedFilesData);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(inputPath);
|
|
});
|
|
});
|
|
|
|
describe('Variant #2: `inputPath` is not a valid path', () => {
|
|
const tmpFileName: string = 'test.js';
|
|
const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
|
|
|
|
let testFunc: () => void;
|
|
|
|
before(() => {
|
|
testFunc = () => new SourceCodeReader(inputPath, {}).readSourceCode();
|
|
});
|
|
|
|
it('should throw an error if `inputPath` is not a valid path', () => {
|
|
assert.throws(testFunc, expectedError);
|
|
});
|
|
});
|
|
|
|
describe('Variant #3: `inputPath` has invalid extension', () => {
|
|
const tmpFileName: string = 'test.ts';
|
|
const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
|
|
|
|
let testFunc: () => void;
|
|
|
|
before(() => {
|
|
fs.writeFileSync(inputPath, fileContent);
|
|
testFunc = () => new SourceCodeReader(inputPath, {}).readSourceCode();
|
|
});
|
|
|
|
it('should throw an error if `inputPath` has invalid extension', () => {
|
|
assert.throws(testFunc, expectedError);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(inputPath);
|
|
});
|
|
});
|
|
|
|
describe('Variant #4: `exclude` option', () => {
|
|
describe('Variant #1: `inputPath` isn\'t excluded path', () => {
|
|
const tmpFileName: string = 'test.js';
|
|
const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
|
|
const expectedFilesData: IFileData[] = [{
|
|
content: fileContent,
|
|
filePath: inputPath
|
|
}];
|
|
|
|
let filesData: IFileData[];
|
|
|
|
before(() => {
|
|
fs.writeFileSync(inputPath, fileContent);
|
|
filesData = new SourceCodeReader(
|
|
inputPath,
|
|
{
|
|
exclude: ['**/foo.js']
|
|
}
|
|
).readSourceCode();
|
|
});
|
|
|
|
it('should return valid files data', () => {
|
|
assert.deepEqual(filesData, expectedFilesData);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(inputPath);
|
|
});
|
|
});
|
|
|
|
describe('Variant #2: `inputPath` is excluded path', () => {
|
|
describe('Variant #1: exclude by `glob` pattern', () => {
|
|
const tmpFileName: string = 'test.js';
|
|
const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
|
|
|
|
let testFunc: () => void;
|
|
|
|
before(() => {
|
|
fs.writeFileSync(inputPath, fileContent);
|
|
testFunc = () => new SourceCodeReader(
|
|
inputPath,
|
|
{
|
|
exclude: [`**/${tmpFileName}`]
|
|
}
|
|
).readSourceCode();
|
|
});
|
|
|
|
it('should throw an error if `inputPath` is the excluded file path', () => {
|
|
assert.throws(testFunc, expectedError);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(inputPath);
|
|
});
|
|
});
|
|
|
|
describe('Variant #2: exclude by file name', () => {
|
|
const tmpFileName: string = 'test.js';
|
|
const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
|
|
|
|
let testFunc: () => void;
|
|
|
|
before(() => {
|
|
fs.writeFileSync(inputPath, fileContent);
|
|
testFunc = () => new SourceCodeReader(
|
|
inputPath,
|
|
{
|
|
exclude: [tmpFileName]
|
|
}
|
|
).readSourceCode();
|
|
});
|
|
|
|
it('should throw an error if `inputPath` is the excluded file path', () => {
|
|
assert.throws(testFunc, expectedError);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(inputPath);
|
|
});
|
|
});
|
|
|
|
describe('Variant #3: exclude by file path', () => {
|
|
const tmpFileName: string = 'test.js';
|
|
const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
|
|
|
|
let testFunc: () => void;
|
|
|
|
before(() => {
|
|
fs.writeFileSync(inputPath, fileContent);
|
|
testFunc = () => new SourceCodeReader(
|
|
inputPath,
|
|
{
|
|
exclude: [inputPath]
|
|
}
|
|
).readSourceCode();
|
|
});
|
|
|
|
it('should throw an error if `inputPath` is the excluded file path', () => {
|
|
assert.throws(testFunc, expectedError);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(inputPath);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Variant #2: input path is a directory path', () => {
|
|
describe('Variant #1: `inputPath` is a valid path', () => {
|
|
const tmpFileName1: string = 'foo.js';
|
|
const tmpFileName2: string = 'bar.js';
|
|
const tmpFileName3: string = 'baz.png';
|
|
const tmpFileName4: string = 'bark-obfuscated.js';
|
|
const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
|
|
const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
|
|
const filePath3: string = `${tmpDirectoryPath}/${tmpFileName3}`;
|
|
const filePath4: string = `${tmpDirectoryPath}/${tmpFileName4}`;
|
|
|
|
const expectedResult: IFileData[] = [
|
|
{
|
|
filePath: filePath2,
|
|
content: fileContent
|
|
},
|
|
{
|
|
filePath: filePath1,
|
|
content: fileContent
|
|
}
|
|
];
|
|
|
|
let result: IFileData[];
|
|
|
|
before(() => {
|
|
fs.writeFileSync(filePath1, fileContent);
|
|
fs.writeFileSync(filePath2, fileContent);
|
|
fs.writeFileSync(filePath3, fileContent);
|
|
fs.writeFileSync(filePath4, fileContent);
|
|
result = new SourceCodeReader(tmpDirectoryPath, {}).readSourceCode();
|
|
});
|
|
|
|
it('should return files data', () => {
|
|
assert.deepEqual(result, expectedResult);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(filePath1);
|
|
fs.unlinkSync(filePath2);
|
|
fs.unlinkSync(filePath3);
|
|
fs.unlinkSync(filePath4);
|
|
});
|
|
});
|
|
|
|
describe('Variant #2: `inputPath` is not a valid path', () => {
|
|
const inputPath: string = 'abc';
|
|
|
|
let testFunc: () => void;
|
|
|
|
before(() => {
|
|
testFunc = () => new SourceCodeReader(inputPath, {}).readSourceCode();
|
|
});
|
|
|
|
it('should throw an error if `inputPath` is not a valid path', () => {
|
|
assert.throws(testFunc, expectedError);
|
|
});
|
|
});
|
|
|
|
describe('Variant #3: `inputPath` is a directory with sub-directories', () => {
|
|
const parentDirectoryName1: string = 'parent1';
|
|
const parentDirectoryName2: string = 'parent';
|
|
const parentDirectoryPath1: string = `${tmpDirectoryPath}/${parentDirectoryName1}`;
|
|
const parentDirectoryPath2: string = `${tmpDirectoryPath}/${parentDirectoryName2}`;
|
|
const tmpFileName1: string = 'foo.js';
|
|
const tmpFileName2: string = 'bar.js';
|
|
const tmpFileName3: string = 'baz.js';
|
|
const tmpFileName4: string = 'bark.js';
|
|
const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
|
|
const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
|
|
const filePath3: string = `${parentDirectoryPath1}/${tmpFileName3}`;
|
|
const filePath4: string = `${parentDirectoryPath2}/${tmpFileName4}`;
|
|
|
|
const expectedResult: IFileData[] = [
|
|
{
|
|
filePath: filePath2,
|
|
content: fileContent
|
|
},
|
|
{
|
|
filePath: filePath1,
|
|
content: fileContent
|
|
},
|
|
{
|
|
filePath: filePath4,
|
|
content: fileContent
|
|
},
|
|
{
|
|
filePath: filePath3,
|
|
content: fileContent
|
|
}
|
|
];
|
|
|
|
let result: IFileData[];
|
|
|
|
before(() => {
|
|
mkdirp.sync(parentDirectoryPath1);
|
|
mkdirp.sync(parentDirectoryPath2);
|
|
fs.writeFileSync(filePath1, fileContent);
|
|
fs.writeFileSync(filePath2, fileContent);
|
|
fs.writeFileSync(filePath3, fileContent);
|
|
fs.writeFileSync(filePath4, fileContent);
|
|
result = new SourceCodeReader(tmpDirectoryPath, {}).readSourceCode();
|
|
});
|
|
|
|
it('should return files data', () => {
|
|
assert.deepEqual(result, expectedResult);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(filePath1);
|
|
fs.unlinkSync(filePath2);
|
|
fs.unlinkSync(filePath3);
|
|
fs.unlinkSync(filePath4);
|
|
rimraf.sync(parentDirectoryPath1);
|
|
rimraf.sync(parentDirectoryPath2);
|
|
});
|
|
});
|
|
|
|
describe('Variant #4: `exclude` option', () => {
|
|
describe('Variant #1: `inputPath` isn\'t excluded path', () => {
|
|
const tmpFileName1: string = 'foo.js';
|
|
const tmpFileName2: string = 'bar.js';
|
|
const tmpFileName3: string = 'baz.png';
|
|
const tmpFileName4: string = 'bark-obfuscated.js';
|
|
const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
|
|
const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
|
|
const filePath3: string = `${tmpDirectoryPath}/${tmpFileName3}`;
|
|
const filePath4: string = `${tmpDirectoryPath}/${tmpFileName4}`;
|
|
|
|
const expectedResult: IFileData[] = [
|
|
{
|
|
filePath: filePath2,
|
|
content: fileContent
|
|
},
|
|
{
|
|
filePath: filePath1,
|
|
content: fileContent
|
|
}
|
|
];
|
|
|
|
let result: IFileData[];
|
|
|
|
before(() => {
|
|
fs.writeFileSync(filePath1, fileContent);
|
|
fs.writeFileSync(filePath2, fileContent);
|
|
fs.writeFileSync(filePath3, fileContent);
|
|
fs.writeFileSync(filePath4, fileContent);
|
|
result = new SourceCodeReader(
|
|
tmpDirectoryPath,
|
|
{
|
|
exclude: ['**/hawk.js']
|
|
}
|
|
).readSourceCode();
|
|
});
|
|
|
|
it('should return files data', () => {
|
|
assert.deepEqual(result, expectedResult);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(filePath1);
|
|
fs.unlinkSync(filePath2);
|
|
fs.unlinkSync(filePath3);
|
|
fs.unlinkSync(filePath4);
|
|
});
|
|
});
|
|
|
|
describe('Variant #2: `inputPath` is excluded path', () => {
|
|
describe('Variant #1: exclude by `glob` pattern', () => {
|
|
const tmpFileName1: string = 'foo.js';
|
|
const tmpFileName2: string = 'bar.js';
|
|
const tmpFileName3: string = 'baz.js';
|
|
const tmpFileName4: string = 'bark.js';
|
|
const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
|
|
const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
|
|
const filePath3: string = `${tmpDirectoryPath}/${tmpFileName3}`;
|
|
const filePath4: string = `${tmpDirectoryPath}/${tmpFileName4}`;
|
|
|
|
const expectedResult: IFileData[] = [
|
|
{
|
|
filePath: filePath3,
|
|
content: fileContent
|
|
},
|
|
{
|
|
filePath: filePath1,
|
|
content: fileContent
|
|
}
|
|
];
|
|
|
|
let result: IFileData[];
|
|
|
|
before(() => {
|
|
fs.writeFileSync(filePath1, fileContent);
|
|
fs.writeFileSync(filePath2, fileContent);
|
|
fs.writeFileSync(filePath3, fileContent);
|
|
fs.writeFileSync(filePath4, fileContent);
|
|
result = new SourceCodeReader(
|
|
tmpDirectoryPath,
|
|
{
|
|
exclude: [
|
|
`**/${tmpFileName2}`,
|
|
`**/${tmpFileName4}`
|
|
]
|
|
}
|
|
).readSourceCode();
|
|
});
|
|
|
|
it('should return files data', () => {
|
|
assert.deepEqual(result, expectedResult);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(filePath1);
|
|
fs.unlinkSync(filePath2);
|
|
fs.unlinkSync(filePath3);
|
|
fs.unlinkSync(filePath4);
|
|
});
|
|
});
|
|
|
|
describe('Variant #2: exclude by file name', () => {
|
|
const tmpFileName1: string = 'foo.js';
|
|
const tmpFileName2: string = 'bar.js';
|
|
const tmpFileName3: string = 'baz.js';
|
|
const tmpFileName4: string = 'bark.js';
|
|
const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
|
|
const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
|
|
const filePath3: string = `${tmpDirectoryPath}/${tmpFileName3}`;
|
|
const filePath4: string = `${tmpDirectoryPath}/${tmpFileName4}`;
|
|
|
|
const expectedResult: IFileData[] = [
|
|
{
|
|
filePath: filePath3,
|
|
content: fileContent
|
|
},
|
|
{
|
|
filePath: filePath1,
|
|
content: fileContent
|
|
}
|
|
];
|
|
|
|
let result: IFileData[];
|
|
|
|
before(() => {
|
|
fs.writeFileSync(filePath1, fileContent);
|
|
fs.writeFileSync(filePath2, fileContent);
|
|
fs.writeFileSync(filePath3, fileContent);
|
|
fs.writeFileSync(filePath4, fileContent);
|
|
result = new SourceCodeReader(
|
|
tmpDirectoryPath,
|
|
{
|
|
exclude: [
|
|
tmpFileName2,
|
|
tmpFileName4
|
|
]
|
|
}
|
|
).readSourceCode();
|
|
});
|
|
|
|
it('should return files data', () => {
|
|
assert.deepEqual(result, expectedResult);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(filePath1);
|
|
fs.unlinkSync(filePath2);
|
|
fs.unlinkSync(filePath3);
|
|
fs.unlinkSync(filePath4);
|
|
});
|
|
});
|
|
|
|
describe('Variant #3: exclude by file path', () => {
|
|
const tmpFileName1: string = 'foo.js';
|
|
const tmpFileName2: string = 'bar.js';
|
|
const tmpFileName3: string = 'baz.js';
|
|
const tmpFileName4: string = 'bark.js';
|
|
const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
|
|
const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
|
|
const filePath3: string = `${tmpDirectoryPath}/${tmpFileName3}`;
|
|
const filePath4: string = `${tmpDirectoryPath}/${tmpFileName4}`;
|
|
|
|
const expectedResult: IFileData[] = [
|
|
{
|
|
filePath: filePath3,
|
|
content: fileContent
|
|
},
|
|
{
|
|
filePath: filePath1,
|
|
content: fileContent
|
|
}
|
|
];
|
|
|
|
let result: IFileData[];
|
|
|
|
before(() => {
|
|
fs.writeFileSync(filePath1, fileContent);
|
|
fs.writeFileSync(filePath2, fileContent);
|
|
fs.writeFileSync(filePath3, fileContent);
|
|
fs.writeFileSync(filePath4, fileContent);
|
|
result = new SourceCodeReader(
|
|
tmpDirectoryPath,
|
|
{
|
|
exclude: [
|
|
filePath2,
|
|
filePath4
|
|
]
|
|
}
|
|
).readSourceCode();
|
|
});
|
|
|
|
it('should return files data', () => {
|
|
assert.deepEqual(result, expectedResult);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(filePath1);
|
|
fs.unlinkSync(filePath2);
|
|
fs.unlinkSync(filePath3);
|
|
fs.unlinkSync(filePath4);
|
|
});
|
|
});
|
|
|
|
describe('Variant #4: exclude whole directory', () => {
|
|
const tmpFileName1: string = 'foo.js';
|
|
const tmpFileName2: string = 'bar.js';
|
|
const tmpFileName3: string = 'baz.js';
|
|
const tmpFileName4: string = 'bark.js';
|
|
const filePath1: string = `${tmpDirectoryPath}/${tmpFileName1}`;
|
|
const filePath2: string = `${tmpDirectoryPath}/${tmpFileName2}`;
|
|
const filePath3: string = `${tmpDirectoryPath}/${tmpFileName3}`;
|
|
const filePath4: string = `${tmpDirectoryPath}/${tmpFileName4}`;
|
|
|
|
let testFunc: () => void;
|
|
|
|
before(() => {
|
|
fs.writeFileSync(filePath1, fileContent);
|
|
fs.writeFileSync(filePath2, fileContent);
|
|
fs.writeFileSync(filePath3, fileContent);
|
|
fs.writeFileSync(filePath4, fileContent);
|
|
testFunc = () => new SourceCodeReader(
|
|
tmpDirectoryPath,
|
|
{
|
|
exclude: [tmpDirectoryPath]
|
|
}
|
|
).readSourceCode();
|
|
});
|
|
|
|
it('should return files data', () => {
|
|
assert.throws(testFunc, expectedError);
|
|
});
|
|
|
|
after(() => {
|
|
fs.unlinkSync(filePath1);
|
|
fs.unlinkSync(filePath2);
|
|
fs.unlinkSync(filePath3);
|
|
fs.unlinkSync(filePath4);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Variant #3: logging', () => {
|
|
const tmpFileName: string = 'test.js';
|
|
const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
|
|
const expectedConsoleLogCallResult: boolean = true;
|
|
const expectedLoggingMessage: string = `[javascript-obfuscator-cli] Obfuscating file: ${inputPath}...`;
|
|
|
|
let consoleLogSpy: sinon.SinonSpy<any, void>,
|
|
consoleLogCallResult: boolean,
|
|
loggingMessageResult: string;
|
|
|
|
before(() => {
|
|
consoleLogSpy = sinon.spy(console, 'log');
|
|
|
|
fs.writeFileSync(inputPath, fileContent);
|
|
new SourceCodeReader(inputPath, {}).readSourceCode();
|
|
|
|
consoleLogCallResult = consoleLogSpy.called;
|
|
loggingMessageResult = consoleLogSpy.getCall(0).args[0];
|
|
});
|
|
|
|
it('should call `console.log`', () => {
|
|
assert.equal(consoleLogCallResult, expectedConsoleLogCallResult);
|
|
});
|
|
|
|
it('should log file name to the console', () => {
|
|
assert.include(loggingMessageResult, expectedLoggingMessage);
|
|
});
|
|
|
|
|
|
after(() => {
|
|
consoleLogSpy.restore();
|
|
fs.unlinkSync(inputPath);
|
|
});
|
|
});
|
|
});
|
|
|
|
after(() => {
|
|
rimraf.sync(tmpDirectoryPath);
|
|
});
|
|
});
|