Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix card form validation script with saved cards feature #151

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions assets/shop/js/card_form.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const MAX_CARD_NUMBER_LENGTH = 16;

export class CardForm {
#form;
#savedCardsSelect;
#cardDataContainer;
#cardNumber;
#cardOperatorIcon;
#cardsApi;
Expand All @@ -15,6 +17,8 @@ export class CardForm {

constructor(selector) {
this.#form = document.querySelector(selector);
this.#savedCardsSelect = this.#form.querySelector('[data-tpay-saved-card]');
this.#cardDataContainer = this.#form.querySelector('[data-tpay-card-data]');
this.#cardNumber = this.#form.querySelector('[data-tpay-card-number]');
this.#cardOperatorIcon = this.#form.querySelector('[data-tpay-card-operator-icon]');
this.#cardsApi = this.#form.querySelector('[data-tpay-cards-api]');
Expand Down Expand Up @@ -150,6 +154,7 @@ export class CardForm {
this.#cardNumber.addEventListener('keyup', this.#updateCardOperatorIcon.bind(this));
this.#expirationMonth.addEventListener('change', this.#validateExpirationDate.bind(this));
this.#expirationYear.addEventListener('change', this.#validateExpirationDate.bind(this));
this.#savedCardsSelect.addEventListener('change', this.#updateCardDataVisibility.bind(this));

this.#form.addEventListener('submit', (event) => {
if (!this.#isVisible()) {
Expand Down Expand Up @@ -230,6 +235,10 @@ export class CardForm {
this.#cardOperatorIcon.classList.remove('mastercard');
}

#updateCardDataVisibility() {
this.#cardDataContainer.style.display = this.#savedCardsSelect.selectedIndex === 0 ? 'block' : 'none';
}

#isVisaCard() {
return this.getCardNumber().startsWith('4');
}
Expand Down
2 changes: 1 addition & 1 deletion src/Form/DataTransformer/CardTypeDataTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ public function reverseTransform(mixed $value): string
return '';
}

return $value['card'];
return (string) ($value['card'] ?? '');
}
}
103 changes: 51 additions & 52 deletions templates/shop/payment/_card.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -11,66 +11,65 @@
</div>
</div>
</div>
<div class="ui horizontal divider">
{{ 'sylius.ui.or'|trans }}
</div>
{% endif %}
<div class="field">
<div class="field required" data-tpay-field>
{{ form_label(form.tpay.card.number) }}
<div class="ui left icon input">
{{ form_widget(form.tpay.card.number, {
attr: {
'data-validation-error': 'commerce_weavers_sylius_tpay.shop.pay.card.number'|trans({}, 'validators'),
'data-tpay-card-number': ''
},
}) }}
<i class="icon" data-tpay-card-operator-icon></i>
<div data-tpay-card-data>
<div class="field">
<div class="field required" data-tpay-field>
{{ form_label(form.tpay.card.number) }}
<div class="ui left icon input">
{{ form_widget(form.tpay.card.number, {
attr: {
'data-validation-error': 'commerce_weavers_sylius_tpay.shop.pay.card.number'|trans({}, 'validators'),
'data-tpay-card-number': ''
},
}) }}
<i class="icon" data-tpay-card-operator-icon></i>
</div>
<div data-tpay-error-container></div>
</div>
<div data-tpay-error-container></div>
</div>
</div>
<div class="fields">
<div class="three wide field" data-tpay-field>
{{ form_row(form.tpay.card.cvv, { attr: {
'data-validation-error': 'commerce_weavers_sylius_tpay.shop.pay.card.cvc'|trans({}, 'validators'),
'data-tpay-cvc': ''
} }) }}
<div data-tpay-error-container></div>
</div>
<div class="twelve wide field" data-tpay-field>
<div class="two fields">
<div class="field" data-tpay-field>
{{ form_row(form.tpay.card.expiration_date_month, { attr: {
'data-validation-error': 'commerce_weavers_sylius_tpay.shop.pay.card.expiration_month'|trans({}, 'validators'),
'data-tpay-expiration-month': ''
} }) }}
<div data-tpay-error-container></div>
<div class="fields">
<div class="three wide field" data-tpay-field>
{{ form_row(form.tpay.card.cvv, { attr: {
'data-validation-error': 'commerce_weavers_sylius_tpay.shop.pay.card.cvc'|trans({}, 'validators'),
'data-tpay-cvc': ''
} }) }}
<div data-tpay-error-container></div>
</div>
<div class="twelve wide field" data-tpay-field>
<div class="two fields">
<div class="field" data-tpay-field>
{{ form_row(form.tpay.card.expiration_date_month, { attr: {
'data-validation-error': 'commerce_weavers_sylius_tpay.shop.pay.card.expiration_month'|trans({}, 'validators'),
'data-tpay-expiration-month': ''
} }) }}
<div data-tpay-error-container></div>
</div>
<div class="field" data-tpay-field>
{{ form_row(form.tpay.card.expiration_date_year, {attr: {
'data-validation-error': 'commerce_weavers_sylius_tpay.shop.pay.card.expiration_year'|trans({}, 'validators'),
'data-tpay-expiration-year': ''
} }) }}
<div data-tpay-error-container></div>
</div>
</div>
<div class="field" data-tpay-field>
{{ form_row(form.tpay.card.expiration_date_year, {attr: {
'data-validation-error': 'commerce_weavers_sylius_tpay.shop.pay.card.expiration_year'|trans({}, 'validators'),
'data-tpay-expiration-year': ''
} }) }}
</div>
{% if form.tpay.save_credit_card_for_later is defined %}
<div class="three wide field" data-tpay-save-card>
{{ form_row(form.tpay.save_credit_card_for_later) }}
<div data-tpay-error-container></div>
</div>
</div>
{% endif %}
</div>
{% if form.tpay.save_credit_card_for_later is defined %}
<div class="three wide field" data-tpay-save-card>
{{ form_row(form.tpay.save_credit_card_for_later) }}
<div data-tpay-error-container></div>
</div>
{% endif %}
</div>
{{ form_row(form.tpay.card.card, { attr: {'data-tpay-encrypted-card': '' } }) }}
{{ form_row(form.tpay.card.card, { attr: {'data-tpay-encrypted-card': '' } }) }}

