Merge pull request #8631 from turbo124/v5-stable

v5.6.16
This commit is contained in:
David Bomba 2023-07-09 17:08:59 +10:00 committed by GitHub
commit b2e535b6cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
86 changed files with 2893 additions and 5731 deletions

View File

@ -1 +1 @@
5.6.15
5.6.16

View File

@ -79,6 +79,7 @@ class OpenApiYaml extends Command
Storage::disk('base')->append('/openapi/api-docs.yaml', file_get_contents($path.'/components.yaml'));
Storage::disk('base')->append('/openapi/api-docs.yaml', file_get_contents($path.'/components/responses.yaml'));
Storage::disk('base')->append('/openapi/api-docs.yaml', file_get_contents($path.'/components/examples.yaml'));
$directory = new DirectoryIterator($path . '/components/responses/');

View File

@ -51,6 +51,7 @@ class TranslationsExport extends Command
'fi',
'fr',
'fr_CA',
'fr_CH',
'he',
'hr',
'hu',

View File

@ -223,9 +223,12 @@ class Rule extends BaseRule implements RuleInterface
public function calculateRates(): self
{
if ($this->client->is_tax_exempt) {
// nlog("tax exempt");
$this->tax_rate = 0;
$this->reduced_tax_rate = 0;
return $this;
}
// } elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->has_valid_vat_number && $this->eu_business_tax_exempt) {
// nlog("euro zone and tax exempt");
// $this->tax_rate = 0;
@ -246,10 +249,9 @@ class Rule extends BaseRule implements RuleInterface
// $this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate;
// $this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate;
// }
} else {
$this->tax_rate = $this->client->company->tax_data->regions->AU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate;
$this->reduced_tax_rate = $this->client->company->tax_data->regions->AU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate;
}
$this->tax_rate = $this->client->company->tax_data->regions->AU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate;
$this->reduced_tax_rate = $this->client->company->tax_data->regions->AU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate;
return $this;

View File

