Skip to content

Commit

Permalink
build: Add unit tests for task-import command
Browse files Browse the repository at this point in the history
...
  • Loading branch information
Göran Sander committed Nov 22, 2023
1 parent 855b714 commit be0ca72
Show file tree
Hide file tree
Showing 8 changed files with 419 additions and 81 deletions.
Expand Up @@ -20,7 +20,6 @@ const options = {
};

const defaultTestTimeout = process.env.CTRL_Q_TEST_TIMEOUT || 600000; // 10 minute default timeout
console.log(`Jest timeout: ${defaultTestTimeout}`);
jest.setTimeout(defaultTestTimeout);

// Mock logger
Expand All @@ -38,7 +37,7 @@ const nonExistingTaskId = '9f0d0e02-cccc-bbbb-aaaa-3e9a4d0c8a3d';
const nonExistingTaskName = 'Non-existing task 298374293874298734';

// Check if task exists by ID
describe('taskExistById: Check if task exists by ID', () => {
describe('taskExistById: Check if task exists by ID (cert auth)', () => {
test('existing task', async () => {
const result = await taskExistById(existingTaskId, options);
expect(result).toBe(true);
Expand All @@ -51,7 +50,7 @@ describe('taskExistById: Check if task exists by ID', () => {
});

// Get task by name
describe('getTaskByName: Get task by name', () => {
describe('getTaskByName: Get task by name (cert auth)', () => {
test('no matching task', async () => {
const result = await getTaskByName(nonExistingTaskName, options);
expect(result).toBe(false);
Expand Down Expand Up @@ -81,7 +80,7 @@ describe('getTaskByName: Get task by name', () => {
});

// Get task by ID
describe('getTaskById: Get task by ID', () => {
describe('getTaskById: Get task by ID (cert auth)', () => {
test('no matching task', async () => {
const result = await getTaskById(nonExistingTaskId, options);
expect(result).toEqual(false);
Expand Down
Expand Up @@ -22,19 +22,18 @@ const options = {
};

const defaultTestTimeout = process.env.CTRL_Q_TEST_TIMEOUT || 600000; // 10 minute default timeout
console.log(`Jest timeout: ${defaultTestTimeout}`);
jest.setTimeout(defaultTestTimeout);

test('get tasks (verify parameters)', async () => {
expect(options.authCertFile).not.toHaveLength(0);
expect(options.authCertKeyFile).not.toHaveLength(0);
expect(options.host).not.toHaveLength(0);
expect(options.authUserDir).not.toHaveLength(0);
expect(options.authUserId).not.toHaveLength(0);
});

// Test suite for task import
describe('import task', () => {
describe('import task (cert auth)', () => {
test('get tasks (verify parameters)', async () => {
expect(options.authCertFile).not.toHaveLength(0);
expect(options.authCertKeyFile).not.toHaveLength(0);
expect(options.host).not.toHaveLength(0);
expect(options.authUserDir).not.toHaveLength(0);
expect(options.authUserId).not.toHaveLength(0);
});

test('csv 1: reload task, no triggers', async () => {
const inputDir = './testdata';
const inputFile = `tasks-1.csv`;
Expand Down
200 changes: 200 additions & 0 deletions src/__tests__/task_import_jwt.tes.js
@@ -0,0 +1,200 @@
/* eslint-disable no-await-in-loop */
/* eslint-disable no-console */
const { test, expect, describe } = require('@jest/globals');

const { importTaskFromFile } = require('../lib/cmd/importtask');
const { getTaskById, deleteExternalProgramTaskById, deleteReloadTaskById } = require('../lib/util/task');
const { mapTaskType } = require('../lib/util/lookups');

const options = {
logLevel: process.env.CTRL_Q_LOG_LEVEL || 'info',
authType: process.env.CTRL_Q_AUTH_TYPE || 'cert',
host: process.env.CTRL_Q_HOST || '',
port: process.env.CTRL_Q_PORT || '4242',
schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0',
virtualProxy: process.env.CTRL_Q_VIRTUAL_PROXY || '',
secure: process.env.CTRL_Q_SECURE || true,
authUserDir: process.env.CTRL_Q_AUTH_USER_DIR || '',
authUserId: process.env.CTRL_Q_AUTH_USER_ID || '',
updateMode: process.env.CTRL_Q_UPDATE_MODE || 'create',
authJwt: process.env.CTRL_Q_AUTH_JWT || '',
};

const defaultTestTimeout = process.env.CTRL_Q_TEST_TIMEOUT || 600000; // 10 minute default timeout
jest.setTimeout(defaultTestTimeout);

// Test suite for task import
describe('import task (jwt auth)', () => {
options.authType = 'jwt';
options.port = '443';
options.virtualProxy = 'jwt';

test('get tasks (verify parameters)', async () => {
expect(options.host).not.toHaveLength(0);
expect(options.authUserDir).not.toHaveLength(0);
expect(options.authUserId).not.toHaveLength(0);
});

test('csv 1: reload task, no triggers', async () => {
const inputDir = './testdata';
const inputFile = `tasks-1.csv`;

options.fileType = 'csv';
options.fileName = `${inputDir}/${inputFile}`;

const result = await importTaskFromFile(options);

// Result should be array with length 1
expect(result).not.toBe(false);
expect(result.length).toBe(1);

// Delete all tasks in array
for (let i = 0; i < result.length; i += 1) {
const task = result[i];
const { taskId } = task;

await deleteReloadTaskById(taskId, options);
}
});

test('csv 2: reload task, 1 schema trigger', async () => {
const inputDir = './testdata';
const inputFile = `tasks-2.csv`;

options.fileType = 'csv';
options.fileName = `${inputDir}/${inputFile}`;

const result = await importTaskFromFile(options);

// Result should be array with length 1
expect(result).not.toBe(false);
expect(result.length).toBe(1);

// Delete all tasks in array
for (let i = 0; i < result.length; i += 1) {
const task = result[i];
const { taskId } = task;

await deleteReloadTaskById(taskId, options);
}
});

test('csv 3: reload task, 1 composite trigger', async () => {
const inputDir = './testdata';
const inputFile = `tasks-3.csv`;

options.fileType = 'csv';
options.fileName = `${inputDir}/${inputFile}`;

const result = await importTaskFromFile(options);

// Result should be array with length 1
expect(result).not.toBe(false);
expect(result.length).toBe(1);

// Delete all tasks in array
for (let i = 0; i < result.length; i += 1) {
const task = result[i];
const { taskId } = task;

await deleteReloadTaskById(taskId, options);
}
});

test('csv 4: 2 reload tasks, composite & schema triggers', async () => {
const inputDir = './testdata';
const inputFile = `tasks-4.csv`;

options.fileType = 'csv';
options.fileName = `${inputDir}/${inputFile}`;

const result = await importTaskFromFile(options);

// Result should be array with length 2
expect(result).not.toBe(false);
expect(result.length).toBe(2);

// Delete all tasks in array
for (let i = 0; i < result.length; i += 1) {
const task = result[i];
const { taskId } = task;

await deleteReloadTaskById(taskId, options);
}
});

test('csv 5: 1 ext program task, schema trigger', async () => {
const inputDir = './testdata';
const inputFile = `tasks-5.csv`;

options.fileType = 'csv';
options.fileName = `${inputDir}/${inputFile}`;

const result = await importTaskFromFile(options);

// Result should be array with length 1
expect(result).not.toBe(false);
expect(result.length).toBe(1);

// Delete all tasks in array
for (let i = 0; i < result.length; i += 1) {
const task = result[i];
const { taskId } = task;

await deleteExternalProgramTaskById(taskId, options);
}
});

test('csv 6: 1 ext program task, composite trigger', async () => {
const inputDir = './testdata';
const inputFile = `tasks-6.csv`;

options.fileType = 'csv';
options.fileName = `${inputDir}/${inputFile}`;

const result = await importTaskFromFile(options);

// Result should be array with length 1
expect(result).not.toBe(false);
expect(result.length).toBe(1);

// Delete all tasks in array
for (let i = 0; i < result.length; i += 1) {
const task = result[i];
const { taskId } = task;

await deleteExternalProgramTaskById(taskId, options);
}
});

test('csv 7: complex. many schema and composite triggers', async () => {
const inputDir = './testdata';
const inputFile = `tasks-7.csv`;

options.fileType = 'csv';
options.fileName = `${inputDir}/${inputFile}`;

const result = await importTaskFromFile(options);

// Result should be array with length 1
expect(result).not.toBe(false);
expect(result.length).toBe(18);

// Delete all tasks in array
for (let i = 0; i < result.length; i += 1) {
const task = result[i];
const { taskId } = task;

// Call getTaskById to verify that task exists and what task type it is
const task2 = await getTaskById(taskId, options);
const taskType = mapTaskType.get(task2.taskType);

// taskType should be 'Reload' or 'External Program'
if (taskType === 'Reload') {
await deleteReloadTaskById(taskId, options);
} else if (taskType === 'ExternalProgram') {
await deleteExternalProgramTaskById(taskId, options);
}
}
});
});
98 changes: 98 additions & 0 deletions src/__tests__/task_jwt.test.js
@@ -0,0 +1,98 @@
/* eslint-disable no-console */
const { test, expect, describe } = require('@jest/globals');

const { taskExistById, getTaskByName, getTaskById } = require('../lib/util/task');

const options = {
logLevel: process.env.CTRL_Q_LOG_LEVEL || 'info',
authType: process.env.CTRL_Q_AUTH_TYPE || 'cert',
authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem',
authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem',
host: process.env.CTRL_Q_HOST || '',
port: process.env.CTRL_Q_PORT || '4242',
schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0',
virtualProxy: process.env.CTRL_Q_VIRTUAL_PROXY || '',
secure: process.env.CTRL_Q_SECURE || true,
authUserDir: process.env.CTRL_Q_AUTH_USER_DIR || '',
authUserId: process.env.CTRL_Q_AUTH_USER_ID || '',

taskType: process.env.CTRL_Q_TASK_TYPE || 'reload',
};

const defaultTestTimeout = process.env.CTRL_Q_TEST_TIMEOUT || 600000; // 10 minute default timeout
jest.setTimeout(defaultTestTimeout);

// Mock logger
global.console = {
log: jest.fn(),
info: jest.fn(),
error: jest.fn(),
};

// Define existing and non-existing tasks
const existingTaskId = 'e9100e69-4e8e-414b-bf88-10a1110c43a9';
const existingTaskName = '[ctrl-q unit test] app 1, task 1';
const multipleMatchingTaskNames = '[ctrl-q unit test] app 1, task 2 (duplicates exist)';
const nonExistingTaskId = '9f0d0e02-cccc-bbbb-aaaa-3e9a4d0c8a3d';
const nonExistingTaskName = 'Non-existing task 298374293874298734';

// Check if task exists by ID
describe('taskExistById: Check if task exists by ID (cert auth)', () => {
test('existing task', async () => {
const result = await taskExistById(existingTaskId, options);
expect(result).toBe(true);
});

test('non-existing task', async () => {
const result = await taskExistById(nonExistingTaskId, options);
expect(result).toBe(false);
});
});

// Get task by name
describe('getTaskByName: Get task by name (cert auth)', () => {
test('no matching task', async () => {
const result = await getTaskByName(nonExistingTaskName, options);
expect(result).toBe(false);
});

test('1 matching task name', async () => {
const result = await getTaskByName(existingTaskName, options);
expect(result.id).toEqual(existingTaskId);
});

test('multiple matching task names', async () => {
const result = await getTaskByName(multipleMatchingTaskNames, options);

// Should return false
expect(result).toEqual(false);

// Ensure correct substring was written to global console log
expect(global.console.log).toHaveBeenCalledWith(
expect.stringContaining(`More than one task with name ${multipleMatchingTaskNames} found.`)
);
});

test('no task name provided', async () => {
const result = await getTaskByName('', options);
expect(result).toEqual(false);
});
});

// Get task by ID
describe('getTaskById: Get task by ID (cert auth)', () => {
test('no matching task', async () => {
const result = await getTaskById(nonExistingTaskId, options);
expect(result).toEqual(false);
});

test('1 matching task', async () => {
const result = await getTaskById(existingTaskId, options);
expect(result.id).toEqual(existingTaskId);
});

test('no task id provided', async () => {
const result = await getTaskById('', options);
expect(result).toEqual(false);
});
});
8 changes: 5 additions & 3 deletions src/lib/task/class_allcompositeevents.js
Expand Up @@ -16,9 +16,11 @@ class QlikSenseCompositeEvents {
this.compositeEventList = [];
this.options = options;

// Make sure certificates exist
this.fileCert = path.resolve(execPath, options.authCertFile);
this.fileCertKey = path.resolve(execPath, options.authCertKeyFile);
if (this.options.authType === 'cert') {
// Make sure certificates exist
this.fileCert = path.resolve(execPath, options.authCertFile);
this.fileCertKey = path.resolve(execPath, options.authCertKeyFile);
}
} catch (err) {
logger.error(`GET COMPOSITE EVENT: ${err}`);
}
Expand Down
8 changes: 5 additions & 3 deletions src/lib/task/class_allschemaevents.js
Expand Up @@ -16,9 +16,11 @@ class QlikSenseSchemaEvents {
this.schemaEventList = [];
this.options = options;

// Make sure certificates exist
this.fileCert = path.resolve(execPath, options.authCertFile);
this.fileCertKey = path.resolve(execPath, options.authCertKeyFile);
if (this.options.authType === 'cert') {
// Make sure certificates exist
this.fileCert = path.resolve(execPath, options.authCertFile);
this.fileCertKey = path.resolve(execPath, options.authCertKeyFile);
}
} catch (err) {
logger.error(`GET SCHEMA EVENT: ${err}`);
}
Expand Down

0 comments on commit be0ca72

Please sign in to comment.