r96644 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r96643‎ | r96644 | r96645 >
Date:02:47, 9 September 2011
Author:khorn
Status:deferred (Comments)
Tags:fundraising 
Comment:
Added more unit tests to DonationInterface.
Modified paths:
  • /branches/fundraising/extensions/DonationInterface/donationinterface.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/gateway_common/DonationData.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/gateway_common/gateway.adapter.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect.adapter.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/globalcollect_gateway/newXMLDocument.xml (deleted) (history)
  • /branches/fundraising/extensions/DonationInterface/tests/DonationDataTest.php (added) (history)
  • /branches/fundraising/extensions/DonationInterface/tests/DonationInterfaceTest.php (deleted) (history)
  • /branches/fundraising/extensions/DonationInterface/tests/GatewayAdapterTest.php (added) (history)

Diff [purge]

Index: branches/fundraising/extensions/DonationInterface/donationinterface.php
@@ -21,6 +21,7 @@
2222 //This is going to be a little funky.
2323 //Override this in LocalSettings.php BEFORE you include this file, if you want
2424 //to disable gateways.
 25+//TODO: Unfunktify, if you have a better idea here for auto-loading the classes after LocalSettings.php runs all the way.
2526 if ( !isset( $wgDonationInterfaceEnabledGateways ) ) {
2627 $wgDonationInterfaceEnabledGateways = array(
2728 'paypal',
@@ -70,3 +71,12 @@
7172 */
7273 //$wgHooks['DonationInterface_Value'][] = 'pfpGatewayValue';
7374 //$wgHooks['DonationInterface_Page'][] = 'pfpGatewayPage';
 75+
 76+# Unit tests
 77+$wgHooks['UnitTestsList'][] = 'efDonationInterfaceUnitTests';
 78+
 79+function efDonationInterfaceUnitTests( &$files ) {
 80+ $files[] = dirname( __FILE__ ) . '/tests/GatewayAdapterTest.php';
 81+ $files[] = dirname( __FILE__ ) . '/tests/DonationDataTest.php';
 82+ return true;
 83+}
Index: branches/fundraising/extensions/DonationInterface/tests/DonationInterfaceTest.php
@@ -1,233 +0,0 @@
2 -<?php
3 -
4 -/**
5 - * TODO: Something.
6 - * Something roughly test-shaped. Here.
7 - * ...to be more precise: Test that ALL the gateway adapters (Yes: All two of them)
8 - * are building the XML we think they are, and that they can process sample
9 - * return XML the way we think they should.
10 - *
11 - * TODO: Then, write all the other tests as well. :|
12 - *
13 - * @group Fundraising
14 - * @group Splunge
15 - * @group Gateways
16 - * @author Katie Horn <khorn@wikimedia.org>
17 - */
18 -class DonationInterfaceTest extends MediaWikiTestCase {
19 -
20 - function testbuildRequestXML() {
21 - $gateway = new TestAdapter();
22 - $gateway->publicCurrentTransaction( 'Test1' );
23 - $built = $gateway->buildRequestXML();
24 - $expected = '<?xml version="1.0"?>' . "\n";
25 - $expected .= '<XML><REQUEST><ACTION>Donate</ACTION><ACCOUNT><MERCHANTID>128</MERCHANTID><PASSWORD>k4ftw</PASSWORD><VERSION>3.2</VERSION><RETURNURL>http://localhost/index.php/Donate-thanks/en</RETURNURL></ACCOUNT><DONATION><DONOR> </DONOR><AMOUNT>0</AMOUNT><CURRENCYCODE>USD</CURRENCYCODE><LANGUAGECODE>en</LANGUAGECODE><COUNTRYCODE>US</COUNTRYCODE></DONATION></REQUEST></XML>' . "\n";
26 - $this->assertEquals($built, $expected, "The constructed XML for transaction type Test1 does not match our expected.");
27 -
28 - }
29 -
30 - function testParseResponseXML() {
31 - $gateway = new TestAdapter();
32 - $returned = $gateway->do_transaction( 'Test2' );
33 -
34 - $expected_errors = array(
35 - 128 => "Your shoe's untied...",
36 - 45 => "Low clearance!"
37 - );
38 -
39 - $expected_data = array(
40 - 'thing' => 'stuff',
41 - 'otherthing' => 12,
42 - );
43 -
44 - $this->assertEquals($returned['status'], true, "Status should be true at this point.");
45 -
46 - $this->assertEquals($returned['errors'], $expected_errors, "Expected errors were not found.");
47 -
48 - $this->assertEquals($returned['data'], $expected_data, "Expected data was not found.");
49 -
50 - $this->assertEquals($returned['message'], "Test2 Transaction Successful!", "Expected message was not returned.");
51 -
52 - }
53 -
54 -}
55 -
56 -$dir = dirname( __FILE__ ) . '/';
57 -require_once( $dir . '../gateway_common/gateway.adapter.php' );
58 -
59 -class TestAdapter extends GatewayAdapter {
60 -
61 - const gatewayname = 'Test Gateway';
62 - const identifier = 'testgateway';
63 - const communicationtype = 'xml';
64 - const globalprefix = 'wgTestAdapterGateway';
65 -
66 - function stageData(){
67 - $this->postdata['amount'] = $this->postdata['amount'] * 1000;
68 - $this->postdata['name'] = $this->postdata['fname'] . " " . $this->postdata['lname'];
69 - }
70 -
71 - function __construct( ) {
72 - global $wgTestAdapterGatewayTestVar, $wgTestAdapterGatewayUseSyslog;
73 - $wgTestAdapterGatewayTestVar = "Hi there!";
74 - $wgTestAdapterGatewayUseSyslog = true;
75 - $this->classlocation = __FILE__;
76 - parent::__construct();
77 -
78 - }
79 -
80 - function defineAccountInfo(){
81 - $this->accountInfo = array(
82 - 'MERCHANTID' => '128',
83 - 'PASSWORD' => 'k4ftw',
84 - //'IPADDRESS' => '', //TODO: Not sure if this should be OUR ip, or the user's ip. Hurm.
85 - 'VERSION' => "3.2",
86 - );
87 - }
88 -
89 - function defineVarMap(){
90 - $this->var_map = array(
91 - 'DONOR' => 'name',
92 - 'AMOUNT' => 'amount',
93 - 'CURRENCYCODE' => 'currency',
94 - 'LANGUAGECODE' => 'language',
95 - 'COUNTRYCODE' => 'country',
96 - 'OID' => 'order_id',
97 - 'RETURNURL' => 'returnto', //TODO: Fund out where the returnto URL is supposed to be coming from.
98 - );
99 - }
100 -
101 - function defineReturnValueMap(){
102 - $this->return_value_map = array(
103 - 'AOK' => true,
104 - 'WRONG' => false,
105 - );
106 - }
107 -
108 - function defineTransactions(){
109 - $this->transactions = array();
110 -
111 - $this->transactions['Test1'] = array(
112 - 'request' => array(
113 - 'REQUEST' => array(
114 - 'ACTION',
115 - 'ACCOUNT' => array(
116 - 'MERCHANTID',
117 - 'PASSWORD',
118 - 'VERSION',
119 - 'RETURNURL',
120 - ),
121 - 'DONATION' => array(
122 - 'DONOR',
123 - 'AMOUNT',
124 - 'CURRENCYCODE',
125 - 'LANGUAGECODE',
126 - 'COUNTRYCODE',
127 - //'OID', //move this to another test. It's different every time, dorkus.
128 - )
129 - )
130 - ),
131 - 'values' => array(
132 - 'ACTION' => 'Donate',
133 - ),
134 - );
135 -
136 - $this->transactions['Test2'] = array(
137 - 'request' => array(
138 - 'REQUEST' => array(
139 - 'ACTION',
140 - )
141 - ),
142 - 'values' => array(
143 - 'ACTION' => 'Donate2',
144 - ),
145 - );
146 - self::log(print_r($this->transactions, true));
147 - }
148 -
149 - /**
150 - * Take the entire response string, and strip everything we don't care about.
151 - * For instance: If it's XML, we only want correctly-formatted XML. Headers must be killed off.
152 - * return a string.
153 - */
154 - function getFormattedResponse( $rawResponse ){
155 - $xmlString = $this->stripXMLResponseHeaders($rawResponse);
156 - $displayXML = $this->formatXmlString( $xmlString );
157 - $realXML = new DomDocument( '1.0' );
158 - self::log( "Here is the Raw XML: " . $displayXML ); //I am apparently a huge fibber.
159 - $realXML->loadXML( trim( $xmlString ) );
160 - return $realXML;
161 - }
162 -
163 - /**
164 - * Parse the response to get the status. Not sure if this should return a bool, or something more... telling.
165 - */
166 - function getResponseStatus( $response ){
167 -
168 - $aok = true;
169 -
170 - foreach ( $response->getElementsByTagName( 'RESULT' ) as $node ) {
171 - if ( array_key_exists( $node->nodeValue, $this->return_value_map ) && $this->return_value_map[$node->nodeValue] !== true ) {
172 - $aok = false;
173 - }
174 - }
175 -
176 - return $aok;
177 - }
178 -
179 - /**
180 - * Parse the response to get the errors in a format we can log and otherwise deal with.
181 - * return a key/value array of codes (if they exist) and messages.
182 - */
183 - function getResponseErrors( $response ){
184 - $errors = array();
185 - foreach ( $response->getElementsByTagName( 'warning' ) as $node ) {
186 - $code = '';
187 - $message = '';
188 - foreach ( $node->childNodes as $childnode ) {
189 - if ($childnode->nodeName === "code"){
190 - $code = $childnode->nodeValue;
191 - }
192 - if ($childnode->nodeName === "message"){
193 - $message = $childnode->nodeValue;
194 - }
195 - }
196 - $errors[$code] = $message;
197 - self::log( "ON NOES! ERRORS: " . print_r($errors, true) );
198 - }
199 - return $errors;
200 - }
201 -
202 - /**
203 - * Harvest the data we need back from the gateway.
204 - * return a key/value array
205 - */
206 - function getResponseData( $response ){
207 - $data = array();
208 - foreach ( $response->getElementsByTagName( 'ImportantData' ) as $node ) {
209 - foreach ( $node->childNodes as $childnode ) {
210 - if (trim($childnode->nodeValue) != ''){
211 - $data[$childnode->nodeName] = $childnode->nodeValue;
212 - }
213 - }
214 - }
215 - self::log( "Returned Data: " . print_r($data, true));
216 - return $data;
217 - }
218 -
219 - function processResponse( $response ) {
220 - //TODO: Stuff.
221 - }
222 -
223 - function publicCurrentTransaction( $transaction = '' ){
224 - $this->currentTransaction( $transaction );
225 - }
226 -
227 - function curl_transaction($data) {
228 - $data = "";
229 - $data['result'] = 'BLAH BLAH BLAH BLAH whatever something blah blah<?xml version="1.0"?>' . "\n" . '<XML><Response><Status>AOK</Status><ImportantData><thing>stuff</thing><otherthing>12</otherthing></ImportantData><errorswarnings><warning><code>128</code><message>Your shoe\'s untied...</message></warning><warning><code>45</code><message>Low clearance!</message></warning></errorswarnings></Response></XML>';
230 - return $data;
231 - }
232 -}
233 -
234 -?>
Index: branches/fundraising/extensions/DonationInterface/tests/GatewayAdapterTest.php
@@ -0,0 +1,256 @@
 2+<?php
 3+
 4+/**
 5+ * TODO: Something.
 6+ * Something roughly test-shaped. Here.
 7+ * ...to be more precise: Test that ALL the gateway adapters (Yes: All two of them)
 8+ * are building the XML we think they are, and that they can process sample
 9+ * return XML the way we think they should.
 10+ *
 11+ * TODO: Then, write all the other tests as well. :|
 12+ *
 13+ * @group Fundraising
 14+ * @group Splunge
 15+ * @group Gateways
 16+ * @author Katie Horn <khorn@wikimedia.org>
 17+ */
 18+class GatewayAdapterTest extends MediaWikiTestCase {
 19+
 20+ function testbuildRequestXML() {
 21+ $gateway = new TestAdapter();
 22+ $gateway->publicCurrentTransaction( 'Test1' );
 23+ $built = $gateway->buildRequestXML();
 24+ $expected = '<?xml version="1.0"?>' . "\n";
 25+ $expected .= '<XML><REQUEST><ACTION>Donate</ACTION><ACCOUNT><MERCHANTID>128</MERCHANTID><PASSWORD>k4ftw</PASSWORD><VERSION>3.2</VERSION><RETURNURL>http://localhost/index.php/Donate-thanks/en</RETURNURL></ACCOUNT><DONATION><DONOR>Tester Testington</DONOR><AMOUNT>35000</AMOUNT><CURRENCYCODE>USD</CURRENCYCODE><LANGUAGECODE>en</LANGUAGECODE><COUNTRYCODE>US</COUNTRYCODE></DONATION></REQUEST></XML>' . "\n";
 26+ $this->assertEquals($built, $expected, "The constructed XML for transaction type Test1 does not match our expected.");
 27+
 28+ }
 29+
 30+ function testParseResponseStatusXML() {
 31+
 32+ $returned = $this->getTestGatewayTransactionTest2Results();
 33+ $this->assertEquals($returned['status'], true, "Status should be true at this point.");
 34+ }
 35+
 36+ function testParseResponseErrorsXML() {
 37+
 38+ $returned = $this->getTestGatewayTransactionTest2Results();
 39+ $expected_errors = array(
 40+ 128 => "Your shoe's untied...",
 41+ 45 => "Low clearance!"
 42+ );
 43+ $this->assertEquals($returned['errors'], $expected_errors, "Expected errors were not found.");
 44+
 45+ }
 46+
 47+ function testParseResponseDataXML() {
 48+
 49+ $returned = $this->getTestGatewayTransactionTest2Results();
 50+ $expected_data = array(
 51+ 'thing' => 'stuff',
 52+ 'otherthing' => 12,
 53+ );
 54+ $this->assertEquals($returned['data'], $expected_data, "Expected data was not found.");
 55+
 56+ }
 57+
 58+ function testResponseMessage() {
 59+
 60+ $returned = $this->getTestGatewayTransactionTest2Results();
 61+ $this->assertEquals($returned['message'], "Test2 Transaction Successful!", "Expected message was not returned.");
 62+
 63+ }
 64+
 65+ function testGetGlobal(){
 66+ $gateway = new TestAdapter();
 67+ $found = $gateway::getGlobal("TestVar");
 68+ $expected = "Hi there!";
 69+ $this->assertEquals($found, $expected, "getGlobal is not functioning properly.");
 70+ }
 71+
 72+
 73+ function getTestGatewayTransactionTest2Results(){
 74+ $gateway = new TestAdapter();
 75+ return $gateway->do_transaction( 'Test2' );
 76+ }
 77+
 78+}
 79+
 80+$dir = dirname( __FILE__ ) . '/';
 81+require_once( $dir . '../gateway_common/gateway.adapter.php' );
 82+
 83+class TestAdapter extends GatewayAdapter {
 84+
 85+ const gatewayname = 'Test Gateway';
 86+ const identifier = 'testgateway';
 87+ const communicationtype = 'xml';
 88+ const globalprefix = 'wgTestAdapterGateway';
 89+
 90+ function stageData(){
 91+ $this->postdata['amount'] = $this->postdata['amount'] * 1000;
 92+ $this->postdata['name'] = $this->postdata['fname'] . " " . $this->postdata['lname'];
 93+ }
 94+
 95+ function __construct( ) {
 96+ global $wgTestAdapterGatewayTestVar, $wgTestAdapterGatewayUseSyslog, $wgTestAdapterGatewayTest;
 97+ $wgTestAdapterGatewayTest = true;
 98+ $wgTestAdapterGatewayTestVar = "Hi there!";
 99+ $wgTestAdapterGatewayUseSyslog = true;
 100+ $this->classlocation = __FILE__;
 101+ parent::__construct();
 102+
 103+ }
 104+
 105+ function defineAccountInfo(){
 106+ $this->accountInfo = array(
 107+ 'MERCHANTID' => '128',
 108+ 'PASSWORD' => 'k4ftw',
 109+ //'IPADDRESS' => '', //TODO: Not sure if this should be OUR ip, or the user's ip. Hurm.
 110+ 'VERSION' => "3.2",
 111+ );
 112+ }
 113+
 114+ function defineVarMap(){
 115+ $this->var_map = array(
 116+ 'DONOR' => 'name',
 117+ 'AMOUNT' => 'amount',
 118+ 'CURRENCYCODE' => 'currency',
 119+ 'LANGUAGECODE' => 'language',
 120+ 'COUNTRYCODE' => 'country',
 121+ 'OID' => 'order_id',
 122+ 'RETURNURL' => 'returnto', //TODO: Fund out where the returnto URL is supposed to be coming from.
 123+ );
 124+ }
 125+
 126+ function defineReturnValueMap(){
 127+ $this->return_value_map = array(
 128+ 'AOK' => true,
 129+ 'WRONG' => false,
 130+ );
 131+ }
 132+
 133+ function defineTransactions(){
 134+ $this->transactions = array();
 135+
 136+ $this->transactions['Test1'] = array(
 137+ 'request' => array(
 138+ 'REQUEST' => array(
 139+ 'ACTION',
 140+ 'ACCOUNT' => array(
 141+ 'MERCHANTID',
 142+ 'PASSWORD',
 143+ 'VERSION',
 144+ 'RETURNURL',
 145+ ),
 146+ 'DONATION' => array(
 147+ 'DONOR',
 148+ 'AMOUNT',
 149+ 'CURRENCYCODE',
 150+ 'LANGUAGECODE',
 151+ 'COUNTRYCODE',
 152+ //'OID', //move this to another test. It's different every time, dorkus.
 153+ )
 154+ )
 155+ ),
 156+ 'values' => array(
 157+ 'ACTION' => 'Donate',
 158+ ),
 159+ );
 160+
 161+ $this->transactions['Test2'] = array(
 162+ 'request' => array(
 163+ 'REQUEST' => array(
 164+ 'ACTION',
 165+ )
 166+ ),
 167+ 'values' => array(
 168+ 'ACTION' => 'Donate2',
 169+ ),
 170+ );
 171+ }
 172+
 173+ /**
 174+ * Take the entire response string, and strip everything we don't care about.
 175+ * For instance: If it's XML, we only want correctly-formatted XML. Headers must be killed off.
 176+ * return a string.
 177+ */
 178+ function getFormattedResponse( $rawResponse ){
 179+ $xmlString = $this->stripXMLResponseHeaders($rawResponse);
 180+ $displayXML = $this->formatXmlString( $xmlString );
 181+ $realXML = new DomDocument( '1.0' );
 182+ self::log( "Here is the Raw XML: " . $displayXML ); //I am apparently a huge fibber.
 183+ $realXML->loadXML( trim( $xmlString ) );
 184+ return $realXML;
 185+ }
 186+
 187+ /**
 188+ * Parse the response to get the status. Not sure if this should return a bool, or something more... telling.
 189+ */
 190+ function getResponseStatus( $response ){
 191+
 192+ $aok = true;
 193+
 194+ foreach ( $response->getElementsByTagName( 'RESULT' ) as $node ) {
 195+ if ( array_key_exists( $node->nodeValue, $this->return_value_map ) && $this->return_value_map[$node->nodeValue] !== true ) {
 196+ $aok = false;
 197+ }
 198+ }
 199+
 200+ return $aok;
 201+ }
 202+
 203+ /**
 204+ * Parse the response to get the errors in a format we can log and otherwise deal with.
 205+ * return a key/value array of codes (if they exist) and messages.
 206+ */
 207+ function getResponseErrors( $response ){
 208+ $errors = array();
 209+ foreach ( $response->getElementsByTagName( 'warning' ) as $node ) {
 210+ $code = '';
 211+ $message = '';
 212+ foreach ( $node->childNodes as $childnode ) {
 213+ if ($childnode->nodeName === "code"){
 214+ $code = $childnode->nodeValue;
 215+ }
 216+ if ($childnode->nodeName === "message"){
 217+ $message = $childnode->nodeValue;
 218+ }
 219+ }
 220+ $errors[$code] = $message;
 221+ }
 222+ return $errors;
 223+ }
 224+
 225+ /**
 226+ * Harvest the data we need back from the gateway.
 227+ * return a key/value array
 228+ */
 229+ function getResponseData( $response ){
 230+ $data = array();
 231+ foreach ( $response->getElementsByTagName( 'ImportantData' ) as $node ) {
 232+ foreach ( $node->childNodes as $childnode ) {
 233+ if (trim($childnode->nodeValue) != ''){
 234+ $data[$childnode->nodeName] = $childnode->nodeValue;
 235+ }
 236+ }
 237+ }
 238+ self::log( "Returned Data: " . print_r($data, true));
 239+ return $data;
 240+ }
 241+
 242+ function processResponse( $response ) {
 243+ //TODO: Stuff.
 244+ }
 245+
 246+ function publicCurrentTransaction( $transaction = '' ){
 247+ $this->currentTransaction( $transaction );
 248+ }
 249+
 250+ function curl_transaction($data) {
 251+ $data = "";
 252+ $data['result'] = 'BLAH BLAH BLAH BLAH whatever something blah blah<?xml version="1.0"?>' . "\n" . '<XML><Response><Status>AOK</Status><ImportantData><thing>stuff</thing><otherthing>12</otherthing></ImportantData><errorswarnings><warning><code>128</code><message>Your shoe\'s untied...</message></warning><warning><code>45</code><message>Low clearance!</message></warning></errorswarnings></Response></XML>';
 253+ return $data;
 254+ }
 255+}
 256+
 257+?>
Property changes on: branches/fundraising/extensions/DonationInterface/tests/GatewayAdapterTest.php
___________________________________________________________________
Added: svn:eol-style
1258 + native
Index: branches/fundraising/extensions/DonationInterface/tests/DonationDataTest.php
@@ -0,0 +1,275 @@
 2+<?php
 3+
 4+/**
 5+ * @group Fundraising
 6+ * @group Splunge
 7+ * @group Gateways
 8+ * @author Katie Horn <khorn@wikimedia.org>
 9+ */
 10+$dir = dirname( __FILE__ ) . '/';
 11+require_once( $dir . '../gateway_common/DonationData.php' );
 12+class DonationDataTest extends MediaWikiTestCase {
 13+
 14+ function __construct(){
 15+ parent::__construct();
 16+ $this->testData = array(
 17+ 'amount' => '128',
 18+ 'email' => 'unittest@example.com',
 19+ 'fname' => 'Testocres',
 20+ 'mname' => 'S.',
 21+ 'lname' => 'McTestingyou',
 22+ 'street' => '123 Fake Street',
 23+ 'city' => 'Springfield',
 24+ 'state' => 'US',
 25+ 'zip' => '99999',
 26+ 'country' => 'US',
 27+ 'fname2' => 'Testor',
 28+ 'lname2' => 'Testeyton',
 29+ 'street2' => '123 W. Grand Ave.',
 30+ 'city2' => 'Oakland',
 31+ 'state2' => 'CA',
 32+ 'zip2' => '94607',
 33+ 'country2' => 'US',
 34+ 'size' => 'Big mcLargeHuge',
 35+ 'premium_language' => 'fr',
 36+ 'card_num' => '42',
 37+ 'card' => 'visa',
 38+ 'expiration' => '1138',
 39+ 'cvv' => '665',
 40+ 'currency' => 'USD',
 41+ 'payment_method' => '',
 42+ 'i_order_id' => '1234567890',
 43+ 'numAttempt' => '5',
 44+ 'referrer' => 'http://www.testing.com/',
 45+ 'utm_source' => '..dd',
 46+ 'utm_medium' => 'large',
 47+ 'utm_campaign' => 'yes',
 48+ 'comment-option' => '',
 49+ 'comment' => 'My hovercraft is full of eels',
 50+ 'email-opt' => '',
 51+ 'test_string' => '',
 52+ 'token' => '113811',
 53+ 'contribution_tracking_id' => '',
 54+ 'data_hash' => '',
 55+ 'action' => '',
 56+ 'gateway' => 'chainlink',
 57+ 'owa_session' => '',
 58+ 'owa_ref' => 'http://localhost/importedTestData',
 59+ );
 60+
 61+ }
 62+
 63+
 64+ function testConstruct(){
 65+ $ddObj = new DonationData(''); //as if we were posted.
 66+ $returned = $ddObj->getData();
 67+ $expected = array( 'posted' => '',
 68+ 'amount' => '0.00',
 69+ 'email' => '',
 70+ 'fname' => '',
 71+ 'mname' => '',
 72+ 'lname' => '',
 73+ 'street' => '',
 74+ 'city' => '',
 75+ 'state' => '',
 76+ 'zip' => '',
 77+ 'country' => '',
 78+ 'fname2' => '',
 79+ 'lname2' => '',
 80+ 'street2' => '',
 81+ 'city2' => '',
 82+ 'state2' => '',
 83+ 'zip2' => '',
 84+ 'country2' => '',
 85+ 'size' => '',
 86+ 'premium_language' => 'en',
 87+ 'card_num' => '',
 88+ 'card' => '',
 89+ 'expiration' => '',
 90+ 'cvv' => '',
 91+ 'currency' => '',
 92+ 'payment_method' => '',
 93+ 'numAttempt' => '0',
 94+ 'referrer' => '',
 95+ 'utm_source' => '..cc',
 96+ 'utm_medium' => '',
 97+ 'utm_campaign' => '',
 98+ 'language' => '',
 99+ 'comment-option' => '',
 100+ 'comment' => '',
 101+ 'email-opt' => '',
 102+ 'test_string' => '',
 103+ '_cache_' => '',
 104+ 'token' => '',
 105+ 'contribution_tracking_id' => '',
 106+ 'data_hash' => '',
 107+ 'action' => '',
 108+ 'gateway' => '',
 109+ 'owa_session' => '',
 110+ 'owa_ref' => '',
 111+ );
 112+ unset($returned['order_id']);
 113+ unset($returned['i_order_id']);
 114+ $this->assertEquals($returned, $expected, "Staged post data does not match expected (largely empty).");
 115+ }
 116+
 117+ function testConstructAsTest(){
 118+ $ddObj = new DonationData('', true); //test mode from the start, no data
 119+ $returned = $ddObj->getData();
 120+ $expected = array(
 121+ 'amount' => '35',
 122+ 'email' => 'test@example.com',
 123+ 'fname' => 'Tester',
 124+ 'mname' => 'T.',
 125+ 'lname' => 'Testington',
 126+ 'street' => '548 Market St.',
 127+ 'city' => 'San Francisco',
 128+ 'state' => 'CA',
 129+ 'zip' => '94104',
 130+ 'country' => 'US',
 131+ 'fname2' => 'Testy',
 132+ 'lname2' => 'Testerson',
 133+ 'street2' => '123 Telegraph Ave.',
 134+ 'city2' => 'Berkeley',
 135+ 'state2' => 'CA',
 136+ 'zip2' => '94703',
 137+ 'country2' => 'US',
 138+ 'size' => 'small',
 139+ 'premium_language' => 'es',
 140+ 'card_num' => '378282246310005',
 141+ 'card' => 'american',
 142+ 'expiration' => '1012',
 143+ 'cvv' => '001',
 144+ 'currency' => 'USD',
 145+ 'payment_method' => '',
 146+ 'i_order_id' => '1234567890',
 147+ 'numAttempt' => '0',
 148+ 'referrer' => 'http://www.baz.test.com/index.php?action=foo&amp;action=bar',
 149+ 'utm_source' => '..cc',
 150+ 'utm_medium' => '',
 151+ 'utm_campaign' => '',
 152+ 'language' => 'en',
 153+ 'comment-option' => '',
 154+ 'comment' => '',
 155+ 'email-opt' => '',
 156+ 'test_string' => '',
 157+ 'token' => '',
 158+ 'contribution_tracking_id' => '',
 159+ 'data_hash' => '',
 160+ 'action' => '',
 161+ 'gateway' => 'payflowpro',
 162+ 'owa_session' => '',
 163+ 'owa_ref' => 'http://localhost/defaultTestData',
 164+ );
 165+ unset($returned['order_id']);
 166+
 167+ $this->assertEquals($expected, $returned, "Staged default test data does not match expected.");
 168+ }
 169+
 170+ function testRepopulate(){
 171+ $expected = $this->testData;
 172+ //just unset a handfull... doesn't matter what, really.
 173+ unset($expected['comment-option']);
 174+ unset($expected['email-opt']);
 175+ unset($expected['test_string']);
 176+
 177+ $ddObj = new DonationData('');
 178+ $ddObj->populateData(true, $expected); //change to test mode with explicit test data
 179+ $returned = $ddObj->getData();
 180+ //unset these, because they're always new
 181+ unset($returned['order_id']);
 182+ unset($expected['order_id']);
 183+ $this->assertEquals($returned, $expected, "The forced test data did not populate as expected.");
 184+ }
 185+
 186+ function testIsSomething(){
 187+ $data = $this->testData;
 188+ unset($data['zip']);
 189+ $ddObj = new DonationData('', true, $data);
 190+ $this->assertEquals($ddObj->isSomething('zip'), false, "Zip should currently be nothing.");
 191+ $this->assertEquals($ddObj->isSomething('lname'), true, "Lname should currently be something.");
 192+ }
 193+
 194+ function testGetVal(){
 195+ $data = $this->testData;
 196+ unset($data['zip']);
 197+ $ddObj = new DonationData('', true, $data);
 198+ $this->assertEquals($ddObj->getVal('zip'), null, "Zip should currently be nothing.");
 199+ $this->assertEquals($ddObj->getVal('lname'), 'McTestingyou', "Lname should currently be 'McTestingyou'.");
 200+ }
 201+
 202+ function testSetNormalizedAmount_amtGiven() {
 203+ $data = $this->testData;
 204+ $data['amount'] = 'this is not a number';
 205+ $data['amountGiven'] = 42.50;
 206+ //unset($data['zip']);
 207+ $ddObj = new DonationData('', true, $data);
 208+ $returned = $ddObj->getData();
 209+ $this->assertEquals($returned['amount'], '42.50', "Amount was not properly reset");
 210+ $this->assertTrue(!(array_key_exists('amountGiven', $returned)), "amountGiven should have been removed from the data");
 211+ }
 212+
 213+ function testSetNormalizedAmount_amount() {
 214+ $data = $this->testData;
 215+ $data['amount'] = 88.15;
 216+ $data['amountGiven'] = 42.50;
 217+ //unset($data['zip']);
 218+ $ddObj = new DonationData('', true, $data);
 219+ $returned = $ddObj->getData();
 220+ $this->assertEquals($returned['amount'], 88.15, "Amount was not properly reset");
 221+ $this->assertTrue(!(array_key_exists('amountGiven', $returned)), "amountGiven should have been removed from the data");
 222+ }
 223+
 224+ function testSetNormalizedAmount_neagtiveAmount() {
 225+ $data = $this->testData;
 226+ $data['amount'] = -1;
 227+ $data['amountOther'] = 3.25;
 228+ //unset($data['zip']);
 229+ $ddObj = new DonationData('', true, $data);
 230+ $returned = $ddObj->getData();
 231+ $this->assertEquals($returned['amount'], 3.25, "Amount was not properly reset");
 232+ $this->assertTrue(!(array_key_exists('amountOther', $returned)), "amountOther should have been removed from the data");
 233+ }
 234+
 235+ function testSetNormalizedAmount_noGoodAmount() {
 236+ $data = $this->testData;
 237+ $data['amount'] = 'splunge';
 238+ $data['amountGiven'] = 'wombat';
 239+ $data['amountOther'] = 'macedonia';
 240+ //unset($data['zip']);
 241+ $ddObj = new DonationData('', true, $data);
 242+ $returned = $ddObj->getData();
 243+ $this->assertEquals($returned['amount'], 0.00, "Amount was not properly reset");
 244+ $this->assertTrue(!(array_key_exists('amountOther', $returned)), "amountOther should have been removed from the data");
 245+ $this->assertTrue(!(array_key_exists('amountGiven', $returned)), "amountGiven should have been removed from the data");
 246+ }
 247+
 248+ /*
 249+ * TODO: Make sure ALL these functions in DonationData are tested, either directly or through a calling function.
 250+ * I know that's more regression-ish, but I stand by it. :p
 251+ function isCache(){
 252+ function setOwaRefId(){
 253+ function setNormalizedOrderIDs(){
 254+ function generateOrderId() {
 255+ public function sanitizeInput( &$value, $key, $flags=ENT_COMPAT, $double_encode=false ) {
 256+ function setGateway(){
 257+ function doCacheStuff(){
 258+ function getAnnoyingOrderIDLogLinePrefix(){
 259+ public function getEditToken( $salt = '' ) {
 260+ public static function generateToken( $salt = '' ) {
 261+ function matchEditToken( $val, $salt = '' ) {
 262+ function unsetEditToken() {
 263+ public static function ensureSession() {
 264+ public function checkTokens() {
 265+ function wasPosted(){
 266+ public static function getUtmSource( $utm_source = null, $utm_source_id = null ) {
 267+ public function getOptOuts() {
 268+ public function getCleanTrackingData( $clean_optouts = false ) {
 269+ function saveContributionTracking() {
 270+ public static function insertContributionTracking( $tracking_data ) {
 271+ public function updateContributionTracking( $force = false ) {
 272+
 273+ */
 274+}
 275+
 276+?>
Property changes on: branches/fundraising/extensions/DonationInterface/tests/DonationDataTest.php
___________________________________________________________________
Added: svn:eol-style
1277 + native
Index: branches/fundraising/extensions/DonationInterface/globalcollect_gateway/newXMLDocument.xml
@@ -1,13 +0,0 @@
2 -<?xml version="1.0" encoding="UTF-8"?>
3 -
4 -<!--
5 - Document : newXMLDocument.xml
6 - Created on : August 29, 2011, 12:35 PM
7 - Author : khorn
8 - Description:
9 - Purpose of the document follows.
10 -
11 -<root>
12 -
13 -</root>
Index: branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect.adapter.php
@@ -157,7 +157,6 @@
158158 }
159159 }
160160 $errors[$code] = $message;
161 - self::log( "ON NOES! ERRORS: " . print_r($errors, true) );
162161 }
163162 return $errors;
164163 }
Index: branches/fundraising/extensions/DonationInterface/gateway_common/gateway.adapter.php
@@ -94,15 +94,6 @@
9595 const globalprefix = 'wgDonationGateway'; //...for example.
9696
9797 function __construct(){
98 -
99 - $dir = dirname( __FILE__ ) . '/';
100 - require_once( $dir . '../gateway_common/DonationData.php' );
101 - $this->dataObj = new DonationData(get_called_class());
102 -
103 - $this->postdata = $this->dataObj->getData();
104 - //TODO: Fix this a bit.
105 - $this->posted = $this->dataObj->wasPosted();
106 -
10798 global $wgDonationInterfaceTest; //this is so the forms can see it.
10899 //TODO: Alter the forms so they don't need the global?
109100 if ( !self::getGlobal('Test') ) {
@@ -112,7 +103,15 @@
113104 $this->url = self::getGlobal('TestingURL');
114105 $wgDonationInterfaceTest = true;
115106 }
 107+
 108+ $dir = dirname( __FILE__ ) . '/';
 109+ require_once( $dir . '../gateway_common/DonationData.php' );
 110+ $this->dataObj = new DonationData(get_called_class(), $wgDonationInterfaceTest);
116111
 112+ $this->postdata = $this->dataObj->getData();
 113+ //TODO: Fix this a bit.
 114+ $this->posted = $this->dataObj->wasPosted();
 115+
117116 $this->setPostDefaults();
118117 $this->defineTransactions();
119118 $this->defineVarMap();
@@ -480,6 +479,7 @@
481480 $c = get_called_class();
482481 return $c::globalprefix;
483482 }
 483+