@ -37,9 +37,9 @@ class TokenFilters extends QueryFilters
}
public function is_system(bool $value = false): Builder
public function is_system(string $value = 'false'): Builder
{
return $this->builder->where('is_system', $value);
return $this->builder->where('is_system', $value == 'false' ? false : true);
}
/**

View File

@ -25,6 +25,8 @@ class PdfSlot extends Component
public $pdf;
public $url;
public function mount()
{
MultiDB::setDb($this->db);

View File

@ -42,6 +42,8 @@ trait MakesInvoiceHtml
{
$data['__env'] = app(Factory::class);
return Blade::render($string, $data); //potential fix for removing eval()
$php = Blade::compileString($string);
$obLevel = ob_get_level();

View File

@ -106,7 +106,6 @@
"filp/whoops": "^2.7",
"friendsofphp/php-cs-fixer": "^3.14",
"laracasts/cypress": "^3.0",
"laravel/dusk": "^6.15",
"mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^6.1",
"nunomaduro/larastan": "^2.0",

View File

@ -15,8 +15,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => '5.6.15',
'app_tag' => '5.6.15',
'app_version' => env('APP_VERSION','5.6.16'),
'app_tag' => env('APP_TAG','5.6.16'),
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''),

View File

@ -0,0 +1,37 @@
<?php
use App\Models\Language;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Language::unguard();
$language = Language::find(40);
if (! $language) {
Language::create(['id' => 40, 'name' => 'French - Swiss', 'locale' => 'fr_CH']);
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
};

View File

@ -64,6 +64,7 @@ class LanguageSeeder extends Seeder
['id' => 37, 'name' => 'Hebrew', 'locale' => 'he'],
['id' => 38, 'name' => 'Khmer', 'locale' => 'km_KH'],
['id' => 39, 'name' => 'Hungarian', 'locale' => 'hu'],
['id' => 40, 'name' => 'French - Swiss', 'locale' => 'fr_CH'],
];
foreach ($languages as $language) {

64
dusk.sh
View File

@ -1,64 +0,0 @@
#!/bin/bash
n=1
TYPE=${!n}
if [ -z "$TYPE" ]; then
TYPE="all"
fi
echo "$ RUNNING: '$TYPE'"
echo "$ php artisan optimize"
php artisan optimize
echo "=========================================="
GENERIC_TESTS=`find tests/Browser/ClientPortal/ -maxdepth 1 -type f -name '*.php'`
if [ $TYPE == 'gateways' ]; then
GENERIC_TESTS=""
echo "$ Skippping generic tests."
echo "=========================================="
fi
for TEST_CLASS in $GENERIC_TESTS; do
echo "Test class: $TEST_CLASS"
echo "$ php artisan migrate:fresh --seed"
php artisan migrate:fresh --seed &> /dev/null
echo "$ php artisan ninja:create-single-account"
php artisan ninja:create-single-account &> /dev/null
echo "$ php artisan dusk $TEST_CLASS"
php -d memory_limit=1G artisan dusk ${@:2} --stop-on-error --stop-on-failure $TEST_CLASS || exit 1
echo "=========================================="
done || exit 1
GATEWAY_TESTS=`find tests/Browser/ClientPortal/Gateways/ -type f -name '*.php'`
if [ $TYPE == 'generic' ]; then
GATEWAY_TESTS=""
echo "$ Skippping gateway tests."
echo "=========================================="
fi
for TEST_CLASS in $GATEWAY_TESTS; do
echo "Test class: $TEST_CLASS"
echo "$ php artisan migrate:fresh --seed"
php artisan migrate:fresh --seed &> /dev/null
echo "$ php artisan ninja:create-single-account"
php artisan ninja:create-single-account &> /dev/null
echo "$ php artisan dusk $TEST_CLASS"
php -d memory_limit=1G artisan dusk ${@:2} --stop-on-error --stop-on-failure $TEST_CLASS || exit 1
echo "=========================================="
done || exit 1
echo 'All tests completed successfully.'

View File

@ -767,7 +767,7 @@ $LANG = array(
'activity_19' => ':user aktualisierte Angebot :quote',
'activity_20' => ':user mailte Angebot :quote für :client an :contact',
'activity_21' => ':contact schaute Angebot :quote an',
'activity_22' => ':user archivierte Angebot :quote',
'activity_22' => ':user archiviertes Angebot :quote',
'activity_23' => ':user löschte Angebot :quote',
'activity_24' => ':user stellte Angebot :quote wieder her',
'activity_25' => ':user stellte Rechnung :invoice wieder her',
@ -904,7 +904,7 @@ $LANG = array(
'payment_terms_net' => 'Netto',
'vendor' => 'Lieferant',
'edit_vendor' => 'Lieferant Bearbeiten',
'archive_vendor' => 'Lieferant Archivieren',
'archive_vendor' => 'Lieferant archivieren',
'delete_vendor' => 'Lieferant Löschen',
'view_vendor' => 'Lieferant Ansehen',
'deleted_expense' => 'Ausgabe erfolgreich gelöscht',
@ -923,7 +923,7 @@ $LANG = array(
'should_be_invoiced' => 'Sollte in Rechnung gestellt werden',
'view_expense' => 'Ausgabe # :expense ansehen',
'edit_expense' => 'Ausgabe Bearbeiten',
'archive_expense' => 'Ausgabe Archivieren',
'archive_expense' => 'Ausgabe archivieren',
'delete_expense' => 'Ausgabe Löschen',
'view_expense_num' => 'Ausgabe # :expense',
'updated_expense' => 'Ausgabe erfolgreich aktualisiert',
@ -4534,12 +4534,12 @@ https://invoiceninja.github.io/docs/migration/#troubleshooting',
'auto_archive_invoice_cancelled_help' => 'Automatisch Rechnungen archivieren, wenn diese storniert wurden',
'no_invoices_found' => 'Keine Rechnungen gefunden',
'created_record' => 'Eintrag erfolgreich erstellt.',
'auto_archive_paid_invoices' => 'Bezahltes Automatisch Archivieren',
'auto_archive_paid_invoices' => 'Bezahltes automatisch archivieren',
'auto_archive_paid_invoices_help' => 'Automatische Archivierung von Rechnungen, wenn diese als bezahlt markiert werden.',
'auto_archive_cancelled_invoices' => 'Auto-Archivierung abgebrochen',
'auto_archive_cancelled_invoices_help' => 'Automatisch Rechnungen archivieren, wenn diese storniert wurden.',
'alternate_pdf_viewer' => 'Alternativer PDF Viewer',
'alternate_pdf_viewer_help' => 'Verbessere das Scrolling über die PDF Vorschau [BETA]',
'alternate_pdf_viewer_help' => 'Verbessere das Scrolling über die PDF-Vorschau [BETA]',
'currency_cayman_island_dollar' => 'Cayman Island Dollar',
'download_report_description' => 'Bitte das angehängte Dokument öffnen, um den Report anzusehen.',
'left' => 'Links',
@ -4604,7 +4604,7 @@ https://invoiceninja.github.io/docs/migration/#troubleshooting',
'yes_its_great' => 'Ja, es ist super!',
'not_so_much' => 'Nein, eher weniger',
'would_you_rate_it' => 'Danke für das Feedback, mächten Sie die App bewerten?',
'would_you_tell_us_more' => 'Das tut uns leid, dass zu hören. Was gefällt Ihnen nicht?',
'would_you_tell_us_more' => 'Es tut uns leid, das zu hören. Was gefällt Ihnen nicht?',
'sure_happy_to' => 'Gerne',
'no_not_now' => 'Nein, nicht jetzt.',
'add' => 'Hinzufügen',
@ -5116,6 +5116,12 @@ https://invoiceninja.github.io/docs/migration/#troubleshooting',
'item_tax_rate2' => 'Item Tax Rate 2',
'item_tax_rate3' => 'Item Tax Rate 3',
'buy_price' => 'Buy Price',
'country_Macedonia' => 'Macedonia',
'admin_initiated_payments' => 'Admin Initiated Payments',
'admin_initiated_payments_help' => 'Support entering a payment in the admin portal without an invoice',
'paid_date' => 'Paid Date',
'downloaded_entities' => 'An email will be sent with the PDFs',
);

View File

@ -5119,7 +5119,10 @@ $LANG = array(
'admin_initiated_payments_help' => 'Support entering a payment in the admin portal without an invoice',
'paid_date' => 'Paid Date',
'downloaded_entities' => 'An email will be sent with the PDFs',
'lang_French - Swiss' => 'French - Swiss',
'currency_swazi_lilangeni' => 'Swazi Lilangeni',
'income' => 'Income',
);

View File

@ -5110,6 +5110,8 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'admin_initiated_payments' => 'Paiements initiés par l\'administration',
'admin_initiated_payments_help' => 'Permet la saisie d\'un paiement dans le portal d\'administration sans facture',
'paid_date' => 'Date de paiement',
'downloaded_entities' => 'Un courriel sera envoyé avec le ou les PDF',
);

View File

@ -748,7 +748,7 @@ $LANG = array(
'activity_7' => ':contact a visualisé la facture :invoice pour :client',
'activity_8' => ':user a archivé la facture :invoice',
'activity_9' => ':user a supprimé la facture :invoice',
'activity_10' => ':user entered payment :payment for :payment_amount on invoice :invoice for :client',
'activity_10' => ':user a saisi le paiement :payment pour :payment_montant sur la facture :invoice pour :client',
'activity_11' => ':user a mis à jour le paiement :payment',
'activity_12' => ':user a archivé le paiement :payment',
'activity_13' => ':user a supprimé le paiement :payment',
@ -1991,7 +1991,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'current_quarter' => 'Trimestre en cours',
'last_quarter' => 'Dernier trimestre',
'last_year' => 'Dernière année',
'all_time' => 'All Time',
'all_time' => 'Tout le temps',
'custom_range' => 'Personnalisé',
'url' => 'URL',
'debug' => 'Débogage',
@ -2252,7 +2252,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'restore_recurring_expense' => 'Restaurer la dépense récurrente',
'restored_recurring_expense' => 'La dépense récurrente a été restaurée avec succès',
'delete_recurring_expense' => 'Supprimer la dépense récurrente',
'deleted_recurring_expense' => 'Successfully deleted recurring expense',
'deleted_recurring_expense' => 'Dépense récurrente supprimée avec succès',
'view_recurring_expense' => 'Visualiser la dépense récurrente',
'taxes_and_fees' => 'Taxes et frais',
'import_failed' => 'L\'importation a échoué',
@ -2507,8 +2507,8 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'partial_due_date' => 'Date d\'échéance du paiement partiel',
'task_fields' => 'Champs d\'intervention',
'product_fields_help' => 'Glisser et déposer les champs pour changer l\'ordre',
'custom_value1' => 'Custom Value 1',
'custom_value2' => 'Custom Value 2',
'custom_value1' => 'Valeur personnalisée 1',
'custom_value2' => 'Valeur personnalisée 2',
'enable_two_factor' => 'Authentification à deux facteurs',
'enable_two_factor_help' => 'Utilisez votre téléphone pour confirmer votre identité lors de la connexion',
'two_factor_setup' => 'Configuration de l\'authentification à deux facteurs',
@ -3855,7 +3855,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'notification_credit_viewed' => 'Un crédit de :amount a été vu par le client :client.',
'reset_password_text' => 'Saisissez votre adresse courriel pour réinitialiser votre mot de passe.',
'password_reset' => 'Réinitialisation du mot de passe',
'account_login_text' => 'Welcome! Glad to see you.',
'account_login_text' => 'Accueillir! Content de te voir.',
'request_cancellation' => 'Annuler la demande',
'delete_payment_method' => 'Supprimer le mode de paiement',
'about_to_delete_payment_method' => 'Le mode de paiement sera supprimé',
@ -3969,7 +3969,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'add_payment_method_first' => 'ajouter un mode de paiement',
'no_items_selected' => 'Aucun article sélectionné',
'payment_due' => 'Paiement dû',
'account_balance' => 'Account Balance',
'account_balance' => 'Solde du compte',
'thanks' => 'Merci',
'minimum_required_payment' => 'Le paiement minimum requis est :amount',
'under_payments_disabled' => 'La société ne tolère pas le sous-paiement.',
@ -3994,7 +3994,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'notification_invoice_reminder1_sent_subject' => 'Le rappel 1 pour la facture :invoice a été envoyé à :client',
'notification_invoice_reminder2_sent_subject' => 'Le rappel 2 pour la facture :invoice a été envoyé à :client',
'notification_invoice_reminder3_sent_subject' => 'Le rappel 3 pour la facture :invoice a été envoyé à :client',
'notification_invoice_custom_sent_subject' => 'Custom reminder for Invoice :invoice was sent to :client',
'notification_invoice_custom_sent_subject' => 'Un rappel personnalisé pour la facture :invoice a été envoyé à :client',
'notification_invoice_reminder_endless_sent_subject' => 'Un rappel perpétuel pour la facture :invoice a été envoyé à :client',
'assigned_user' => 'Utilisateur affecté',
'setup_steps_notice' => 'Pour accéder à la prochaine étape, vous devez tester chaque section.',
@ -4372,7 +4372,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'imported_customers' => 'Successfully started importing customers',
'login_success' => 'Successful Login',
'login_failure' => 'Failed Login',
'exported_data' => 'Once the file is ready you\'ll receive an email with a download link',
'exported_data' => 'Une fois le fichier prêt, vous recevrez un e-mail avec un lien de téléchargement',
'include_deleted_clients' => 'Include Deleted Clients',
'include_deleted_clients_help' => 'Load records belonging to deleted clients',
'step_1_sign_in' => 'Step 1: Sign In',
@ -4461,7 +4461,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'activity_123' => ':user deleted recurring expense :recurring_expense',
'activity_124' => ':user restored recurring expense :recurring_expense',
'fpx' => "FPX",
'to_view_entity_set_password' => 'To view the :entity you need to set a password.',
'to_view_entity_set_password' => 'Pour afficher le :entity, vous devez définir un mot de passe.',
'unsubscribe' => 'Unsubscribe',
'unsubscribed' => 'Unsubscribed',
'unsubscribed_text' => 'You have been removed from notifications for this document',
@ -4559,7 +4559,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'purchase_order_number' => 'Numéro de bon de commande',
'purchase_order_number_short' => 'Bon de commande #',
'inventory_notification_subject' => 'Inventory threshold notification for product: :product',
'inventory_notification_body' => 'Threshold of :amount has been reached for product: :product',
'inventory_notification_body' => 'Le seuil de :amount a été atteint pour le produit : :product',
'activity_130' => ':user a créé le bon de commande :purchase_order',
'activity_131' => ':user a mis à jour le bon de commande :purchase_order',
'activity_132' => ':user a archivé le bon de commande :purchase_order',
@ -4591,7 +4591,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'vendor_document_upload' => 'Vendor Document Upload',
'vendor_document_upload_help' => 'Enable vendors to upload documents',
'are_you_enjoying_the_app' => 'Are you enjoying the app?',
'yes_its_great' => 'Yes, it\'s great!',
'yes_its_great' => 'Oui c&#39;est super!',
'not_so_much' => 'Not so much',
'would_you_rate_it' => 'Great to hear! Would you like to rate it?',
'would_you_tell_us_more' => 'Sorry to hear it! Would you like to tell us more?',
@ -4900,7 +4900,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'all_clients' => 'All Clients',
'show_aging_table' => 'Show Aging Table',
'show_payments_table' => 'Afficher le tableau de paiement',
'only_clients_with_invoices' => 'Only Clients with Invoices',
'only_clients_with_invoices' => 'Seuls les clients avec factures',
'email_statement' => 'Email Statement',
'once' => 'Once',
'schedules' => 'Schedules',
@ -4962,9 +4962,9 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'white_label_body' => 'Thank you for purchasing a white label license. <br><br> Your license key is: <br><br> :license_key',
'payment_type_Klarna' => 'Klarna',
'payment_type_Interac E Transfer' => 'Interac E Transfer',
'xinvoice_payable' => 'Payable within :payeddue days net until :paydate',
'xinvoice_no_buyers_reference' => "No buyer's reference given",
'xinvoice_online_payment' => 'The invoice needs to be paid online via the provided link',
'xinvoice_payable' => 'Payable sous :payeddue jours net jusqu&#39;à :paydate',
'xinvoice_no_buyers_reference' => "Aucune référence d&#39;acheteur donnée",
'xinvoice_online_payment' => 'La facture doit être payée en ligne via le lien fourni',
'pre_payment' => 'Prépaiement',
'number_of_payments' => 'Nombre de paiements',
'number_of_payments_helper' => 'Le nombre de fois que ce paiement sera exécuté',
@ -5013,99 +5013,105 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'quote_product_columns' => 'Quote Product Columns',
'vendors' => 'Vendors',
'product_sales' => 'Product Sales',
'user_sales_report_header' => 'User sales report for client/s :client from :start_date to :end_date',
'client_balance_report' => 'Customer balance report',
'client_sales_report' => 'Customer sales report',
'user_sales_report' => 'User sales report',
'aged_receivable_detailed_report' => 'Aged Receivable Detailed Report',
'aged_receivable_summary_report' => 'Aged Receivable Summary Report',
'taxable_amount' => 'Taxable Amount',
'tax_summary' => 'Tax Summary',
'oauth_mail' => 'OAuth / Mail',
'preferences' => 'Preferences',
'analytics' => 'Analytics',
'reduced_rate' => 'Reduced Rate',
'tax_all' => 'Tax All',
'tax_selected' => 'Tax Selected',
'user_sales_report_header' => 'Rapport sur les ventes des utilisateurs pour le ou les clients :client de :start_date à :end_date',
'client_balance_report' => 'Rapport sur le solde du client',
'client_sales_report' => 'Rapport de ventes client',
'user_sales_report' => 'Rapport de ventes utilisateur',
'aged_receivable_detailed_report' => 'Rapport détaillé sur les créances chronologiques',
'aged_receivable_summary_report' => 'Rapport récapitulatif des créances chronologiques',
'taxable_amount' => 'Montant imposable',
'tax_summary' => 'Récapitulatif fiscal',
'oauth_mail' => 'OAuth / Courrier',
'preferences' => 'Préférences',
'analytics' => 'Analytique',
'reduced_rate' => 'Tarif réduit',
'tax_all' => 'Taxe Tout',
'tax_selected' => 'Taxe sélectionnée',
'version' => 'version',
'seller_subregion' => 'Seller Subregion',
'calculate_taxes' => 'Calculate Taxes',
'calculate_taxes_help' => 'Automatically calculate taxes when saving invoices',
'link_expenses' => 'Link Expenses',
'converted_client_balance' => 'Converted Client Balance',
'converted_payment_balance' => 'Converted Payment Balance',
'total_hours' => 'Total Hours',
'date_picker_hint' => 'Use +days to set the date in the future',
'app_help_link' => 'More information ',
'here' => 'here',
'industry_Restaurant & Catering' => 'Restaurant & Catering',
'show_credits_table' => 'Show Credits Table',
'manual_payment' => 'Payment Manual',
'tax_summary_report' => 'Tax Summary Report',
'tax_category' => 'Tax Category',
'physical_goods' => 'Physical Goods',
'digital_products' => 'Digital Products',
'services' => 'Services',
'shipping' => 'Shipping',
'tax_exempt' => 'Tax Exempt',
'late_fee_added_locked_invoice' => 'Late fee for invoice :invoice added on :date',
'seller_subregion' => 'Sous-région du vendeur',
'calculate_taxes' => 'Calculer les taxes',
'calculate_taxes_help' => 'Calculer automatiquement les taxes lors de l&#39;enregistrement des factures',
'link_expenses' => 'Dépenses de lien',
'converted_client_balance' => 'Solde client converti',
'converted_payment_balance' => 'Solde de paiement converti',
'total_hours' => 'Heures totales',
'date_picker_hint' => 'Utilisez + jours pour définir la date dans le futur',
'app_help_link' => 'Plus d&#39;information',
'here' => 'ici',
'industry_Restaurant & Catering' => 'Restauration &amp; Traiteur',
'show_credits_table' => 'Afficher le tableau des crédits',
'manual_payment' => 'Manuel de paiement',
'tax_summary_report' => 'Rapport récapitulatif des taxes',
'tax_category' => 'Catégorie de taxe',
'physical_goods' => 'Biens physiques',
'digital_products' => 'Produits numériques',
'services' => 'Prestations de service',
'shipping' => 'Expédition',
'tax_exempt' => 'Exonéré d&#39;impôt',
'late_fee_added_locked_invoice' => 'Frais de retard pour facture :invoice ajouté sur :date',
'lang_Khmer' => 'Khmer',
'routing_id' => 'Routing ID',
'enable_e_invoice' => 'Enable E-Invoice',
'e_invoice_type' => 'E-Invoice Type',
'reduced_tax' => 'Reduced Tax',
'override_tax' => 'Override Tax',
'zero_rated' => 'Zero Rated',
'reverse_tax' => 'Reverse Tax',
'updated_tax_category' => 'Successfully updated the tax category',
'updated_tax_categories' => 'Successfully updated the tax categories',
'set_tax_category' => 'Set Tax Category',
'payment_manual' => 'Payment Manual',
'expense_payment_type' => 'Expense Payment Type',
'payment_type_Cash App' => 'Cash App',
'rename' => 'Rename',
'renamed_document' => 'Successfully renamed document',
'e_invoice' => 'E-Invoice',
'light_dark_mode' => 'Light/Dark Mode',
'activities' => 'Activities',
'recent_transactions' => "Here are your company's most recent transactions:",
'routing_id' => 'ID de routage',
'enable_e_invoice' => 'Activer la facture électronique',
'e_invoice_type' => 'Type de facture électronique',
'reduced_tax' => 'Taxe réduite',
'override_tax' => 'Remplacer la taxe',
'zero_rated' => 'Évalué zéro',
'reverse_tax' => 'Taxe inversée',
'updated_tax_category' => 'Mise à jour réussie de la catégorie de taxe',
'updated_tax_categories' => 'Mise à jour réussie des catégories de taxes',
'set_tax_category' => 'Définir la catégorie de taxe',
'payment_manual' => 'Manuel de paiement',
'expense_payment_type' => 'Type de paiement des dépenses',
'payment_type_Cash App' => 'Application de trésorerie',
'rename' => 'Renommer',
'renamed_document' => 'Document renommé avec succès',
'e_invoice' => 'Facture électronique',
'light_dark_mode' => 'Mode clair/foncé',
'activities' => 'Activités',
'recent_transactions' => "Voici les transactions les plus récentes de votre entreprise :",
'country_Palestine' => "Palestine",
'country_Taiwan' => 'Taiwan',
'duties' => 'Duties',
'order_number' => 'Order Number',
'order_id' => 'Order',
'total_invoices_outstanding' => 'Total Invoices Outstanding',
'recent_activity' => 'Recent Activity',
'enable_auto_bill' => 'Enable auto billing',
'email_count_invoices' => 'Email :count invoices',
'invoice_task_item_description' => 'Invoice Task Item Description',
'invoice_task_item_description_help' => 'Add the item description to the invoice line items',
'next_send_time' => 'Next Send Time',
'uploaded_certificate' => 'Successfully uploaded certificate',
'certificate_set' => 'Certificate set',
'certificate_not_set' => 'Certificate not set',
'passphrase_set' => 'Passphrase set',
'passphrase_not_set' => 'Passphrase not set',
'upload_certificate' => 'Upload Certificate',
'certificate_passphrase' => 'Certificate Passphrase',
'valid_vat_number' => 'Valid VAT Number',
'react_notification_link' => 'React Notification Links',
'react_notification_link_help' => 'Admin emails will contain links to the react application',
'show_task_billable' => 'Show Task Billable',
'credit_item' => 'Credit Item',
'drop_file_here' => 'Drop file here',
'files' => 'Files',
'camera' => 'Camera',
'gallery' => 'Gallery',
'project_location' => 'Project Location',
'add_gateway_help_message' => 'Add a payment gateway (ie. Stripe, WePay or PayPal) to accept online payments',
'lang_Hungarian' => 'Hungarian',
'use_mobile_to_manage_plan' => 'Use your phone subscription settings to manage your plan',
'item_tax3' => 'Item Tax3',
'item_tax_rate1' => 'Item Tax Rate 1',
'item_tax_rate2' => 'Item Tax Rate 2',
'item_tax_rate3' => 'Item Tax Rate 3',
'buy_price' => 'Buy Price',
'country_Taiwan' => 'Taïwan',
'duties' => 'Devoirs',
'order_number' => 'Numéro de commande',
'order_id' => 'Commande',
'total_invoices_outstanding' => 'Total des factures impayées',
'recent_activity' => 'Activité récente',
'enable_auto_bill' => 'Activer la facturation automatique',
'email_count_invoices' => 'E-mail :count factures',
'invoice_task_item_description' => 'Description de l&#39;élément de tâche de la facture',
'invoice_task_item_description_help' => 'Ajouter la description de l&#39;article aux éléments de ligne de la facture',
'next_send_time' => 'Prochaine heure d&#39;envoi',
'uploaded_certificate' => 'Certificat téléchargé avec succès',
'certificate_set' => 'Ensemble de certificats',
'certificate_not_set' => 'Certificat non défini',
'passphrase_set' => 'Jeu de mots de passe',
'passphrase_not_set' => 'Mot de passe non défini',
'upload_certificate' => 'Télécharger le certificat',
'certificate_passphrase' => 'Phrase de passe du certificat',
'valid_vat_number' => 'Numéro de TVA valide',
'react_notification_link' => 'Liens de notification de réaction',
'react_notification_link_help' => 'Les e-mails d&#39;administration contiendront des liens vers l&#39;application de réaction',
'show_task_billable' => 'Afficher la tâche facturable',
'credit_item' => 'Article de crédit',
'drop_file_here' => 'Déposez le fichier ici',
'files' => 'Des dossiers',
'camera' => 'Caméra',
'gallery' => 'Galerie',
'project_location' => 'Emplacement du projet',
'add_gateway_help_message' => 'Ajoutez une passerelle de paiement (c.-à-d. Stripe, WePay ou PayPal) pour accepter les paiements en ligne',
'lang_Hungarian' => 'hongrois',
'use_mobile_to_manage_plan' => 'Utilisez les paramètres de votre abonnement téléphonique pour gérer votre forfait',
'item_tax3' => 'Taxe sur les articles3',
'item_tax_rate1' => 'Taux de taxe sur l&#39;article 1',
'item_tax_rate2' => 'Taux de taxe sur l&#39;article 2',
'item_tax_rate3' => 'Taux de taxe sur l&#39;article 3',
'buy_price' => 'Prix d&#39;achat',
'country_Macedonia' => 'Macédoine',
'admin_initiated_payments' => 'Paiements initiés par l&#39;administrateur',
'admin_initiated_payments_help' => 'Prise en charge de la saisie d&#39;un paiement dans le portail d&#39;administration sans facture',
'paid_date' => 'La date de paiement',
'downloaded_entities' => 'Un email sera envoyé avec les PDF',
);

View File

@ -39,7 +39,7 @@ paths:
- $ref: "#/components/parameters/page_meta"
responses:
200:
description: "Returns the client object"
description: "Returns the list of activities"
headers:
X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
@ -49,8 +49,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Client"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Activity'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -266,8 +274,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/BankIntegration"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/BankIntegration'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -670,8 +686,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/BankTransaction"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/BankTransaction'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -1015,8 +1039,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/BankTransactionRule"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/BankTransactionRule'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -1347,8 +1379,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/ClientGatewayToken"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/ClientGatewayToken'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -1604,8 +1644,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Company"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Company'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -1947,8 +1995,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/CompanyGateway"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/CompanyGateway'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -2254,8 +2310,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/CompanyLedger"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/CompanyLedger'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -2358,8 +2422,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Design"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Design'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -2666,8 +2738,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Document"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Document'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -2751,8 +2831,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/ExpenseCategory"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/ExpenseCategory'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -3047,8 +3135,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Expense"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Expense'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -3415,8 +3511,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/GroupSetting"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/GroupSetting'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -3899,8 +4003,8 @@ paths:
post:
tags:
- logout
summary: "Gets a list of logout"
description: "Lists all logout"
summary: "Logs the user out of their current session"
description: "Logs the user out of their current session"
operationId: getLogout
parameters:
- $ref: "#/components/parameters/X-API-TOKEN"
@ -4086,8 +4190,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/PaymentTerm"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/PaymentTerm'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -4520,8 +4632,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/RecurringExpense"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/RecurringExpense'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -4862,8 +4982,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/RecurringQuote"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/RecurringQuote'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -5758,8 +5886,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Subscription"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Subscription'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -6099,8 +6235,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/SystemLog"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/SystemLog'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -6404,8 +6548,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/TaskStatus"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/TaskStatus'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -6709,8 +6861,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/TaxRate"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/TaxRate'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -7018,8 +7178,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/CompanyToken"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/CompanyToken'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -7318,8 +7486,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/User"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -7766,8 +7942,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Webhook"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Webhook'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -8098,8 +8282,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Product"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Product'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: '#/components/responses/401'
403:
@ -8503,8 +8695,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Task"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Task'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -8914,8 +9114,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Project"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Project'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -9387,8 +9595,20 @@ paths:
$ref: '#/components/headers/X-RateLimit-Limit'
content:
application/json:
schema:
$ref: '#/components/schemas/Client'
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Client'
example:
$ref: '#/components/examples/Client'
meta:
type: object
$ref: '#/components/schemas/Meta'
example:
$ref: '#/components/examples/Meta'
401:
$ref: '#/components/responses/401'
403:
@ -9936,8 +10156,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Credit"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Credit'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -10395,8 +10623,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Payment"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Payment'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -10964,8 +11200,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Invoice"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Invoice'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -11593,8 +11837,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/RecurringInvoice"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/RecurringInvoice'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -12140,8 +12392,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Quote"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Quote'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -12612,8 +12872,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Credit"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/PurchaseOrder'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -12649,7 +12917,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Credit"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -12695,7 +12963,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Credit"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -12740,7 +13008,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Credit"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -12825,7 +13093,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Invoice"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -12863,7 +13131,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Credit"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -12950,7 +13218,7 @@ paths:
example: clone_to_quote
responses:
200:
description: "Returns the invoice object"
description: "Returns the purchase order object"
headers:
X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
@ -12961,7 +13229,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Invoice"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -13006,7 +13274,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Vendor"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -13084,8 +13352,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Vendor"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Vendor'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -13459,6 +13735,78 @@ components:
in: header
name: X-API-TOKEN
responses:
examples:
Client:
- id: Opnel5aKBz
user_id: Ua6Rw4pVbS
assigned_user_id: Ua6Rw4pVbS
company_id: Co7Vn3yLmW
name: "Jim's Housekeeping"
website: https://www.jims-housekeeping.com
private_notes: Client prefers email communication over phone calls
client_hash: asdfkjhk342hjhbfdvmnfb1
industry_id: 5
size_id: 2
address1: 123 Main St
address2: Apt 4B
city: Beverly Hills
state: California
postal_code: 90210
phone: 555-3434-3434
country_id: 1
custom_value1: Email
custom_value2: John Doe
custom_value3: Yes
custom_value4: $50,000
vat_number: VAT123456
id_number: ID123456
number: CL-0001
shipping_address1: 5 Wallaby Way
shipping_address2: Suite 5
shipping_city: Perth
shipping_state: Western Australia
shipping_postal_code: 6110
shipping_country_id: 4
is_deleted: false
balance: 500.00
paid_to_date: 2000.00
credit_balance: 100.00
last_login: 1628686031
created_at: 1617629031
updated_at: 1628445631
group_settings_id: Opnel5aKBz
routing_id: Opnel5aKBz3489-dfkiu-2239-sdsd
is_tax_exempt: false
has_valid_vat_number: false
payment_balance: 100
contacts:
- id: Opnel5aKBz
first_name: John
last_name: Doe
email: jim@gmail.com
phone: 555-3434-3434
send_invoice: true
custom_value1: Email
custom_value2: John Doe
custom_value3: Yes
custom_value4: $50,000
is_primary: true
created_at: 1617629031
updated_at: 1628445631
deleted_at: 1628445631
Meta:
value:
pagination:
total: 1
count: 1
per_page: 20
current_page: 1
total_pages: 1
links:
- first: https://invoicing.co/api/v1/invoices?page=1
- last: https://invoicing.co/api/v1/invoices?page=1
- prev: null
- next: null
429:
description: 'Rate Limit Exceeded'
content:
@ -16613,6 +16961,42 @@ components:
type: integer
example: '1'
type: object
Meta:
properties:
pagination:
$ref: '#/components/schemas/Pagination'
Pagination:
type: object
properties:
total:
type: integer
description: 'The total number of items'
example: 1
readOnly: true
count:
type: integer
description: 'The number of items per page'
example: 1
readOnly: true
per_page:
type: integer
description: 'The number of items per page'
example: 1
readOnly: true
current_page:
type: integer
description: 'The current page number'
example: 1
readOnly: true
total_pages:
type: integer
description: 'The total number of pages'
example: 1
readOnly: true
links:
type: array
description: 'The pagination links'
readOnly: true
FeesAndLimits:
properties:
@ -18597,8 +18981,6 @@ components:
type: string
format: date
example: '1994-07-30'
settings:
$ref: '#/components/schemas/CompanySettings'
last_viewed:
description: Timestamp
type: number

View File

@ -0,0 +1,72 @@
examples:
Client:
- id: Opnel5aKBz
user_id: Ua6Rw4pVbS
assigned_user_id: Ua6Rw4pVbS
company_id: Co7Vn3yLmW
name: "Jim's Housekeeping"
website: https://www.jims-housekeeping.com
private_notes: Client prefers email communication over phone calls
client_hash: asdfkjhk342hjhbfdvmnfb1
industry_id: 5
size_id: 2
address1: 123 Main St
address2: Apt 4B
city: Beverly Hills
state: California
postal_code: 90210
phone: 555-3434-3434
country_id: 1
custom_value1: Email
custom_value2: John Doe
custom_value3: Yes
custom_value4: $50,000
vat_number: VAT123456
id_number: ID123456
number: CL-0001
shipping_address1: 5 Wallaby Way
shipping_address2: Suite 5
shipping_city: Perth
shipping_state: Western Australia
shipping_postal_code: 6110
shipping_country_id: 4
is_deleted: false
balance: 500.00
paid_to_date: 2000.00
credit_balance: 100.00
last_login: 1628686031
created_at: 1617629031
updated_at: 1628445631
group_settings_id: Opnel5aKBz
routing_id: Opnel5aKBz3489-dfkiu-2239-sdsd
is_tax_exempt: false
has_valid_vat_number: false
payment_balance: 100
contacts:
- id: Opnel5aKBz
first_name: John
last_name: Doe
email: jim@gmail.com
phone: 555-3434-3434
send_invoice: true
custom_value1: Email
custom_value2: John Doe
custom_value3: Yes
custom_value4: $50,000
is_primary: true
created_at: 1617629031
updated_at: 1628445631
deleted_at: 1628445631
Meta:
value:
pagination:
total: 1
count: 1
per_page: 20
current_page: 1
total_pages: 1
links:
- first: https://invoicing.co/api/v1/invoices?page=1
- last: https://invoicing.co/api/v1/invoices?page=1
- prev: null
- next: null

View File

@ -168,8 +168,6 @@
type: string
format: date
example: '1994-07-30'
settings:
$ref: '#/components/schemas/CompanySettings'
last_viewed:
description: Timestamp
type: number

View File

@ -0,0 +1,36 @@
Meta:
properties:
pagination:
$ref: '#/components/schemas/Pagination'
Pagination:
type: object
properties:
total:
type: integer
description: 'The total number of items'
example: 1
readOnly: true
count:
type: integer
description: 'The number of items per page'
example: 1
readOnly: true
per_page:
type: integer
description: 'The number of items per page'
example: 1
readOnly: true
current_page:
type: integer
description: 'The current page number'
example: 1
readOnly: true
total_pages:
type: integer
description: 'The total number of pages'
example: 1
readOnly: true
links:
type: array
description: 'The pagination links'
readOnly: true

View File

@ -15,7 +15,7 @@ paths:
- $ref: "#/components/parameters/page_meta"
responses:
200:
description: "Returns the client object"
description: "Returns the list of activities"
headers:
X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
@ -25,8 +25,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Client"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Activity'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -242,8 +250,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/BankIntegration"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/BankIntegration'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -646,8 +662,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/BankTransaction"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/BankTransaction'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -991,8 +1015,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/BankTransactionRule"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/BankTransactionRule'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -1323,8 +1355,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/ClientGatewayToken"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/ClientGatewayToken'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -1580,8 +1620,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Company"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Company'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -1923,8 +1971,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/CompanyGateway"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/CompanyGateway'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -2230,8 +2286,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/CompanyLedger"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/CompanyLedger'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -2334,8 +2398,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Design"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Design'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -2642,8 +2714,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Document"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Document'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -2727,8 +2807,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/ExpenseCategory"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/ExpenseCategory'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -3023,8 +3111,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Expense"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Expense'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -3391,8 +3487,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/GroupSetting"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/GroupSetting'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -3875,8 +3979,8 @@ paths:
post:
tags:
- logout
summary: "Gets a list of logout"
description: "Lists all logout"
summary: "Logs the user out of their current session"
description: "Logs the user out of their current session"
operationId: getLogout
parameters:
- $ref: "#/components/parameters/X-API-TOKEN"
@ -4062,8 +4166,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/PaymentTerm"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/PaymentTerm'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -4496,8 +4608,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/RecurringExpense"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/RecurringExpense'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -4838,8 +4958,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/RecurringQuote"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/RecurringQuote'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -5734,8 +5862,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Subscription"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Subscription'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -6075,8 +6211,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/SystemLog"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/SystemLog'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -6380,8 +6524,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/TaskStatus"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/TaskStatus'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -6685,8 +6837,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/TaxRate"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/TaxRate'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -6994,8 +7154,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/CompanyToken"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/CompanyToken'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -7294,8 +7462,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/User"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -7742,8 +7918,16 @@ paths:
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Webhook"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Webhook'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:

View File

@ -117,8 +117,20 @@
$ref: '#/components/headers/X-RateLimit-Limit'
content:
application/json:
schema:
$ref: '#/components/schemas/Client'
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Client'
example:
$ref: '#/components/examples/Client'
meta:
type: object
$ref: '#/components/schemas/Meta'
example:
$ref: '#/components/examples/Meta'
401:
$ref: '#/components/responses/401'
403:

View File

@ -21,8 +21,16 @@
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Credit"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Credit'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:

View File

@ -106,8 +106,16 @@
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Invoice"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Invoice'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:

View File

@ -57,8 +57,16 @@
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Payment"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Payment'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:

View File

@ -52,8 +52,16 @@
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Product"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Product'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: '#/components/responses/401'
403:

View File

@ -22,8 +22,16 @@
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Project"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Project'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:

View File

@ -21,8 +21,16 @@
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Credit"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/PurchaseOrder'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:
@ -58,7 +66,7 @@
content:
application/json:
schema:
$ref: "#/components/schemas/Credit"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -104,7 +112,7 @@
content:
application/json:
schema:
$ref: "#/components/schemas/Credit"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -149,7 +157,7 @@
content:
application/json:
schema:
$ref: "#/components/schemas/Credit"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -234,7 +242,7 @@
content:
application/json:
schema:
$ref: "#/components/schemas/Invoice"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -272,7 +280,7 @@
content:
application/json:
schema:
$ref: "#/components/schemas/Credit"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -359,7 +367,7 @@
example: clone_to_quote
responses:
200:
description: "Returns the invoice object"
description: "Returns the purchase order object"
headers:
X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
@ -370,7 +378,7 @@
content:
application/json:
schema:
$ref: "#/components/schemas/Invoice"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:
@ -415,7 +423,7 @@
content:
application/json:
schema:
$ref: "#/components/schemas/Vendor"
$ref: "#/components/schemas/PurchaseOrder"
401:
$ref: "#/components/responses/401"
403:

View File

@ -70,8 +70,16 @@
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Quote"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Quote'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:

View File

@ -60,8 +60,16 @@
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/RecurringInvoice"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/RecurringInvoice'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:

View File

@ -22,8 +22,16 @@
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Task"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Task'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:

View File

@ -22,8 +22,16 @@
$ref: "#/components/headers/X-RateLimit-Limit"
content:
application/json:
schema:
$ref: "#/components/schemas/Vendor"
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Vendor'
meta:
type: object
$ref: '#/components/schemas/Meta'
401:
$ref: "#/components/responses/401"
403:

View File

@ -3,11 +3,11 @@ const MANIFEST = 'flutter-app-manifest';
const TEMP = 'flutter-temp-cache';
const CACHE_NAME = 'flutter-app-cache';
const RESOURCES = {
"/": "26db67421962886d10771e134288cbed",
"/": "faecf4eb3989415f8ac174b178967581",
"flutter.js": "a85fcf6324d3c4d3ae3be1ae4931e9c5",
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
"main.dart.js": "b3dc261859fddeebc78cc668c7259ea5",
"version.json": "6f194d02bb20caf51f9b3d380aa58f7d",
"main.dart.js": "b0022e7084e6d7ec1e1a04e5d9f20501",
"version.json": "bf49df736fed3f74ade0dbaebf08de11",
"canvaskit/profiling/canvaskit.js": "c21852696bc1cc82e8894d851c01921a",
"canvaskit/profiling/canvaskit.wasm": "371bc4e204443b0d5e774d64a046eb99",
"canvaskit/canvaskit.js": "97937cb4c2c2073c968525a3e08c86a3",

1702
public/main.dart.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1628
public/main.foss.dart.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -66070,7 +66070,7 @@
if (B.JSString_methods.startsWith$1(url, "https://invoicing.co"))
secret = "";
t1 = type$.legacy_String;
headers = A.LinkedHashMap_LinkedHashMap$_literal(["X-CLIENT", A.getPlatformName(), "X-CLIENT-VERSION", "5.0.122", "X-API-SECRET", secret, "X-Requested-With", "XMLHttpRequest", "Content-Type", "application/json; charset=utf-8"], t1, t1);
headers = A.LinkedHashMap_LinkedHashMap$_literal(["X-CLIENT-PLATFORM", A.getPlatformName(), "X-CLIENT-VERSION", "5.0.123", "X-API-SECRET", secret, "X-Requested-With", "XMLHttpRequest", "Content-Type", "application/json; charset=utf-8"], t1, t1);
if (token.length !== 0)
headers.$indexSet(0, "X-API-Token", token);
if ((idToken == null ? "" : idToken).length !== 0)
@ -66094,9 +66094,9 @@
t2 = response.get$body(response).length > 200 ? B.JSString_methods.substring$2(response.get$body(response), 0, 200) : response.get$body(response);
throw A.wrapException("Error: please check that Invoice Ninja v5 is installed on the server\n\nURL: " + url + "\n\nResponse: " + t2 + "\n\nHeaders: " + t1.toString$0(0) + "}");
} else {
t1 = A.Version__compare(A.Version_parse("5.0.122"), A.Version_parse(minClientVersion));
t1 = A.Version__compare(A.Version_parse("5.0.123"), A.Version_parse(minClientVersion));
if (t1 < 0)
throw A.wrapException("Error: client not supported, please update to the latest version [Current v5.0.122 < Minimum v" + A.S(minClientVersion) + "]");
throw A.wrapException("Error: client not supported, please update to the latest version [Current v5.0.123 < Minimum v" + A.S(minClientVersion) + "]");
else {
t1 = A.Version__compare(A.Version_parse(serverVersion), A.Version_parse("5.0.4"));
if (t1 < 0)
@ -392504,7 +392504,7 @@
version = "v" + (t1 == null ? "" : t1);
if (version.length !== 0)
version += "-";
return B.JSString_methods.$add(version + A.getPlatformLetter(), B.JSArray_methods.get$last("5.0.122".split(".")));
return B.JSString_methods.$add(version + A.getPlatformLetter(), B.JSArray_methods.get$last("5.0.123".split(".")));
},
get$historyList() {
var _this = this,
@ -455903,10 +455903,10 @@
};
A.DocumentTile_build_closure.prototype = {
call$1(context) {
var t3, _null = null,
var t2, t3, _null = null,
t1 = A._setArrayType([], type$.JSArray_legacy_PopupMenuEntry_legacy_String),
t2 = this.$this.document.name;
if (B.JSString_methods.endsWith$1(t2, ".png") || B.JSString_methods.endsWith$1(t2, ".jpg") || B.JSString_methods.endsWith$1(t2, ".jpeg")) {
fileName = this.$this.document.name.toLowerCase();
if (B.JSString_methods.endsWith$1(fileName, ".png") || B.JSString_methods.endsWith$1(fileName, ".jpg") || B.JSString_methods.endsWith$1(fileName, ".jpeg") || B.JSString_methods.endsWith$1(fileName, ".bmp") || B.JSString_methods.endsWith$1(fileName, ".webp")) {
t2 = this.localization;
t1.push(A.PopupMenuItem$(new A.IconText(t2.get$view(t2), B.IconData_58458_MaterialIcons_null_false, _null, _null, false, _null), t2.get$view(t2), type$.legacy_String));
}

View File

@ -1 +1 @@
{"app_name":"invoiceninja_flutter","version":"5.0.122","build_number":"122","package_name":"invoiceninja_flutter"}
{"app_name":"invoiceninja_flutter","version":"5.0.123","build_number":"123","package_name":"invoiceninja_flutter"}

View File

@ -0,0 +1,98 @@
@php
//$mobile = stripos(request()->server('HTTP_USER_AGENT'), 'Android') || stripos(request()->server('HTTP_USER_AGENT'), 'iPhone') || stripos(request()->server('HTTP_USER_AGENT'), 'iPod') || stripos(request()->server('HTTP_USER_AGENT'), 'iPad');
$mobile = false;
@endphp
@push('head')
<meta name="pdf-url" content="{{ $url ?? $entity->pdf_file_path($invitation, 'url', true) }}?cache_buster={{time()}}">
<script src="{{ asset('js/vendor/pdf.js/pdf.min.js') }}"></script>
@endpush
<div class="flex items-center justify-between mt-4">
<section class="flex items-center">
<div class="items-center" style="{{ $mobile ? '' : 'display: none' }}" id="pagination-button-container">
<button class="input-label focus:outline-none hover:text-blue-600 transition ease-in-out duration-300"
id="previous-page-button" title="Previous page">
<svg class="w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
</svg>
</button>
<button class="input-label focus:outline-none hover:text-blue-600 transition ease-in-out duration-300"
id="next-page-button" title="Next page">
<svg class="w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
<span class="text-sm text-gray-700 ml-2 {{ $mobile ? 'block' : 'hidden' }}">{{ ctrans('texts.page') }}:
<span id="current-page-container"></span>
<span>{{ strtolower(ctrans('texts.of')) }}</span>
<span id="total-page-container"></span>
</span>
</section>
<section class="flex items-center space-x-1">
<div class="flex items-center mr-4 space-x-1 {{ $mobile ? 'block' : 'hidden' }}">
<span class="text-gray-600 mr-2" id="zoom-level">100%</span>
<a href="#" id="zoom-in">
<svg class="text-gray-400 hover:text-gray-600 focus:outline-none focus:text-gray-600 cursor-pointer"
xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
<line x1="11" y1="8" x2="11" y2="14"></line>
<line x1="8" y1="11" x2="14" y2="11"></line>
</svg>
</a>
<a href="#" id="zoom-out">
<svg class="text-gray-400 hover:text-gray-600 focus:outline-none focus:text-gray-600 cursor-pointer"
xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
<line x1="8" y1="11" x2="14" y2="11"></line>
</svg>
</a>
</div>
<div x-data="{ open: false }" @keydown.escape="open = false" @click.away="open = false"
class="relative inline-block text-left">
<div>
<button @click="open = !open"
class="flex items-center text-gray-400 hover:text-gray-600 focus:outline-none focus:text-gray-600">
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
<path
d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" />
</svg>
</button>
</div>
<div x-show="open" x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="transform opacity-0 scale-95"
x-transition:enter-end="transform opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="transform opacity-100 scale-100"
x-transition:leave-end="transform opacity-0 scale-95"
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg">
<div class="rounded-md bg-white ring-1 ring-black ring-opacity-5">
<div class="py-1">
<a target="_blank" href="{{ $fullscreen_url ?? '?mode=fullscreen' }}"
class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900">{{ ctrans('texts.open_in_new_tab') }}</a>
</div>
</div>
</div>
</div>
</section>
</div>
@if($mobile)
<div class="w-full h-full overflow-auto mt-4">
<canvas id="pdf-placeholder" class="shadow rounded-lg bg-white"></canvas>
</div>
@else
<iframe id="pdf-iframe" src="{{ $url ?? $entity->pdf_file_path($invitation, 'url', true) }}?cache_buster={{time()}}" class="h-screen w-full border-0 mt-4"></iframe>
@endif
@if($mobile)
@push('footer')
<script src="{{ asset('js/clients/shared/pdf.js') }}" defer></script>
@endpush
@endif

View File

@ -44,7 +44,7 @@
<button onclick="setTimeout(() => this.disabled = true, 0); setTimeout(() => this.disabled = false, 5000); return true;" id="pdf-download" class="button button-primary bg-primary mt-4 md:mt-0">{{ ctrans('texts.download') }}</button>
</div>
@include('portal.ninja2020.components.pdf-viewer', ['url' => route('client.statement.raw')])
@include('portal.ninja2020.components.statement-pdf-viewer', ['url' => route('client.statement.raw')])
@endsection

View File

@ -1,45 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class CreditsTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPageLoads()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.credits.index')
->assertSeeIn('span[data-ref="meta-title"]', 'Credits')
->visitRoute('client.logout');
});
}
}

View File

@ -1,45 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class DocumentsTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPageLoads()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.documents.index')
->assertSee('Documents')
->visitRoute('client.logout');
});
}
}

View File

@ -1,127 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\AuthorizeNet;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class CreditCardTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
if (getenv('GITHUB_ACTIONS')) {
$this->markTestSkipped('Skipping Authorize.net (GitHub Actions)');
}
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', '3b6621f970ab18887c4f6dca78d3f8bb')->restore();
}
public function testPayWithNewCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->type('card-number', '4007000000027')
->type('card-holders-name', 'John Doe')
->type('.expiry', '12/28')
->type('cvc', '100')
->press('Pay Now')
->waitForText('Details of the payment', 60);
});
}
public function testPayWithNewCardAndSaveForFutureUse()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->radio('#proxy_is_default', true)
->type('card-number', '4007000000027')
->type('card-holders-name', 'John Doe')
->type('.expiry', '12/28')
->type('cvc', '100')
->press('Pay Now')
->waitForText('Details of the payment', 60)
->visitRoute('client.payment_methods.index')
->clickLink('View')
->assertSee('0027');
});
}
public function testPayWithSavedCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->click('.toggle-payment-with-token')
->press('Pay Now')
->waitForText('Details of the payment', 60);
});
}
public function testRemoveCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->clickLink('View')
->press('Remove Payment Method')
->waitForText('Confirmation')
->click('@confirm-payment-removal')
->assertSee('Payment method has been successfully removed.');
});
}
public function testAddingCreditCardStandalone()
{
$this->markTestIncomplete("E00117 OTS Service Error 'Field validation error.'");
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->press('Add Payment Method')
->clickLink('Credit Card')
->type('card-number', '4012888818888')
->type('card-holders-name', 'John Doe')
->type('.expiry', '12/28')
->type('cvc', '900')
->press('Add Payment Method')
->waitForText('0027', 60);
});
}
}

View File

@ -1,91 +0,0 @@
<?php
namespace Tests\Browser\ClientPortal\Gateways\Braintree;
use App\DataMapper\FeesAndLimits;
use App\Models\Company;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class ACHTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', 'f7ec488676d310683fb51802d076d713')->restore();
$cg = CompanyGateway::where('gateway_key', 'f7ec488676d310683fb51802d076d713')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::BANK_TRANSFER} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
$company = Company::first();
$settings = $company->settings;
$settings->client_portal_allow_under_payment = true;
$settings->client_portal_allow_over_payment = true;
$company->settings = $settings;
$company->save();
}
public function testAddingBankAccount()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->press('Add Payment Method')
->clickLink('Bank Account')
->type('#account-holder-name', 'John Doe')
->type('#account-number', '1000000000')
->type('#routing-number', '011000015')
->type('#billing-postal-code', '12345')
->press('Add Payment Method')
->waitForText('Added payment method.');
});
}
public function testPayingWithExistingACH()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Bank Transfer')
->click('.toggle-payment-with-token')
->press('Pay Now')
->waitForText('Details of the payment', 60);
});
}
public function testRemoveACHAccount()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->clickLink('View')
->press('Remove Payment Method')
->waitForText('Confirmation')
->click('@confirm-payment-removal')
->assertSee('Payment method has been successfully removed.');
});
}
}

View File

@ -1,145 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Braintree;
use App\DataMapper\FeesAndLimits;
use App\Models\Company;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class CreditCardTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', 'f7ec488676d310683fb51802d076d713')->restore();
$cg = CompanyGateway::where('gateway_key', 'f7ec488676d310683fb51802d076d713')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::CREDIT_CARD} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
$company = Company::first();
$settings = $company->settings;
$settings->client_portal_allow_under_payment = true;
$settings->client_portal_allow_over_payment = true;
$company->settings = $settings;
$company->save();
}
public function testPayWithNewCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->type('@underpayment-input', '100')
->press('Pay Now')
->clickLink('Credit Card')
->waitFor('#braintree-hosted-field-number', 60)
->withinFrame('#braintree-hosted-field-number', function (Browser $browser) {
$browser->type('credit-card-number', '4111111111111111');
})
->withinFrame('#braintree-hosted-field-expirationDate', function (Browser $browser) {
$browser->type('expiration', '04/25');
})
->press('Pay Now')
->waitForText('Details of the payment', 60);
});
}
public function testPayWithNewCardAndSaveForFuture()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->type('@underpayment-input', '100')
->press('Pay Now')
->clickLink('Credit Card')
->waitFor('#braintree-hosted-field-number', 60)
->withinFrame('#braintree-hosted-field-number', function (Browser $browser) {
$browser->typeSlowly('credit-card-number', '4005519200000004');
})
->withinFrame('#braintree-hosted-field-expirationDate', function (Browser $browser) {
$browser->typeSlowly('expiration', '04/25');
})
->radio('#proxy_is_default', true)
->press('Pay Now')
->waitForText('Details of the payment', 60)
->visitRoute('client.payment_methods.index')
->clickLink('View')
->assertSee('0004');
});
}
public function testPayWithSavedCard()
{
$this->markTestSkipped('Works in "real" browser, otherwise giving error code 0.');
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->type('@underpayment-input', '100')
->press('Pay Now')
->clickLink('Credit Card')
->click('.toggle-payment-with-token')
->click('#pay-now-with-token')
->waitForText('Details of the payment', 60);
});
}
public function testRemoveCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->clickLink('View')
->press('Remove Payment Method')
->waitForText('Confirmation')
->click('@confirm-payment-removal')
->assertSee('Payment method has been successfully removed.');
});
}
public function testAddingPaymentMethodShouldntBePossible()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->press('Add Payment Method')
->clickLink('Credit Card')
->assertSee('This payment method can be can saved for future use, once you complete your first transaction. Don\'t forget to check "Store credit card details" during payment process.');
});
}
}

View File

@ -1,45 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Braintree;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class PayPalTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', 'f7ec488676d310683fb51802d076d713')->restore();
}
public function testOffsitePayment()
{
$this->markTestSkipped('Sometimes after redirect PayPal shows the register-like page with credit card, sometimes is login page.');
}
}

View File

@ -1,127 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\CheckoutCom;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class CreditCardTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', '3758e7f7c6f4cecf0f4f348b9a00f456')->restore();
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPayWithNewCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('cardnumber', '4242424242424242')
->type('exp-date', '04/22')
->type('cvc', '100');
})
->press('#pay-button')
->waitForText('Details of the payment', 60);
});
}
public function testPayWithNewCardAndSaveForFutureUse()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('cardnumber', '4242424242424242')
->type('exp-date', '04/22')
->type('cvc', '100');
})
->radio('#proxy_is_default', true)
->press('#pay-button')
->waitForText('Details of the payment', 60)
->visitRoute('client.payment_methods.index')
->clickLink('View')
->assertSee('4242');
});
}
public function testPayWithSavedCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->click('.toggle-payment-with-token')
->click('#pay-now-with-token')
->waitForText('Details of the payment', 60);
});
}
public function testRemoveCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->clickLink('View')
->press('Remove Payment Method')
->waitForText('Confirmation')
->click('@confirm-payment-removal')
->assertSee('Payment method has been successfully removed.');
});
}
public function testAddingCreditCardStandalone()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->press('Add Payment Method')
->clickLink('Credit Card')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('cardnumber', '4242424242424242')
->type('exp-date', '04/22')
->type('cvc', '100');
})
->press('#pay-button')
->waitForText('Details of payment method', 60);
});
}
}

View File

@ -1,125 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Eway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class CreditCardTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPaymentWithNewCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->click('@pay-now-dropdown')
->clickLink('Credit Card')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('EWAY_CARDNAME', 'Invoice Ninja')
->type('EWAY_CARDNUMBER', '4111 1111 1111 1111')
->type('EWAY_CARDEXPIRY', '04/22')
->type('EWAY_CARDCVN', '100');
})
->click('#pay-now')
->waitForText('Details of the payment', 60);
});
}
public function testPayWithNewCardAndSaveForFutureUse()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->click('@pay-now-dropdown')
->clickLink('Credit Card')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('EWAY_CARDNAME', 'Invoice Ninja')
->type('EWAY_CARDNUMBER', '4111 1111 1111 1111')
->type('EWAY_CARDEXPIRY', '04/22')
->type('EWAY_CARDCVN', '100');
})
->radio('#proxy_is_default', true)
->click('#pay-now')
->waitForText('Details of the payment', 60)
->visitRoute('client.payment_methods.index')
->clickLink('View')
->assertSee('1111');
});
}
public function testPayWithSavedCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->click('@pay-now-dropdown')
->clickLink('Credit Card')
->click('.toggle-payment-with-token')
->click('#pay-now')
->waitForText('Details of the payment', 60);
});
}
public function testRemoveCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->clickLink('View')
->press('Remove Payment Method')
->waitForText('Confirmation')
->click('@confirm-payment-removal')
->assertSee('Payment method has been successfully removed.');
});
}
public function testAddingCreditCardStandalone()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->press('Add Payment Method')
->clickLink('Credit Card')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('EWAY_CARDNAME', 'Invoice Ninja')
->type('EWAY_CARDNUMBER', '4111 1111 1111 1111')
->type('EWAY_CARDEXPIRY', '04/22')
->type('EWAY_CARDCVN', '100');
})
->press('Add Payment Method')
->waitForText('**** 1111');
});
}
}

View File

@ -1,42 +0,0 @@
<?php
namespace Tests\Browser\ClientPortal\Gateways\GoCardless;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class ACHTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', 'b9886f9257f0c6ee7c302f1c74475f6c')->restore();
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPayingWithNoPreauthorizedIsntPossible()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Bank Transfer')
->assertSee('To pay with a bank account, first you have to add it as payment method.');
});
}
}

View File

@ -1,42 +0,0 @@
<?php
namespace Tests\Browser\ClientPortal\Gateways\GoCardless;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class DirectDebitTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', 'b9886f9257f0c6ee7c302f1c74475f6c')->restore();
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPayingWithNoPreauthorizedIsntPossible()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Direct Debit')
->assertSee('To pay with a bank account, first you have to add it as payment method.');
});
}
}

View File

@ -1,42 +0,0 @@
<?php
namespace Tests\Browser\ClientPortal\Gateways\GoCardless;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class SEPATest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', 'b9886f9257f0c6ee7c302f1c74475f6c')->restore();
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPayingWithNoPreauthorizedIsntPossible()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('SEPA Direct Debit')
->assertSee('To pay with a bank account, first you have to add it as payment method.');
});
}
}

View File

@ -1,102 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Mollie;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class BancontactTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', '1bd651fb213ca0c9d66ae3c336dc77e8')->restore();
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testSuccessfulPayment(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Bancontact')
->waitForText('Test profile')
->radio('final_state', 'paid')
->press('Continue')
->waitForText('Details of the payment')
->assertSee('Completed');
});
}
public function testOpenPayments(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Bancontact')
->waitForText('Test profile')
->radio('final_state', 'open')
->press('Continue')
->waitForText('Details of the payment')
->assertSee('Pending');
});
}
public function testFailedPayment(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Bancontact')
->waitForText('Test profile')
->radio('final_state', 'failed')
->press('Continue')
->waitForText('Failed.');
});
}
public function testCancelledTest(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Bancontact')
->waitForText('Test profile')
->radio('final_state', 'canceled')
->press('Continue')
->waitForText('Cancelled.');
});
}
}

View File

@ -1,72 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Mollie;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class BankTransferTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', '1bd651fb213ca0c9d66ae3c336dc77e8')->restore();
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testSuccessfulPayment(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Bank Transfer')
->waitForText('Test profile')
->radio('final_state', 'paid')
->press('Continue')
->waitForText('Details of the payment')
->assertSee('Completed');
});
}
public function testPendingPayment(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Bank Transfer')
->waitForText('Test profile')
->radio('final_state', 'open')
->press('Continue')
->waitForText('Details of the payment')
->assertSee('Pending');
});
}
}

View File

@ -1,134 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Mollie;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class CreditCardTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', '1bd651fb213ca0c9d66ae3c336dc77e8')->restore();
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPayWithNewCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->pause(5000)
->withinFrame('iframe[name=cardNumber-input]', function (Browser $browser) {
$browser->type('#cardNumber', '4242424242424242');
})
->withinFrame('iframe[name=cardHolder-input]', function (Browser $browser) {
$browser->type('#cardHolder', 'Invoice Ninja Test Suite');
})
->withinFrame('iframe[name=expiryDate-input]', function (Browser $browser) {
$browser->type('#expiryDate', '12/29');
})
->withinFrame('iframe[name=verificationCode-input]', function (Browser $browser) {
$browser->type('#verificationCode', '100');
})
->press('Pay Now')
->waitForText('Details of the payment', 60);
});
}
public function testPayWithNewCreditCardAndSaveForFutureUse()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->pause(5000)
->withinFrame('iframe[name=cardNumber-input]', function (Browser $browser) {
$browser->type('#cardNumber', '4242424242424242');
})
->withinFrame('iframe[name=cardHolder-input]', function (Browser $browser) {
$browser->type('#cardHolder', 'Invoice Ninja Test Suite');
})
->withinFrame('iframe[name=expiryDate-input]', function (Browser $browser) {
$browser->type('#expiryDate', '12/29');
})
->withinFrame('iframe[name=verificationCode-input]', function (Browser $browser) {
$browser->type('#verificationCode', '100');
})
->radio('#proxy_is_default', true)
->press('Pay Now')
->waitForText('Details of the payment', 60)
->visitRoute('client.payment_methods.index')
->clickLink('View')
->assertSee('4242');
});
}
public function testPayWithSavedCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->click('.toggle-payment-with-token')
->press('Pay Now')
->waitForText('Details of the payment', 60);
});
}
public function testAddingPaymentMethodShouldntBePossible()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->press('Add Payment Method')
->clickLink('Credit Card')
->assertSee('This payment method can be can saved for future use, once you complete your first transaction. Don\'t forget to check "Store credit card details" during payment process.');
});
}
public function testRemoveCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->clickLink('View')
->press('Remove Payment Method')
->waitForText('Confirmation')
->click('@confirm-payment-removal')
->assertSee('Payment method has been successfully removed.');
});
}
}

View File

@ -1,106 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Mollie;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class IDEALTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', '1bd651fb213ca0c9d66ae3c336dc77e8')->restore();
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testSuccessfulPayment(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('iDEAL')
->waitForText('Test profile')
->press('ABN AMRO')
->radio('final_state', 'paid')
->press('Continue')
->waitForText('Details of the payment')
->assertSee('Completed');
});
}
public function testOpenPayment(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('iDEAL')
->waitForText('Test profile')
->press('ABN AMRO')
->radio('final_state', 'open')
->press('Continue')
->waitForText('Details of the payment')
->assertSee('Pending');
});
}
public function testFailedPayment(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('iDEAL')
->waitForText('Test profile')
->press('ABN AMRO')
->radio('final_state', 'failed')
->press('Continue')
->waitForText('Failed.');
});
}
public function testCancelledPayment(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('iDEAL')
->waitForText('Test profile')
->press('ABN AMRO')
->radio('final_state', 'canceled')
->press('Continue')
->waitForText('Cancelled.');
});
}
}

View File

@ -1,89 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Mollie;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class KBCTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', '1bd651fb213ca0c9d66ae3c336dc77e8')->restore();
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testSuccessfulPayment(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Undefined.')
->waitForText('Test profile')
->press('CBC')
->radio('final_state', 'paid')
->press('Continue')
->waitForText('Details of the payment')
->assertSee('Completed');
});
}
public function testFailedPayment(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Undefined.')
->waitForText('Test profile')
->press('CBC')
->radio('final_state', 'failed')
->press('Continue')
->waitForText('Failed.');
});
}
public function testCancelledTest(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Undefined.')
->waitForText('Test profile')
->press('CBC')
->radio('final_state', 'canceled')
->press('Continue')
->waitForText('Cancelled.');
});
}
}

View File

@ -1,40 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\PayPal;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class PayPalTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testOffsitePayment()
{
$this->markTestSkipped('Sometimes after redirect PayPal shows the register-like page with credit card, sometimes is login page.');
}
}

View File

@ -1,62 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\PayTrace;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class CreditCardTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', 'bbd736b3254b0aabed6ad7fda1298c88')->restore();
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPayingWithNewCreditCard()
{
$this->markTestSkipped('Credit card not supported.');
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('CC', '4012000098765439')
->select('EXP_MM', '12')
->select('EXP_YY', '30')
->type('SEC', '999');
})
->press('Pay Now')
->waitForText('Details of the payment', 60);
});
}
}

View File

@ -1,128 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Square;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class CreditCardTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPaymentWithNewCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->click('@pay-now-dropdown')
->clickLink('Credit Card')
->type('#cardholder-name', 'John Doe')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('#cardNumber', '4111 1111 1111 1111')
->type('#expirationDate', '04/22')
->type('#cvv', '1111')
->type('#postalCode', '12345');
})
->click('#pay-now')
->waitForText('Details of the payment', 60);
});
}
public function testPayWithNewCardAndSaveForFutureUse()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->click('@pay-now-dropdown')
->clickLink('Credit Card')
->type('#cardholder-name', 'John Doe')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('#cardNumber', '4111 1111 1111 1111')
->type('#expirationDate', '04/22')
->type('#cvv', '1111')
->type('#postalCode', '12345');
})
->radio('#proxy_is_default', true)
->click('#pay-now')
->waitForText('Details of the payment', 60)
->visitRoute('client.payment_methods.index')
->clickLink('View')
->assertSee('4242');
});
}
public function testPayWithSavedCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->click('@pay-now-dropdown')
->clickLink('Credit Card')
->click('.toggle-payment-with-token')
->click('#pay-now')
->waitForText('Details of the payment', 60);
});
}
public function testRemoveCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->clickLink('View')
->press('Remove Payment Method')
->waitForText('Confirmation')
->click('@confirm-payment-removal')
->assertSee('Payment method has been successfully removed.');
});
}
public function testAddingCreditCardStandalone()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->press('Add Payment Method')
->clickLink('Credit Card')
->type('#cardholder-name', 'John Doe')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('#cardNumber', '4111 1111 1111 1111')
->type('#expirationDate', '04/22')
->type('#cvv', '1111')
->type('#postalCode', '12345');
})
->press('Add Payment Method')
->waitForText('**** 1111');
});
}
}

View File

@ -1,133 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Stripe;
use App\DataMapper\FeesAndLimits;
use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class ACHTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
// Enable ACH.
$cg = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::BANK_TRANSFER} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
// ACH required US to be billing country.
$client = Client::first();
$client->country_id = 840;
$client->save();
}
public function testAddingACHAccountAndVerifyingIt()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->press('Add Payment Method')
->clickLink('Bank Account')
->type('#account-holder-name', 'John Doe')
->select('#country', 'US')
->select('#currency', 'USD')
->type('#routing-number', '110000000')
->type('#account-number', '000123456789')
->check('#accept-terms')
->press('Add Payment Method')
->waitForText('ACH (Verification)', 60)
->type('@verification-1st', '32')
->type('@verification-2nd', '45')
->press('Complete Verification')
->assertSee('Verification completed successfully')
->assertSee('Bank Transfer');
});
}
public function testPayingWithExistingACH()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Bank Transfer')
->click('.toggle-payment-with-token')
->press('Pay Now')
->waitForText('Details of the payment', 60);
});
}
public function testRemoveACHAccount()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->clickLink('View')
->press('Remove Payment Method')
->waitForText('Confirmation')
->click('@confirm-payment-removal')
->assertSee('Payment method has been successfully removed.');
});
}
public function testIntegerAndMinimumValueOnVerification()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->press('Add Payment Method')
->clickLink('Bank Account')
->type('#account-holder-name', 'John Doe')
->select('#country', 'US')
->select('#currency', 'USD')
->type('#routing-number', '110000000')
->type('#account-number', '000123456789')
->check('#accept-terms')
->press('Add Payment Method')
->waitForText('ACH (Verification)', 60)
->type('@verification-1st', '0.1')
->type('@verification-2nd', '0')
->press('Complete Verification')
->assertSee('The transactions.0 must be an integer')
->assertSee('The transactions.1 must be at least 1')
->type('@verification-1st', '32')
->type('@verification-2nd', '45')
->press('Complete Verification')
->assertSee('Bank Transfer');
});
}
}

View File

@ -1,75 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Stripe;
use App\DataMapper\FeesAndLimits;
use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class ACSSTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
// Enable SOFORT.
$cg = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::ACSS} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
$client = Client::first();
$client->country_id = 276; // Change to US or Canada
$client->save();
}
public function testPayingWithACSS()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('ACSS')
->type('#acss-name', 'John Doe')
->type('#acss-name', 'John@Doe.com')
->withinFrame('iframe', function (Browser $browser) {
$browser->type('acss', '12345');
})
->click('#pay-now')
->waitForText('ACSS test payment page', 120)
->press('.common-Button.common-Button--default')
->waitForText('Details of the payment', 60);
});
}
}

View File

@ -1,71 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Stripe;
use App\DataMapper\FeesAndLimits;
use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class AlipayTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
// Enable Alipay.
$cg = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::ALIPAY} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
// Setting country to DEU (276).
$client = Client::first();
$client->country_id = 276;
$client->save();
}
public function testPayingWithAlipay()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Alipay')
->press('Pay Now')
->waitForText('Alipay test payment page', 120)
->press('.common-Button.common-Button--default')
->waitForText('Details of the payment', 60);
});
}
}

View File

@ -1,75 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Stripe;
use App\DataMapper\FeesAndLimits;
use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class BECSTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
// Enable SOFORT.
$cg = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::BECS} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
$client = Client::first();
$client->country_id = 276; // Change to austria
$client->save();
}
public function testPayingWithBECS()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('BECS')
->type('#becs-name', 'John Doe')
->type('#becs-email', 'john@doe.com')
->withinFrame('iframe', function (Browser $browser) {
$browser->type('becs-iban', '000123456');
})
->click('#pay-now')
->waitForText('BECS test payment page', 120)
->press('.common-Button.common-Button--default')
->waitForText('Details of the payment', 60);
});
}
}

View File

@ -1,71 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Stripe;
use App\DataMapper\FeesAndLimits;
use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class BancontactTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
// Enable SOFORT.
$cg = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::BANCONTACT} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
$client = Client::first();
$client->country_id = 276;
$client->save();
}
public function testPayingWithBancontact()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('EPS')
->type('#bancontact-name', 'John Doe')
->click('#pay-now')
->waitForText('Bancontact test payment page', 120)
->press('.common-Button.common-Button--default')
->waitForText('Details of the payment', 60);
});
}
}

View File

@ -1,139 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Stripe;
use App\DataMapper\FeesAndLimits;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class CreditCardTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
$cg = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::CREDIT_CARD} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
}
public function testPaymentWithNewCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->click('@pay-now-dropdown')
->clickLink('Credit Card')
->type('#cardholder-name', 'John Doe')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('cardnumber', '4242 4242 4242 4242')
->type('exp-date', '04/22')
->type('cvc', '242');
})
->click('#pay-now')
->waitForText('Details of the payment', 60);
});
}
public function testPayWithNewCardAndSaveForFutureUse()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->click('@pay-now-dropdown')
->clickLink('Credit Card')
->type('#cardholder-name', 'John Doe')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('cardnumber', '4242 4242 4242 4242')
->type('exp-date', '04/22')
->type('cvc', '242');
})
->radio('#proxy_is_default', true)
->click('#pay-now')
->waitForText('Details of the payment', 60)
->visitRoute('client.payment_methods.index')
->clickLink('View')
->assertSee('4242');
});
}
public function testPayWithSavedCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->click('@pay-now-dropdown')
->clickLink('Credit Card')
->click('.toggle-payment-with-token')
->click('#pay-now')
->waitForText('Details of the payment', 60);
});
}
public function testRemoveCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->clickLink('View')
->press('Remove Payment Method')
->waitForText('Confirmation')
->click('@confirm-payment-removal')
->assertSee('Payment method has been successfully removed.');
});
}
public function testAddingCreditCardStandalone()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->press('Add Payment Method')
->clickLink('Credit Card')
->type('#cardholder-name', 'John Doe')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('cardnumber', '4242 4242 4242 4242')
->type('exp-date', '04/22')
->type('cvc', '242');
})
->press('Add Payment Method')
->waitForText('**** 4242');
});
}
}

View File

@ -1,74 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Stripe;
use App\DataMapper\FeesAndLimits;
use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class EPSTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
// Enable SOFORT.
$cg = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::EPS} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
$client = Client::first();
$client->country_id = 276;
$client->save();
}
public function testPayingWithEPS()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('EPS')
->type('#eps-name', 'John Doe')
->withinFrame('iframe', function (Browser $browser) {
$browser->type('eps', '12345');
})
->click('#pay-now')
->waitForText('EPS test payment page', 120)
->press('.common-Button.common-Button--default')
->waitForText('Details of the payment', 60);
});
}
}

View File

@ -1,71 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Stripe;
use App\DataMapper\FeesAndLimits;
use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class GiropayTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
// Enable SOFORT.
$cg = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::GIROPAY} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
$client = Client::first();
$client->country_id = 276;
$client->save();
}
public function testPayingWithGiropay()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Giropay')
->type('#giropay-name', 'John Doe')
->click('#pay-now')
->waitForText('Giropay test payment page', 120)
->press('.common-Button.common-Button--default')
->waitForText('Details of the payment', 60);
});
}
}

View File

@ -1,76 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Stripe;
use App\DataMapper\FeesAndLimits;
use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class Prezelewy24Test extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
// Enable SOFORT.
$cg = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::PRZELEWY24} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
$client = Client::first();
$client->country_id = 276;
$client->save();
}
public function testPayingWithPrezelewy24()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('EPS')
->type('#eps-name', 'John Doe')
->type('#eps-email', 'john@doe.com')
->check('#p24-mandate-acceptance', 'John Doe')
->withinFrame('iframe', function (Browser $browser) {
$browser->type('p24', '12345');
})
->click('#pay-now')
->waitForText('P24 test payment page', 120)
->press('.common-Button.common-Button--default')
->waitForText('Details of the payment', 60);
});
}
}

View File

@ -1,127 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Stripe;
use App\DataMapper\FeesAndLimits;
use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class SEPATest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
// Enable SEPA.
$cg = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::SEPA} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
// SEPA required DE to be billing country.
$client = Client::first();
$client->country_id = 276;
$settings = $client->settings;
$settings->currency_id = '3';
$client->settings = $settings;
$client->save();
}
public function testPayingWithNewSEPABankAccount(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->click('@pay-now-dropdown')
->clickLink('SEPA Direct Debit')
->type('#sepa-name', 'John Doe')
->type('#sepa-email-address', 'test@invoiceninja.com')
->withinFrame('iframe', function (Browser $browser) {
$browser->type('iban', 'DE89370400440532013000');
})
->check('#sepa-mandate-acceptance', true)
->click('#pay-now')
->waitForText('Details of the payment', 60);
});
}
public function testPayingWithNewSEPABankAccountAndSaveForFuture(): void
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->click('@pay-now-dropdown')
->clickLink('SEPA Direct Debit')
->type('#sepa-name', 'John Doe')
->type('#sepa-email-address', 'test@invoiceninja.com')
->withinFrame('iframe', function (Browser $browser) {
$browser->type('iban', 'DE89370400440532013000');
})
->check('#sepa-mandate-acceptance', true)
->radio('#proxy_is_default', true)
->click('#pay-now')
->waitForText('Details of the payment', 60);
});
}
public function testPayWithSavedBankAccount()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->click('@pay-now-dropdown')
->clickLink('SEPA Direct Debit')
->click('.toggle-payment-with-token')
->click('#pay-now')
->waitForText('Details of the payment', 60);
});
}
public function testRemoveBankAccount()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->clickLink('View')
->press('Remove Payment Method')
->waitForText('Confirmation')
->click('@confirm-payment-removal')
->assertSee('Payment method has been successfully removed.');
});
}
}

View File

@ -1,72 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Stripe;
use App\DataMapper\FeesAndLimits;
use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class SofortTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
// Enable SOFORT.
$cg = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::SOFORT} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
// SOFORT required ['AUT', 'BEL', 'DEU', 'ITA', 'NLD', 'ESP'] to be billing country.
// Setting country to DEU (276).
$client = Client::first();
$client->country_id = 276;
$client->save();
}
public function testPayingWithSofort()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Sofort')
->press('Pay Now')
->waitForText('Sofort test payment page', 120)
->press('.common-Button.common-Button--default')
->waitForText('Details of the payment', 60);
});
}
}

View File

@ -1,74 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\Stripe;
use App\DataMapper\FeesAndLimits;
use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class iDEAL extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
// Enable SOFORT.
$cg = CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::IDEAL} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
$client = Client::first();
$client->country_id = 276;
$client->save();
}
public function testPayingWithiDeal()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('iDeal')
->type('#ideal-name', 'John Doe')
->withinFrame('iframe', function (Browser $browser) {
$browser->type('ideal', '12345');
})
->click('#pay-now')
->waitForText('iDeal test payment page', 120)
->press('.common-Button.common-Button--default')
->waitForText('Details of the payment', 60);
});
}
}

View File

@ -1,62 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\WePay;
use App\DataMapper\FeesAndLimits;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class ACHTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', '8fdeed552015b3c7b44ed6c8ebd9e992')->restore();
// Enable ACH.
$cg = CompanyGateway::where('gateway_key', '8fdeed552015b3c7b44ed6c8ebd9e992')->firstOrFail();
$fees_and_limits = $cg->fees_and_limits;
$fees_and_limits->{GatewayType::BANK_TRANSFER} = new FeesAndLimits();
$cg->fees_and_limits = $fees_and_limits;
$cg->save();
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPayingWithNoPreauthorizedIsntPossible()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Bank Transfer')
->assertSee('To pay with a bank account, first you have to add it as payment method.');
});
}
}

View File

@ -1,126 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal\Gateways\WePay;
use App\Models\Client;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class CreditCardTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->disableCompanyGateways();
CompanyGateway::where('gateway_key', '8fdeed552015b3c7b44ed6c8ebd9e992')->restore();
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
Client::first()->update(['postal_code' => 99501]);
}
public function testPayWithNewCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->type('card-number', '4003830171874018')
->type('card-holders-name', 'John Doe')
->type('.expiry', '12/28')
->type('cvc', '100')
->press('Pay Now')
->waitForText('Details of the payment', 60);
});
}
public function testPayWithNewCardAndSaveForFutureUse()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->type('card-number', '4003830171874018')
->type('card-holders-name', 'John Doe')
->type('.expiry', '12/28')
->type('cvc', '100')
->radio('#proxy_is_default', true)
->press('Pay Now')
->waitForText('Details of the payment', 60)
->visitRoute('client.payment_methods.index')
->clickLink('View')
->assertSee('4018');
});
}
public function testPayWithSavedCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->click('.toggle-payment-with-token')
->press('Pay Now')
->waitForText('Details of the payment', 60);
});
}
public function testRemoveCreditCard()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->clickLink('View')
->press('Remove Payment Method')
->waitForText('Confirmation')
->click('@confirm-payment-removal')
->assertSee('Payment method has been successfully removed.');
});
}
public function testAddingCreditCardStandalone()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->press('Add Payment Method')
->clickLink('Credit Card')
->waitForText('Credit Card')
->type('#cardholder_name', 'John Doe')
->type('card-number', '4003830171874018')
->type('card-holders-name', 'John Doe')
->type('.expiry', '12/28')
->type('cvc', '100')
->press('Add Payment Method')
->waitForText(4018, 60);
});
}
}

View File

@ -1,101 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class InvoicesTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPageLoads()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->assertSeeIn('span[data-ref="meta-title"]', 'Invoices')
->visitRoute('client.logout');
});
}
public function testClickingPayNowWithoutInvoices()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->press('Pay Now')
->assertSee('No payable invoices selected. Make sure you are not trying to pay draft invoice or invoice with zero balance due.')
->visitRoute('client.logout');
});
}
public function testClickingDownloadWithoutInvoices()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->press('Download')
->assertSee('No items selected.')
->visitRoute('client.logout');
});
}
public function testCheckingInvoiceAndClickingPayNow()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->check('.form-check.form-check-child')
->press('Pay Now')
->assertPathIs('/client/invoices/payment')
->visitRoute('client.logout');
});
}
public function testPayNowButtonIsntShowingWhenNoGatewaysConfigured()
{
$this->disableCompanyGateways();
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->assertDontSee('Pay Now');
});
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->assertSee('Pay Now')
->visitRoute('client.logout');
});
}
}

View File

@ -1,64 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;
class LoginTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
}
public function testLoginPage()
{
$this->browse(function (Browser $browser) {
$browser
->visit(route('client.login'))
->assertSee('Client Portal')
->type('email', 'user@example.com')
->type('password', 'password')
->press('Login');
$browser->assertPathIs('/client/invoices');
});
}
public function testLoginFormValidation()
{
$this->browse(function (Browser $browser) {
$browser
->visit(route('client.login'))
->press('Login')
->assertSee('The email field is required.')
->assertSee('The password field is required.');
});
}
public function testForgotPasswordLink()
{
$this->browse(function (Browser $browser) {
$browser
->visit(route('client.login'))
->assertSeeLink('Forgot your password?')
->clickLink('Forgot your password?')
->assertPathIs('/client/password/reset');
});
}
}

View File

@ -1,45 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class PaymentMethodsTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPageLoads()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payment_methods.index')
->assertSeeIn('span[data-ref="meta-title"]', 'Payment Methods')
->visitRoute('client.logout');
});
}
}

View File

@ -1,80 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal;
use App\Models\Client;
use App\Models\CompanyGateway;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class PaymentsTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPageLoads()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.payments.index')
->assertSeeIn('span[data-ref="meta-title"]', 'Payments')
->visitRoute('client.logout');
});
}
public function testRequiredFieldsCheck()
{
$this->disableCompanyGateways();
// Enable Stripe.
CompanyGateway::where('gateway_key', 'd14dd26a37cecc30fdd65700bfb55b23')->restore();
// Stripe requires post code.
Client::first()->update(['postal_code' => null]);
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('@pay-now')
->press('Pay Now')
->clickLink('Credit Card')
->assertSee('Postal Code')
->type('client_postal_code', 10000)
->press('Continue')
->pause(2000)
->type('#cardholder-name', 'John Doe')
->withinFrame('iframe', function (Browser $browser) {
$browser
->type('cardnumber', '4242 4242 4242 4242')
->type('exp-date', '04/22')
->type('cvc', '242');
})
->click('#pay-now')
->waitForText('Details of the payment', 60)
->visitRoute('client.logout');
});
}
}

View File

@ -1,210 +0,0 @@
<?php
namespace Tests\Browser\ClientPortal;
use Faker\Factory;
use Faker\Generator;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class ProfileSettingsTest extends DuskTestCase
{
/** @var Generator */
public $faker;
protected function setUp(): void
{
parent::setUp();
$this->faker = Factory::create();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPageLoads()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.invoices.index')
->click('button[data-ref="client-profile-dropdown"]')
->click('a[data-ref="client-profile-dropdown-settings"]')
->waitForText('Client Information')
->assertSeeIn('span[data-ref="meta-title"]', 'Client Information')
->visitRoute('client.logout');
});
}
public function testClientDetailsUpdate()
{
$original = [
'name' => $this->faker->name(),
'vat_number' => (string) $this->faker->randomNumber(6),
'phone' => $this->faker->phoneNumber(),
'website' => $this->faker->url(),
];
$this->browse(function (Browser $browser) use ($original) {
$browser
->visitRoute('client.invoices.index')
->click('button[data-ref="client-profile-dropdown"]')
->click('a[data-ref="client-profile-dropdown-settings"]')
->waitForText('Client Information');
$browser
->with('#update_contact', function (Browser $form) use ($original) {
$form
->type('#client_name', $original['name'])
->type('#client_vat_number', $original['vat_number'])
->type('#client_phone', $original['phone'])
->type('#client_website', $original['website'])
->press('Save');
})
->pause(2000)
->refresh();
$updated = [
'name' => $browser->value('#client_name'),
'vat_number' => $browser->value('#client_vat_number'),
'phone' => $browser->value('#client_phone'),
'website' => $browser->value('#client_website'),
];
$this->assertSame($original, $updated);
});
}
public function testContactDetailsUpdate()
{
$original = [
'first_name' => $this->faker->firstName(),
'last_name' => $this->faker->lastName(),
'email_address' => 'user@example.com',
'phone' => $this->faker->phoneNumber(),
];
$this->browse(function (Browser $browser) use ($original) {
$browser
->visitRoute('client.invoices.index')
->click('button[data-ref="client-profile-dropdown"]')
->click('a[data-ref="client-profile-dropdown-settings"]')
->waitForText('Client Information');
$browser
->with('#update_client', function (Browser $form) use ($original) {
$form
->type('#contact_first_name', $original['first_name'])
->type('#contact_last_name', $original['last_name'])
->scrollIntoView('#contact_email_address')
->type('#contact_email_address', $original['email_address'])
->type('#contact_phone', $original['phone'])
->click('button[data-ref="update-contact-details"]');
})
->pause(2000)
->refresh();
$updated = [
'first_name' => $browser->value('#contact_first_name'),
'last_name' => $browser->value('#contact_last_name'),
'email_address' => $browser->value('#contact_email_address'),
'phone' => $browser->value('#contact_phone'),
];
$this->assertSame($original, $updated);
});
}
public function testBillingAddressUpdate()
{
$original = [
'street' => $this->faker->streetName(),
'apt' => $this->faker->streetAddress(),
'city' => $this->faker->city(),
'state' => $this->faker->state(),
'postal_code' => $this->faker->postcode(),
];
$this->browse(function (Browser $browser) use ($original) {
$browser
->visitRoute('client.invoices.index')
->click('button[data-ref="client-profile-dropdown"]')
->click('a[data-ref="client-profile-dropdown-settings"]')
->waitForText('Client Information');
$browser
->with('#update_billing_address', function (Browser $form) use ($original) {
$form
->type('#address1', $original['street'])
->type('#address2', $original['apt'])
->type('#city', $original['city'])
->type('#state', $original['state'])
->type('#postal_code', $original['postal_code'])
->select('#country')
->press('Save');
})
->pause(1000)
->refresh();
$updated = [
'street' => $browser->value('#address1'),
'apt' => $browser->value('#address2'),
'city' => $browser->value('#city'),
'state' => $browser->value('#state'),
'postal_code' => $browser->value('#postal_code'),
];
$this->assertSame($original, $updated);
});
}
public function testShippingAddressUpdate()
{
$original = [
'street' => $this->faker->streetName(),
'apt' => $this->faker->streetAddress(),
'city' => $this->faker->city(),
'state' => $this->faker->state(),
'postal_code' => $this->faker->postcode(),
];
$this->browse(function (Browser $browser) use ($original) {
$browser
->visitRoute('client.invoices.index')
->click('button[data-ref="client-profile-dropdown"]')
->click('a[data-ref="client-profile-dropdown-settings"]')
->waitForText('Client Information');
$browser
->with('#update_shipping_address', function (Browser $form) use ($original) {
$form
->type('#shipping_address1', $original['street'])
->type('#shipping_address2', $original['apt'])
->type('#shipping_city', $original['city'])
->type('#shipping_state', $original['state'])
->type('#shipping_postal_code', $original['postal_code'])
->select('#shipping_country')
->press('Save');
})
->pause(1000)
->refresh();
$updated = [
'street' => $browser->value('#shipping_address1'),
'apt' => $browser->value('#shipping_address2'),
'city' => $browser->value('#shipping_city'),
'state' => $browser->value('#shipping_state'),
'postal_code' => $browser->value('#shipping_postal_code'),
];
$this->assertSame($original, $updated);
});
}
}