<input
id="sylius_checkout_complete_tpay_cards_api"
type="hidden"
value="{{ cw_tpay_get_gateway_config_value(method.gatewayConfig, 'cards_api') }}"
data-tpay-cards-api
/>
<input
id="sylius_checkout_complete_tpay_cards_api"
type="hidden"
value="{{ cw_tpay_get_gateway_config_value(method.gatewayConfig, 'cards_api') }}"
data-tpay-cards-api
/>
</div>
{% include '@CommerceWeaversSyliusTpayPlugin/shop/partial/_policies.html.twig' %}
</div>
</div>
Expand Down
10 changes: 10 additions & 0 deletions tests/Unit/Form/DataTransformer/CardTypeDataTransformerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public function test_it_returns_null_on_a_transform(): void
$this->assertSame(null, $dataTransformer->transform(true));
$this->assertSame(null, $dataTransformer->transform('string'));
$this->assertSame(null, $dataTransformer->transform(1));
$this->assertSame(null, $dataTransformer->transform([]));
}

public function test_it_returns_an_empty_string_when_trying_to_reverse_transform_a_non_array(): void
Expand All @@ -28,6 +29,15 @@ public function test_it_returns_an_empty_string_when_trying_to_reverse_transform
$this->assertSame('', $dataTransformer->reverseTransform(true));
$this->assertSame('', $dataTransformer->reverseTransform('string'));
$this->assertSame('', $dataTransformer->reverseTransform(1));
$this->assertSame('', $dataTransformer->reverseTransform([]));
}

public function test_it_returns_card_value_when_trying_to_reverse_transform_an_array_with_a_card_key(): void
{
$dataTransformer = $this->createTestSubject();

$this->assertSame('wheee!', $dataTransformer->reverseTransform(['card' => 'wheee!']));
$this->assertSame('123', $dataTransformer->reverseTransform(['card' => 123]));
}

private function createTestSubject(): DataTransformerInterface
Expand Down
Loading