2018-05-03 11:20:13 +02:00
/* eslint no-console: 0 */
/ * *
* nodeApi . js
*
* Test node api utilities
*
* @ author d98762625 [ d98762625 @ gmail . com ]
* @ copyright Crown Copyright 2018
* @ license Apache - 2.0
* /
import assert from "assert" ;
import it from "../assertionHandler" ;
import chef from "../../../src/node/index" ;
2018-06-06 18:29:30 +02:00
import OperationError from "../../../src/core/errors/OperationError" ;
import SyncDish from "../../../src/node/SyncDish" ;
2018-08-23 22:40:45 +02:00
import { toBase32 , Dish } from "../../../src/node/index" ;
2018-05-03 11:20:13 +02:00
import TestRegister from "../../TestRegister" ;
TestRegister . addApiTests ( [
it ( "should have some operations" , ( ) => {
assert ( chef ) ;
assert ( chef . toBase32 ) ;
assert ( chef . setUnion ) ;
assert ( ! chef . randomFunction ) ;
} ) ,
2018-06-06 18:29:30 +02:00
it ( "should export other functions at top level" , ( ) => {
assert ( toBase32 ) ;
} ) ,
it ( "should be synchronous" , ( ) => {
2018-05-03 11:20:13 +02:00
try {
2018-06-06 18:29:30 +02:00
const result = chef . toBase32 ( "input" ) ;
2018-05-03 11:20:13 +02:00
assert . notEqual ( "something" , result ) ;
} catch ( e ) {
// shouldnt reach here
assert ( false ) ;
}
try {
const fail = chef . setUnion ( "1" ) ;
// shouldnt get here
2018-05-03 14:58:15 +02:00
assert ( ! fail || false ) ;
2018-05-03 11:20:13 +02:00
} catch ( e ) {
assert ( true ) ;
}
} ) ,
2018-06-06 18:29:30 +02:00
it ( "should not catch Errors" , ( ) => {
try {
chef . setUnion ( "1" ) ;
2018-05-03 11:20:13 +02:00
assert ( false ) ;
2018-06-06 18:29:30 +02:00
} catch ( e ) {
assert ( e instanceof OperationError ) ;
}
2018-05-11 20:25:14 +02:00
} ) ,
2018-06-06 18:29:30 +02:00
it ( "should accept arguments in object format for operations" , ( ) => {
const result = chef . setUnion ( "1 2 3 4:3 4 5 6" , {
2018-05-11 20:25:14 +02:00
itemDelimiter : " " ,
sampleDelimiter : ":"
} ) ;
2018-06-06 18:29:30 +02:00
assert . equal ( result . value , "1 2 3 4 5 6" ) ;
2018-05-11 20:25:14 +02:00
} ) ,
2018-06-06 18:29:30 +02:00
it ( "should accept just some of the optional arguments being overriden" , ( ) => {
const result = chef . setIntersection ( "1 2 3 4 5\\n\\n3 4 5" , {
2018-05-11 20:25:14 +02:00
itemDelimiter : " " ,
} ) ;
2018-06-06 18:29:30 +02:00
assert . equal ( result . value , "3 4 5" ) ;
2018-05-11 20:25:14 +02:00
} ) ,
2018-06-06 18:29:30 +02:00
it ( "should accept no override arguments and just use the default values" , ( ) => {
const result = chef . powerSet ( "1,2,3" ) ;
assert . equal ( result . value , "\n3\n2\n1\n2,3\n1,3\n1,2\n1,2,3\n" ) ;
} ) ,
it ( "should return an object with a .to method" , ( ) => {
const result = chef . toBase32 ( "input" ) ;
assert ( result . to ) ;
assert . equal ( result . to ( "string" ) , "NFXHA5LU" ) ;
} ) ,
it ( "should return an object with a .get method" , ( ) => {
const result = chef . toBase32 ( "input" ) ;
assert ( result . get ) ;
assert . equal ( result . get ( "string" ) , "NFXHA5LU" ) ;
} ) ,
it ( "should return a SyncDish" , ( ) => {
const result = chef . toBase32 ( "input" ) ;
assert ( result instanceof SyncDish ) ;
} ) ,
it ( "should coerce to a string as you expect" , ( ) => {
const result = chef . fromBase32 ( chef . toBase32 ( "something" ) ) ;
assert . equal ( String ( result ) , "something" ) ;
// This kind of coercion uses toValue
assert . equal ( "" + result , "NaN" ) ;
} ) ,
it ( "should coerce to a number as you expect" , ( ) => {
const result = chef . fromBase32 ( chef . toBase32 ( "32" ) ) ;
assert . equal ( 3 + result , 35 ) ;
} ) ,
2018-06-19 17:41:16 +02:00
it ( "chef.help: should exist" , ( ) => {
assert ( chef . help ) ;
} ) ,
it ( "chef.help: should describe a operation" , ( ) => {
const result = chef . help ( "tripleDESDecrypt" ) ;
2018-07-06 12:13:38 +02:00
assert . strictEqual ( result . name , "Triple DES Decrypt" ) ;
2018-06-19 17:41:16 +02:00
assert . strictEqual ( result . module , "Ciphers" ) ;
assert . strictEqual ( result . inputType , "string" ) ;
assert . strictEqual ( result . outputType , "string" ) ;
assert . strictEqual ( result . description , "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br>DES uses a key length of 8 bytes (64 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used." ) ;
assert . strictEqual ( result . args . length , 5 ) ;
} ) ,
it ( "chef.help: null for invalid operation" , ( ) => {
const result = chef . help ( "some invalid function name" ) ;
assert . strictEqual ( result , null ) ;
} ) ,
2018-06-25 18:58:57 +02:00
it ( "chef.help: takes a wrapped operation as input" , ( ) => {
const result = chef . help ( chef . toBase32 ) ;
2018-07-06 12:13:38 +02:00
assert . strictEqual ( result . name , "To Base32" ) ;
2018-06-25 18:58:57 +02:00
assert . strictEqual ( result . module , "Default" ) ;
2018-07-06 13:54:19 +02:00
} ) ,
it ( "chef.bake: should exist" , ( ) => {
assert ( chef . bake ) ;
} ) ,
it ( "chef.bake: should return SyncDish" , ( ) => {
const result = chef . bake ( "input" , "to base 64" ) ;
assert ( result instanceof SyncDish ) ;
} ) ,
it ( "chef.bake: should take an input and an op name and perform it" , ( ) => {
const result = chef . bake ( "some input" , "to base 32" ) ;
assert . strictEqual ( result . toString ( ) , "ONXW2ZJANFXHA5LU" ) ;
} ) ,
it ( "chef.bake: should complain if recipe isnt a valid object" , ( ) => {
try {
chef . bake ( "some input" , 3264 ) ;
} catch ( e ) {
assert . strictEqual ( e . name , "TypeError" ) ;
assert . strictEqual ( e . message , "Recipe can only contain function names or functions" ) ;
}
} ) ,
it ( "chef.bake: Should complain if string op is invalid" , ( ) => {
try {
chef . bake ( "some input" , "not a valid operation" ) ;
assert . fail ( "Shouldn't be hit" ) ;
} catch ( e ) {
assert . strictEqual ( e . name , "TypeError" ) ;
assert . strictEqual ( e . message , "Couldn't find an operation with name 'not a valid operation'." ) ;
}
} ) ,
it ( "chef.bake: Should take an input and an operation and perform it" , ( ) => {
const result = chef . bake ( "https://google.com/search?q=help" , chef . parseURI ) ;
assert . strictEqual ( result . toString ( ) , "Protocol:\thttps:\nHostname:\tgoogle.com\nPath name:\t/search\nArguments:\n\tq = help\n" ) ;
} ) ,
it ( "chef.bake: Should complain if an invalid operation is inputted" , ( ) => {
try {
chef . bake ( "https://google.com/search?q=help" , ( ) => { } ) ;
assert . fail ( "Shouldn't be hit" ) ;
} catch ( e ) {
assert . strictEqual ( e . name , "TypeError" ) ;
assert . strictEqual ( e . message , "Inputted function not a Chef operation." ) ;
}
} ) ,
it ( "chef.bake: accepts an array of operation names and performs them all in order" , ( ) => {
const result = chef . bake ( "https://google.com/search?q=that's a complicated question" , [ "URL encode" , "URL decode" , "Parse URI" ] ) ;
assert . strictEqual ( result . toString ( ) , "Protocol:\thttps:\nHostname:\tgoogle.com\nPath name:\t/search\nArguments:\n\tq = that's a complicated question\n" ) ;
} ) ,
it ( "chef.bake: if recipe is empty array, return input as dish" , ( ) => {
const result = chef . bake ( "some input" , [ ] ) ;
assert . strictEqual ( result . toString ( ) , "some input" ) ;
assert ( result instanceof SyncDish , "Result is not instance of SyncDish" ) ;
} ) ,
it ( "chef.bake: accepts an array of operations as recipe" , ( ) => {
const result = chef . bake ( "https://google.com/search?q=that's a complicated question" , [ chef . URLEncode , chef . URLDecode , chef . parseURI ] ) ;
assert . strictEqual ( result . toString ( ) , "Protocol:\thttps:\nHostname:\tgoogle.com\nPath name:\t/search\nArguments:\n\tq = that's a complicated question\n" ) ;
} ) ,
it ( "should complain if an invalid operation is inputted as part of array" , ( ) => {
try {
chef . bake ( "something" , [ ( ) => { } ] ) ;
} catch ( e ) {
assert . strictEqual ( e . name , "TypeError" ) ;
assert . strictEqual ( e . message , "Inputted function not a Chef operation." ) ;
}
} ) ,
it ( "chef.bake: should take single JSON object describing op and args OBJ" , ( ) => {
const result = chef . bake ( "some input" , {
op : chef . toHex ,
args : {
Delimiter : "Colon"
}
2018-07-20 14:59:52 +02:00
} ) ;
2018-07-06 13:54:19 +02:00
assert . strictEqual ( result . toString ( ) , "73:6f:6d:65:20:69:6e:70:75:74" ) ;
} ) ,
it ( "chef.bake: should take single JSON object describing op and args ARRAY" , ( ) => {
const result = chef . bake ( "some input" , {
op : chef . toHex ,
args : [ "Colon" ]
2018-07-20 14:59:52 +02:00
} ) ;
2018-07-06 13:54:19 +02:00
assert . strictEqual ( result . toString ( ) , "73:6f:6d:65:20:69:6e:70:75:74" ) ;
} ) ,
it ( "chef.bake: should error if op in JSON is not chef op" , ( ) => {
try {
chef . bake ( "some input" , {
op : ( ) => { } ,
args : [ "Colon" ] ,
} ) ;
} catch ( e ) {
assert . strictEqual ( e . name , "TypeError" ) ;
assert . strictEqual ( e . message , "Inputted function not a Chef operation." ) ;
}
} ) ,
it ( "chef.bake: should take multiple ops in JSON object form, some ops by string" , ( ) => {
const result = chef . bake ( "some input" , [
{
op : chef . toHex ,
args : [ "Colon" ]
} ,
{
op : "to octal" ,
args : {
delimiter : "Semi-colon" ,
}
}
] ) ;
assert . strictEqual ( result . toString ( ) , "67;63;72;66;146;72;66;144;72;66;65;72;62;60;72;66;71;72;66;145;72;67;60;72;67;65;72;67;64" ) ;
} ) ,
it ( "chef.bake: should handle op with multiple args" , ( ) => {
const result = chef . bake ( "some input" , {
op : "to morse code" ,
args : {
formatOptions : "Dash/Dot" ,
wordDelimiter : "Comma" ,
letterDelimiter : "Backslash" ,
}
} ) ;
assert . strictEqual ( result . toString ( ) , "DotDotDot\\DashDashDash\\DashDash\\Dot,DotDot\\DashDot\\DotDashDashDot\\DotDotDash\\Dash" ) ;
} ) ,
it ( "chef.bake: should take compact JSON format from Chef Website as recipe" , ( ) => {
2018-07-20 14:59:52 +02:00
const result = chef . bake ( "some input" , [ { "op" : "To Morse Code" , "args" : [ "Dash/Dot" , "Backslash" , "Comma" ] } , { "op" : "Hex to PEM" , "args" : [ "SOMETHING" ] } , { "op" : "To Snake case" , "args" : [ false ] } ] ) ;
2018-07-06 13:54:19 +02:00
assert . strictEqual ( result . toString ( ) , "begin_something_anananaaaaak_da_aaak_da_aaaaananaaaaaaan_da_aaaaaaanan_da_aaak_end_something" ) ;
} ) ,
it ( "chef.bake: should accept Clean JSON format from Chef website as recipe" , ( ) => {
const result = chef . bake ( "some input" , [
{ "op" : "To Morse Code" ,
"args" : [ "Dash/Dot" , "Backslash" , "Comma" ] } ,
{ "op" : "Hex to PEM" ,
"args" : [ "SOMETHING" ] } ,
{ "op" : "To Snake case" ,
"args" : [ false ] }
] ) ;
assert . strictEqual ( result . toString ( ) , "begin_something_anananaaaaak_da_aaak_da_aaaaananaaaaaaan_da_aaaaaaanan_da_aaak_end_something" ) ;
} ) ,
2018-08-23 22:40:45 +02:00
it ( "Composable Dish: Should have top level Dish object" , ( ) => {
assert . ok ( Dish ) ;
} ) ,
it ( "Composable Dish: Should construct empty dish object" , ( ) => {
const dish = new Dish ( ) ;
assert . deepEqual ( dish . value , [ ] ) ;
assert . strictEqual ( dish . type , 0 ) ;
} ) ,
it ( "Composable Dish: constructed dish should have operation prototype functions" , ( ) => {
const dish = new Dish ( ) ;
assert . ok ( dish . translateDateTimeFormat ) ;
assert . ok ( dish . stripHTTPHeaders ) ;
assert . throws ( ( ) => dish . someInvalidFunction ( ) ) ;
} ) ,
it ( "Composable Dish: composed function returns another dish" , ( ) => {
const result = new Dish ( "some input" ) . toBase32 ( ) ;
assert . ok ( result instanceof SyncDish ) ;
} ) ,
it ( "Composable dish: infers type from input if needed" , ( ) => {
const dish = new Dish ( "string input" ) ;
assert . strictEqual ( dish . type , 1 ) ;
const numberDish = new Dish ( 333 ) ;
assert . strictEqual ( numberDish . type , 2 ) ;
const arrayBufferDish = new Dish ( Buffer . from ( "some buffer input" ) . buffer ) ;
assert . strictEqual ( arrayBufferDish . type , 4 ) ;
const JSONDish = new Dish ( { key : "value" } ) ;
assert . strictEqual ( JSONDish . type , 6 ) ;
} ) ,
2018-05-03 11:20:13 +02:00
] ) ;