Skip to content

Commit e84ddf1

Browse files
authored
Merge pull request #3126 from codecrafters-io/pk-branch-4
pk-branch-4
2 parents c7edde5 + c7c72e9 commit e84ddf1

File tree

6 files changed

+85
-18
lines changed

6 files changed

+85
-18
lines changed

app/components/gift-payment-page/confirm-and-pay-step-container.hbs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,15 @@
7474
{{/if}}
7575

7676
<PrimaryButtonWithSpinner
77-
@isDisabled={{this.isProcessingPayment}}
78-
@shouldShowSpinner={{this.isProcessingPayment}}
77+
@isDisabled={{this.isProcessingPayButtonClick}}
78+
@shouldShowSpinner={{this.isProcessingPayButtonClick}}
7979
@size="large"
8080
{{on "click" this.handlePaymentButtonClick}}
8181
class="w-full sm:w-auto justify-center"
8282
data-test-pay-button
8383
>
84-
{{#if this.isProcessingPayment}}
85-
Loading...
84+
{{#if this.isProcessingPayButtonClick}}
85+
Saving...
8686
{{else}}
8787
Pay ${{this.totalAmount}}
8888

app/components/gift-payment-page/confirm-and-pay-step-container.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { PRICING_PLANS } from 'codecrafters-frontend/components/pay-page/choose-
55
import { action } from '@ember/object';
66
import { task } from 'ember-concurrency';
77
import { tracked } from '@glimmer/tracking';
8+
import window from 'ember-window-mock';
9+
import { waitFor } from '@ember/test-waiters';
810

911
interface Signature {
1012
Element: HTMLDivElement;
@@ -17,7 +19,7 @@ interface Signature {
1719

1820
export default class ConfirmAndPayStepContainer extends Component<Signature> {
1921
@tracked errorMessage: string | null = null;
20-
@tracked isProcessingPayment = false;
22+
@tracked isProcessingPayButtonClick = false;
2123

2224
pricingPlans = PRICING_PLANS;
2325

@@ -32,27 +34,26 @@ export default class ConfirmAndPayStepContainer extends Component<Signature> {
3234
}
3335

3436
@action
37+
@waitFor
3538
async handlePaymentButtonClick() {
3639
this.errorMessage = null;
37-
this.isProcessingPayment = true;
40+
this.isProcessingPayButtonClick = true;
3841

3942
try {
4043
await this.processPaymentTask.perform();
4144
} catch {
4245
this.errorMessage = 'Payment failed. Please try again.';
43-
this.isProcessingPayment = false;
46+
this.isProcessingPayButtonClick = false;
4447
}
4548
}
4649

4750
processPaymentTask = task({ keepLatest: true }, async (): Promise<void> => {
48-
// TODO: Implement actual payment processing
49-
// This would typically involve:
50-
// 1. Creating a checkout session with Stripe
51-
// 2. Redirecting to Stripe Checkout
52-
// 3. Handling the success/cancel redirects
53-
54-
// For now, simulate a delay
55-
await new Promise((resolve) => setTimeout(resolve, 2000));
51+
const response = await this.args.giftPaymentFlow.generateCheckoutSession({
52+
'success-url': `${window.location.origin}/gifts/success`,
53+
'cancel-url': `${window.location.origin}/gifts/buy?f=${this.args.giftPaymentFlow.id}`,
54+
});
55+
56+
window.location.href = response.link;
5657
});
5758
}
5859

app/models/gift-payment-flow.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
import Model, { attr } from '@ember-data/model';
2+
import { memberAction } from 'ember-api-actions';
23

34
export default class GiftPaymentFlowModel extends Model {
45
@attr('string') declare giftMessage: string;
56
@attr('string') declare pricingPlanId: string;
67
@attr('string') declare senderEmailAddress: string;
8+
9+
declare generateCheckoutSession: (
10+
this: GiftPaymentFlowModel,
11+
payload: { 'success-url': string; 'cancel-url': string },
12+
) => Promise<{ link: string }>;
713
}
14+
15+
GiftPaymentFlowModel.prototype.generateCheckoutSession = memberAction({
16+
path: 'generate-checkout-session',
17+
type: 'post',
18+
});

mirage/handlers/gift-payment-flows.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@ export default function (server) {
22
server.post('/gift-payment-flows');
33
server.patch('/gift-payment-flows/:id');
44

5-
// TODO: Add this when we implement fetching an existing payment flow
6-
// server.get('/gift-payment-flows/:id');
5+
server.get('/gift-payment-flows/:id');
6+
7+
server.post('/gift-payment-flows/:id/generate-checkout-session', function (schema, request) {
8+
const body = JSON.parse(request.requestBody);
9+
10+
if (!body['success-url']) {
11+
throw new Error('success-url is required');
12+
}
13+
14+
if (!body['cancel-url']) {
15+
throw new Error('cancel-url is required');
16+
}
17+
18+
return {
19+
link: 'https://checkout.stripe.com/test-checkout-session',
20+
};
21+
});
722
}

tests/acceptance/buy-gift-page/purchase-test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { setupWindowMock } from 'ember-window-mock/test-support';
44
import giftPaymentPage from 'codecrafters-frontend/tests/pages/gift-payment-page';
55
import testScenario from 'codecrafters-frontend/mirage/scenarios/test';
66
import percySnapshot from '@percy/ember';
7+
import windowMock from 'ember-window-mock';
78

89
module('Acceptance | buy-gift-page | purchase', function (hooks) {
910
setupApplicationTest(hooks);
@@ -28,5 +29,42 @@ module('Acceptance | buy-gift-page | purchase', function (hooks) {
2829
await percySnapshot('Gift Payment - Confirm and Pay Step');
2930

3031
await giftPaymentPage.confirmAndPayStepContainer.clickOnPayButton();
32+
assert.strictEqual(windowMock.location.href, 'https://checkout.stripe.com/test-checkout-session', 'should redirect to Stripe checkout');
33+
});
34+
35+
test('user can revisit an existing payment flow with pre-populated data', async function (assert) {
36+
testScenario(this.server);
37+
38+
// Create an existing gift payment flow with some data
39+
const existingFlow = this.server.create('gift-payment-flow', {
40+
senderEmailAddress: 'existing@codecrafters.io',
41+
giftMessage: 'This is a pre-existing gift message!',
42+
pricingPlanId: 'v1-lifetime',
43+
});
44+
45+
await giftPaymentPage.visit({ giftPaymentFlowId: existingFlow.id });
46+
assert.ok(giftPaymentPage.enterDetailsStepContainer.isVisible, 'Enter details step is visible');
47+
48+
assert.strictEqual(
49+
giftPaymentPage.enterDetailsStepContainer.senderEmailAddressInputValue,
50+
'existing@codecrafters.io',
51+
'Email address is pre-populated',
52+
);
53+
54+
assert.strictEqual(
55+
giftPaymentPage.enterDetailsStepContainer.giftMessageInputValue,
56+
'This is a pre-existing gift message!',
57+
'Gift message is pre-populated',
58+
);
59+
60+
// Continue with the flow to ensure it still works
61+
await giftPaymentPage.enterDetailsStepContainer.clickOnContinueButton();
62+
assert.ok(giftPaymentPage.choosePlanStepContainer.isVisible, 'Choose plan step is visible');
63+
64+
await giftPaymentPage.choosePlanStepContainer.clickOnContinueButton();
65+
assert.ok(giftPaymentPage.confirmAndPayStepContainer.isVisible, 'Confirm and pay step is visible');
66+
67+
await giftPaymentPage.confirmAndPayStepContainer.clickOnPayButton();
68+
assert.strictEqual(windowMock.location.href, 'https://checkout.stripe.com/test-checkout-session', 'should redirect to Stripe checkout');
3169
});
3270
});

tests/pages/gift-payment-page.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
import { clickable, fillable, visitable } from 'ember-cli-page-object';
1+
import { clickable, fillable, property, visitable } from 'ember-cli-page-object';
22
import createPage from 'codecrafters-frontend/tests/support/create-page';
33

44
export default createPage({
55
enterDetailsStepContainer: {
66
clickOnContinueButton: clickable('[data-test-continue-button]'),
77
fillInSenderEmailAddress: fillable('#sender_email_address_input'),
88
fillInGiftMessage: fillable('#gift_message_input'),
9+
senderEmailAddressInputValue: property('value', '#sender_email_address_input'),
10+
giftMessageInputValue: property('value', '#gift_message_input'),
911
scope: '[data-test-enter-details-step-container]',
1012
},
1113

0 commit comments

Comments
 (0)