484484 static function getIdentifier() {
485485 $c = get_called_class();
486486 return $c::identifier;
Index: branches/fundraising/extensions/DonationInterface/gateway_common/DonationData.php
@@ -11,12 +11,12 @@
1212
1313 public $boss;
1414
15 - function __construct($owning_class){
 15+ function __construct($owning_class, $test = false, $testdata = false){
1616 //TODO: Actually think about this bit.
1717 // ...and keep in mind we can re-populate if it's a test or whatever. (But that may not be a good idea either)
1818 //maybe we should just explicitly pass in where we get the data from. (Test, post, API...)
1919 $this->boss = $owning_class;
20 - $this->populateData();
 20+ $this->populateData($test, $testdata);
2121 }
2222
2323 function populateData($test = false, $testdata = false){
@@ -24,11 +24,10 @@
2525 //TODO: Uh, the API should probably be able to get in this far, too... and have its own populate function.
2626 //Maybe check for the boss class...
2727 if ($test){
28 - $this->populateData_Test($testdata = false);
 28+ $this->populateData_Test($testdata);
2929 } else {
3030 $this->populateData_Form();
3131 }
32 - //TODO: Unit test the goodness out of this thing.
3332 $this->doCacheStuff();
3433
3534
@@ -43,7 +42,6 @@
4443 $this->saveContributionTracking();
4544 }
4645
47 - self::log("FORM DATA OBJECT: Data has been populated! " . print_r($this->normalized, true));
4846 }
4947
5048 function getData(){
@@ -75,7 +73,7 @@
7674 global $wgRequest; //TODO: ARRRGHARGHARGH. That is all.
7775
7876 $this->normalized = array(
79 - 'amount' => ( $amount != "0.00" ) ? $amount : "35",
 77+ 'amount' => "35",
8078 'amountOther' => '',
8179 'email' => 'test@example.com',
8280 'fname' => 'Tester',
@@ -101,9 +99,9 @@
102100 'cvv' => '001',
103101 'currency' => 'USD',
104102 'payment_method' => $wgRequest->getText( 'payment_method' ),
105 - 'order_id' => $order_id,
106 - 'i_order_id' => $i_order_id,
107 - 'numAttempt' => $numAttempt,
 103+ 'order_id' => '1234567890',
 104+ 'i_order_id' => '1234567890',
 105+ 'numAttempt' => 0,
108106 'referrer' => 'http://www.baz.test.com/index.php?action=foo&action=bar',
109107 'utm_source' => self::getUtmSource(),
110108 'utm_medium' => $wgRequest->getText( 'utm_medium' ),
@@ -113,13 +111,13 @@
114112 'comment' => $wgRequest->getText( 'comment' ),
115113 'email-opt' => $wgRequest->getText( 'email-opt' ),
116114 'test_string' => $wgRequest->getText( 'process' ),
117 - 'token' => $token,
 115+ 'token' => '',
118116 'contribution_tracking_id' => $wgRequest->getText( 'contribution_tracking_id' ),
119117 'data_hash' => $wgRequest->getText( 'data_hash' ),
120118 'action' => $wgRequest->getText( 'action' ),
121119 'gateway' => 'payflowpro',
122120 'owa_session' => $wgRequest->getText( 'owa_session', null ),
123 - 'owa_ref' => $owa_ref,
 121+ 'owa_ref' => 'http://localhost/defaultTestData',
124122 );
125123 }
126124 }
@@ -214,18 +212,6 @@
215213 }
216214
217215 function setNormalizedAmount(){
218 -// // find out if amount was a radio button or textbox, set amount
219 -// if ( isset( $_REQUEST['amount'] ) && preg_match( '/^\d+(\.(\d+)?)?$/', $wgRequest->getText( 'amount' ) ) ) {
220 -// $amount = $wgRequest->getText( 'amount' );
221 -// } elseif ( isset( $_REQUEST['amountGiven'] ) && preg_match( '/^\d+(\.(\d+)?)?$/', $wgRequest->getText( 'amountGiven' ) ) ) {
222 -// $amount = number_format( $wgRequest->getText( 'amountGiven' ), 2, '.', '' );
223 -// } elseif ( isset( $_REQUEST['amount'] ) ) {
224 -// $amount = '0.00';
225 -// } elseif ( $wgRequest->getText( 'amount' ) == '-1' ) {
226 -// $amount = $wgRequest->getText( 'amountOther' );
227 -// } else {
228 -// $amount = '0.00';
229 -// }
230216
231217 if (!($this->isSomething('amount')) || !(preg_match( '/^\d+(\.(\d+)?)?$/', $this->getVal('amount') ) )){
232218 if ($this->isSomething('amountGiven') && preg_match( '/^\d+(\.(\d+)?)?$/', $this->getVal('amountGiven') ) ){
@@ -255,13 +241,7 @@
256242
257243 if (!$this->isSomething('i_order_id')){
258244 $this->setVal('i_order_id', $this->generateOrderId());
259 - }
260 -
261 - //TODO: Take this out when you know it's okay.
262 - //In fact: TODO: Clean up the logs all over.
263 -
264 - $this->log("Internal Order ID = " . $this->getVal('i_order_id'));
265 -
 245+ }
266246 }
267247
268248 /**
@@ -318,12 +298,14 @@
319299
320300 // if we have squid caching enabled, set the maxage
321301 global $wgUseSquid, $wgOut;
322 - $g = $this->boss; //the 'g' is for "Gateway"!
323 - $maxAge = $g::getGlobal('SMaxAge');
 302+ if (class_exists($this->boss)){
 303+ $g = $this->boss; //the 'g' is for "Gateway"!
 304+ $maxAge = $g::getGlobal('SMaxAge');
324305
325 - if ( $wgUseSquid ) {
326 - self::log( $this->getAnnoyingOrderIDLogLinePrefix() . ' Setting s-max-age: ' . $maxAge, LOG_DEBUG );
327 - $wgOut->setSquidMaxage( $maxAge );
 306+ if ( $wgUseSquid ) {
 307+ self::log( $this->getAnnoyingOrderIDLogLinePrefix() . ' Setting s-max-age: ' . $maxAge, LOG_DEBUG );
 308+ $wgOut->setSquidMaxage( $maxAge );
 309+ }
328310 }
329311 } else {
330312 $this->cache = false; //TODO: Kill this one in the face, too. (see above)
@@ -354,8 +336,12 @@
355337 // make sure we have a session open for tracking a CSRF-prevention token
356338 self::ensureSession();
357339
358 - $g = $this->boss;
359 - $gateway_ident = $g::getIdentifier();
 340+ if (class_exists($this->boss)){
 341+ $g = $this->boss;
 342+ $gateway_ident = $g::getIdentifier();
 343+ } else {
 344+ $gateway_ident = 'DonationData';
 345+ }
360346
361347 if ( !isset( $_SESSION[ $gateway_ident . 'EditToken' ] ) ) {
362348 // generate unsalted token to place in the session
@@ -404,8 +390,12 @@
405391 * Unset the payflow edit token from a user's session
406392 */
407393 function unsetEditToken() {
408 - $g = $this->boss;
409 - $gateway_ident = $g::getIdentifier();
 394+ if (class_exists($this->boss)){
 395+ $g = $this->boss;
 396+ $gateway_ident = $g::getIdentifier();
 397+ } else {
 398+ $gateway_ident = "DonationData";
 399+ }
410400 unset( $_SESSION[ $gateway_ident . 'EditToken' ] );
411401 }
412402
@@ -427,10 +417,13 @@
428418 static $match = null;
429419
430420 if ($match === null) {
 421+ if (class_exists($this->boss)){
 422+ $g = $this->boss;
 423+ $salt = $g::getGlobal('Salt');
 424+ } else {
 425+ $salt = 'gotToBeInAUnitTest';
 426+ }
431427
432 - $g = $this->boss;
433 - $salt = $g::getGlobal('Salt');
434 -
435428 // establish the edit token to prevent csrf
436429 $token = $this->getEditToken( $salt );
437430
@@ -452,10 +445,8 @@
453446 function wasPosted(){
454447 //TODO: Get rid of these log statements.
455448 if ( $this->isSomething('posted') ){
456 - $this->log("Posted = '" . $this->getVal('posted') . "'");
457449 return true;
458450 }
459 - $this->log("We were NOT Posted.");
460451 return false;
461452 }
462453

Follow-up revisions

RevisionCommit summaryAuthorDate
r99280Cleaning up the $this->boss mess in DonationData, and in the process found so...khorn23:18, 7 October 2011

Comments

#Comment by Khorn (WMF) (talk | contribs)   18:40, 23 September 2011

Please note that this branch is in the middle of a serious refactoring, and is by no means ready to be merged back into trunk. (Latest DonationInterface branch rev at the time of this comment is r97833.)

#Comment by Awjrichards (talk | contribs)   22:30, 29 September 2011

I am seeing:

if (class_exists($this->boss)){
+			$g = $this->boss;
+			$gateway_ident = $g::getIdentifier();
+		} else {
+			$gateway_ident = "DonationData";
+		}

happening a lot in DonationData.php.

Is there a reason this shouldn't get set in the class constructor as an object property? Or at least turn this into a method within DonationData.php of its own?

#Comment by Khorn (WMF) (talk | contribs)   23:19, 7 October 2011

Fixed this (and one other thing) in r99280.

Status & tagging log