#!/usr/bin/env node
/**
* Test script for Master Items creation on Qlik Cloud
*
* Usage:
* QLIK_TENANT_URL=https://your-tenant.region.qlikcloud.com \
* QLIK_API_KEY=your-api-key \
* QLIK_APP_ID=your-app-id \
* node test-master-items.mjs
*/
import enigma from 'enigma.js';
import WebSocket from 'ws';
import { readFileSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
// Load schema
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
let schema;
try {
const schemaPath = join(__dirname, 'node_modules/enigma.js/schemas/12.1306.0.json');
schema = JSON.parse(readFileSync(schemaPath, 'utf-8'));
} catch {
console.error('❌ Could not load enigma.js schema');
process.exit(1);
}
// Config from environment
const tenantUrl = process.env.QLIK_TENANT_URL;
const apiKey = process.env.QLIK_API_KEY;
const appId = process.env.QLIK_APP_ID;
if (!tenantUrl || !apiKey || !appId) {
console.error('❌ Missing required environment variables:');
console.error(' QLIK_TENANT_URL - e.g., https://your-tenant.region.qlikcloud.com');
console.error(' QLIK_API_KEY - Your Qlik Cloud API key');
console.error(' QLIK_APP_ID - App ID to create master items in');
process.exit(1);
}
const host = tenantUrl.replace('https://', '').replace('http://', '');
const wsUrl = `wss://${host}/app/${appId}`;
console.log('🔧 Test Master Items Creation (Qlik Cloud)');
console.log('==========================================');
console.log(`Tenant: ${host}`);
console.log(`App ID: ${appId}`);
console.log(`WebSocket URL: ${wsUrl}`);
console.log('');
let session;
let createdDimensionId;
let createdMeasureId;
async function runTests() {
try {
// ===== CONNECT =====
console.log('1️⃣ Connecting to Qlik Cloud...');
session = enigma.create({
schema,
url: wsUrl,
createSocket: (url) => new WebSocket(url, {
headers: {
'Authorization': `Bearer ${apiKey}`
}
})
});
const global = await session.open();
console.log(' ✅ Connected to Engine');
const app = await global.openDoc(appId);
console.log(' ✅ Opened app');
console.log('');
// ===== CREATE DIMENSION =====
console.log('2️⃣ Creating test master dimension...');
const dimProps = {
qInfo: { qType: 'dimension' },
qDim: {
qGrouping: 'N',
qFieldDefs: ['_test_field_'],
qFieldLabels: ['Test Dimension Label']
},
qMetaDef: {
title: '_MCP_TEST_DIMENSION_',
description: 'Test dimension created by MCP test script',
tags: ['mcp-test', 'auto-created']
}
};
const dimension = await app.createDimension(dimProps);
const dimLayout = await dimension.getLayout();
createdDimensionId = dimLayout.qInfo.qId;
console.log(` ✅ Dimension created: ${createdDimensionId}`);
console.log(` Title: ${dimLayout.qMeta?.title || dimProps.qMetaDef.title}`);
console.log('');
// ===== CREATE MEASURE =====
console.log('3️⃣ Creating test master measure...');
const measureProps = {
qInfo: { qType: 'measure' },
qMeasure: {
qLabel: 'Test Measure Label',
qDef: 'Count(1)',
qGrouping: 'N',
qNumFormat: {
qType: 'F',
qnDec: 0,
qUseThou: 1,
qFmt: '#,##0',
qDec: '.',
qThou: ','
}
},
qMetaDef: {
title: '_MCP_TEST_MEASURE_',
description: 'Test measure created by MCP test script',
tags: ['mcp-test', 'auto-created']
}
};
const measure = await app.createMeasure(measureProps);
const measureLayout = await measure.getLayout();
createdMeasureId = measureLayout.qInfo.qId;
console.log(` ✅ Measure created: ${createdMeasureId}`);
console.log(` Title: ${measureLayout.qMeta?.title || measureProps.qMetaDef.title}`);
console.log('');
// ===== CLEANUP =====
console.log('4️⃣ Cleaning up test items...');
await app.destroyDimension(createdDimensionId);
console.log(` ✅ Deleted dimension: ${createdDimensionId}`);
await app.destroyMeasure(createdMeasureId);
console.log(` ✅ Deleted measure: ${createdMeasureId}`);
console.log('');
// ===== SUCCESS =====
console.log('==========================================');
console.log('✅ ALL TESTS PASSED!');
console.log('');
console.log('The master items recipe should work correctly.');
console.log('');
} catch (error) {
console.error('');
console.error('❌ TEST FAILED');
console.error('==========================================');
console.error('Error:', error.message);
if (error.message.includes('401') || error.message.includes('Unauthorized')) {
console.error('');
console.error('💡 Hint: Check your API key is valid and has access to this app');
} else if (error.message.includes('404') || error.message.includes('not found')) {
console.error('');
console.error('💡 Hint: Check the app ID exists and you have access to it');
} else if (error.message.includes('ENOTFOUND') || error.message.includes('getaddrinfo')) {
console.error('');
console.error('💡 Hint: Check your tenant URL is correct');
}
process.exit(1);
} finally {
if (session) {
try {
await session.close();
console.log('Session closed.');
} catch (e) {
// ignore
}
}
}
}
runTests();