View File

@ -1,105 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class QuotesTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPageLoads()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.quotes.index')
->assertSeeIn('span[data-ref="meta-title"]', 'Quotes')
->visitRoute('client.logout');
});
}
public function testClickingApproveWithoutQuotesDoesntWork()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.quotes.index')
->press('Approve')
->assertPathIs('/client/quotes');
});
}
public function testApprovingQuotes()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.quotes.index')
->check('.form-check.form-check-child')
->press('Approve')
->assertPathIs('/client/quotes/approve')
->press('Approve')
->assertPathIs('/client/quotes')
->assertSee('Quote(s) approved successfully.')
->visitRoute('client.logout');
});
}
public function testQuotesWithSentStatusCanOnlyBeApproved()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.quotes.index')
->clickLink('View')
->assertSee('Only quotes with "Sent" status can be approved.')
->visitRoute('client.logout');
});
}
public function testMessageForNonApprovableQuotesIsVisible()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.quotes.index')
->check('.form-check.form-check-child')
->press('Approve')
->assertPathIs('/client/quotes')
->assertDontSee('Quote(s) approved successfully.')
->assertSee('Only quotes with "Sent" status can be approved.')
->visitRoute('client.logout');
});
}
public function testNoQuotesAvailableForDownloadMessage()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.quotes.index')
->press('Download')
->assertSee('No quotes available for download.');
});
}
}

