Ejegg has uploaded a new change for review.
https://gerrit.wikimedia.org/r/281703
Change subject: Merge master into deployment
......................................................................
Merge master into deployment
add52c2 Actually random dummy fiscal number for MX
Removed tests
Change-Id: Ie6d5e376be7888690d712fcf4015819b1bdb45f9
---
D tests/Adapter/Astropay/AstropayTest.php
D tests/DonationInterfaceTestCase.php
2 files changed, 0 insertions(+), 1,298 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/DonationInterface
refs/changes/03/281703/1
diff --git a/tests/Adapter/Astropay/AstropayTest.php
b/tests/Adapter/Astropay/AstropayTest.php
deleted file mode 100644
index 932b38e..0000000
--- a/tests/Adapter/Astropay/AstropayTest.php
+++ /dev/null
@@ -1,598 +0,0 @@
-<<<<<<< HEAD (27e1fd Merge master into deployment)
-=======
-<?php
-/**
- * Wikimedia Foundation
- *
- * LICENSE
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-use \Psr\Log\LogLevel;
-
-/**
- *
- * @group Fundraising
- * @group DonationInterface
- * @group Astropay
- */
-class DonationInterface_Adapter_Astropay_AstropayTest extends
DonationInterfaceTestCase {
-
- /**
- * @param $name string The name of the test case
- * @param $data array Any parameters read from a dataProvider
- * @param $dataName string|int The name or index of the data set
- */
- function __construct( $name = null, array $data = array(), $dataName =
'' ) {
- parent::__construct( $name, $data, $dataName );
- $this->testAdapterClass = 'TestingAstropayAdapter';
- }
-
- function setUp() {
- parent::setUp();
- $this->setMwGlobals( array(
- 'wgAstropayGatewayEnabled' => true,
- ) );
- }
-
- /**
- * Ensure we're setting the right url for each transaction
- * @covers AstropayAdapter::getCurlBaseOpts
- */
- function testCurlUrl() {
- $init = $this->getDonorTestData( 'BR' );
- $gateway = $this->getFreshGatewayObject( $init );
- $gateway->setCurrentTransaction( 'NewInvoice' );
-
- $result = $gateway->getCurlBaseOpts();
-
- $this->assertEquals(
-
'https://sandbox.astropay.example.com/api_curl/streamline/NewInvoice',
- $result[CURLOPT_URL],
- 'Not setting URL to transaction-specific value.'
- );
- }
-
- /**
- * Test the NewInvoice transaction is making a sane request and signing
- * it correctly
- */
- function testNewInvoiceRequest() {
- $init = $this->getDonorTestData( 'BR' );
- $session['Donor']['order_id'] = '123456789';
- $this->setUpRequest( $init, $session );
- $this->setLanguage( $init['language'] );
- $gateway = new TestingAstropayAdapter();
-
- $gateway->do_transaction( 'NewInvoice' );
- parse_str( $gateway->curled[0], $actual );
-
- $expected = array(
- 'x_login' => 'createlogin',
- 'x_trans_key' => 'createpass',
- 'x_invoice' => '123456789',
- 'x_amount' => '100.00',
- 'x_currency' => 'BRL',
- 'x_bank' => 'TE',
- 'x_country' => 'BR',
- 'x_description' => wfMessage(
'donate_interface-donation-description' )->inLanguage( $init['language']
)->text(),
- 'x_iduser' => '[email protected]',
- 'x_cpf' => '00003456789',
- 'x_name' => 'Nome Apelido',
- 'x_email' => '[email protected]',
- // 'x_address' => 'Rua Falso 123',
- // 'x_zip' => '01110-111',
- // 'x_city' => 'São Paulo',
- // 'x_state' => 'SP',
- 'control' =>
'AC43664E0C4DF30607A26F271C8998BC4EE26511366E65AFB69B96E89BFD4359',
- 'type' => 'json',
- );
- $this->assertEquals( $expected, $actual, 'NewInvoice is not
including the right parameters' );
- }
-
- /**
- * When Astropay sends back valid JSON with status "0", we should set
txn
- * status to true and errors should be empty.
- */
- function testStatusNoErrors() {
- $init = $this->getDonorTestData( 'BR' );
- $gateway = $this->getFreshGatewayObject( $init );
-
- $gateway->do_transaction( 'NewInvoice' );
-
- $this->assertEquals( true, $gateway->getTransactionStatus(),
- 'Transaction status should be true for code "0"' );
-
- $this->assertEmpty( $gateway->getTransactionErrors(),
- 'Transaction errors should be empty for code "0"' );
- }
-
- /**
- * If astropay sends back non-JSON, communication status should be false
- */
- function testGibberishResponse() {
- $init = $this->getDonorTestData( 'BR' );
- $this->setLanguage( $init['language'] );
- $gateway = $this->getFreshGatewayObject( $init );
- $gateway->setDummyGatewayResponseCode( 'notJson' );
-
- $gateway->do_transaction( 'NewInvoice' );
-
- $this->assertEquals( false, $gateway->getTransactionStatus(),
- 'Transaction status should be false for bad format' );
- }
-
- /**
- * When Astropay sends back valid JSON with status "1", we should set
- * error array to generic error and log a warning.
- */
- function testStatusErrors() {
- $init = $this->getDonorTestData( 'BR' );
- $this->setLanguage( $init['language'] );
- $gateway = $this->getFreshGatewayObject( $init );
- $gateway->setDummyGatewayResponseCode( '1' );
-
- $gateway->do_transaction( 'NewInvoice' );
-
- $expected = array(
- 'internal-0000' => wfMessage(
'donate_interface-processing-error')->inLanguage( $init['language'] )->text()
- );
- $this->assertEquals( $expected,
$gateway->getTransactionErrors(),
- 'Wrong error for code "1"' );
- $logged = $this->getLogMatches( LogLevel::WARNING, '/This error
message should appear in the log./' );
- $this->assertNotEmpty( $logged );
- }
-
- /**
- * do_transaction should set redirect key when we get a valid response.
- */
- function testRedirectOnSuccess() {
- $init = $this->getDonorTestData( 'BR' );
- $gateway = $this->getFreshGatewayObject( $init );
-
- $gateway->do_transaction( 'NewInvoice' );
-
- // from the test response
- $expected =
'https://sandbox.astropaycard.com/go_to_bank?id=A5jvKfK1iHIRUTPXXt8lDFGaRRLzPgBg';
- $response = $gateway->getTransactionResponse();
- $this->assertEquals( $expected, $response->getRedirect(),
- 'do_transaction is not setting the right redirect' );
- }
-
- /**
- * do_transaction should set redirect key when we get a valid response.
- */
- function testDoPaymentSuccess() {
- $init = $this->getDonorTestData( 'BR' );
- $init['payment_method'] = 'cc';
- $gateway = $this->getFreshGatewayObject( $init );
-
- $result = $gateway->doPayment();
-
- // from the test response
- $expected =
'https://sandbox.astropaycard.com/go_to_bank?id=A5jvKfK1iHIRUTPXXt8lDFGaRRLzPgBg';
- $this->assertEquals( $expected, $result->getRedirect(),
- 'doPayment is not setting the right redirect' );
- }
-
- /**
- * When Astropay sends back valid JSON with status "1", we should set
- * error array to generic error and log a warning.
- */
- function testDoPaymentErrors() {
- $init = $this->getDonorTestData( 'BR' );
- $this->setLanguage( $init['language'] );
- $gateway = $this->getFreshGatewayObject( $init );
- $gateway->setDummyGatewayResponseCode( '1' );
-
- $result = $gateway->doPayment();
-
- $expectedMessage = wfMessage(
'donate_interface-processing-error')->inLanguage( $init['language'] )->text();
- $actual = $result->getErrors();
- $this->assertEquals( $expectedMessage,
$actual['internal-0000']['message'],
- 'Wrong error array in PaymentResult' );
-
- $logged = $this->getLogMatches( LogLevel::WARNING, '/This error
message should appear in the log./' );
- $this->assertNotEmpty( $logged );
- // TODO: Should this really be a refresh, or should we finalize
to failed here?
- $this->assertTrue( $result->getRefresh(), 'PaymentResult should
be a refresh' );
- }
-
- /**
- * Should set a validation error on amount
- */
- function testDoPaymentLimitExceeded() {
- $init = $this->getDonorTestData( 'BR' );
- $this->setLanguage( $init['language'] );
- $init['payment_method'] = 'cc';
- $gateway = $this->getFreshGatewayObject( $init );
- $gateway->setDummyGatewayResponseCode( 'limit_exceeded' );
-
- $result = $gateway->doPayment();
- $this->assertTrue( $result->getRefresh(), 'PaymentResult should
be a refresh' );
-
- $errors = $gateway->getTransactionResponse()->getErrors();
- $expectedMessage = wfMessage(
'donate_interface-error-msg-limit')->inLanguage( $init['language'] )->text();
- $this->assertEquals( $expectedMessage,
$errors['internal-0000']['message'] );
- $this->assertEquals( 'amount',
$errors['internal-0000']['context'] );
- }
-
- /**
- * Should set a validation error on fiscal_number
- */
- function testDoPaymentBadFiscalNumber() {
- $init = $this->getDonorTestData( 'BR' );
- $this->setLanguage( $init['language'] );
- $init['payment_method'] = 'cc';
- $gateway = $this->getFreshGatewayObject( $init );
- $gateway->setDummyGatewayResponseCode( 'fiscal_number' );
-
- $result = $gateway->doPayment();
- $this->assertTrue( $result->getRefresh(), 'PaymentResult should
be a refresh' );
-
- $errors = $gateway->getTransactionResponse()->getErrors();
- $expectedMessage = DataValidator::getErrorMessage(
'fiscal_number', 'calculated', $init['language'], $init['country'] );
- $this->assertEquals( $expectedMessage,
$errors['internal-0000']['message'] );
- $this->assertEquals( 'fiscal_number',
$errors['internal-0000']['context'] );
- }
-
- /**
- * Should finalize to failed
- */
- function testDoPaymentUserUnauthorized() {
- $init = $this->getDonorTestData( 'BR' );
- $this->setLanguage( $init['language'] );
- $init['payment_method'] = 'cc';
- $gateway = $this->getFreshGatewayObject( $init );
- $gateway->setDummyGatewayResponseCode( 'user_unauthorized' );
-
- $result = $gateway->doPayment();
- $this->assertTrue( $result->isFailed() );
- }
-
- /**
- * Should tell the user to try again
- */
- function testDoPaymentCouldNotRegister() {
- $init = $this->getDonorTestData( 'BR' );
- $this->setLanguage( $init['language'] );
- $init['payment_method'] = 'cc';
- $gateway = $this->getFreshGatewayObject( $init );
- $gateway->setDummyGatewayResponseCode( 'could_not_register' );
-
- $result = $gateway->doPayment();
- $this->assertTrue( $result->getRefresh(), 'PaymentResult should
be a refresh' );
-
- $errors = $gateway->getTransactionResponse()->getErrors();
- $expectedMessage = wfMessage(
'donate_interface-try-again')->inLanguage( $init['language'] )->text();
- $this->assertEquals( $expectedMessage,
$errors['internal-0000']['message'] );
- }
-
- /**
- * Should tell the user to try again
- */
- function testDoPaymentCouldNotMakeDeposit() {
- $init = $this->getDonorTestData( 'BR' );
- $this->setLanguage( $init['language'] );
- $init['payment_method'] = 'cc';
- $gateway = $this->getFreshGatewayObject( $init );
- $gateway->setDummyGatewayResponseCode( 'could_not_make_deposit'
);
-
- $result = $gateway->doPayment();
- $this->assertTrue( $result->getRefresh(), 'PaymentResult should
be a refresh' );
-
- $errors = $gateway->getTransactionResponse()->getErrors();
- $expectedMessage = wfMessage(
'donate_interface-try-again')->inLanguage( $init['language'] )->text();
- $this->assertEquals( $expectedMessage,
$errors['internal-0000']['message'] );
- }
-
- /**
- * PaymentStatus transaction should interpret the delimited response
- */
- function testPaymentStatus() {
- $init = $this->getDonorTestData( 'BR' );
- $session['Donor']['order_id'] = '123456789';
- $this->setUpRequest( $init, $session );
- $gateway = new TestingAstropayAdapter();
-
- $gateway->do_transaction( 'PaymentStatus' );
-
- // from the test response
- $expected = array(
- 'result' => '9',
- 'x_amount' => '100.00',
- 'x_iduser' => '08feb2d12771bbcfeb86',
- 'x_invoice' => '123456789',
- 'PT' => '1',
- 'x_control' =>
'0656B92DF44B814D48D84FED2F444CCA1E991A24A365FBEECCCA15B73CC08C2A',
- 'x_document' => '987654321',
- 'x_bank' => 'TE',
- 'x_payment_type' => '03',
- 'x_bank_name' => 'GNB',
- 'x_currency' => 'BRL',
- );
- $results = $gateway->getTransactionData();
- $this->assertEquals( $expected, $results,
- 'PaymentStatus response not interpreted correctly' );
- // Should not throw exception
- $gateway->verifyStatusSignature( $results );
- }
-
- /**
- * Invalid signature should be recognized as such.
- */
- function testInvalidSignature() {
- $init = $this->getDonorTestData( 'BR' );
- $session['Donor']['order_id'] = '123456789';
- $this->setUpRequest( $init, $session );
- $gateway = new TestingAstropayAdapter();
-
- $gateway->setDummyGatewayResponseCode( 'badsig' );
- $gateway->do_transaction( 'PaymentStatus' );
-
- $results = $gateway->getTransactionData();
- $this->setExpectedException( 'ResponseProcessingException' );
- $gateway->verifyStatusSignature( $results );
- }
-
- /**
- * If status is paid and signature is correct, processResponse should
not
- * throw exception and final status should be 'completed'
- */
- function testSuccessfulReturn() {
- $init = $this->getDonorTestData( 'BR' );
- $session['Donor']['order_id'] = '123456789';
- $this->setUpRequest( $init, $session );
- $gateway = new TestingAstropayAdapter();
-
- // Next lines mimic Astropay resultswitcher
- $gateway->setCurrentTransaction( 'ProcessReturn' );
- $response = array(
- 'result' => '9',
- 'x_amount' => '100.00',
- 'x_amount_usd' => '42.05',
- 'x_control' =>
'DDF89085AC70C0B0628150C51D64419D8592769F2439E3936570E26D24881730',
- 'x_description' => 'Donation to the Wikimedia
Foundation',
- 'x_document' => '32869',
- 'x_iduser' => '08feb2d12771bbcfeb86',
- 'x_invoice' => '123456789',
- );
-
- $gateway->processResponse( $response );
- $status = $gateway->getFinalStatus();
- $this->assertEquals( FinalStatus::COMPLETE, $status );
- }
-
- /**
- * Make sure we record the actual amount charged, even if the donor has
- * opened a new window and screwed up their session data.
- */
- function testReturnUpdatesAmount() {
- $init = $this->getDonorTestData( 'BR' );
- $init['amount'] = '22.55'; // junk session data from another
banner click
- $session['Donor']['order_id'] = '123456789';
- $this->setUpRequest( $init, $session );
- $gateway = new TestingAstropayAdapter();
-
- $amount = $gateway->getData_Unstaged_Escaped( 'amount' );
- $this->assertEquals( '22.55', $amount );
-
- // Next lines mimic Astropay resultswitcher
- $gateway->setCurrentTransaction( 'ProcessReturn' );
- $response = array(
- 'result' => '9',
- 'x_amount' => '100.00',
- 'x_amount_usd' => '42.05',
- 'x_control' =>
'DDF89085AC70C0B0628150C51D64419D8592769F2439E3936570E26D24881730',
- 'x_description' => 'Donation to the Wikimedia
Foundation',
- 'x_document' => '32869',
- 'x_iduser' => '08feb2d12771bbcfeb86',
- 'x_invoice' => '123456789',
- );
-
- $gateway->processResponse( $response );
- $amount = $gateway->getData_Unstaged_Escaped( 'amount' );
- $this->assertEquals( '100.00', $amount, 'Not recording correct
amount' );
- }
-
- /**
- * If payment is rejected, final status should be 'failed'
- */
- function testRejectedReturn() {
- $init = $this->getDonorTestData( 'BR' );
- $session['Donor']['order_id'] = '123456789';
- $this->setUpRequest( $init, $session );
- $gateway = new TestingAstropayAdapter();
-
- $gateway->setCurrentTransaction( 'ProcessReturn' );
- $response = array(
- 'result' => '8', // rejected by bank
- 'x_amount' => '100.00',
- 'x_amount_usd' => '42.05',
- 'x_control' =>
'706F57BC3E74906B14B1DEB946F027104513797CC62AC0F5107BC98F42D5DC95',
- 'x_description' => 'Donation to the Wikimedia
Foundation',
- 'x_document' => '32869',
- 'x_iduser' => '08feb2d12771bbcfeb86',
- 'x_invoice' => '123456789',
- );
-
- $gateway->processResponse( $response );
- $status = $gateway->getFinalStatus();
- $this->assertEquals( FinalStatus::FAILED, $status );
- }
-
- function testStageBankCode() {
- $init = $this->getDonorTestData( 'BR' );
- $init['payment_method'] = 'cc';
- $init['payment_submethod'] = 'elo';
- $gateway = $this->getFreshGatewayObject( $init );
-
- $gateway->doPayment();
-
- $exposed = TestingAccessWrapper::newFromObject( $gateway );
- $bank_code = $exposed->getData_Staged( 'bank_code' );
- $this->assertEquals( 'EL', $bank_code, 'Not setting bank_code
in doPayment' );
- }
-
- /**
- * Test that we run the AntiFraud hooks before redirecting
- */
- function testAntiFraudHooks() {
- DonationInterface_FraudFiltersTest::setupFraudMaps();
- $init = $this->getDonorTestData( 'BR' );
- $init['payment_method'] = 'cc';
- $init['bank_code'] = 'VD';
- // following data should trip fraud alarms
- $init['utm_medium'] = 'somethingmedia';
- $init['utm_source'] = 'somethingmedia';
- $init['email'] = '[email protected]';
-
- $gateway = $this->getFreshGatewayObject( $init );
-
- $result = $gateway->doPayment();
-
- $this->assertTrue( $result->isFailed(), 'Result should be
failure if fraud filters say challenge' );
- $this->assertEquals( 'challenge',
$gateway->getValidationAction(), 'Validation action is not as expected' );
- $exposed = TestingAccessWrapper::newFromObject( $gateway );
- $this->assertEquals( 60, $exposed->risk_score, 'RiskScore is
not as expected' );
- }
-
- /**
- * Before redirecting a user to the processor, we should log all of
their
- * details at info level
- */
- function testLogDetails() {
- $init = $this->getDonorTestData( 'BR' );
- $init['payment_method'] = 'cc';
- $session['Donor']['order_id'] = '123456789';
- $this->setUpRequest( $init, $session );
- $gateway = new TestingAstropayAdapter();
-
- $gateway->doPayment();
- $logged = $this->getLogMatches( LogLevel::INFO, '/^Redirecting
for transaction: /' );
- $this->assertEquals( 1, count( $logged ), 'Should have logged
details once' );
- preg_match( '/Redirecting for transaction: (.*)$/', $logged[0],
$matches );
- $detailString = $matches[1];
- $expected = array(
- 'referrer' => 'www.yourmom.com',
- 'currency_code' => 'BRL',
- 'payment_submethod' => 'test_bank',
- 'fname' => 'Nome',
- 'lname' => 'Apelido',
- 'amount' => '100.00',
- 'language' => 'pt',
- 'email' => '[email protected]',
- 'country' => 'BR',
- 'payment_method' => 'cc',
- 'user_ip' => '127.0.0.1',
- 'recurring' => '',
- 'utm_source' => '..cc',
- 'gateway' => 'astropay',
- 'gateway_account' => 'test',
- 'gateway_txn_id' => false,
- 'response' => false,
- 'correlation-id' => 'astropay-123456789',
- 'php-message-class' =>
'SmashPig\CrmLink\Messages\DonationInterfaceMessage',
- );
- $actual = json_decode( $detailString, true );
- // TODO: when tests use PHPUnit 4.4
- // $this->assertArraySubset( $expected, $actual, false, 'Logged
the wrong stuff' );
- unset( $actual['contribution_tracking_id'] );
- unset( $actual['date'] );
- $this->assertEquals( $expected, $actual, 'Logged the wrong
stuff!' );
- }
-
- function testStageFiscalNumber() {
- $init = $this->getDonorTestData( 'BR' );
- $init['fiscal_number'] = '000.034.567-89';
- $gateway = $this->getFreshGatewayObject( $init );
-
- $gateway->doPayment();
-
- $exposed = TestingAccessWrapper::newFromObject( $gateway );
- $staged = $exposed->getData_Staged( 'fiscal_number' );
- $this->assertEquals( '00003456789', $staged, 'Not stripping
fiscal_number punctuation in doPayment' );
- }
-
- /**
- * We should increment the order ID with each NewInvoice call
- */
- function testNewInvoiceOrderId() {
- $init = $this->getDonorTestData( 'BR' );
- $firstRequest = $this->setUpRequest( $init );
- $firstAttempt = new TestingAstropayAdapter();
- $firstAttempt->setDummyGatewayResponseCode( '1' );
-
- $firstAttempt->doPayment();
-
- $this->setUpRequest( $init, $firstRequest->getSessionArray() );
- $secondAttempt = new TestingAstropayAdapter();
- $secondAttempt->doPayment();
-
- parse_str( $firstAttempt->curled[0], $firstParams );
- parse_str( $secondAttempt->curled[0], $secondParams );
-
- $this->assertNotEquals( $firstParams['x_invoice'],
$secondParams['x_invoice'],
- 'Not generating new order id for NewInvoice call'
- );
- }
-
- /**
- * We should increment the order ID with each NewInvoice call, even when
- * retrying inside a single doPayment call
- */
- function testNewInvoiceOrderIdRetry() {
- $init = $this->getDonorTestData( 'BR' );
- $gateway = $this->getFreshGatewayObject( $init );
- $gateway->setDummyGatewayResponseCode( 'collision' );
-
- $gateway->doPayment();
-
- parse_str( $gateway->curled[0], $firstParams );
- parse_str( $gateway->curled[1], $secondParams );
-
- $this->assertNotEquals( $firstParams['x_invoice'],
$secondParams['x_invoice'],
- 'Not generating new order id for retried NewInvoice
call'
- );
- }
-
- /**
- * We should show an error for incompatible country / currency
combinations
- */
- function testBadCurrencyForCountry() {
- $init = $this->getDonorTestData( 'BR' );
- $init['currency_code'] = 'CLP';
- $gateway = $this->getFreshGatewayObject( $init );
-
- $errors = $gateway->getValidationErrors();
-
- $this->assertNotEmpty( $errors );
- $this->assertTrue(
- isset( $errors['currency_code'] ),
- 'Should show a currency code error for trying to use
CLP in BR'
- );
- }
-
- function testDummyFiscalNumber() {
- $init = $this->getDonorTestData( 'MX' );
- $gateway = $this->getFreshGatewayObject( $init );
- $gateway->doPayment();
-
- parse_str( $gateway->curled[0], $firstParams );
- $fiscalNumber = $firstParams['x_cpf'];
- $this->assertEquals(
- 13, strlen( $fiscalNumber ),
- 'Fake fiscal number should be 13 digits'
- );
- }
-}
->>>>>>> BRANCH (add52c Actually random dummy fiscal number for MX)
diff --git a/tests/DonationInterfaceTestCase.php
b/tests/DonationInterfaceTestCase.php
deleted file mode 100644
index 35d66d8..0000000
--- a/tests/DonationInterfaceTestCase.php
+++ /dev/null
@@ -1,700 +0,0 @@
-<<<<<<< HEAD (27e1fd Merge master into deployment)
-=======
-<?php
-/**
- * Wikimedia Foundation
- *
- * LICENSE
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-use Psr\Log\LogLevel;
-
-/**
- * @group Fundraising
- * @group QueueHandling
- * @group ClassMethod
- * @group ListenerAdapter
- *
- * @category UnitTesting
- * @package Fundraising_QueueHandling
- */
-abstract class DonationInterfaceTestCase extends MediaWikiTestCase {
- protected $backupGlobalsBlacklist = array(
- 'wgHooks',
- );
-
- /**
- * An array of the vars we expect to be set before people hit payments.
- * @var array
- */
- public static $initial_vars = array (
- 'ffname' => 'testytest',
- 'referrer' => 'www.yourmom.com', //please don't go there.
- 'currency_code' => 'USD',
- );
-
- /**
- * This will be set by a test method with the adapter object.
- *
- * @var GatewayAdapter $gatewayAdapter
- */
- protected $gatewayAdapter;
-
- /**
- * @var TestingDonationLogger
- */
- protected $testLogger;
-
- /**
- * @param $name string The name of the test case
- * @param $data array Any parameters read from a dataProvider
- * @param $dataName string|int The name or index of the data set
- */
- public function __construct( $name = null, array $data = array(),
$dataName = '' ) {
-
- //Just in case you got here without running the configuration...
- global $wgDonationInterfaceTestMode;
- $wgDonationInterfaceTestMode = true;
-
- $adapterclass = TESTS_ADAPTER_DEFAULT;
- $this->testAdapterClass = $adapterclass;
-
- parent::__construct( $name, $data, $dataName );
- }
-
- protected function setUp() {
- $this->testLogger = new TestingDonationLogger();
- DonationLoggerFactory::$overrideLogger = $this->testLogger;
- parent::setUp();
- }
-
- protected function tearDown() {
- $this->resetAllEnv();
- DonationLoggerFactory::$overrideLogger = null;
- parent::tearDown();
- }
-
- /**
- * Set up a fake request with the given data. Returns the fake request.
- * @param array $data
- * @param array $session
- * @return FauxRequest
- */
- protected function setUpRequest( $data, $session = null ) {
- RequestContext::resetMain();
- $request = new FauxRequest( $data, false, $session );
- RequestContext::getMain()->setRequest( $request );
- return $request;
- }
-
- /**
- * Set global language for the duration of the test
- *
- * @param string $language language code to force
- */
- protected function setLanguage( $language ) {
- RequestContext::getMain()->setLanguage( $language );
- // BackCompat
- $this->setMwGlobals( 'wgLang',
RequestContext::getMain()->getLanguage() );
- }
-
- /**
- * buildRequestXmlForGlobalCollect
- *
- * @todo
- * - there are many cases to this that need to be developed.
- * - Do not consider this a complete test!
- *
- * @covers GatewayAdapter::__construct
- * @covers GatewayAdapter::setCurrentTransaction
- * @covers GatewayAdapter::buildRequestXML
- */
- public function buildRequestXmlForGlobalCollect( $optionsForTestData,
$options ) {
-
- global $wgDonationInterfaceTest;
-
- $wgDonationInterfaceTest = true;
-
- $this->setUpRequest( $options );
- $this->gatewayAdapter = new TestingGlobalCollectAdapter();
-
-
$this->gatewayAdapter->setCurrentTransaction('INSERT_ORDERWITHPAYMENT');
-
- $exposed = TestingAccessWrapper::newFromObject(
$this->gatewayAdapter );
- $request = trim( $exposed->buildRequestXML() );
-
- $this->setUpRequest( $options );
- $expected = $this->getExpectedXmlRequestForGlobalCollect(
$optionsForTestData, $options );
-
- $this->assertEquals( $expected, $request, 'The constructed XML
for payment_method [' . $optionsForTestData['payment_method'] . '] and
payment_submethod [' . $optionsForTestData['payment_submethod'] . '] does not
match our expected request.' );
- }
-
- /**
- *
- * @param string $country The country we want the test user to be from.
- * @return array Donor data to use
- * @throws OutOfBoundsException when there is no data available for the
requested country
- */
- public static function getDonorTestData( $country = '' ) {
- $donortestdata = array (
- 'US' => array ( //default
- 'city' => 'San Francisco',
- 'state' => 'CA',
- 'zip' => '94105',
- 'currency_code' => 'USD',
- 'street' => '123 Fake Street',
- 'fname' => 'Firstname',
- 'lname' => 'Surname',
- 'amount' => '1.55',
- 'language' => 'en',
- 'email' => '[email protected]',
- ),
- 'ES' => array (
- 'city' => 'Barcelona',
- 'state' => 'XX',
- 'zip' => '0',
- 'currency_code' => 'EUR',
- 'street' => '123 Calle Fake',
- 'fname' => 'Nombre',
- 'lname' => 'Apellido',
- 'amount' => '1.55',
- 'language' => 'es',
- ),
- 'Catalonia' => array (
- 'city' => 'Barcelona',
- 'state' => 'XX',
- 'zip' => '0',
- 'currency_code' => 'EUR',
- 'street' => '123 Calle Fake',
- 'fname' => 'Nombre',
- 'lname' => 'Apellido',
- 'amount' => '1.55',
- 'language' => 'ca',
- ),
- 'NO' => array (
- 'city' => 'Oslo',
- 'state' => 'XX',
- 'zip' => '0',
- 'currency_code' => 'EUR',
- 'street' => '123 Fake Gate',
- 'fname' => 'Fornavn',
- 'lname' => 'Etternavn',
- 'amount' => '1.55',
- 'language' => 'no',
- ),
- 'FR' => array (
- 'city' => 'Versailles',
- 'state' => 'XX',
- 'zip' => '0',
- 'currency_code' => 'EUR',
- 'street' => '123 Rue Faux',
- 'fname' => 'Prénom',
- 'lname' => 'Nom',
- 'amount' => '1.55',
- 'language' => 'fr',
- ),
- // Fiji is configured as a snowflake to test special
treatment for certain store IDs
- 'FJ' => array (
- 'city' => 'Suva',
- 'state' => 'XX',
- 'zip' => '0',
- 'currency_code' => 'EUR',
- 'street' => '123 Fake Street',
- 'fname' => 'FirstName',
- 'lname' => 'LastName',
- 'amount' => '1.55',
- 'language' => 'en',
- ),
- 'NL' => array (
- 'city' => 'Amsterdam',
- 'state' => 'XX',
- 'zip' => '0',
- 'currency_code' => 'EUR',
- 'street' => '123 nep straat',
- 'fname' => 'Voornaam',
- 'lname' => 'Achternaam',
- 'amount' => '1.55',
- 'language' => 'nl',
- ),
- 'BE' => array (
- 'city' => 'Antwerp',
- 'state' => 'XX',
- 'zip' => '0',
- 'currency_code' => 'EUR',
- 'street' => '123 nep straat',
- 'fname' => 'Voornaam',
- 'lname' => 'Achternaam',
- 'amount' => '1.55',
- 'language' => 'nl',
- ),
- 'IT' => array (
- 'city' => 'Torino',
- 'state' => 'TO',
- 'zip' => '10123',
- 'currency_code' => 'EUR',
- 'street' => 'Via Falso 123',
- 'fname' => 'Nome',
- 'lname' => 'Cognome',
- 'amount' => '1.55',
- 'language' => 'it',
- ),
- 'CA' => array (
- 'city' => 'Saskatoon',
- 'state' => 'SK',
- 'zip' => 'S7K 0J5',
- 'currency_code' => 'CAD',
- 'street' => '123 Fake Street',
- 'fname' => 'Firstname',
- 'lname' => 'Surname',
- 'amount' => '1.55',
- 'language' => 'en',
- ),
- 'BR' => array (
- 'currency_code' => 'BRL',
- 'fiscal_number' => '00003456789',
- 'payment_submethod' => 'test_bank',
- 'fname' => 'Nome',
- 'lname' => 'Apelido',
- 'amount' => '100',
- 'language' => 'pt',
- 'email' => '[email protected]'
- ),
- 'MX' => array (
- 'city' => 'Tuxtla Gutiérrez',
- 'state' => 'CHP',
- 'currency_code' => 'MXN',
- 'street' => 'Calle Falso 123',
- 'fname' => 'Nombre',
- 'lname' => 'Apellido',
- 'email' => '[email protected]',
- 'amount' => '155',
- 'language' => 'es',
- ),
- );
- //default to US
- if ( $country === '' ) {
- $country = 'US';
- }
-
- if ( array_key_exists( $country, $donortestdata ) ) {
- $donortestdata = array_merge( self::$initial_vars,
$donortestdata[$country] );
- $donortestdata['country'] = $country;
- return $donortestdata;
- }
- throw new OutOfBoundsException( __FUNCTION__ . ": No donor data
for country '$country'" );
- }
-
- /**
- * Supported languages for Belgium
- */
- public function belgiumLanguageProvider() {
- return array(
- array( 'nl' ),
- array( 'de' ),
- array( 'fr' ),
- );
- }
-
- /**
- * Supported languages for Canada
- */
- public function canadaLanguageProvider() {
- return array(
- array( 'en' ),
- array( 'fr' ),
- );
- }
-
- /**
- * Transaction codes for GC and GC orphan adapters not to be retried
- * on pain of $1000+ fines by MasterCard
- */
- public function mcNoRetryCodeProvider() {
- return array(
- array( '430260' ),
- array( '430306' ),
- array( '430330' ),
- array( '430354' ),
- array( '430357' ),
- );
- }
-
- public function benignNoRetryCodeProvider() {
- return array(
- array( '430285' ),
- );
- }
-
- /**
- * Get the expected XML request from GlobalCollect
- *
- * @param $optionsForTestData
- * @param array $options
- * @return string The expected XML request
- */
- public function getExpectedXmlRequestForGlobalCollect(
$optionsForTestData, $options = array() ) {
- global $wgDonationInterfaceThankYouPage;
- $request = RequestContext::getMain()->getRequest();
-
- $orderId = $this->gatewayAdapter->getData_Unstaged_Escaped(
'order_id' );
- $exposed = TestingAccessWrapper::newFromObject(
$this->gatewayAdapter );
- $merchantref = $exposed->getData_Staged(
'contribution_tracking_id' );
- //@TODO: WHY IN THE NAME OF ZARQUON are we building XML in a
STRING format here?!?!?!!!1one1!?. Great galloping galumphing giraffes.
- $expected = '<?xml version="1.0" encoding="UTF-8"?' . ">\n";
- $expected .= '<XML>';
- $expected .= '<REQUEST>';
- $expected .=
'<ACTION>INSERT_ORDERWITHPAYMENT</ACTION>';
- $expected .= '<META><MERCHANTID>' .
$exposed->account_config[ 'MerchantID' ] . '</MERCHANTID>';
-
- if ( isset( $request ) ) {
- $expected .= '<IPADDRESS>' .
$request->getIP() . '</IPADDRESS>';
- }
-
- $expected .= '<VERSION>1.0</VERSION>';
- $expected .= '</META>';
- $expected .= '<PARAMS>';
- $expected .= '<ORDER>';
- $expected .= '<ORDERID>' . $orderId
. '</ORDERID>';
- $expected .= '<AMOUNT>' .
$options['amount'] * 100 . '</AMOUNT>';
- $expected .= '<CURRENCYCODE>' .
$options['currency_code'] . '</CURRENCYCODE>';
- $expected .= '<LANGUAGECODE>' .
$options['language'] . '</LANGUAGECODE>';
- $expected .= '<COUNTRYCODE>' .
$options['country'] . '</COUNTRYCODE>';
- $expected .= '<MERCHANTREFERENCE>' . $merchantref .
'</MERCHANTREFERENCE>';
-
- if ( isset( $request ) ) {
- $expected .= '<IPADDRESSCUSTOMER>' .
$request->getIP() . '</IPADDRESSCUSTOMER>';
- }
-
- $expected .= '<EMAIL>' . TESTS_EMAIL
. '</EMAIL>';
- $expected .= '</ORDER>';
- $expected .= '<PAYMENT>';
- $expected .= '<PAYMENTPRODUCTID>' .
$optionsForTestData['payment_product_id'] . '</PAYMENTPRODUCTID>';
- $expected .= '<AMOUNT>' .
$options['amount'] * 100 . '</AMOUNT>';
- $expected .= '<CURRENCYCODE>' .
$options['currency_code'] . '</CURRENCYCODE>';
- $expected .= '<LANGUAGECODE>' .
$options['language'] . '</LANGUAGECODE>';
- $expected .= '<COUNTRYCODE>' .
$options['country'] . '</COUNTRYCODE>';
- $expected .=
'<HOSTEDINDICATOR>1</HOSTEDINDICATOR>';
- $expected .=
"<RETURNURL>{$wgDonationInterfaceThankYouPage}/{$options['language']}?country={$options['country']}</RETURNURL>";
- $expected .=
'<AUTHENTICATIONINDICATOR>0</AUTHENTICATIONINDICATOR>';
- $expected .= '<FIRSTNAME>' .
$options['fname'] . '</FIRSTNAME>';
- $expected .= '<SURNAME>' .
$options['lname'] . '</SURNAME>';
- $expected .= '<STREET>' .
$options['street'] . '</STREET>';
- $expected .= '<CITY>' .
$options['city'] . '</CITY>';
- $expected .= '<STATE>' .
$options['state'] . '</STATE>';
- $expected .= '<ZIP>' .
$options['zip'] . '</ZIP>';
- $expected .= '<EMAIL>' . TESTS_EMAIL . '</EMAIL>';
-
- // Set the issuer id if it is passed.
- if ( isset( $optionsForTestData['descriptor'] ) ) {
- $expected .= '<DESCRIPTOR>' .
$optionsForTestData['descriptor'] . '</DESCRIPTOR>';
- }
-
- // Set the issuer id if it is passed.
- if ( isset( $optionsForTestData['issuer_id'] ) ) {
- $expected .= '<ISSUERID>' .
$optionsForTestData['issuer_id'] . '</ISSUERID>';
- }
-
-
- // If we're doing Direct Debit...
- //@TODO: go ahead and split this out into a "Get the direct
debit I_OWP XML block function" the second this gets even slightly annoying.
- if ( $optionsForTestData['payment_method'] === 'dd' ) {
- $expected .= '<ACCOUNTNAME>' .
$optionsForTestData['account_name'] . '</ACCOUNTNAME>';
- $expected .= '<ACCOUNTNUMBER>' .
$optionsForTestData['account_number'] . '</ACCOUNTNUMBER>';
- $expected .= '<BANKCODE>' .
$optionsForTestData['bank_code'] . '</BANKCODE>';
- $expected .= '<BRANCHCODE>' .
$optionsForTestData['branch_code'] . '</BRANCHCODE>';
- $expected .= '<BANKCHECKDIGIT>' .
$optionsForTestData['bank_check_digit'] . '</BANKCHECKDIGIT>';
- $expected .= '<DATECOLLECT>' . gmdate( 'Ymd' ) .
'</DATECOLLECT>'; //is this cheating? Probably.
- $expected .= '<DIRECTDEBITTEXT>' .
$optionsForTestData['direct_debit_text'] . '</DIRECTDEBITTEXT>';
- }
-
- $expected .= '</PAYMENT>';
- $expected .= '</PARAMS>';
- $expected .= '</REQUEST>';
- $expected .= '</XML>';
-
- return $expected;
-
- }
-
- /**
- * Get a fresh gateway object of the type specified in the variable
- * $this->testAdapterClass.
- * @param array $external_data If you want to shoehorn in some external
- * data, do that here.
- * @param array $setup_hacks An array of things that override stuff in
- * the constructor of the gateway object that I can't get to without
- * refactoring the whole thing. @TODO: Refactor the gateway adapter
- * constructor.
- * @return GatewayAdapter The new relevant gateway adapter object.
- */
- function getFreshGatewayObject( $external_data = null, $setup_hacks =
array() ) {
- $p1 = null;
- if ( !is_null( $external_data ) ) {
- $p1 = array (
- 'external_data' => $external_data,
- );
- }
-
- if ( $setup_hacks ) {
- if ( !is_null( $p1 ) ) {
- $p1 = array_merge( $p1, $setup_hacks );
- } else {
- $p1 = $setup_hacks;
- }
- }
-
- $class = $this->testAdapterClass;
- $gateway = new $class( $p1 );
-
- // FIXME: Find a more elegant way to hackity hacken hack.
- // We want to override any define- functions with hacky values.
- foreach ( $setup_hacks as $field => $value ) {
- $gateway->$field = $value;
- }
-
- return $gateway;
- }
-
- function resetAllEnv() {
- $_SESSION = array ( );
- $_GET = array ( );
- $_POST = array ( );
-
- $_SERVER = array ( );
- $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
- $_SERVER['HTTP_HOST'] = TESTS_HOSTNAME;
- $_SERVER['SERVER_NAME'] = TESTS_HOSTNAME;
- $_SERVER['SCRIPT_NAME'] = __FILE__;
-
- RequestContext::resetMain();
- // The following is only needed until 1.27, as the above reset
only
- // sets the request back to $wgRequest
- $request = RequestContext::getMain()->getRequest();
- if ( $request instanceof FauxRequest ) {
- $session = $request->getSessionArray();
- if ( is_array( $session ) ) {
- foreach( $session as $key => $value ) {
- $request->setSessionData( $key, null );
- }
- }
- }
-
- // Wipe out the $instance of these classes to make sure they're
- // re-created with fresh gateway instances for the next test
- $singleton_classes = array(
- 'Gateway_Extras_ConversionLog',
- 'Gateway_Extras_CustomFilters',
- 'Gateway_Extras_CustomFilters_Functions',
- 'Gateway_Extras_CustomFilters_IP_Velocity',
- 'Gateway_Extras_CustomFilters_MinFraud',
- 'Gateway_Extras_CustomFilters_Referrer',
- 'Gateway_Extras_CustomFilters_Source',
- 'Gateway_Extras_SessionVelocityFilter',
- );
- foreach( $singleton_classes as $singleton_class ) {
- $singleton_class::$instance = null;
- }
- }
-
- /**
- * Instantiates the $special_page_class with supplied $initial_vars,
- * yoinks the html output from the output buffer, loads that into a
- * DomDocument and performs asserts on the results per the checks
- * supplied in $perform_these_checks.
- * Optional: Asserts that the gateway has logged nothing at ERROR level.
- *
- * @param class $special_page_class A testing descendant of GatewayPage
- * @param array $initial_vars Array that will be loaded straight into a
- * test version of the http request.
- * @param array $perform_these_checks Array of checks to perform in the
- * following format:
- *
$perform_these_checks[$element_id][$check_to_perform][$expected_result]
- * So far, $check_to_perform can be either 'nodename' or 'innerhtml'
- * @param boolean $fail_on_log_errors When true, this will fail the
- * current test if there are entries in the gateway's error log.
- * @param array $session pre-existing session data.
- */
- function verifyFormOutput( $special_page_class, $initial_vars,
$perform_these_checks, $fail_on_log_errors = false, $session = null ) {
- // Nasty hack to clear output from any previous tests.
- $mainContext = RequestContext::getMain();
- $newOutput = new OutputPage( $mainContext );
- $newRequest = new TestingRequest( $initial_vars, false,
$session );
- $newTitle = Title::newFromText( 'nonsense is apparently fine' );
- $mainContext->setRequest( $newRequest );
- $mainContext->setOutput( $newOutput );
- $mainContext->setTitle( $newTitle );
-
- $globals = array (
- 'wgTitle' => $newTitle,
- 'wgOut' => $newOutput,
- );
-
- $this->setMwGlobals( $globals );
-
- $this->setLanguage( $initial_vars['language'] );
-
- ob_start();
- $formpage = new $special_page_class();
- $formpage->execute( NULL );
- $formpage->getOutput()->output();
- $form_html = ob_get_contents();
- ob_end_clean();
-
- // In the event that something goes crazy, uncomment the next
line for much easier local debugging
- // file_put_contents( '/tmp/xmlout.txt', $form_html );
-
- if ( $fail_on_log_errors ) {
- $this->verifyNoLogErrors();
- }
-
- $dom_thingy = new DomDocument();
- //// DEBUGGING, foo
- // if (property_exists($this, 'FOO')) {
- //
error_log(var_export($formpage->getRequest()->response()->getheader('Location'),
true));
- // error_log(var_export($form_html, true));
- // }
-
- if ( $form_html ) {
- // p.s. i'm SERIOUS about the character encoding.
- $dom_thingy->loadHTML( '<?xml encoding="UTF-8">' .
$form_html );
- $dom_thingy->encoding = 'UTF-8';
- }
-
- foreach ( $perform_these_checks as $id => $checks ) {
- if ( $id == 'headers' ) {
- foreach ( $checks as $name => $expected ) {
- $actual =
$formpage->getRequest()->response()->getheader( $name );
- $this->performCheck( $actual,
$expected, "header '$name'");
- break;
- }
- continue;
- }
- unset( $perform_these_checks['headers'] );
-
- $input_node = $dom_thingy->getElementById( $id );
- $this->assertNotNull( $input_node, "Couldn't find the
'$id' element" );
- foreach ( $checks as $name => $expected ) {
- switch ( $name ) {
- case 'nodename':
- $this->performCheck(
$input_node->nodeName, $expected, "name of node with id '$id'");
- break;
- case 'innerhtml':
- $actual_html =
self::getInnerHTML( $input_node );
- // Strip comments
- $actual_html = preg_replace(
'/<!--[^>]*-->/', '', $actual_html );
- $this->performCheck(
$actual_html, $expected, "innerHTML of node '$id'");
- break;
- case 'innerhtmlmatches':
- $this->assertEquals( 1,
preg_match( $expected, self::getInnerHTML( $input_node ) ), "Value of the node
with id '$id' does not match pattern '$expected'. It has value " .
self::getInnerHTML( $input_node ) );
- break;
- case 'value':
- $this->performCheck(
$input_node->getAttribute('value'), $expected, "value of node with id '$id'");
- break;
- case 'selected':
- $selected = null;
- if ( $input_node->nodeName ===
'select' ) {
- $options =
$input_node->getElementsByTagName( 'option' );
- foreach ( $options as
$option ) {
- if (
$option->hasAttribute( 'selected' ) ) {
-
$selected = $option->getAttribute( 'value' );
- break;
- }
- }
- $this->performCheck(
$selected, $expected, "selected option value of node with id '$id'");
- } else {
- $this->fail( "Attempted
to test for selected value on non-select node, id '$id'" );
- }
- break;
- }
- }
- }
-
- // Are there untranslated boogers?
- if ( preg_match_all( '/<[^<]+(>|>)/', $form_html,
$matches ) ) {
- $this->fail( 'Untranslated messages present: ' .
implode( ', ', $matches[0] ) );
- }
- }
-
- /**
- * Performs some sort of assertion on a value.
- *
- * @param string $value the value to test
- * @param string|callable $check
- * if $check is callable, it is called with argument $value
- * otherwise, $value is asserted to be equal to $check
- * @param string $label identifies the value in assertion failures
- * @return void
- */
- function performCheck( $value, $check, $label = 'Tested value' ) {
- if ( is_callable( $check ) ) {
- $check( $value );
- return;
- }
- $this->assertEquals( $check, $value, "Expected $label to be
$check, found $value instead.");
- }
- /**
- * Asserts that there are no log entries of LOG_ERR or worse.
- */
- function verifyNoLogErrors( ) {
- $log = $this->testLogger->messages;
-
- $this->assertTrue( is_array( $log ), "Missing the test log" );
-
- //for our purposes, an "error" is LOG_ERR or less.
- $checklogs = array (
- LogLevel::ERROR => "Oops: We've got LOG_ERRors.",
- LogLevel::CRITICAL => "Critical errors!",
- LogLevel::ALERT => "Log Alerts!",
- LogLevel::EMERGENCY => "Logs says the servers are
actually on fire.",
- );
-
- $message = false;
- foreach ( $checklogs as $level => $levelmessage ) {
- if ( array_key_exists( $level, $log ) ) {
- $message = $levelmessage . ' ' . print_r(
$log[$level], true ) . "\n";
- }
- }
-
- $this->assertFalse( $message, $message ); //ha
- }
-
- /**
- * Finds a relevant line/lines in a gateway's log array
- * @param string $log_level One of the constants in \Psr\Log\LogLevel
- * @param string $match A regex to match against the log lines.
- * @return array All log lines that match $match.
- */
- public function getLogMatches( $log_level, $match ) {
- $log = $this->testLogger->messages;
- if ( !array_key_exists( $log_level, $log ) ) {
- return false;
- }
- $return = array ( );
- foreach ( $log[$log_level] as $line ) {
- if ( preg_match( $match, $line ) ) {
- $return[] = $line;
- }
- }
- return $return;
- }
-
- static function getInnerHTML( $node ) {
- $innerHTML = '';
- $children = $node->childNodes;
- foreach ( $children as $child ) {
- $innerHTML .= $child->ownerDocument->saveXML( $child );
- }
- return $innerHTML;
- }
-}
->>>>>>> BRANCH (add52c Actually random dummy fiscal number for MX)
--
To view, visit https://gerrit.wikimedia.org/r/281703
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie6d5e376be7888690d712fcf4015819b1bdb45f9
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/DonationInterface
Gerrit-Branch: deployment
Gerrit-Owner: Ejegg <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits