verschieben des sofortigen verzichts auf das Widerrrufsrecht zum Anlegen des Events
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { cleanup, render, screen } from '@testing-library/react';
|
||||
import { CheckoutWizardProvider } from '../WizardContext';
|
||||
import { PaymentStep } from '../steps/PaymentStep';
|
||||
|
||||
const basePackage = {
|
||||
id: 1,
|
||||
price: 49,
|
||||
paddle_price_id: 'pri_test_123',
|
||||
};
|
||||
|
||||
describe('PaymentStep', () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
window.Paddle = {
|
||||
Environment: { set: vi.fn() },
|
||||
Checkout: { open: vi.fn() },
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
delete window.Paddle;
|
||||
});
|
||||
|
||||
it('renders the payment experience without crashing', async () => {
|
||||
render(
|
||||
<CheckoutWizardProvider initialPackage={basePackage} packageOptions={[basePackage]}>
|
||||
<PaymentStep />
|
||||
</CheckoutWizardProvider>,
|
||||
);
|
||||
|
||||
expect(await screen.findByText('checkout.payment_step.guided_title')).toBeInTheDocument();
|
||||
expect(screen.queryByText('checkout.legal.checkbox_digital_content_label')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -120,13 +120,12 @@ const PaddleCta: React.FC<{ onCheckout: () => Promise<void>; disabled: boolean;
|
||||
|
||||
export const PaymentStep: React.FC = () => {
|
||||
const { t, i18n } = useTranslation('marketing');
|
||||
const { selectedPackage, nextStep, paddleConfig, authUser, setPaymentCompleted } = useCheckoutWizard();
|
||||
const { selectedPackage, nextStep, paddleConfig, authUser, paymentCompleted, setPaymentCompleted } = useCheckoutWizard();
|
||||
const [status, setStatus] = useState<PaymentStatus>('idle');
|
||||
const [message, setMessage] = useState<string>('');
|
||||
const [initialised, setInitialised] = useState(false);
|
||||
const [inlineActive, setInlineActive] = useState(false);
|
||||
const [acceptedTerms, setAcceptedTerms] = useState(false);
|
||||
const [acceptedWaiver, setAcceptedWaiver] = useState(false);
|
||||
const [consentError, setConsentError] = useState<string | null>(null);
|
||||
const [couponCode, setCouponCode] = useState<string>(() => {
|
||||
if (typeof window === 'undefined') {
|
||||
@@ -171,7 +170,6 @@ export const PaymentStep: React.FC = () => {
|
||||
}, [i18n.language]);
|
||||
|
||||
const isFree = useMemo(() => (selectedPackage ? Number(selectedPackage.price) <= 0 : false), [selectedPackage]);
|
||||
const requiresImmediateWaiver = useMemo(() => Boolean(selectedPackage?.activates_immediately), [selectedPackage]);
|
||||
|
||||
const applyCoupon = useCallback(async (code: string) => {
|
||||
if (!selectedPackage) {
|
||||
@@ -263,7 +261,7 @@ export const PaymentStep: React.FC = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!acceptedTerms || (requiresImmediateWaiver && !acceptedWaiver)) {
|
||||
if (!acceptedTerms) {
|
||||
setConsentError(t('checkout.legal.checkbox_terms_error'));
|
||||
return;
|
||||
}
|
||||
@@ -285,7 +283,6 @@ export const PaymentStep: React.FC = () => {
|
||||
body: JSON.stringify({
|
||||
package_id: selectedPackage.id,
|
||||
accepted_terms: acceptedTerms,
|
||||
accepted_waiver: requiresImmediateWaiver ? acceptedWaiver : false,
|
||||
locale: paddleLocale,
|
||||
}),
|
||||
});
|
||||
@@ -317,7 +314,7 @@ export const PaymentStep: React.FC = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!acceptedTerms || (requiresImmediateWaiver && !acceptedWaiver)) {
|
||||
if (!acceptedTerms) {
|
||||
setConsentError(t('checkout.legal.checkbox_terms_error'));
|
||||
return;
|
||||
}
|
||||
@@ -362,7 +359,6 @@ export const PaymentStep: React.FC = () => {
|
||||
locale: paddleLocale,
|
||||
coupon_code: couponPreview?.coupon.code ?? undefined,
|
||||
accepted_terms: acceptedTerms,
|
||||
accepted_waiver: requiresImmediateWaiver ? acceptedWaiver : false,
|
||||
inline: inlineSupported,
|
||||
}),
|
||||
});
|
||||
@@ -792,29 +788,6 @@ export const PaymentStep: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{requiresImmediateWaiver && (
|
||||
<div className="flex items-start gap-3">
|
||||
<Checkbox
|
||||
id="checkout-waiver-free"
|
||||
checked={acceptedWaiver}
|
||||
onCheckedChange={(checked) => {
|
||||
setAcceptedWaiver(Boolean(checked));
|
||||
if (consentError) {
|
||||
setConsentError(null);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div className="space-y-1 text-sm">
|
||||
<Label htmlFor="checkout-waiver-free" className="cursor-pointer">
|
||||
{t('checkout.legal.checkbox_digital_content_label')}
|
||||
</Label>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{t('checkout.legal.hint_subscription_withdrawal')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{consentError && (
|
||||
<div className="flex items-center gap-2 text-sm text-destructive">
|
||||
<XCircle className="h-4 w-4" />
|
||||
@@ -827,7 +800,7 @@ export const PaymentStep: React.FC = () => {
|
||||
<Button
|
||||
size="lg"
|
||||
onClick={handleFreeActivation}
|
||||
disabled={freeActivationBusy || !acceptedTerms || (requiresImmediateWaiver && !acceptedWaiver)}
|
||||
disabled={freeActivationBusy || !acceptedTerms}
|
||||
>
|
||||
{freeActivationBusy && <LoaderCircle className="mr-2 h-4 w-4 animate-spin" />}
|
||||
{t('checkout.payment_step.activate_package')}
|
||||
@@ -940,30 +913,6 @@ export const PaymentStep: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{requiresImmediateWaiver && (
|
||||
<div className="flex items-start gap-3">
|
||||
<Checkbox
|
||||
id="checkout-waiver-hero"
|
||||
checked={acceptedWaiver}
|
||||
onCheckedChange={(checked) => {
|
||||
setAcceptedWaiver(Boolean(checked));
|
||||
if (consentError) {
|
||||
setConsentError(null);
|
||||
}
|
||||
}}
|
||||
className="border-white/60 data-[state=checked]:bg-white data-[state=checked]:text-[#001835]"
|
||||
/>
|
||||
<div className="space-y-1 text-sm">
|
||||
<Label htmlFor="checkout-waiver-hero" className="cursor-pointer text-white">
|
||||
{t('checkout.legal.checkbox_digital_content_label')}
|
||||
</Label>
|
||||
<p className="text-xs text-white/80">
|
||||
{t('checkout.legal.hint_subscription_withdrawal')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{consentError && (
|
||||
<div className="flex items-center gap-2 text-sm text-red-200">
|
||||
<XCircle className="h-4 w-4" />
|
||||
@@ -975,7 +924,7 @@ export const PaymentStep: React.FC = () => {
|
||||
<div className="space-y-2">
|
||||
<PaddleCta
|
||||
onCheckout={startPaddleCheckout}
|
||||
disabled={status === 'processing' || !acceptedTerms || (requiresImmediateWaiver && !acceptedWaiver)}
|
||||
disabled={status === 'processing' || !acceptedTerms}
|
||||
isProcessing={status === 'processing'}
|
||||
className={cn('bg-white text-[#001835] hover:bg-white/90', PRIMARY_CTA_STYLES)}
|
||||
/>
|
||||
@@ -1070,7 +1019,7 @@ export const PaymentStep: React.FC = () => {
|
||||
</p>
|
||||
<PaddleCta
|
||||
onCheckout={startPaddleCheckout}
|
||||
disabled={status === 'processing' || !acceptedTerms || (requiresImmediateWaiver && !acceptedWaiver)}
|
||||
disabled={status === 'processing' || !acceptedTerms}
|
||||
isProcessing={status === 'processing'}
|
||||
className={PRIMARY_CTA_STYLES}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user