View File

@ -1,65 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal;
use App\Models\RecurringInvoice;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class RecurringInvoicesTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPageLoads()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.recurring_invoices.index')
->assertSeeIn('span[data-ref="meta-title"]', 'Recurring Invoices')
->visitRoute('client.logout');
});
}
public function testRequestingCancellation()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.recurring_invoices.index')
->clickLink('View')
->assertSee('Cancellation')
->press('Request Cancellation')
->pause(1000)
->waitForText('Request cancellation')
->press('Confirm')
->pause(5000)
->assertPathIs(
route('client.recurring_invoices.request_cancellation', RecurringInvoice::first()->hashed_id, false)
)
->visitRoute('client.logout');
});
}
}

View File

@ -1,45 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Browser\ClientPortal;
use Laravel\Dusk\Browser;
use Tests\Browser\Pages\ClientPortal\Login;
use Tests\DuskTestCase;
class SubscriptionsTest extends DuskTestCase
{
protected function setUp(): void
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
$this->browse(function (Browser $browser) {
$browser
->visit(new Login())
->auth();
});
}
public function testPageLoads()
{
$this->browse(function (Browser $browser) {
$browser
->visitRoute('client.subscriptions.index')
->assertSeeIn('span[data-ref="meta-title"]', 'Subscriptions')
->visitRoute('client.logout');
});
}
}

