# jibo-cai-utils ## Description Provides general purpose utilities that can be useful across many libraries and skills. ## `TimeUtils` Example ```js import { TimeUtils, PromiseUtils, PromiseQueue, FileUtils } from 'jibo-cai-utils'; // Waits for a period of time TimeUtils.wait(300).then( () => console.log('Done') ); // We can dispatch a timeline of actions // This will print "1\n 2\n 3\n Done" 20ms apart TimeUtils.dispatchTimeline([ { timeMs: 20, action: () => console.log(1) }, { timeMs: 40, action: () => console.log(2) }, { timeMs: 60, action: () => console.log(3) }, ]).then( () => console.log('Done') ); ``` ## `PromiseUtils` and `PromiseQueue` Example ```js // We can guarantee that a handler has been installed for unhandled promise errors // This makes sure that at least one handler for those errors is installed PromiseUtils.catchUnhandledRejection(); // We can convert any async method that uses callbacks to a promise as long // as the callback method accepts arguments of type: (e: error, d?: data) PromiseUtils.promisify( h => fs.readFile('somePath', 'utf8', h)) .then( fileData => console.log(fileData) ) .catch(console.error); // We can wait for first promise to return // Can be useful to create a timeout behavior for a promise PromiseUtils.firstToSucceed([ TimeUtils.wait(1000), TimeUtils.wait(100).then( () => 'Foobar') ]) .then( (data) => console.log(data) ) // Should print 'Foobar' after 100ms .catch(console.error); // We can create a queue of promises which will execute them in sequence let queue = new PromiseQueue(); // These will print '1\n 2\n 3\n Done' 30ms apart queue.add( () => TimeUtils.wait(30).then( () => console.log(1) ) ); queue.add( () => TimeUtils.wait(30).then( () => console.log(2) ) ); queue.add( () => TimeUtils.wait(30).then( () => console.log(3) ) ); queue.add( () => TimeUtils.wait(30) ); queue.waitUntilEmpty().then( () => console.log('Done') ); ``` ## `FileUtils` Example ```js // Retrieves the root directory of a project (where 'package.json' is found) // This is superior to using `__dirname + '/some/path'` since that will break // when code gets minified let projectRoot = FileUtils.getProjectRoot(module); // We can read files and get results in a promise FileUtils.readFile('somePath') .then( fileData => console.log(fileData) ); // We can walk directory structures recursively for files of a certain extension FileUtils.findAllFilesWithExt('somePath', 'ts') .then( fileList => console.log(fileList) ); // We can walk directory structures recursively for files whose names match pattern FileUtils.findAllFiles('somePath', (filePath) => filePath.indexOf('bla') >= 0 ) .then( fileList => console.log(fileList) ); ``` # TestUtils ## Description A library that supports testing branches of skills or other functionality that depends on either branching based on random numbers, time of day, or other factors. Allows truly getting a random number, time of day, etc. as well as nailing down that value for testing. Whenever a skill is about to make a decision based on a random number or a date, it should use methods from this library, that way when testing the skill those branching points can be fixed. ## How to use ### Random numbers ```js import { TestUtils } from 'jibo-cai-utils'; TestUtils.getRandom('someId'); // truly random, different on every call // We can force it to return whatever value we like TestUtils.enableTesting(true); TestUtils.setTestRandom(0.1, 'someId'); TestUtils.getRandom('someId'); // always returns 0.1 TestUtils.clearTests(); TestUtils.getRandom('someId'); // back to truly random ``` ### Date ```js import { TestUtils } from 'jibo-TestUtils'; TestUtils.getDate('someId'); // Returns current date and time (new Date()) // We can force it to return whatever value we like TestUtils.enableTesting(true); TestUtils.setTestDate(new Date(2001, 11, 25)); TestUtils.getDate('someId'); // always 11/25 '01 TestUtils.clearTests(); TestUtils.getDate('someId'); // back to current time ``` ### Namespaces ```js import { TestUtils } from 'jibo-TestUtils'; TestUtils.enableTesting(true); TestUtils.getRandom(); // Random number (default namespace '') TestUtils.setTestRandom(0.1); TestUtils.getRandom(); // Always 0.1 TestUtils.getRandom('someId', 'skillName'); // Random number TestUtils.setTestRandom(0.2, 'someId', 'skillName'); TestUtils.getRandom('someId', 'skillName'); // Always 0.2 TestUtils.clearTests('skillName'); TestUtils.getRandom('someId', 'skillName'); // Back to a random number ```