def test_currency(self): with self.assertRaisesRegex(ValueError, "Currency can only contain: CHF, EUR"): bill = QRBill( account="CH 53 8000 5000 0102 83664", currency="USD", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', 'country': 'CH', }, ) bill = QRBill( account="CH 53 8000 5000 0102 83664", currency="CHF", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', 'country': 'CH', }, ) self.assertEqual(bill.currency, "CHF") bill = QRBill( account="CH 53 8000 5000 0102 83664", currency="EUR", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', 'country': 'CH', }, ) self.assertEqual(bill.currency, "EUR")
def test_mandatory_fields(self): with self.assertRaisesRegex(ValueError, "The account parameter is mandatory"): QRBill() with self.assertRaisesRegex(ValueError, "Creditor information is mandatory"): QRBill(account="CH5380005000010283664")
def test_account(self): with self.assertRaisesRegex(ValueError, "Sorry, the IBAN is not valid"): bill = QRBill( account="CH53800050000102836", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', 'country': 'CH', }, ) with self.assertRaisesRegex(ValueError, "Sorry, the IBAN is not valid"): bill = QRBill( account="CH5380005000010288664", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', 'country': 'CH', }, ) with self.assertRaisesRegex(ValueError, "IBAN must start with: CH, LI"): bill = QRBill( account="DE 89 37040044 0532013000", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', 'country': 'CH', }, ) # Spaces are auto-stripped bill = QRBill( account="CH 53 8000 5000 0102 83664", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', 'country': 'CH', }, ) self.assertEqual(bill.account, "CH5380005000010283664")
def test_mandatory_fields(self): with self.assertRaisesRegex(ValueError, "The account parameter is mandatory"): QRBill() with self.assertRaisesRegex(ValueError, "Creditor information is mandatory"): QRBill(account="CH4431999123000889012")
def test_country(self): bill_data = { 'account': 'CH5380005000010283664', 'creditor': { 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', }, } # Switzerland - German/French/Italian/Romansh/English/code for country_name in ('Schweiz', 'Suisse', 'Svizzera', 'Svizra', 'Switzerland', 'CH'): bill_data['creditor']['country'] = country_name bill = QRBill(**bill_data) self.assertEqual(bill.creditor.country, 'CH') # Liechtenstein - short and long names/code for country_name in ('Liechtenstein', 'Fürstentum Liechtenstein', 'LI'): bill_data['creditor']['country'] = country_name bill = QRBill(**bill_data) self.assertEqual(bill.creditor.country, 'LI') with self.assertRaisesRegex(ValueError, "The country code 'XY' is not valid"): bill_data['creditor']['country'] = 'XY' bill = QRBill(**bill_data)
def test_minimal_data(self): bill = QRBill( account="CH 44 3199 9123 0008 89012", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', }, ) self.assertEqual( bill.qr_data(), 'SPC\r\n0100\r\n1\r\nCH4431999123000889012\r\nJane\r\n\r\n\r\n' '1000\r\nLausanne\r\nCH\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nCHF\r\n' '\r\n\r\n\r\n\r\n\r\n\r\n\r\nNON\r\n\r\n' )
def test_as_svg_filelike(self): bill = QRBill( account="CH 53 8000 5000 0102 83664", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', }, ) buff = StringIO() bill.as_svg(buff) self.assertEqual(buff.getvalue()[:40], '<?xml version="1.0" encoding="utf-8" ?>\n')
def test_full_page(self): bill = QRBill( account="CH 53 8000 5000 0102 83664", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', }, ) buff = StringIO() bill.as_svg(buff, full_page=True) file_head = buff.getvalue()[:250] self.assertIn('width="210mm"', file_head) self.assertIn('height="297mm"', file_head)
def test_reference(self): min_data = { 'account': "CH 53 8000 5000 0102 83664", 'creditor': { 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', }, } bill = QRBill(**min_data) self.assertEqual(bill.ref_type, 'NON') self.assertEqual(format_ref_number(bill), '') bill = QRBill(**min_data, ref_number='RF18539007547034') self.assertEqual(bill.ref_type, 'SCOR') self.assertEqual(format_ref_number(bill), 'RF18 5390 0754 7034') with self.assertRaisesRegex(ValueError, "The reference number is invalid"): bill = QRBill(**min_data, ref_number='RF19539007547034') with self.assertRaisesRegex( ValueError, "A QRR reference number is only allowed for a QR-IBAN"): bill = QRBill(**min_data, ref_number='18 78583') min_data = { 'account': "CH 44 3199 9123 0008 89012", 'creditor': { 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', }, } bill = QRBill(**min_data, ref_number='210000000003139471430009017') self.assertEqual(bill.ref_type, 'QRR') self.assertEqual(format_ref_number(bill), '21 00000 00003 13947 14300 09017') # check leading zeros bill = QRBill(**min_data, ref_number='18 78583') self.assertEqual(bill.ref_type, 'QRR') self.assertEqual(format_ref_number(bill), '00 00000 00000 00000 00018 78583') # invalid QRR with self.assertRaisesRegex(ValueError, "The reference number is invalid"): bill = QRBill(**min_data, ref_number='18539007547034') with self.assertRaisesRegex(ValueError, "The reference number is invalid"): bill = QRBill(**min_data, ref_number='ref-number') with self.assertRaisesRegex( ValueError, "A QR-IBAN requires a QRR reference number"): bill = QRBill(**min_data, ref_number='RF18539007547034')
def test_spec_example1(self): bill = QRBill( account='CH4431999123000889012', creditor={ 'name': 'Robert Schneider AG', 'street': 'Rue du Lac', 'house_num': '1268/2/22', 'pcode': '2501', 'city': 'Biel', 'country': 'CH', }, final_creditor={ 'name': 'Robert Schneider Services Switzerland AG', 'street': 'Rue du Lac', 'house_num': '1268/3/1', 'pcode': '2501', 'city': 'Biel', 'country': 'CH', }, amount='123949.75', currency='CHF', due_date='2019-10-31', debtor={ 'name': 'Pia-Maria Rutschmann-Schnyder', 'street': 'Grosse Marktgasse', 'house_num': '28', 'pcode': '9400', 'city': 'Rorschach', 'country': 'CH', }, ref_number='210000000003139471430009017', extra_infos=( 'Order of 15.09.2019##S1/01/20170309/11/10201409/20/1400' '0000/22/36958/30/CH106017086/40/1020/41/3010' ) ) ''' AP1 – Parameters UV1;1.1;1278564;1A-2F-43-AC-9B-33-21-B0-CC-D4- 28-56;TCXVMKC22;2019-02-10T15: 12:39; 2019-02- 10T15:18:16¶ AP2 – Parameters XY2;2a-2.2r;_R1-CH2_ConradCH-2074-1_33 50_2019-03-13T10:23:47_16,99_0,00_0,00_ 0,00_0,00_+8FADt/DQ=_1== ''' with tempfile.NamedTemporaryFile(suffix='.svg') as fh: bill.as_svg(fh.name) content = fh.read().decode() self.assertTrue(content.startswith('<?xml version="1.0" encoding="utf-8" ?>'))
def test_amount(self): amount_err = ( "If provided, the amount must match the pattern '###.##' and cannot " "be larger than 999'999'999.99") type_err = "Amount can only be specified as str or Decimal." unvalid_inputs = [ ("1234567890.00", amount_err), # Too high value ("1.001", amount_err), # More than 2 decimals (Decimal("1.001"), amount_err), # Same but with Decimal type ("CHF800", amount_err), # Currency included (1.35, type_err), # Float are not accepted (rounding issues) ] for value, err in unvalid_inputs: with self.assertRaisesRegex(ValueError, err): bill = QRBill( account="CH 53 8000 5000 0102 83664", amount=value, creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', 'country': 'CH', }, ) valid_inputs = [ (".5", "0.50", "0.50"), ("42", "42.00", "42.00"), ("001'800", "1800.00", "1 800.00"), (" 3.45 ", "3.45", "3.45"), ("9'999'999.4 ", "9999999.40", "9 999 999.40"), (Decimal("35.9"), "35.90", "35.90"), ] for value, expected, printed in valid_inputs: bill = QRBill( account="CH 53 8000 5000 0102 83664", amount=value, creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', 'country': 'CH', }, ) self.assertEqual(bill.amount, expected) self.assertEqual(format_amount(bill.amount), printed)
def test_as_svg_filelike(self): bill = QRBill( account="CH 53 8000 5000 0102 83664", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', }, ) self.assertEqual(self._produce_svg(bill)[:40], '<?xml version="1.0" encoding="utf-8" ?>\n')
def test_minimal_data(self): bill = QRBill( account="CH 53 8000 5000 0102 83664", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', }, ) self.assertEqual( bill.qr_data(), 'SPC\r\n0200\r\n1\r\nCH5380005000010283664\r\nS\r\nJane\r\n\r\n\r\n' '1000\r\nLausanne\r\nCH\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nCHF\r\n' '\r\n\r\n\r\n\r\n\r\n\r\n\r\nNON\r\n\r\n\r\nEPD' ) with tempfile.NamedTemporaryFile(suffix='.svg') as fh: bill.as_svg(fh.name) content = fh.read().decode() self.assertTrue(content.startswith('<?xml version="1.0" encoding="utf-8" ?>'))
def test_alt_procs(self): min_data = { 'account': "CH 53 8000 5000 0102 83664", 'creditor': { 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', }, } err1 = "An alternative procedure line cannot be longer than 100 characters" with self.assertRaisesRegex(ValueError, err1): bill = QRBill(**min_data, alt_procs=['x' * 101]) err2 = "Only two lines allowed in alternative procedure parameters" with self.assertRaisesRegex(ValueError, err2): bill = QRBill(**min_data, alt_procs=['x', 'y', 'z']) bill = QRBill(**min_data, alt_procs=['ABCDEFGH', '012345678']) svg_result = self._produce_svg(bill) self.assertEqual(svg_result[:40], '<?xml version="1.0" encoding="utf-8" ?>\n') self.assertIn('ABCDEFGH', svg_result) self.assertIn('012345678', svg_result)
def test_full_page(self): bill = QRBill( account="CH 53 8000 5000 0102 83664", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', }, ) file_head = self._produce_svg(bill, full_page=True)[:250] self.assertIn('width="210mm"', file_head) self.assertIn('height="297mm"', file_head)
def test_ultimate_creditor(self): bill_data = { 'account': "CH 53 8000 5000 0102 83664", 'creditor': { 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', }, 'final_creditor': { 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', }, } with self.assertRaisesRegex(ValueError, "final creditor is reserved for future use, must not be used"): QRBill(**bill_data)
def test_account(self): with self.assertRaisesRegex(ValueError, "IBAN must have exactly 21 characters"): bill = QRBill( account="CH44319991230008890", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', 'country': 'CH', }, ) with self.assertRaisesRegex(ValueError, "Sorry, the IBAN is not valid"): bill = QRBill( account="CH4431999123000899012", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', 'country': 'CH', }, ) # Spaces are auto-stripped bill = QRBill( account="CH 44 3199 9123 0008 89012", creditor={ 'name': 'Jane', 'pcode': '1000', 'city': 'Lausanne', 'country': 'CH', }, ) self.assertEqual(bill.account, "CH4431999123000889012") self.assertEqual(format_iban('CH4431999123000889012'), 'CH44 3199 9123 0008 8901 2')
def test_spec_example1(self): bill = QRBill( account='CH4431999123000889012', creditor={ 'name': 'Robert Schneider AG', 'street': 'Rue du Lac', 'house_num': '1268', 'pcode': '2501', 'city': 'Biel', 'country': 'CH', }, amount='1949.7', currency='CHF', due_date='2019-10-31', debtor={ 'name': 'Pia-Maria Rutschmann-Schnyder', 'street': 'Grosse Marktgasse', 'house_num': '28', 'pcode': '9400', 'city': 'Rorschach', 'country': 'CH', }, ref_number='210000000003139471430009017', extra_infos=( 'Order of 15.09.2019##S1/01/20170309/11/10201409/20/1400' '0000/22/36958/30/CH106017086/40/1020/41/3010')) ''' AP1 – Parameters UV1;1.1;1278564;1A-2F-43-AC-9B-33-21-B0-CC-D4- 28-56;TCXVMKC22;2019-02-10T15: 12:39; 2019-02- 10T15:18:16¶ AP2 – Parameters XY2;2a-2.2r;_R1-CH2_ConradCH-2074-1_33 50_2019-03-13T10:23:47_16,99_0,00_0,00_ 0,00_0,00_+8FADt/DQ=_1== ''' self.assertEqual( bill.qr_data(), 'SPC\r\n0200\r\n1\r\nCH4431999123000889012\r\nS\r\nRobert Schneider AG\r\n' 'Rue du Lac\r\n1268\r\n2501\r\nBiel\r\nCH\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n' '1949.70\r\nCHF\r\nS\r\nPia-Maria Rutschmann-Schnyder\r\nGrosse Marktgasse\r\n' '28\r\n9400\r\nRorschach\r\nCH\r\nQRR\r\n210000000003139471430009017\r\n' 'Order of 15.09.2019##S1/01/20170309/11/10201409/20/14000000/22/36958/30/CH106017086' '/40/1020/41/3010\r\nEPD') with tempfile.NamedTemporaryFile(suffix='.svg') as fh: bill.as_svg(fh.name) content = fh.read().decode() self.assertTrue( content.startswith('<?xml version="1.0" encoding="utf-8" ?>')) font8 = 'font-family="helvetica" font-size="8" font-weight="bold"' font10 = 'font-family="helvetica" font-size="10"' # Test the Payable by section: self.assertIn( '<text {font8} {x} y="52.5mm">Payable by</text>' '<text {font10} {x} y="56.0mm">Pia-Maria Rutschmann-Schnyder</text>' '<text {font10} {x} y="59.5mm">Grosse Marktgasse 28</text>' '<text {font10} {x} y="63.0mm">CH-9400 Rorschach</text>' '<text {font8} {x} y="67.5mm">Payable by </text>' '<text {font10} {x} y="71.0mm">31.10.2019</text>'.format( font8=font8, font10=font10, x='x="137.0mm"'), content) # IBAN formatted self.assertIn( '<text {font10} x="5mm" y="18.5mm">CH44 3199 9123 0008 8901 2</text>' .format(font10=font10), content) # amount formatted self.assertIn( '<text {font10} x="17.0mm" y="85mm">1 949.70</text>'.format( font10=font10), content)