@sasjs/cli
Version:
Command line interface for SASjs
352 lines (351 loc) • 19.4 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var __1 = require("../");
var utils_1 = require("@sasjs/utils");
var test_1 = require("../../../../utils/test");
var path_1 = __importDefault(require("path"));
var compile_1 = require("../../compile");
var chalk_1 = __importDefault(require("chalk"));
describe('compileTestFile', function () {
var appName = "cli-tests-compile-test-file-".concat((0, utils_1.generateTimestamp)());
var temp = (0, test_1.generateTestTarget)(appName, '/Public/app', {
serviceFolders: [path_1.default.join('sasjs', 'services')],
initProgram: '',
termProgram: '',
macroVars: {}
}, utils_1.ServerType.SasViya);
var target = new utils_1.Target(__assign(__assign({}, temp.toJson()), { jobConfig: {
jobFolders: [path_1.default.join('sasjs', 'jobs')]
}, macroFolders: ['sasjs/macros'] }));
var sasjsPath;
var testBody;
var buildPath;
var testFileName = 'random.test.sas';
beforeAll(function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
process.logger = new utils_1.Logger(utils_1.LogLevel.Off);
buildPath = path_1.default.join(__dirname, appName, 'sasjsbuild');
return [4 /*yield*/, (0, test_1.createTestMinimalApp)(__dirname, target.name)];
case 1:
_a.sent();
return [4 /*yield*/, copyTestFiles(appName)];
case 2:
_a.sent();
return [4 /*yield*/, (0, utils_1.readFile)(path_1.default.join(__dirname, 'testFiles', 'services', testFileName))];
case 3:
testBody = _a.sent();
sasjsPath = path_1.default.join(__dirname, appName, 'sasjs');
return [2 /*return*/];
}
});
}); });
afterAll(function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, (0, test_1.removeTestApp)(__dirname, target.name)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
afterEach(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, (0, utils_1.deleteFolder)(buildPath)];
case 1: return [2 /*return*/, _a.sent()];
}
}); }); });
describe('compileTestFile function', function () {
it('should compile test file', function () { return __awaiter(void 0, void 0, void 0, function () {
var testContent;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, (0, compile_1.compile)(target)];
case 1:
_a.sent();
testContent = function (filePath) { return __awaiter(void 0, void 0, void 0, function () {
var compiledTestFilePath, testFileContent, _a, testVar, testInit, testTerm, mvWebout;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
compiledTestFilePath = path_1.default.join(__dirname, appName, 'sasjsbuild', 'tests', filePath);
return [4 /*yield*/, expect((0, utils_1.fileExists)(compiledTestFilePath)).resolves.toEqual(true)];
case 1:
_b.sent();
_a = replaceLineBreaks;
return [4 /*yield*/, (0, utils_1.readFile)(compiledTestFilePath)];
case 2:
testFileContent = _a.apply(void 0, [_b.sent()]);
testVar = replaceLineBreaks("* Test Variables start;\n\n%let ".concat(Object.keys(target.testConfig.macroVars)[0], "=").concat(Object.values(target.testConfig.macroVars)[0], ";\n\n* Test Variables end;"));
testInit = replaceLineBreaks("* TestInit start;\n\n\n%put testing, init;\n* TestInit end;");
testTerm = replaceLineBreaks("* TestTerm start;\n\n\n%put testing, termed;\n* TestTerm end;");
mvWebout = "%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=N,stream=Y,missing=NULL";
expect(testFileContent.indexOf(testVar)).toBeGreaterThan(-1);
expect(testFileContent.indexOf(testInit)).toBeGreaterThan(-1);
expect(testFileContent.indexOf(testTerm)).toBeGreaterThan(-1);
expect(testFileContent.indexOf(mvWebout)).toBeGreaterThan(-1);
return [2 /*return*/];
}
});
}); };
return [4 /*yield*/, testContent(path_1.default.join('services', 'services', 'admin', testFileName))];
case 2:
_a.sent();
return [4 /*yield*/, testContent(path_1.default.join('jobs', 'jobs', 'testJob.test.sas'))];
case 3:
_a.sent();
return [4 /*yield*/, testContent(path_1.default.join('testsetup.sas'))];
case 4:
_a.sent();
return [4 /*yield*/, testContent(path_1.default.join('testteardown.sas'))];
case 5:
_a.sent();
return [4 /*yield*/, testContent(path_1.default.join('macros', 'testMacro.test.sas'))];
case 6:
_a.sent();
return [2 /*return*/];
}
});
}); });
});
describe('compileTestFlow', function () {
it('should compile test flow', function () { return __awaiter(void 0, void 0, void 0, function () {
var testSetUp, testTearDown, testFlowPath, expectedTestFlow, _a, _b, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
testSetUp = path_1.default.join('tests', 'testsetup.sas');
testTearDown = path_1.default.join('tests', 'testteardown.sas');
return [4 /*yield*/, (0, compile_1.compile)(target)];
case 1:
_d.sent();
return [4 /*yield*/, (0, __1.compileTestFlow)(target)];
case 2:
_d.sent();
testFlowPath = path_1.default.join(buildPath, 'testFlow.json');
return [4 /*yield*/, expect((0, utils_1.fileExists)(testFlowPath)).resolves.toEqual(true)];
case 3:
_d.sent();
expectedTestFlow = {
tests: [
['tests', 'jobs', 'jobs', 'testJob.test.sas'].join('/'),
['tests', 'macros', 'testMacro.test.sas'].join('/'),
['tests', 'services', 'services', 'admin', 'random.test.sas'].join('/'),
['tests', 'services', 'services', 'admin', 'random.test.0.sas'].join('/')
].sort(),
testSetUp: testSetUp.split(path_1.default.sep).join('/'),
testTearDown: testTearDown.split(path_1.default.sep).join('/')
};
_a = expect;
_c = (_b = JSON).parse;
return [4 /*yield*/, (0, utils_1.readFile)(testFlowPath)];
case 4: return [4 /*yield*/, _a.apply(void 0, [_c.apply(_b, [_d.sent()])]).toEqual(expectedTestFlow)];
case 5:
_d.sent();
return [2 /*return*/];
}
});
}); });
it('should log coverage', function () { return __awaiter(void 0, void 0, void 0, function () {
var expectedHeader, expectedData;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
jest.spyOn(process.logger, 'table').mockImplementation(function () { return ''; });
expectedHeader = { head: ['File', 'Type', 'Coverage'] };
expectedData = [
[
['services', 'common', 'appinit.sas'].join('/'),
'service',
'not covered'
],
[
['services', 'common', 'getdata.sas'].join('/'),
'service',
'not covered'
],
[
['services', 'services', 'common', 'appinit.sas'].join('/'),
'service',
'not covered'
],
[
['services', 'services', 'common', 'getdata.sas'].join('/'),
'service',
'not covered'
],
[
['tests', 'services', 'services', 'admin', 'random.test.0.sas'].join('/'),
'test',
'standalone'
],
[
['tests', 'jobs', 'jobs', 'testJob.test.sas'].join('/'),
'test',
'standalone'
],
[
['tests', 'macros', 'testMacro.test.sas'].join('/'),
'test',
'standalone'
],
[
['tests', 'services', 'services', 'admin', 'random.test.sas'].join('/'),
'test',
'standalone'
]
].sort();
return [4 /*yield*/, (0, compile_1.compile)(target)];
case 1:
_a.sent();
expect(process.logger.table).toHaveBeenCalledTimes(1);
expect(process.logger.table).toHaveBeenCalledWith(expectedData, expectedHeader);
return [2 /*return*/];
}
});
}); });
it('should not log 0/0 coverage', function () { return __awaiter(void 0, void 0, void 0, function () {
var totalCalls;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
jest.spyOn(process.logger, 'info').mockImplementation(function () { return ''; });
return [4 /*yield*/, (0, compile_1.compile)(target)];
case 1:
_a.sent();
totalCalls = 16;
expect(process.logger.info).toHaveBeenCalledTimes(totalCalls);
expect(process.logger.info).toHaveBeenNthCalledWith(13, "Test coverage:");
expect(process.logger.info).toHaveBeenNthCalledWith(14, "Services coverage: 0/4 (".concat(chalk_1.default.greenBright('0%'), ")"));
expect(process.logger.info).toHaveBeenNthCalledWith(totalCalls - 1, "Overall coverage: 0/4 (".concat(chalk_1.default.greenBright('0%'), ")"));
return [2 /*return*/];
}
});
}); });
it('should log a warning is testFolders was used in root or target configuration', function () { return __awaiter(void 0, void 0, void 0, function () {
var testTarget, testConfig, expectedWarn;
return __generator(this, function (_a) {
testTarget = {
name: 'viya',
serverUrl: '',
serverType: utils_1.ServerType.SasViya,
appLoc: '/Public/sasjs/jobs',
macroFolders: [],
programFolders: [],
binaryFolders: [],
testConfig: {
testSetUp: '',
testTearDown: '',
macroVars: {},
initProgram: '',
termProgram: '',
testFolders: ['tests']
}
};
testConfig = {
macroFolders: ['macros'],
testConfig: {
testFolders: ['tests']
},
defaultTarget: 'viya',
targets: [testTarget]
};
expectedWarn = "'testFolders' is not supported 'testConfig' entry, please use 'serviceFolders' entry in 'serviceConfig' or 'jobFolders' entry in 'jobConfig'.";
jest.spyOn(process.logger, 'warn');
(0, __1.compileTestFlow)(testTarget);
expect(process.logger.warn).toHaveBeenCalledWith(expectedWarn);
(0, __1.compileTestFlow)(testTarget);
expect(process.logger.warn).toHaveBeenCalledWith(expectedWarn);
return [2 /*return*/];
});
}); });
});
});
describe('isTestFile', function () {
it('should return true if test SAS file', function () {
expect((0, utils_1.isTestFile)('random.test.sas')).toEqual(true);
expect((0, utils_1.isTestFile)('random.test.SAS')).toEqual(true);
expect((0, utils_1.isTestFile)('random.test.0.sas')).toEqual(true);
expect((0, utils_1.isTestFile)('random.test.10.sas')).toEqual(true);
});
it('should return false if not a test SAS file', function () {
expect((0, utils_1.isTestFile)('random.test.txt')).toEqual(false);
expect((0, utils_1.isTestFile)('random.sas')).toEqual(false);
expect((0, utils_1.isTestFile)('random.0.sas')).toEqual(false);
expect((0, utils_1.isTestFile)('random.tests.sas')).toEqual(false);
});
});
var copyTestFiles = function (appName) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, (0, utils_1.copy)(path_1.default.join(__dirname, 'testFiles', 'tests'), path_1.default.join(__dirname, appName, 'tests'))];
case 1:
_a.sent();
return [4 /*yield*/, (0, utils_1.copy)(path_1.default.join(__dirname, 'testFiles', 'services'), path_1.default.join(__dirname, appName, 'sasjs', 'services', 'admin'))];
case 2:
_a.sent();
return [4 /*yield*/, (0, utils_1.copy)(path_1.default.join(__dirname, 'testFiles', 'jobs'), path_1.default.join(__dirname, appName, 'sasjs', 'jobs'))];
case 3:
_a.sent();
return [4 /*yield*/, (0, utils_1.copy)(path_1.default.join(__dirname, 'testFiles', 'macros'), path_1.default.join(__dirname, appName, 'sasjs', 'macros'))];
case 4:
_a.sent();
return [2 /*return*/];
}
});
}); };
var replaceLineBreaks = function (str) {
return str.replace(/(?:\r\n|\r|\n)/g, '<br>');
};