View File

@ -1,51 +0,0 @@
<?php
namespace Tests\Browser\Pages\ClientPortal;
use Laravel\Dusk\Browser;
use Laravel\Dusk\Page;
class Login extends Page
{
/**
* Get the URL for the page.
*
* @return string
*/
public function url(): string
{
return '/client/login';
}
/**
* Assert that the browser is on the page.
*
* @param Browser $browser
* @return void
*/
public function assert(Browser $browser)
{
$browser->assertPathIs($this->url());
}
/**
* Get the element shortcuts for the page.
*
* @return array
*/
public function elements()
{
return [
'@element' => '#selector',
];
}
public function auth(Browser $browser)
{
$browser
->visitRoute('client.login')
->type('email', 'user@example.com')
->type('password', 'password')
->press('Login');
}
}

View File

@ -1,2 +0,0 @@
*
!.gitignore

View File

@ -1,2 +0,0 @@
*
!.gitignore

View File

@ -1,73 +0,0 @@
<?php
namespace Tests;
use App\Models\CompanyGateway;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Laravel\Dusk\TestCase as BaseTestCase;
abstract class DuskTestCase extends BaseTestCase
{
use CreatesApplication;
/**
* Prepare for Dusk test execution.
*
* @beforeClass
* @return void
*/
public static function prepare()
{
if (! static::runningInSail()) {
static::startChromeDriver();
}
}
/**
* Create the RemoteWebDriver instance.
*
* @return RemoteWebDriver
*/
protected function driver()
{
$options = (new ChromeOptions)->addArguments(collect([
'--window-size=1920,1080',
])->unless($this->hasHeadlessDisabled(), function ($items) {
return $items->merge([
'--disable-gpu',
'--headless',
]);
})->all());
return RemoteWebDriver::create(
$_ENV['DUSK_DRIVER_URL'] ?? 'http://localhost:9515',
DesiredCapabilities::chrome()->setCapability(
ChromeOptions::CAPABILITY,
$options
)
);
}
/**
* Determine whether the Dusk command has disabled headless mode.
*
* @return bool
*/
protected function hasHeadlessDisabled()
{
return isset($_SERVER['DUSK_HEADLESS_DISABLED']) ||
isset($_ENV['DUSK_HEADLESS_DISABLED']);
}
/**
* Disable all company gateways, test classes should enable them per need.
*
* @return void
*/
public function disableCompanyGateways()
{
CompanyGateway::where('company_id', 1)->delete();
}
}