diff --git a/lib/countly-bulk.js b/lib/countly-bulk.js index 75dde74..035ad32 100644 --- a/lib/countly-bulk.js +++ b/lib/countly-bulk.js @@ -39,7 +39,6 @@ const StorageTypes = cc.storageTypeEnums; * @param {number} [conf.fail_timeout=60] - set time in seconds to wait after failed connection to server in seconds * @param {number} [conf.session_update=60] - how often in seconds should session be extended * @param {number} [conf.max_events=100] - maximum amount of events to send in one batch - * @deprecated {boolean} [conf.persist_queue=false] - persistent mode instead of using in-memory queue. Use storage_type and storage_path instead * @param {boolean} [conf.force_post=false] - force using post method for all requests * @param {string} [conf.storage_path] - where SDK would store data, including id, queues, etc * @param {string} [conf.http_options=] - function to get http options by reference and overwrite them, before running each request @@ -51,6 +50,7 @@ const StorageTypes = cc.storageTypeEnums; * @param {number} [conf.max_stack_trace_line_length=200] - maximum amount of characters are allowed per stack trace line. This limits also the crash message length * @param {StorageTypes} conf.storage_type - to determine which storage type is going to be applied * @param {Object} conf.custom_storage_method - user given storage methods + * @param {boolean} [conf.persist_queue=false] - *DEPRECATED* persistent mode instead of using in-memory queue. Use storage_type and storage_path instead * @example * var server = new CountlyBulk({ * app_key: "{YOUR-API-KEY}", @@ -607,21 +607,21 @@ function CountlyBulk(conf) { * getBulkEventQueue is a testing purposed method which returns the event queue object * @returns {Object} eventQueue */ - this.getBulkEventQueue = function() { + this._getBulkEventQueue = function() { return eventQueue; }; /** * getBulkRequestQueue is a testing purposed method which returns the request queue object * @returns {Object} requestQueue */ - this.getBulkRequestQueue = function() { + this._getBulkRequestQueue = function() { return requestQueue; }; /** * getBulkQueue is a testing purposed method which returns the bulk queue object * @returns {Object} bulkQueue */ - this.getBulkQueue = function() { + this._getBulkQueue = function() { return bulkQueue; }; } diff --git a/lib/countly.js b/lib/countly.js index c71bee0..77f935d 100644 --- a/lib/countly.js +++ b/lib/countly.js @@ -71,6 +71,7 @@ Countly.Bulk = Bulk; var maxStackTraceLinesPerThread = 30; var maxStackTraceLineLength = 200; var deviceIdType = null; + var heartBeatTimer = null; /** * Array with list of available features that you can require consent for */ @@ -320,6 +321,10 @@ Countly.Bulk = Bulk; maxStackTraceLinesPerThread = 30; maxStackTraceLineLength = 200; deviceIdType = null; + if (heartBeatTimer) { + clearInterval(heartBeatTimer); + heartBeatTimer = null; + } // cc DEBUG cc.debug = false; @@ -1479,7 +1484,7 @@ Countly.Bulk = Bulk; }, "heartBeat", false); } - setTimeout(heartBeat, beatInterval); + heartBeatTimer = setTimeout(heartBeat, beatInterval); } /** diff --git a/test/helpers/helper_functions.js b/test/helpers/helper_functions.js index daf161f..c441fcc 100644 --- a/test/helpers/helper_functions.js +++ b/test/helpers/helper_functions.js @@ -2,28 +2,40 @@ var path = require("path"); var assert = require("assert"); var fs = require("fs"); +var fsp = require("fs/promises"); var Countly = require("../../lib/countly"); // paths for convenience var dir = path.resolve(__dirname, "../../"); -var defaultStoragePath = (`${dir}/data`); -var defaultBulkStoragePath = (`${dir}/bulk_data`); -var idDir = (`${dir}/data/__cly_id.json`); -var idTypeDir = (`${dir}/data/__cly_id_type.json`); -var eventDir = (`${dir}/data/__cly_event.json`); -var reqDir = (`${dir}/data/__cly_queue.json`); -var bulkEventDir = (`${dir}/bulk_data/__cly_bulk_event.json`); -var bulkReqQueueDir = (`${dir}/bulk_data/__cly_req_queue.json`); -var bulkQueueDir = (`${dir}/bulk_data/__cly_req_queue.json`); +var dir_test = path.resolve(__dirname, "../"); + +// paths for convenience +const DIR_CLY = (`${dir}/data`); +const DIR_CLY_ID = (`${dir}/data/__cly_id.json`); +const DIR_CLY_ID_type = (`${dir}/data/__cly_id_type.json`); +const DIR_CLY_event = (`${dir}/data/__cly_event.json`); +const DIR_CLY_request = (`${dir}/data/__cly_queue.json`); + +// Bulk paths for convenience +const DIR_Bulk = (`${dir}/bulk_data`); +const DIR_Bulk_bulk = (`${dir}/bulk_data/__cly_bulk_queue.json`); +const DIR_Bulk_event = (`${dir}/bulk_data/__cly_bulk_event.json`); +const DIR_Bulk_request = (`${dir}/bulk_data/__cly_req_queue.json`); + +// Custom +const DIR_Test = (`${dir_test}/customStorageDirectory`); +const DIR_Test_bulk = (`${dir_test}/customStorageDirectory/__cly_bulk_queue.json`); +const DIR_Test_event = (`${dir_test}/customStorageDirectory/ __cly_bulk_event.json`); +const DIR_Test_request = (`${dir_test}/customStorageDirectory/__cly_req_queue.json`); // timeout variables -var sWait = 50; -var mWait = 3000; -var lWait = 10000; +const sWait = 50; +const mWait = 3000; +const lWait = 10000; // parsing event queue function readEventQueue(givenPath = null, isBulk = false) { - var destination = eventDir; + var destination = DIR_CLY_event; if (givenPath !== null) { destination = givenPath; } @@ -35,7 +47,7 @@ function readEventQueue(givenPath = null, isBulk = false) { } // parsing request queue function readRequestQueue(givenPath = null, isBulk = false) { - var destination = reqDir; + var destination = DIR_CLY_request; if (givenPath !== null) { destination = givenPath; } @@ -45,10 +57,15 @@ function readRequestQueue(givenPath = null, isBulk = false) { } return a; } -function doesFileStoragePathsExist(callback, isBulk = false) { - const paths = isBulk - ? [bulkQueueDir, bulkReqQueueDir, bulkEventDir] - : [idDir, idTypeDir, eventDir]; +function doesFileStoragePathsExist(callback, isBulk = false, testPath = false) { + var paths = [DIR_CLY_ID, DIR_CLY_ID_type, DIR_CLY_event, DIR_CLY_request]; + + if (isBulk) { + paths = [DIR_Bulk_request, DIR_Bulk_event, DIR_Bulk_bulk]; + } + else if (testPath) { + paths = [DIR_Test_bulk, DIR_Test_event, DIR_Test_request]; + } let errors = 0; paths.forEach((p, index) => { @@ -62,25 +79,26 @@ function doesFileStoragePathsExist(callback, isBulk = false) { }); }); } -function clearStorage(customPath = null) { +async function clearStorage(customPath = null) { Countly.halt(true); - // Construct the relative path to the target folder + const relativePath = `../${customPath}`; - // Use path.resolve to create the absolute path const resolvedCustomPath = path.resolve(__dirname, relativePath); - if (fs.existsSync(defaultStoragePath)) { - fs.rmSync(defaultStoragePath, { recursive: true, force: true }); - } - if (fs.existsSync(defaultBulkStoragePath)) { - fs.rmSync(defaultBulkStoragePath, { recursive: true, force: true }); - } - if (resolvedCustomPath !== null && typeof resolvedCustomPath === 'string' && fs.existsSync(resolvedCustomPath)) { - fs.rmSync(resolvedCustomPath, { recursive: true, force: true }); + await fsp.rm(DIR_CLY, { recursive: true, force: true }).catch(() => { }); + await fsp.rm(DIR_Bulk, { recursive: true, force: true }).catch(() => { }); + await fsp.rm(DIR_Test, { recursive: true, force: true }).catch(() => { }); + + if (resolvedCustomPath !== null && typeof resolvedCustomPath === 'string') { + await fsp.rm(resolvedCustomPath, { recursive: true, force: true }).catch(() => { }); } - // make sure the directories are removed - if (fs.existsSync(defaultStoragePath) || fs.existsSync(defaultBulkStoragePath) || (resolvedCustomPath !== null && fs.existsSync(resolvedCustomPath))) { + const storageExists = await fsp.access(DIR_CLY).then(() => true).catch(() => false); + const bulkStorageExists = await fsp.access(DIR_Bulk).then(() => true).catch(() => false); + const customTestStorage = await fsp.access(DIR_Test).then(() => true).catch(() => false); + const customStorageExists = resolvedCustomPath !== null ? await fsp.access(resolvedCustomPath).then(() => true).catch(() => false) : false; + + if (storageExists || bulkStorageExists || customTestStorage || customStorageExists) { throw new Error("Failed to clear storage"); } } @@ -143,7 +161,7 @@ function requestBaseParamValidator(resultingObject, id) { assert.ok(typeof resultingObject.sdk_version !== 'undefined'); assert.ok(typeof resultingObject.timestamp !== 'undefined'); assert.ok(resultingObject.dow > -1 && resultingObject.dow < 24); - assert.ok(resultingObject.dow > 0 && resultingObject.dow < 8); + assert.ok(resultingObject.dow >= 0 && resultingObject.dow < 8); } /** * bunch of tests specifically gathered for testing crashes diff --git a/test/tests_bulk.js b/test/tests_bulk.js index 1a849b3..2d9247a 100644 --- a/test/tests_bulk.js +++ b/test/tests_bulk.js @@ -109,173 +109,134 @@ var userDetailObj = { }, }; +// Create bulk data +function createBulkData(bulk) { + // Add an event + var user = bulk.add_user({ device_id: "testUser1" }); + user.add_event(eventObj); + + // add user details + var user2 = bulk.add_user({ device_id: "testUser2" }); + user2.user_details(userDetailObj); + + // add request + bulk.add_request({ device_id: "TestUser3" }); + + // add Crash + var user4 = bulk.add_user({ device_id: "TestUser4" }); + try { + runthis(); + } + catch (ex) { + user4.report_crash({ + _os: "Android", + _os_version: "7", + _error: "Stack trace goes here", + _app_version: "1.0", + _run: 12345, + _custom: {}, + _nonfatal: true, + _javascript: true, + _not_os_specific: true, + }, 1500645200); + } +} + +// Validate created bulk data +function validateCreatedBulkData(bulk) { + var events = bulk._getBulkEventQueue(); + var reqQueue = bulk._getBulkRequestQueue(); + var bulkQueue = bulk._getBulkQueue(); + + assert.equal(Object.keys(events).length, 1); + assert.equal(reqQueue.length, 3); + assert.equal(bulkQueue.length, 0); + + var deviceEvents = events.testUser1; // Access the events for the specific device + var recordedEvent = deviceEvents[0]; // Access the first event + hp.eventValidator(eventObj, recordedEvent); + + var req = reqQueue[0]; // read user details queue + const actualUserDetails = req.user_details; // Extract the user_details from the actual request + const isValid = validateUserDetails(actualUserDetails, userDetailObj); + assert.equal(true, isValid); + + var testUser3Request = reqQueue.find((request) => request.device_id === "TestUser3"); + assert.ok(testUser3Request); + assert.strictEqual(testUser3Request.device_id, "TestUser3"); + assert.strictEqual(testUser3Request.app_key, "YOUR_APP_KEY"); + assert.strictEqual(testUser3Request.sdk_name, "javascript_native_nodejs_bulk"); + + var testUser4Request = reqQueue.find((request) => request.device_id === "TestUser4"); + validateCrash(testUser4Request, true); +} + +function shouldFilesExist(shouldExist, isCustomTest = false) { + hp.doesFileStoragePathsExist((exists) => { + assert.equal(shouldExist, exists); + }, true, isCustomTest); +} + describe("Bulk Tests", () => { - // Bulk is on memory by default - // If no storage path and storage type provided during init Bulk should use memory storage - it("1- Bulk with No Storage Path and Storage Type", (done) => { - hp.clearStorage(); - var bulk = new CountlyBulk({ - app_key: "YOUR_APP_KEY", - url: "https://try.count.ly", - }); - assert.equal(storage.getStoragePath(), undefined); - hp.doesFileStoragePathsExist((exists) => { - assert.equal(false, exists); - }, true); - done(); + beforeEach(async() => { + await hp.clearStorage(); }); - // Providing storage path and storage type to Bulk - // Storage path should be the provided custom path and default bulk file paths should not exist - it("2- Bulk with Custom Storage Path", (done) => { - hp.clearStorage(); + it("1- CNR", (done) => { var bulk = new CountlyBulk({ app_key: "YOUR_APP_KEY", url: "https://try.count.ly", - storage_path: "../test/customStorageDirectory/", - storage_type: StorageTypes.FILE, }); - hp.doesFileStoragePathsExist((exists) => { - assert.equal(false, exists); - }, true); - assert.equal(storage.getStoragePath(), "../test/customStorageDirectory/"); - done(); - }); + assert.equal(storage.getStoragePath(), undefined); + shouldFilesExist(false); + createBulkData(bulk); - // Initialize CountlyBulk and record an event - // Bulk should initialize correctly, default bulk file paths should not exist - // Event should be recorded and validated in event queue - it("3- Bulk add_user with Record Event", (done) => { - hp.clearStorage(); - var bulk = new CountlyBulk({ - app_key: "YOUR_APP_KEY", - url: "https://try.count.ly", - }); - hp.doesFileStoragePathsExist((exists) => { - assert.equal(false, exists); - }, true); - var user = bulk.add_user({ device_id: "testUser1" }); - user.add_event(eventObj); setTimeout(() => { - var events = bulk.getBulkEventQueue(); - var deviceEvents = events.testUser1; // Access the events for the specific device - var recordedEvent = deviceEvents[0]; // Access the first event - hp.eventValidator(eventObj, recordedEvent); + validateCreatedBulkData(bulk); + shouldFilesExist(false); done(); }, hp.mWait); }); - // Initialize CountlyBulk and record user details - // Bulk should initialize correctly, default bulk file paths should not exist - // User details should be recorded and validated in request queue - it("4- Bulk add_user with User Details", (done) => { - hp.clearStorage(); - var bulk = new CountlyBulk({ - app_key: "YOUR_APP_KEY", - url: "https://try.count.ly", - }); - hp.doesFileStoragePathsExist((exists) => { - assert.equal(false, exists); - }, true); - var user = bulk.add_user({ device_id: "testUser2" }); - user.user_details(userDetailObj); - // read event queue - setTimeout(() => { - var reqQueue = bulk.getBulkRequestQueue(); - var req = reqQueue[0]; - // Extract the user_details from the actual request - const actualUserDetails = req.user_details || {}; - // Validate the user details - const isValid = validateUserDetails(actualUserDetails, userDetailObj); - assert.equal(true, isValid); - done(); - }, hp.sWait); - }); - - // Initialize CountlyBulk and call add_request - // Bulk should initialize correctly, default bulk file paths should not exist - // Request should be added correctly and validated - it("5- Bulk add_request", (done) => { - hp.clearStorage(); + it("2- CNR_cPath_file", (done) => { var bulk = new CountlyBulk({ app_key: "YOUR_APP_KEY", url: "https://try.count.ly", + storage_path: "../test/customStorageDirectory/", + storage_type: StorageTypes.FILE, }); - hp.doesFileStoragePathsExist((exists) => { - assert.equal(false, exists); - }, true); - bulk.add_request({ device_id: "TestUser3" }); - setTimeout(() => { - var reqQueue = bulk.getBulkRequestQueue(); - var testUser3Request = reqQueue.find((req) => req.device_id === "TestUser3"); - assert.ok(testUser3Request); - assert.strictEqual(testUser3Request.device_id, "TestUser3"); - assert.strictEqual(testUser3Request.app_key, "YOUR_APP_KEY"); - assert.strictEqual(testUser3Request.sdk_name, "javascript_native_nodejs_bulk"); - done(); - }, hp.sWait); - }); + shouldFilesExist(true, true); + assert.equal(storage.getStoragePath(), "../test/customStorageDirectory/"); + createBulkData(bulk); - // Initialize CountlyBulk and report crash - // Bulk should initialize correctly, default bulk file paths should not exist - // Crash should be recorded correctly and validated - it("6- Bulk add_user Report Crash", (done) => { - hp.clearStorage(); - var bulk = new CountlyBulk({ - app_key: "YOUR_APP_KEY", - url: "https://try.count.ly", - }); - hp.doesFileStoragePathsExist((exists) => { - assert.equal(false, exists); - }, true); - var user = bulk.add_user({ device_id: "TestUser4" }); - try { - runthis(); - } - catch (ex) { - user.report_crash({ - _os: "Android", - _os_version: "7", - _error: "Stack trace goes here", - _app_version: "1.0", - _run: 12345, - _custom: {}, - _nonfatal: true, - _javascript: true, - _not_os_specific: true, - }, 1500645200); - } - // read event queue setTimeout(() => { - var reqQueue = bulk.getBulkRequestQueue(); - var testUser4Request = reqQueue.find((req) => req.device_id === "TestUser4"); - validateCrash(testUser4Request, true); + validateCreatedBulkData(bulk); + shouldFilesExist(true, true); + assert.equal(storage.getStoragePath(), "../test/customStorageDirectory/"); done(); }, hp.sWait); }); - // Initialize CountlyBulk in File Storage and record an event - // Bulk should initialize correctly, default bulk file paths should exist - // Event should be recorded and validated in event queue - it("7- Bulk File Storage add_user with Record Event", (done) => { - hp.clearStorage(); + it("3- CNR_file", (done) => { var bulk = new CountlyBulk({ app_key: "YOUR_APP_KEY", url: "https://try.count.ly", storage_type: StorageTypes.FILE, }); assert.equal(storage.getStoragePath(), "../bulk_data/"); - hp.doesFileStoragePathsExist((exists) => { - assert.equal(true, exists); - }, true); - var user = bulk.add_user({ device_id: "testUser1" }); - user.add_event(eventObj); + shouldFilesExist(true); + createBulkData(bulk); + setTimeout(() => { - var events = bulk.getBulkEventQueue(); - var deviceEvents = events.testUser1; // Access the events for the specific device - var recordedEvent = deviceEvents[0]; // Access the first event - hp.eventValidator(eventObj, recordedEvent); + validateCreatedBulkData(bulk); + shouldFilesExist(true); + assert.equal(storage.getStoragePath(), "../bulk_data/"); done(); }, hp.mWait); }); -}); \ No newline at end of file +}); + +// Currently tested: CNR, CNR_cPath_file, CNR_file +// TODO: Add tests for the following: +// - CNR: memory, cPath_memory, persistTrue, persistFalse, cPath_persistTrue, cPath_persistFalse, persistTrue_file, persistFalse_file, cPath_persistTrue_file, cPath_persistFalse_file +// - CR_CG for all of the above diff --git a/test/tests_consents.js b/test/tests_consents.js index 057f5d7..a89b4e1 100644 --- a/test/tests_consents.js +++ b/test/tests_consents.js @@ -62,8 +62,10 @@ function events() { // tests describe("Internal event consent tests", () => { + beforeEach(async() => { + await hp.clearStorage(); + }); it("Only custom event should be sent to the queue", (done) => { - hp.clearStorage(); initMain(); Countly.add_consent(["events"]); events(); @@ -75,7 +77,6 @@ describe("Internal event consent tests", () => { }, hp.sWait); }); it("All but custom event should be sent to the queue", (done) => { - hp.clearStorage(); initMain(); Countly.add_consent(["sessions", "views", "users", "star-rating", "apm", "feedback"]); events(); @@ -91,7 +92,6 @@ describe("Internal event consent tests", () => { }, hp.mWait); }); it("Non-merge ID change should reset all consents", (done) => { - hp.clearStorage(); initMain(); Countly.add_consent(["sessions", "views", "users", "star-rating", "apm", "feedback"]); Countly.change_id("Richard Wagner II", false); @@ -102,7 +102,6 @@ describe("Internal event consent tests", () => { }, hp.sWait); }); it("Merge ID change should not reset consents", (done) => { - hp.clearStorage(); initMain(); Countly.add_consent(["sessions", "views", "users", "star-rating", "apm", "feedback"]); // Countly.change_id("Richard Wagner the second", true); diff --git a/test/tests_crashes.js b/test/tests_crashes.js index 2adedb5..ce1255c 100644 --- a/test/tests_crashes.js +++ b/test/tests_crashes.js @@ -14,9 +14,10 @@ function initMain() { } describe("Crash tests", () => { + before(async() => { + await hp.clearStorage(); + }); it("Validate handled error logic", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(); // error logic @@ -34,23 +35,27 @@ describe("Crash tests", () => { done(); }, hp.sWait); }); - // This needs two steps, first creating an error and second checking the logs without erasing, otherwise error would halt the test - describe("Unhandled Error logic", () => { - it("Create unhandled rejection", () => { - // clear previous data - hp.clearStorage(); - // initialize SDK - initMain(); - // send emitter - Countly.track_errors(); - process.emit('unhandledRejection'); - }); - it("Validate unhandled rejection recording", (done) => { - setTimeout(() => { - var req = hp.readRequestQueue()[0]; - hp.crashRequestValidator(req, false); - done(); - }, hp.mWait); - }); +}); +// This needs two steps, first creating an error and second checking the logs without erasing, otherwise error would halt the test +describe("Unhandled Error logic", () => { + before(async() => { + await hp.clearStorage(); + }); + it("Create unhandled rejection", (done) => { + // clear previous data + hp.clearStorage(); + // initialize SDK + initMain(); + // send emitter + Countly.track_errors(); + process.emit('unhandledRejection'); + done(); + }); + it("Validate unhandled rejection recording", (done) => { + setTimeout(() => { + var req = hp.readRequestQueue()[0]; + hp.crashRequestValidator(req, false); + done(); + }, hp.mWait); }); }); diff --git a/test/tests_device_id_type.js b/test/tests_device_id_type.js index afa76f4..650f1b5 100644 --- a/test/tests_device_id_type.js +++ b/test/tests_device_id_type.js @@ -55,9 +55,10 @@ function checkRequestsForT(queue, expectedInternalType) { } describe("Device ID type tests", () => { + beforeEach(async() => { + await hp.clearStorage(); + }); it("1.Generated device ID", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(undefined); Countly.begin_session(); @@ -71,8 +72,6 @@ describe("Device ID type tests", () => { }, hp.sWait); }); it("2.Developer supplied device ID", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain("ID"); Countly.begin_session(); @@ -86,8 +85,6 @@ describe("Device ID type tests", () => { }, hp.sWait); }); it("3.With stored dev ID and no new ID", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain("ID"); Countly.begin_session(); @@ -109,8 +106,6 @@ describe("Device ID type tests", () => { }, hp.sWait); }); it("4.With stored dev ID and with new ID", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain("ID"); Countly.begin_session(); @@ -132,8 +127,6 @@ describe("Device ID type tests", () => { }, hp.sWait); }); it("5.With stored generated ID and no new ID", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(undefined); Countly.begin_session(); @@ -157,8 +150,6 @@ describe("Device ID type tests", () => { }, hp.sWait); }); it("6.With stored generated ID and with new ID", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(undefined); Countly.begin_session(); @@ -182,8 +173,6 @@ describe("Device ID type tests", () => { }, hp.sWait); }); it("7.With stored dev ID and no new ID, flag set", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain("ID"); Countly.begin_session(); @@ -206,31 +195,29 @@ describe("Device ID type tests", () => { }); it("8.With stored dev ID and with new ID, flag set", (done) => { - // clear previous data - hp.clearStorage(); - // initialize SDK - initMain("ID"); - Countly.begin_session(); - // read request queue setTimeout(() => { - var rq = hp.readRequestQueue()[0]; - assert.equal(Countly.get_device_id(), "ID"); - assert.equal(Countly.get_device_id_type(), cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED); - checkRequestsForT(rq, cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED); - Countly.halt(true); - initMain("ID2", true); + // initialize SDK + initMain("ID"); + Countly.begin_session(); + // read request queue setTimeout(() => { - var req = hp.readRequestQueue()[0]; - assert.equal(Countly.get_device_id(), "ID2"); + var rq = hp.readRequestQueue()[0]; + assert.equal(Countly.get_device_id(), "ID"); assert.equal(Countly.get_device_id_type(), cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED); - checkRequestsForT(req, cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED); - done(); - }, hp.sWait); - }, hp.sWait); + checkRequestsForT(rq, cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED); + Countly.halt(true); + initMain("ID2", true); + setTimeout(() => { + var req = hp.readRequestQueue()[0]; + assert.equal(Countly.get_device_id(), "ID2"); + assert.equal(Countly.get_device_id_type(), cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED); + checkRequestsForT(req, cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED); + done(); + }, hp.sWait); + }, hp.lWait); + }, hp.lWait); }); it("9.With stored sdk ID and no new ID, flag set", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(undefined); Countly.begin_session(); @@ -255,8 +242,6 @@ describe("Device ID type tests", () => { }); it("10.With stored sdk ID and with new ID, flag set", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(undefined); Countly.begin_session(); @@ -280,8 +265,6 @@ describe("Device ID type tests", () => { }, hp.sWait); }); it("11.Change generated device ID", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(undefined); Countly.change_id("changedID"); @@ -298,8 +281,6 @@ describe("Device ID type tests", () => { }, hp.sWait); }); it("12.Change developer supplied device ID", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain("ID"); Countly.change_id("changedID"); diff --git a/test/tests_events.js b/test/tests_events.js index 9e93305..246063d 100644 --- a/test/tests_events.js +++ b/test/tests_events.js @@ -32,9 +32,10 @@ var timedEventObj = { }, }; describe("Events tests", () => { + beforeEach(async() => { + await hp.clearStorage(); + }); it("Record and check custom event", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(); // send custom event @@ -47,8 +48,6 @@ describe("Events tests", () => { }, hp.mWait); }); it("Record and check timed events", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(); // send timed event diff --git a/test/tests_internal_limits.js b/test/tests_internal_limits.js index 712da5d..82f0a10 100644 --- a/test/tests_internal_limits.js +++ b/test/tests_internal_limits.js @@ -22,6 +22,9 @@ function initLimitsMain() { // Integration tests with countly initialized describe("Testing internal limits", () => { + beforeEach(async() => { + await hp.clearStorage(); + }); describe("Testing truncation functions", () => { it("truncateSingleValue: Check if the string is truncated", () => { var newStr = cc.truncateSingleValue("123456789", 3, "test"); @@ -56,8 +59,6 @@ describe("Testing internal limits", () => { }); it("1. Check custom event truncation", (done) => { - // clear storage - hp.clearStorage(); // init Countly initLimitsMain(); // send event @@ -88,8 +89,6 @@ describe("Testing internal limits", () => { }); it("2. Check countly view event truncation", (done) => { - // clear storage - hp.clearStorage(); // init Countly initLimitsMain(); // page view @@ -110,8 +109,6 @@ describe("Testing internal limits", () => { }, hp.sWait); }); it("3. Check breadcrumbs and error truncation", (done) => { - // clear storage - hp.clearStorage(); // init Countly initLimitsMain(); // add log @@ -154,8 +151,6 @@ describe("Testing internal limits", () => { }, hp.sWait); }); it("4. Check user details truncation", (done) => { - // clear storage - hp.clearStorage(); // init Countly initLimitsMain(); // add user details @@ -209,8 +204,6 @@ describe("Testing internal limits", () => { }, hp.sWait); }); it("5. Check custom properties truncation", (done) => { - // clear storage - hp.clearStorage(); // init Countly initLimitsMain(); // add custom properties diff --git a/test/tests_sessions.js b/test/tests_sessions.js index 2893cc7..ac17f3b 100644 --- a/test/tests_sessions.js +++ b/test/tests_sessions.js @@ -11,9 +11,10 @@ function initMain() { }); } describe("Sessions tests", () => { + beforeEach(async() => { + await hp.clearStorage(); + }); it("Start session and validate the request queue", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(); // send session calls @@ -25,8 +26,6 @@ describe("Sessions tests", () => { }, hp.sWait); }); it("Start and end session and validate the request queue", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(); // send session calls diff --git a/test/tests_storage.js b/test/tests_storage.js index da677be..06b0fda 100644 --- a/test/tests_storage.js +++ b/test/tests_storage.js @@ -155,30 +155,11 @@ const customFileStorage = { const nonValidStorageMethods = { _storage: {}, - setInvalid: function(key, value, callback) { - if (key) { - const existingValue = this._storage[key]; - if (typeof value === 'string' && typeof existingValue === 'string') { - this._storage[key] = existingValue + value; - } - else { - this._storage[key] = value; - } - if (typeof callback === "function") { - callback(null); - } - } + setInvalid: function() { }, - getInvalid: function(key, def) { - const value = this._storage[key]; - if (typeof value === 'string') { - return value.split('').reverse().join(''); - } - - return value !== undefined ? value : def; + getInvalid: function() { }, - removeInvalid: function(key) { - delete this._storage[key]; + removeInvalid: function() { }, }; const funkyMemoryStorage = { @@ -228,76 +209,26 @@ const customMemoryStorage = { }, }; -describe("Storage Tests", () => { - // initialize the sdk begin a session - // sdk should generate a device id and it should be stored correctly - it("1- Store Generated Device ID", (done) => { - // clear previous data - hp.clearStorage(); - // initialize SDK - initMain(); - Countly.begin_session(); - // read request queue - setTimeout(() => { - validateSdkGeneratedId(Countly.get_device_id()); - done(); - }, hp.sWait); - }); - - // when initialized again sdk should keep the device id and id type correctly - it("1.1- Validate generated device id after process restart", (done) => { - initMain(); - validateDeviceId(Countly.get_device_id(), Countly.get_device_id_type(), undefined, cc.deviceIdTypeEnums.SDK_GENERATED); - done(); - }); - - // initialize the sdk while providing device id and begin a session - // sdk should use the given device id and it should be stored correctly - it("2.Developer supplied device ID", (done) => { - hp.clearStorage(); - initMain("ID"); - Countly.begin_session(); - setTimeout(() => { - validateDeviceId(Countly.get_device_id(), Countly.get_device_id_type(), "ID", cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED); - done(); - }, hp.sWait); - }); - - // when initialized again sdk should keep the device id and id type correctly - it("2.1- Validate generated device id after process restart", (done) => { - validateDeviceId(Countly.get_device_id(), Countly.get_device_id_type(), "ID", cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED); - done(); - }); +// TODO: +// Other tests are testing default (FILE) already, so here focus should be: +// 1. MEMORY (checking it works with a set of events/situations, it does not saves something persistently) +// 2. Persistency (checking default saves persistently, checking default and FILE are same) +// 3. Custom (custom works with valid methods-memory or persistent-, does not work with invalid methods) +// 4. Their interaction with path +// here we test storage, not every - // initialize the sdk and record user details - // all user details informations should be recorded, stored and validated correctly - it("3- Record and validate all user details", (done) => { - hp.clearStorage(); - initMain(); - Countly.user_details(userDetailObj); - setTimeout(() => { - var req = hp.readRequestQueue()[0]; - hp.userDetailRequestValidator(userDetailObj, req); - done(); - }, hp.sWait); - }); - - // validate that user detail stored in the queue correctly - it("3.1- Validate stored user detail", (done) => { - var req = hp.readRequestQueue()[0]; - hp.userDetailRequestValidator(userDetailObj, req); - done(); +describe("Storage Tests", () => { + beforeEach(async() => { + await hp.clearStorage(); }); - // initialize the sdk and record an event // event should be recorded stored and validated correctly it("4- Record event and validate storage", (done) => { - hp.clearStorage(); initMain(); Countly.add_event(eventObj); setTimeout(() => { var storedEvents = hp.readEventQueue(); - assert.strictEqual(storedEvents.length, 1, "There should be exactly one event stored"); + assert.equal(storedEvents.length, 1); var event = storedEvents[0]; hp.eventValidator(eventObj, event); @@ -305,24 +236,9 @@ describe("Storage Tests", () => { }, hp.mWait); }); - // validate that when initialized again the event is stored correctly - it("4.1- Validate event persistence after process restart", (done) => { - // Initialize SDK - initMain(); - - // Read stored events without clearing storage - var storedEvents = hp.readEventQueue(); - assert.strictEqual(storedEvents.length, 1, "There should be exactly one event stored"); - - var event = storedEvents[0]; - hp.eventValidator(eventObj, event); - done(); - }); - // initialize the sdk with providing no storage path or type // if storage path is not provided it will be default "../data/" it("5- Not provide storage path during init", (done) => { - hp.clearStorage(); initMain(); assert.equal(storage.getStoragePath(), "../data/"); done(); @@ -331,7 +247,6 @@ describe("Storage Tests", () => { // initialize the sdk with providing undefined storage path // if set to undefined it should be set to default path it("6- Set storage path to undefined", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -344,7 +259,6 @@ describe("Storage Tests", () => { // initialize the sdk with providing null storage path // if set to null it should be set to default path it("7- Set storage path to null", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -357,7 +271,6 @@ describe("Storage Tests", () => { // initialize the sdk with providing a custom storage path // it should be set to the custom directory if provided a valid storage path it("8- Set storage path to custom directory", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -372,7 +285,6 @@ describe("Storage Tests", () => { // resets the storage path to default and validates that it is set correctly, // then resets it to undefined and confirms the reset. it("9- Reset Storage While on Default Path /no-init", (done) => { - hp.clearStorage(); // will set to default storage path storage.setStoragePath(); assert.equal(storage.getStoragePath(), "../data/"); @@ -385,7 +297,6 @@ describe("Storage Tests", () => { // sets the storage path to default and verifies it, // then records values to storage and ensures they are stored correctly. it("10- Recording to Storage with Default Storage Path /no-init", (done) => { - hp.clearStorage(); storage.initStorage(); assert.equal(storage.getStoragePath(), "../data/"); recordValuesToStorageAndValidate(); @@ -395,7 +306,6 @@ describe("Storage Tests", () => { // sets a custom storage path and verifies it, // then records values to storage and ensures correct storage in the custom path. it("11- Recording to Storage with Custom Storage Path /no-init", (done) => { - hp.clearStorage(); storage.initStorage("../test/customStorageDirectory/"); assert.equal(storage.getStoragePath(), "../test/customStorageDirectory/"); recordValuesToStorageAndValidate("../test/customStorageDirectory/"); @@ -405,7 +315,6 @@ describe("Storage Tests", () => { // sets the storage path to the default bulk storage path and verifies it, // then records values to bulk storage and validates proper storage in bulk mode. it("12- Recording to Bulk Storage with Default Bulk Data Path /no-init", (done) => { - hp.clearStorage(); storage.initStorage(null, StorageTypes.FILE, true); hp.doesFileStoragePathsExist((exists) => { assert.equal(true, exists); @@ -418,7 +327,6 @@ describe("Storage Tests", () => { // sets a custom bulk storage path and verifies it, // then records values to bulk storage and ensures proper recording to the custom path. it("13- Recording to Bulk Storage with Custom Bulk Storage Path /no-init", (done) => { - hp.clearStorage(); // will set to default storage path storage.initStorage("../test/customStorageDirectory/", StorageTypes.FILE, true); hp.doesFileStoragePathsExist((exists) => { @@ -433,7 +341,6 @@ describe("Storage Tests", () => { // without sdk initializing storage should be able to initialize // if no path or type is provided storage should be set to default it("14- Setting storage path to default path via initStorage /no-init", (done) => { - hp.clearStorage(); storage.initStorage(); assert.equal(storage.getStoragePath(), "../data/"); done(); @@ -443,7 +350,6 @@ describe("Storage Tests", () => { // without sdk initializing storage should be able to initialize // if no path is provided storage should be set to default bulk path it("15- Setting bulk storage path to default bulk file path via initStorage /no-init", (done) => { - hp.clearStorage(); storage.initStorage(null, StorageTypes.FILE, true); assert.equal(storage.getStoragePath(), "../bulk_data/"); done(); @@ -453,7 +359,6 @@ describe("Storage Tests", () => { // without sdk initializing storage should be able to initialize // if a valid path is provided storage should be set to that path it("16- Setting custom storage path via initStorage /no-init", (done) => { - hp.clearStorage(); storage.initStorage("../test/customStorageDirectory/"); assert.equal(storage.getStoragePath(), "../test/customStorageDirectory/"); done(); @@ -463,7 +368,6 @@ describe("Storage Tests", () => { // without sdk initializing storage should be able to initialize in memory mode // since initialized in memory mode sdk should have no storage path or storage files should not exist it("17- Setting storage method to memory only and checking storage path /no-init", (done) => { - hp.clearStorage(); storage.initStorage(null, StorageTypes.MEMORY); hp.doesFileStoragePathsExist((exists) => { assert.equal(false, exists); @@ -476,7 +380,6 @@ describe("Storage Tests", () => { // initializes the SDK in memory only mode, validates that file storage files does not exist // retrieve the developer supplied device id and id type from storage it("18- Memory only storage Device-Id", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -496,7 +399,6 @@ describe("Storage Tests", () => { // initializes the SDK in memory only mode, validates that file storage files does not exist // records an event and validates the recorded event it("19- Record event in memory only mode and validate the record", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -520,7 +422,6 @@ describe("Storage Tests", () => { // initializes the SDK in memory only mode, validates that file storage files does not exist // records user details and validates the recorded details it("20- Record and validate user details in memory only mode", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -541,7 +442,6 @@ describe("Storage Tests", () => { // initialize the SDK in memory only mode, check the device id and switch it // SDK and storage should function properly it("21- Memory only storage, change SDK Generated Device-Id", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -564,7 +464,6 @@ describe("Storage Tests", () => { // passing memory storage type during init and initializing storage afterwards // SDK should switch to file storage it("22- Switch to file storage after init", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -586,7 +485,6 @@ describe("Storage Tests", () => { // after initializing the memory storage, without initializing SDK, attempts to set, get and remove values // without initializing SDK storage should function properly it("23- storeRemove Memory Only /no-init", (done) => { - hp.clearStorage(); storage.initStorage(null, StorageTypes.MEMORY); assert.equal(storage.getStoragePath(), undefined); assert.equal(storage.getStorageType(), StorageTypes.MEMORY); @@ -602,7 +500,6 @@ describe("Storage Tests", () => { // after initializing the file storage, without initializing SDK attempts to set, get and remove values // without initializing SDK storage should function properly it("24- storeRemove File Storage /no-init", (done) => { - hp.clearStorage(); storage.initStorage(); assert.equal(storage.getStoragePath(), "../data/"); assert.equal(storage.getStorageType(), StorageTypes.FILE); @@ -618,7 +515,6 @@ describe("Storage Tests", () => { // choosing Custom storage type and passing null in storage methods // passing null as storage method ends up with switching to default file storage it("25- Null Custom Storage Method", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -634,7 +530,6 @@ describe("Storage Tests", () => { // choosing Custom storage type and passing custom storage methods // SDK should use custom methods as storage method, no File Storage should exist it("26- Providing Custom Storage Method", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -651,7 +546,6 @@ describe("Storage Tests", () => { // Recording values in Custom Storage Methods // SDK should use custom methods as storage methods and values should be recorded correctly it("27- Record/Remove Values in Custom Storage Method", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -672,7 +566,6 @@ describe("Storage Tests", () => { // passes a funky storage method, which does store get as reversing string // SDK should use custom methods as storage method it("28- Record/Remove Values in Other Custom Storage Method", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -692,7 +585,6 @@ describe("Storage Tests", () => { // choosing Custom storage type and passing invalid custom storage methods // SDK should not use custom methods as storage method, and switch to File Storage it("29- Providing Invalid Custom Storage Method", (done) => { - hp.clearStorage(); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -703,12 +595,10 @@ describe("Storage Tests", () => { assert.equal(storage.getStorageType(), StorageTypes.FILE); done(); }); - // tests init time storage config options // choosing Custom storage type and passing custom file storage methods // SDK should use custom methods as storage methods it("30- Providing File Custom Storage Method", (done) => { - hp.clearStorage("../test/customStorageDirectory/"); Countly.init({ app_key: "YOUR_APP_KEY", url: "https://test.url.ly", @@ -729,4 +619,37 @@ describe("Storage Tests", () => { done(); }, hp.sWait); }); +}); + +describe('Persistency Related', () => { + // when initialized again sdk should keep the device id and id type correctly + it("1.1- Validate generated device id after process restart", (done) => { + initMain(); + setTimeout(() => { + validateDeviceId(Countly.get_device_id(), Countly.get_device_id_type(), undefined, cc.deviceIdTypeEnums.SDK_GENERATED); + done(); + }, hp.sWait); + }); + // when initialized again sdk should keep the device id and id type correctly + it("2.1- Validate generated device id after process restart", (done) => { + validateDeviceId(Countly.get_device_id(), Countly.get_device_id_type(), "ID", cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED); + done(); + }); + // validate that user detail stored in the queue correctly + it("3.1- Validate stored user detail", (done) => { + var req = hp.readRequestQueue()[0]; + hp.userDetailRequestValidator(userDetailObj, req); + done(); + }); + // validate that when initialized again the event is stored correctly + it("4.1- Validate event persistence after process restart", (done) => { + // Initialize SDK + initMain(); + // Read stored events without clearing storage + var storedEvents = hp.readEventQueue(); + assert.strictEqual(storedEvents.length, 1, "There should be exactly one event stored"); + var event = storedEvents[0]; + hp.eventValidator(eventObj, event); + done(); + }); }); \ No newline at end of file diff --git a/test/tests_user_details.js b/test/tests_user_details.js index 9e859ec..dfb06cd 100644 --- a/test/tests_user_details.js +++ b/test/tests_user_details.js @@ -27,9 +27,10 @@ function initMain() { } describe("User details tests", () => { + beforeEach(async() => { + await hp.clearStorage(); + }); it("Record and validate all user details", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(); // send user details diff --git a/test/tests_views.js b/test/tests_views.js index 664f3ca..07e6926 100644 --- a/test/tests_views.js +++ b/test/tests_views.js @@ -15,9 +15,10 @@ function initMain() { } describe("View test", () => { + beforeEach(async() => { + await hp.clearStorage(); + }); it("Record and validate page views", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(); // send track view @@ -30,8 +31,6 @@ describe("View test", () => { }, hp.sWait); }); it("Record and validate timed page views with same name", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(); Countly.track_view(pageNameOne); @@ -52,8 +51,6 @@ describe("View test", () => { }, hp.mWait); }); it("Record and validate timed page views with same name", (done) => { - // clear previous data - hp.clearStorage(); // initialize SDK initMain(); Countly.track_view(pageNameOne);