component displayname='BaseCommerce Tests' output=false extends='mxunit.framework.TestCase' { public void function setUp() { local.gw.path = 'basecommerce.basecommerce'; //Test account local.gw.Username = ''; local.gw.Password = ''; local.gw.MerchantAccount = ''; local.gw.TestMode = true; // create gw and get reference variables.svc = createObject('component', 'cfpayment.api.core').init(local.gw); variables.gw = variables.svc.getGateway(); //if set to false, will try to connect to remote service to check these all out variables.localMode = true; variables.debugMode = false; } private void function offlineInjector(required any receiver, required any giver, required string functionName, string functionNameInReceiver='') { if(variables.localMode) { injectMethod(arguments.receiver, arguments.giver, arguments.functionName, arguments.functionNameInReceiver); } } private void function standardResponseTests(required any response) { if(variables.debugMode) { debug(arguments.response.getParsedResult()); debug(arguments.response.getResult()); } if(isSimpleValue(arguments.response)) assertTrue(false, 'Response returned a simple value: "#arguments.response#"'); assertTrue(isObject(arguments.response), 'Invalid: response is not an object'); if(arguments.response.hasError()) { if(arrayLen(arguments.response.getMessage())) { assertTrue(false, 'Message returned from BaseCommerce:
#arrayToList(arguments.response.getMessage(), "
")#'); } else { assertTrue(false, 'Error found but no error message attached'); } } if(isSimpleValue(arguments.response.getParsedResult())) assertTrue(false, 'Parsed response is a string, expected a structure. Returned string = "#arguments.response.getParsedResult()#"'); assertTrue(isStruct(arguments.response.getParsedResult()), 'Parsed response is not a structure'); assertFalse(structIsEmpty(arguments.response.getParsedResult()), 'Parsed response structure is empty'); assertTrue(arguments.response.getSuccess(), 'Success flag indicates failure'); } private void function standardErrorResponseTests(required any response) { if(variables.debugMode) { debug(arguments.response.haserror()); debug(arguments.response.getMessage()); } if(isSimpleValue(arguments.response)) assertTrue(false, 'Response returned a simple value: "#arguments.response#"'); assertTrue(isObject(arguments.response), 'Invalid: response is not an object'); assertTrue(arguments.response.hasError(), 'No errors indicated in response'); assertTrue(isSimpleValue(arguments.response.getMessage()), 'Error Message response not a string'); assertTrue(len(arguments.response.getMessage()), 'No error messages available'); assertFalse(arguments.response.getSuccess(), 'Success flag indicates success, but should indicate failure'); } //TESTS public void function testCreateAccount() { createAccountTest(); } public void function testCreditAccount() { local.accountToken = createAccountTest(); //Credit account local.account = variables.svc.createToken(id = local.accountToken.getTokenId()); local.options = structNew(); local.options.sec = 'CCD'; //XS_BAT_METHOD_CCD, XS_BAT_METHOD_PPD, XS_BAT_METHOD_TEL, XS_BAT_METHOD_WEB local.options.effectiveDate = dateAdd('d', 8, now()); offlineInjector(variables.gw, this, 'mockCreditAccountOk', 'transactionData'); local.credit = variables.gw.credit(money = variables.svc.createMoney(500, 'USD'), account = local.account, options = local.options); standardResponseTests(local.credit); assertTrue(local.credit.getParsedResult().amount == 5, 'The credit amount requested and the actual credit given is different, should be 5, is: #local.credit.getParsedResult().amount#'); assertTrue(local.credit.getTransactionId() > 0, 'Invalid transaction id returned: #local.credit.getTransactionId()#'); assertTrue(local.credit.getParsedResult().type == 'CREDIT', 'Incorrect transaction type, should be "CREDIT", is: "#local.credit.getParsedResult().type#"'); } public void function testDebitAccount() { local.accountToken = createAccountTest(); //Debit account local.account = variables.svc.createToken(id = local.accountToken.getTokenId()); local.options = structNew(); local.options.sec = 'CCD'; //XS_BAT_METHOD_CCD, XS_BAT_METHOD_PPD, XS_BAT_METHOD_TEL, XS_BAT_METHOD_WEB offlineInjector(variables.gw, this, 'mockDebitAccountOk', 'transactionData'); local.debit = variables.gw.purchase(money = variables.svc.createMoney(400, 'USD'), account = local.account, options = local.options); standardResponseTests(local.debit); assertTrue(local.debit.getParsedResult().amount == 4, 'The credit amount requested and the actual credit given is different, should be 4, is: #local.debit.getParsedResult().amount#'); assertTrue(local.debit.getTransactionId() > 0, 'Invalid transaction id returned: #local.debit.getTransactionId()#'); assertTrue(local.debit.getParsedResult().type == 'DEBIT', 'Incorrect transaction type, should be "CREDIT", is: "#local.debit.getParsedResult().type#"'); } public void function testCreateInvalidAccountFails() { local.argumentCollection = structNew(); local.accountNumberString = '7'; local.argumentCollection.account = createInvalidAccount(local.accountNumberString); offlineInjector(variables.gw, this, 'mockCreateInvalidAccountFails', 'accountData'); local.accountToken = variables.gw.store(argumentCollection = local.argumentCollection); standardErrorResponseTests(local.accountToken); assertTrue(local.accountToken.getMessage() == 'Account Number must be at least 5 digits', 'Incorrect error message: "#local.accountToken.getMessage()#", expected: "Account Number must be at least 5 digits"'); } public void function testCreateAccountWithInvalidRoutingNumberFails() { local.argumentCollection = structNew(); local.accountRoutingNumberString = '123'; local.argumentCollection.account = createAccountWithInvalidRoutingNumber(local.accountRoutingNumberString); offlineInjector(variables.gw, this, 'mockCreateAccountWithInvalidRoutingNumberFails', 'accountData'); local.accountToken = variables.gw.store(argumentCollection = local.argumentCollection); standardErrorResponseTests(local.accountToken); assertTrue(local.accountToken.getMessage() == 'Invalid Routing Number', 'Incorrect error message: "#local.accountToken.getMessage()#", expected: "Invalid Routing Number"'); } public void function testCreateAccountWithInvalidAccountTypeFails() mxunit:expectedException='BaseCommerce Type' { local.argumentCollection = structNew(); local.argumentCollection.account = createAccountWithInvalidAccountType('XS_BA_TYPE_THISWILLFAIL'); offlineInjector(variables.gw, this, 'mockCreateAccountWithInvalidAccountTypeFails', 'accountData'); variables.gw.store(argumentCollection = local.argumentCollection); } public void function testCreateAccountWithMissingAccountTypeFails() mxunit:expectedException='BaseCommerce Type' { local.argumentCollection = structNew(); local.argumentCollection.account = createAccountWithMissingAccountType(); offlineInjector(variables.gw, this, 'mockCreateAccountWithMissingAccountTypeFails', 'accountData'); variables.gw.store(argumentCollection = local.argumentCollection); } public void function testCreditAccountWithInvalidAmountFails() { local.accountToken = createAccountTest(); //Credit account (unsuccessfully) local.account = variables.svc.createToken(id = local.accountToken.getTokenId()); local.options = structNew(); local.options.sec = 'CCD'; //XS_BAT_METHOD_CCD, XS_BAT_METHOD_PPD, XS_BAT_METHOD_TEL, XS_BAT_METHOD_WEB offlineInjector(variables.gw, this, 'mockCreditDebitAccountWithInvalidAmountFails', 'transactionData'); local.credit = variables.gw.credit(money = variables.svc.createMoney(-1000, 'USD'), account = local.account, options = local.options); standardErrorResponseTests(local.credit); assertTrue(local.credit.getMessage() == 'Invalid Amount', 'Incorrect error message: "#local.credit.getMessage()#", expected: "Invalid Amount"'); } public void function testDebitAccountWithInvalidAmountFails() { local.accountToken = createAccountTest(); //Credit account (unsuccessfully) local.account = variables.svc.createToken(id = local.accountToken.getTokenId()); local.options = structNew(); local.options.sec = 'CCD'; //XS_BAT_METHOD_CCD, XS_BAT_METHOD_PPD, XS_BAT_METHOD_TEL, XS_BAT_METHOD_WEB offlineInjector(variables.gw, this, 'mockCreditDebitAccountWithInvalidAmountFails', 'transactionData'); local.debit = variables.gw.credit(money = variables.svc.createMoney(-2, 'USD'), account = local.account, options = local.options); standardErrorResponseTests(local.debit); assertTrue(local.debit.getMessage() == 'Invalid Amount', 'Incorrect error message: "#local.debit.getMessage()#", expected: "Invalid Amount"'); } public void function testCreditAccountWithInvalidAccountTokenFails() { local.account = variables.svc.createToken(id = 'lk1j43k324h32j4h32hk***FAKE***32j4h3k432kh43jkh'); local.options = structNew(); local.options.sec = 'CCD'; //XS_BAT_METHOD_CCD, XS_BAT_METHOD_PPD, XS_BAT_METHOD_TEL, XS_BAT_METHOD_WEB offlineInjector(variables.gw, this, 'mockCreditAccountWithInvalidAccountTokenFails', 'transactionData'); local.credit = variables.gw.credit(money = variables.svc.createMoney(-1000, 'USD'), account = local.account, options = local.options); standardErrorResponseTests(local.credit); assertTrue(local.credit.getMessage() == 'No bank account exists for given token', 'Incorrect error message: "#local.credit.getMessage()#", expected: "No bank account exists for given token"'); } public void function testCreditAccountWithInvalidMethodFails() { local.accountToken = createAccountTest(); //Credit account (unsuccessfully) local.account = variables.svc.createToken(id = local.accountToken.getTokenId()); local.options = structNew(); local.options.sec = 'THISWILLFAIL'; //XS_BAT_METHOD_CCD, XS_BAT_METHOD_PPD, XS_BAT_METHOD_TEL, XS_BAT_METHOD_WEB offlineInjector(variables.gw, this, 'mockCreditAccountWithInvalidMethodFails', 'transactionData'); local.credit = variables.gw.credit(money = variables.svc.createMoney(1500, 'USD'), account = local.account, options = local.options); standardErrorResponseTests(local.credit); assertTrue(local.credit.getMessage() == 'Invalid transaction method passed in: XS_BAT_METHOD_#local.options.sec#', 'Incorrect error message: "#local.credit.getMessage()#", expected: "Invalid transaction method passed in: #local.options.sec#"'); } public void function testCreditAccountFutureEffectiveDate() { local.accountToken = createAccountTest(); //Credit account local.account = variables.svc.createToken(id = local.accountToken.getTokenId()); local.effectiveDate = dateAdd('d', 4, nextSaturday()); // Wednesday of next week local.options = structNew(); local.options.sec = 'CCD'; //XS_BAT_METHOD_CCD, XS_BAT_METHOD_PPD, XS_BAT_METHOD_TEL, XS_BAT_METHOD_WEB local.options.effectiveDate = local.effectiveDate; offlineInjector(variables.gw, this, 'mockCreditAccountFutureEffectiveDate', 'transactionData'); local.credit = variables.gw.credit(money = variables.svc.createMoney(500, 'USD'), account = local.account, options = local.options); standardResponseTests(local.credit); assertTrue(dateCompare(local.effectiveDate, local.credit.getParsedResult().effectiveDate) == 0, 'Posted effective date (#local.effectiveDate#) and confirmed effective date (#local.credit.getParsedResult().effectiveDate#) don''t match'); } public void function testCreditAccountPastEffectiveDate() { local.accountToken = createAccountTest(); //Credit account local.account = variables.svc.createToken(id = local.accountToken.getTokenId()); local.effectiveDate = dateAdd('d', -4, removeTimePart(now())); //4 days ago local.options = structNew(); local.options.sec = 'CCD'; //XS_BAT_METHOD_CCD, XS_BAT_METHOD_PPD, XS_BAT_METHOD_TEL, XS_BAT_METHOD_WEB local.options.effectiveDate = local.effectiveDate; offlineInjector(variables.gw, this, 'mockCreditAccountPastEffectiveDate', 'transactionData'); local.credit = variables.gw.credit(money = variables.svc.createMoney(500, 'USD'), account = local.account, options = local.options); standardResponseTests(local.credit); assertTrue(dateCompare(local.effectiveDate, local.credit.getParsedResult().effectiveDate) < 0, 'Posted date is in the past, returned effective date should be ammended to curtrent date but isn''t'); } public void function testCreditAccountWeekendEffectiveDateMovedToWeekDay() { local.accountToken = createAccountTest(); //Credit account local.account = variables.svc.createToken(id = local.accountToken.getTokenId()); local.effectiveDate = nextSaturday(); local.options = structNew(); local.options.sec = 'CCD'; //XS_BAT_METHOD_CCD, XS_BAT_METHOD_PPD, XS_BAT_METHOD_TEL, XS_BAT_METHOD_WEB local.options.effectiveDate = local.effectiveDate; offlineInjector(variables.gw, this, 'mockCreditAccountWeekendEffectiveDateMovedToWeekDay', 'transactionData'); local.credit = variables.gw.credit(money = variables.svc.createMoney(500, 'USD'), account = local.account, options = local.options); standardResponseTests(local.credit); assertTrue(dateCompare(local.effectiveDate, local.credit.getParsedResult().effectiveDate) < 0, 'Posted date is on the weekend, returned effective date should be ammended to next working day but isn''t'); } public void function testCreditAccountSettlementDateIsTheBusinessDayAfterEffectiveDay() { local.accountToken = createAccountTest(); //Credit account local.account = variables.svc.createToken(id = local.accountToken.getTokenId()); local.effectiveDate = dateAdd('d', 4, nextSaturday()); // Wednesday of next week local.options = structNew(); local.options.sec = 'CCD'; //XS_BAT_METHOD_CCD, XS_BAT_METHOD_PPD, XS_BAT_METHOD_TEL, XS_BAT_METHOD_WEB local.options.effectiveDate = local.effectiveDate; offlineInjector(variables.gw, this, 'mockCreditAccountSettlementDateIsTheBusinessDayAfterEffectiveDay', 'transactionData'); local.credit = variables.gw.credit(money = variables.svc.createMoney(500, 'USD'), account = local.account, options = local.options); standardResponseTests(local.credit); assertTrue(dateDiff('d', local.effectiveDate, local.credit.getParsedResult().settlementdate) == 1, 'The settlement date should be the next working day after the effective day'); } //HELPERS private any function createAccountTest() { local.argumentCollection = structNew(); local.argumentCollection.account = createAccount(); offlineInjector(variables.gw, this, 'mockCreateAccountOk', 'accountData'); local.accountToken = gw.store(argumentCollection = local.argumentCollection); standardResponseTests(local.accountToken); assertTrue(local.accountToken.getTokenId() != '', 'Token not returned'); return local.accountToken; } private date function nextSaturday(date day=now()) { //Saturday is day 7, subtract today from that to receive next saturday's date arguments.day = dateAdd('d', 7-dayOfWeek(arguments.day), removeTimePart(arguments.day)); return arguments.day; } private date function removeTimePart(date day=now()) { return createDate(year(arguments.day), month(arguments.day), day(arguments.day)); } private any function createAccount() { local.account = variables.svc.createEFT(); local.account.setFirstName('John'); local.account.setLastName('Doe'); local.account.setAddress('123 Comox Street'); local.account.setAddress2('West End'); local.account.setCity('Vancouver'); local.account.setRegion('BC'); local.account.setPostalCode('V6G1S2'); local.account.setCountry('Canada'); local.account.setPhoneNumber('0123456789'); local.account.setAccount(123123123123); local.account.setRoutingNumber(021000021); local.account.setCheckNumber(); local.account.setAccountType('checking'); local.account.setSEC(); return local.account; } private any function createInvalidAccount(required string accountNumberString) { local.account = createAccount(); local.account.setAccount(arguments.accountNumberString); return local.account; } private any function createAccountWithInvalidRoutingNumber(required string accountRoutingNumberString) { local.account = createAccount(); local.account.setRoutingNumber(arguments.accountRoutingNumberString); return local.account; } private any function createAccountWithInvalidAccountType(required string accountTypeString) { local.account = createAccount(); local.account.setAccountType(arguments.accountTypeString); return local.account; } private any function createAccountWithMissingAccountType() { local.account = createAccount(); local.account.setAccountType(''); return local.account; } //MOCKS private any function mockCreditAccountOk() { return { "MERCHANTTRANSACTIONID":0,"EFFECTIVEDATE":"April, 06 2015 00:00:00","TRANSACTIONID":44067,"ACCOUNTTYPE":"CHECKING","METHOD":"CCD","AMOUNT":5.0,"STATUS":0,"SETTLEMENTDATE":"April, 07 2015 00:00:00","TYPE":"CREDIT" }; } private any function mockCreateAccountOk() { return { status=0, tokenId = 'a347d5a9bc92015fe68871403775f012d204002f9f8419590d4363088376c20e', type = 'CHECKING'}; } private any function mockDebitAccountOk() { return { "MERCHANTTRANSACTIONID":0,"EFFECTIVEDATE":"April, 06 2015 00:00:00","TRANSACTIONID":44068,"ACCOUNTTYPE":"CHECKING","METHOD":"CCD","AMOUNT":4.0,"STATUS":0,"SETTLEMENTDATE":"April, 07 2015 00:00:00","TYPE":"DEBIT" }; } private any function mockCreateInvalidAccountFails() { return { Status = 3, message = ['Account Number must be at least 5 digits'] }; } private any function mockCreateAccountWithInvalidRoutingNumberFails() { return { Status = 3, message = ['Invalid Routing Number'] }; } private any function mockCreateAccountWithInvalidAccountTypeFails() { throw(type = 'BaseCommerce Type', message = 'Unknown Account Type: XS_BA_TYPE_THISWILLFAIL'); } private any function mockCreateAccountWithMissingAccountTypeFails() { throw(type = 'BaseCommerce Type', message = 'Unknown Account Type: '); } private any function mockCreateAccountWithMissingAccountType() { return { Status = 3, message = ['Missing account type'] }; } private any function mockCreditDebitAccountWithInvalidAmountFails() { return { Status = 3, message = ['Invalid Amount'] }; } private any function mockCreditAccountWithInvalidAccountTokenFails() { return { Status = 3, message = ['No bank account exists for given token'] }; } private any function mockCreditAccountWithInvalidMethodFails() { return { Status = 3, message = ['Invalid transaction method passed in: XS_BAT_METHOD_THISWILLFAIL'] }; } private any function mockCreditAccountWithInvalideffectiveDateDaysFromNowFails() { return { Status = 3, message = ['Effective date (days from now) must be 0 or greater'] }; } private any function mockCreditAccountSettlementDateIsTheBusinessDayAfterEffectiveDay() { local.nextSaturday = dateAdd('d', 7-dayOfWeek(now()), now()); local.effectiveDate = dateFormat(dateAdd('d', 4, local.nextSaturday), 'Mmm, dd yyyy') & ' 00:00:00'; local.settlementDate = dateFormat(dateAdd('d', 5, local.nextSaturday), 'Mmm, dd yyyy') & ' 00:00:00'; return {"MERCHANTTRANSACTIONID":0,"EFFECTIVEDATE":"#local.effectiveDate#","TRANSACTIONID":44102,"ACCOUNTTYPE":"CHECKING","METHOD":"CCD","AMOUNT":5.0,"STATUS":0,"SETTLEMENTDATE":"#local.settlementDate#","TYPE":"CREDIT"}; } private any function mockCreditAccountWeekendEffectiveDateMovedToWeekDay() { local.nextSaturday = dateAdd('d', 7-dayOfWeek(now()), now()); local.effectiveDate = dateFormat(dateAdd('d', 2, local.nextSaturday), 'Mmm, dd yyyy') & ' 00:00:00'; local.settlementDate = dateFormat(dateAdd('d', 3, local.nextSaturday), 'Mmm, dd yyyy') & ' 00:00:00'; return {"MERCHANTTRANSACTIONID":0,"EFFECTIVEDATE":"#local.effectiveDate#","TRANSACTIONID":44158,"ACCOUNTTYPE":"CHECKING","METHOD":"CCD","AMOUNT":5.0,"STATUS":0,"SETTLEMENTDATE":"#local.settlementDate#","TYPE":"CREDIT"}; } private any function mockCreditAccountPastEffectiveDate() { local.effectiveDate = dateFormat(now(), 'Mmm, dd yyyy') & ' 00:00:00'; local.settlementDate = dateFormat(dateAdd('d', 1, now()), 'Mmm, dd yyyy') & ' 00:00:00'; return {"MERCHANTTRANSACTIONID":0,"EFFECTIVEDATE":"#local.effectiveDate#","TRANSACTIONID":44160,"ACCOUNTTYPE":"CHECKING","METHOD":"CCD","AMOUNT":5.0,"STATUS":0,"SETTLEMENTDATE":"#local.settlementDate#","TYPE":"CREDIT"}; } private any function mockCreditAccountFutureEffectiveDate() { local.nextSaturday = dateAdd('d', 7-dayOfWeek(now()), now()); local.effectiveDate = dateFormat(dateAdd('d', 4, local.nextSaturday), 'Mmm, dd yyyy') & ' 00:00:00'; local.settlementDate = dateFormat(dateAdd('d', 5, local.nextSaturday), 'Mmm, dd yyyy') & ' 00:00:00'; return {"MERCHANTTRANSACTIONID":0,"EFFECTIVEDATE":"#local.effectiveDate#","TRANSACTIONID":44161,"ACCOUNTTYPE":"CHECKING","METHOD":"CCD","AMOUNT":5.0,"STATUS":0,"SETTLEMENTDATE":"#local.settlementDate#","TYPE":"CREDIT"}; } }