ronantakizawa/codereview-bench huggingface dataset:
Repository: freeCodeCamp/freeCodeCamp
File: client/src/components/Donation/wallets-button.tsx (TypeScript)

Code before:
  handlePaymentButtonLoad
}: WalletsButtonProps) => {
  const [paymentMethod, setpaymentMethod] = useState<PaymentMethod | null>(
    null
  );
  const [paymentRequest, setPaymentRequest] = useState<PaymentRequest | null>(
    null
  );
  const { t } = useTranslation();

  useEffect(() => {
    if (!stripe) {
      return;
    }

    const pr = stripe.paymentRequest({
      country: 'US',
      currency: 'usd',
      total: { label, amount },
      requestPayerName: true,
      requestPayerEmail: true,
      disableWallets: ['browserCard']
    });

    pr.on('paymentmethod', async event => {
      setpaymentMethod(event.paymentMethod);
      const {
        payerEmail,
        payerName,
        paymentMethod: { id: paymentMethodId }
      } = event;
      //create payment intent
      const {
        data: { clientSecret, subscriptionId, error }
      } = await createStripePaymentIntent({
        email: payerEmail,
        name: payerName,
        amount,
        duration
      });

      if (error) {
        event.complete('fail');
        displayError(t('donate.try-another-method'));
      } else if (clientSecret) {
        // confirm payment intent
        const { paymentIntent, error: confirmError } =
          await stripe.confirmCardPayment(
            clientSecret,
            { payment_method: event.paymentMethod.id },
            { handleActions: false }

Review comment (suggestion):
```suggestion
      setPaymentMethod(event.paymentMethod);
```
Nit.

Code after:
  handlePaymentButtonLoad
}: WalletsButtonProps) => {
  const [paymentRequest, setPaymentRequest] = useState<PaymentRequest | null>(
    null
  );
  const { t } = useTranslation();

  const displayError = useCallback(
    (errorMessage: string): void => {
      onDonationStateChange({
        redirecting: false,
        processing: false,
        success: false,
        error: errorMessage
      });
    },
    [onDonationStateChange]
  );

  useEffect(() => {
    if (!stripe) {
      return;
    }

    const pr = stripe.paymentRequest({
      country: 'US',
      currency: 'usd',
      total: { label, amount },
      requestPayerName: true,
      requestPayerEmail: true,
      disableWallets: ['browserCard']
    });

    pr.on('paymentmethod', async event => {
      const {
        payerEmail,
        payerName,
        paymentMethod: { id: paymentMethodId }
      } = event;
      //create payment intent
      const {
        data: { clientSecret, subscriptionId, error }
      } = await createStripePaymentIntent({
        email: payerEmail,
        name: payerName,
        amount,
        duration
      });

      if (error) {
        event.complete('fail');
Repository: freeCodeCamp/freeCodeCamp
File: api-server/src/server/utils/donation.js (JavaScript)

Code before:

  const { customerId, subscriptionId } = donation;

  log(subscriptionId);

  // Create a Stripe checkout session
  // updating customer payment method is handled by webhook handler
  const session = await stripe.checkout.sessions.create({
    payment_method_types: ['card'],
    mode: 'setup',
    customer: customerId,
    setup_intent_data: {
      metadata: {
        customer_id: customerId,
        subscription_id: subscriptionId
      }
    },
    success_url: `${process.env.HOME_LOCATION}/update-stripe-card?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.HOME_LOCATION}/update-stripe-card`
  });
  return { sessionId: session.id };
}

export function inLastFiveMinutes(unixTimestamp) {
  const currentTimestamp = Math.floor(Date.now() / 1000);
  const timeDifference = Math.abs(currentTimestamp - unixTimestamp);
  return timeDifference <= 300; // 300 seconds is 5 minutes
}


Review comment (suggestion):
```suggestion
  const timeDifference = currentTimestamp - unixTimestamp;
```
If `unixTimestamp` is always in the past, `abs` isn't necessary. If it can be in the future, something very strange is going on!

Code after:

  const { customerId, subscriptionId } = donation;

  log(subscriptionId);

  // Create a Stripe checkout session
  // updating customer payment method is handled by webhook handler
  const session = await stripe.checkout.sessions.create({
    payment_method_types: ['card'],
    mode: 'setup',
    customer: customerId,
    setup_intent_data: {
      metadata: {
        customer_id: customerId,
        subscription_id: subscriptionId
      }
    },
    success_url: `${process.env.HOME_LOCATION}/update-stripe-card?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.HOME_LOCATION}/update-stripe-card`
  });
  return { sessionId: session.id };
}

export function inLastFiveMinutes(unixTimestamp) {
  const currentTimestamp = Math.floor(Date.now() / 1000);
  const timeDifference = currentTimestamp - unixTimestamp;
  return timeDifference <= 300; // 300 seconds is 5 minutes
}
Repository: freeCodeCamp/freeCodeCamp
File: client/src/components/Donation/wallets-button.tsx (TypeScript)

Code before:
                payerEmail,
                payerName,
                subscriptionId
              });
            }
          } else {
            postPayment({
              paymentProvider: PaymentProvider.Stripe,
              paymentMethodId,
              payerEmail,
              subscriptionId
            });
          }
        }
      }
    });

    void pr.canMakePayment().then(result => {
      if (result) setPaymentRequest(pr);
    });

    return () => {
      setPaymentRequest(null);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [label, amount, stripe, postPayment, handlePaymentButtonLoad]);

  const displayError = (errorMessage: string): void => {
    onDonationStateChange({
      redirecting: false,
      processing: false,
      success: false,
      error: errorMessage
    });
  };

  return (
    <form className='wallets-form'>
      {paymentRequest && (
        <PaymentRequestButtonElement
          onReady={() => handlePaymentButtonLoad('stripe')}
          options={{
            style: {
              paymentRequestButton: {
                type: 'default',
                theme: theme === Themes.Night ? 'light' : 'dark',
                height: '43px'
              }
            },
            paymentRequest
          }}

Review comment (suggestion):
It's tricky for me to test, but is there any reason _not_ to provide all the deps? You'd need to pull `displayError` inside the `useEffect` callback, but that seems fine.

Code after:
          event.complete('fail');
          displayError(t('donate.try-another-method'));
        } else {
          event.complete('success');
          if (paymentIntent.status === 'requires_action') {
            const { error } = await stripe.confirmCardPayment(clientSecret);
            if (error) {
              return displayError(t('donate.try-another-method'));
            }
          }
          postPayment({
            paymentProvider: PaymentProvider.Stripe,
            paymentMethodId,
            payerEmail,
            payerName,
            subscriptionId
          });
        }
      }
    });

    void pr.canMakePayment().then(result => {
      if (result) setPaymentRequest(pr);
    });

    return () => {
      setPaymentRequest(null);
    };
  }, [
    label,
    amount,
    stripe,
    postPayment,
    handlePaymentButtonLoad,
    duration,
    displayError,
    t
  ]);

  return (
    <form className='wallets-form'>
      {paymentRequest && (
        <PaymentRequestButtonElement
          onReady={() => handlePaymentButtonLoad('stripe')}
          options={{
            style: {
              paymentRequestButton: {
                type: 'default',
                theme: theme === Themes.Night ? 'light' : 'dark',
                height: '43px'
              }
Repository: freeCodeCamp/freeCodeCamp
File: e2e/report-user.spec.ts (TypeScript)

Code before:
import { test, expect } from '@playwright/test';
test.use({ storageState: 'playwright/.auth/certified-user.json' });

//TODO: run email server?

test('should be possible to report a user from their profile page', async ({
  page
}) => {
  await page.goto('/twaha');

  // The following line is required if you're running the test in local development
  // await page.getByRole('button', { name: 'Preview custom 404 page' }).click();

  await page.getByText("Flag This User's Account for Abuse").click();

  await expect(
    page.getByText("Do you want to report twaha's portfolio for abuse?")
  ).toBeVisible();

  await page.getByRole('textbox').nth(1).fill('Some details');
  await page.getByRole('button', { name: 'Submit the report' }).click();
  await expect(page).toHaveURL('/learn');
});


Review comment (suggestion):
```suggestion
```
It's not strictly necessary, since the test will pass either way.

It might be worth requiring it and checking that `flash.report-sent` appears at the end of the test.



Code after:
import { test, expect } from '@playwright/test';
test.use({ storageState: 'playwright/.auth/certified-user.json' });

// To run this test you will need to run the email server.
// To do this: https://contribute.freecodecamp.org/#/how-to-catch-outgoing-emails-locally?id=using-mailhog

test('should be possible to report a user from their profile page', async ({
  page
}) => {
  await page.goto('/twaha');

  // If you build the client locally, delete the button click below.
  if (!process.env.CI) {
    await page.getByRole('button', { name: 'Preview custom 404 page' }).click();
  }

  await page.getByText("Flag This User's Account for Abuse").click();

  await expect(
    page.getByText("Do you want to report twaha's portfolio for abuse?")
  ).toBeVisible();

  await page.getByRole('textbox').nth(1).fill('Some details');
  await page.getByRole('button', { name: 'Submit the report' }).click();
  await expect(page).toHaveURL('/learn');

  await expect(page.getByTestId('flash-message')).toBeVisible();
  await expect(page.getByTestId('flash-message')).toContainText(
    'A report was sent to the team with foo@bar.com in copy'
Repository: freeCodeCamp/freeCodeCamp
File: e2e/report-user.spec.ts (TypeScript)

Code before:
import { test, expect } from '@playwright/test';
test.use({ storageState: 'playwright/.auth/certified-user.json' });

// To run this test you will need to run the email server.
// To do this: https://contribute.freecodecamp.org/#/how-to-catch-outgoing-emails-locally?id=using-mailhog

test('should be possible to report a user from their profile page', async ({
  page
}) => {
  await page.goto('/twaha');

  // The following line is required if you're running the test in local development
  await page.getByRole('button', { name: 'Preview custom 404 page' }).click();

  await page.getByText("Flag This User's Account for Abuse").click();

  await expect(
    page.getByText("Do you want to report twaha's portfolio for abuse?")
  ).toBeVisible();

  await page.getByRole('textbox').nth(1).fill('Some details');
  await page.getByRole('button', { name: 'Submit the report' }).click();
  await expect(page).toHaveURL('/learn');

  await expect(page.getByTestId('flash-message')).toBeVisible();
  await expect(page.getByTestId('flash-message')).toContainText(
    'A report was sent to the team with foo@bar.com in copy'
  );
});


Review comment (suggestion):
```suggestion
  // If you build the client locally, delete the button click below.
  if (!process.env.CI) {
    await page.getByRole('button', { name: 'Preview custom 404 page' }).click();
  }
```
As a rough heuristic, most people working locally will be running the client in dev mode, so this should be right more often than not.

Code after:
import { test, expect } from '@playwright/test';
test.use({ storageState: 'playwright/.auth/certified-user.json' });

// To run this test you will need to run the email server.
// To do this: https://contribute.freecodecamp.org/#/how-to-catch-outgoing-emails-locally?id=using-mailhog

test('should be possible to report a user from their profile page', async ({
  page
}) => {
  await page.goto('/twaha');

  // If you build the client locally, delete the button click below.
  if (!process.env.CI) {
    await page.getByRole('button', { name: 'Preview custom 404 page' }).click();
  }

  await page.getByText("Flag This User's Account for Abuse").click();

  await expect(
    page.getByText("Do you want to report twaha's portfolio for abuse?")
  ).toBeVisible();

  await page.getByRole('textbox').nth(1).fill('Some details');
  await page.getByRole('button', { name: 'Submit the report' }).click();
  await expect(page).toHaveURL('/learn');

  await expect(page.getByTestId('flash-message')).toBeVisible();
  await expect(page.getByTestId('flash-message')).toContainText(
    'A report was sent to the team with foo@bar.com in copy'
  );
});
Repository: freeCodeCamp/freeCodeCamp
File: e2e/global-setup.ts (TypeScript)

Code before:
import { test as setup } from '@playwright/test';

setup('Login', async ({ page }) => {
  await page.goto('/');
  await page.getByRole('link', { name: 'Sign in' }).click();
  await page
    .context()
    .storageState({ path: 'playwright/.auth/certified-user.json' });
});


Review comment (security):
Quick question: Do we need to create this file as well (we currently only have `playwright/.auth/certified-user.json`)?

Code after:
import { test as setup } from '@playwright/test';

setup.describe('certifieduser', () => {
  setup('can sign in', async ({ request }) => {
    await request.get(process.env.API_LOCATION + '/signin');
    await request.storageState({
      path: 'playwright/.auth/certified-user.json'
    });
  });
});

setup.describe('developmentuser', () => {
  // We can only sign in as a single user (one with email: 'foo@bar.com'), so
  // changing users means changing the record with that email in the database.
  setup.beforeAll(() => {
    execSync('node ./tools/scripts/seed/seed-demo-user');
  });

  setup.afterAll(() => {
    execSync('node ./tools/scripts/seed/seed-demo-user certified-user');
  });

  setup('can sign in', async ({ request }) => {
    await request.get(process.env.API_LOCATION + '/signin');
    await request.storageState({
      path: 'playwright/.auth/development-user.json'
    });
  });
});
Repository: freeCodeCamp/freeCodeCamp
File: api/src/utils/normalize.ts (TypeScript)

Code before:

type NormalizedSurvey = {
  title: string;
  responses: {
    question: string;
    response: string;
  }[];
};

/**
 * Remove the extra properties from the SurveyResults array.
 *
 * @param surveyResults The SurveyResults array.
 * @returns The input without the id and userid.
 */
export const normalizeSurveys = (
  surveyResults: Survey[]
): NormalizedSurvey[] => {
  return surveyResults.map(survey => {
    const { title, responses } = survey;
    return { title, responses };
  });
};

/**
 * Replace undefined flags with false.
 * @param flags Object with nullable boolean flags.
 * @returns Same object with boolean flags, defaulting to false.
 */
export const normalizeFlags = <T extends Record<string, boolean | null>>(
  flags: T
): { [K in keyof T]: boolean } => {
  const out = {} as { [K in keyof T]: boolean };
  for (const key in flags) {
    const v = flags[key];
    out[key] = typeof v === 'boolean' ? v : false;
  }
  return out;
};


Review comment (suggestion):
```suggestion
 * Replace null flags with false.
```

Code after:

type NormalizedSurvey = {
  title: string;
  responses: {
    question: string;
    response: string;
  }[];
};

/**
 * Remove the extra properties from the SurveyResults array.
 *
 * @param surveyResults The SurveyResults array.
 * @returns The input without the id and userid.
 */
export const normalizeSurveys = (
  surveyResults: Survey[]
): NormalizedSurvey[] => {
  return surveyResults.map(survey => {
    const { title, responses } = survey;
    return { title, responses };
  });
};

/**
 * Replace null flags with false.
 * @param flags Object with nullable boolean flags.
 * @returns Same object with boolean flags, defaulting to false.
 */
export const normalizeFlags = <T extends Record<string, boolean | null>>(
  flags: T
): { [K in keyof T]: boolean } => {
  const out = {} as { [K in keyof T]: boolean };
  for (const key in flags) {
    const v = flags[key];
    out[key] = typeof v === 'boolean' ? v : false;
  }
  return out;
};
Repository: freeCodeCamp/freeCodeCamp
File: e2e/help-button.spec.ts (TypeScript)

Code before:
    //The video link is hidden
    await expect(page.getByTestId('watch-a-video')).toBeHidden();
  });
});

test.describe('help-button tests for a page with a reset and help button', () => {
  test('should not be present before the user checks their code three times', async ({
    page
  }) => {
    await page.goto(
      'learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-8'
    );
    await expect(page.getByTestId('get-help-button')).toBeHidden();
  });

  test('should be present after the user checks their code three times', async ({
    page
  }) => {
    await page.goto(
      'learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-8'
    );
    const checkButton = page.getByTestId('lowerJaw-check-button');
    await checkButton.click();
    await checkButton.click();
    await checkButton.click();
    await expect(page.getByText(translations.buttons.help)).toBeVisible();
  });
  test('icon should be invisible to screen-reader', async ({ page }) => {
    await page.goto(
      'learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-8'
    );
    const checkButton = page.getByTestId('lowerJaw-check-button');
    await checkButton.click();
    await checkButton.click();
    await checkButton.click();
    const helpButton = page.getByText(translations.buttons.help);
    const helpIconGroup = helpButton.getByRole('group', {
      includeHidden: false
    });
    await expect(helpIconGroup).toBeHidden();
  });
});


Review comment (suggestion):
```suggestion
    await expect(page.getByRole('button', { name: 'Help' })).toBeVisible();
```

Code after:
    await expect(page.getByTestId('watch-a-video')).toBeHidden();
  });
});

test.describe('help-button tests for a page with a reset and help button', () => {
  test('should not be present before the user checks their code three times', async ({
    page
  }) => {
    await page.goto(
      'learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-8'
    );
    await expect(page.getByRole('button', { name: 'Help' })).toBeHidden();
  });

  test('should be present after the user checks their code three times', async ({
    page
  }) => {
    await page.goto(
      'learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-8'
    );
    const checkButton = page.getByTestId('lowerJaw-check-button');
    await checkButton.click();
    await checkButton.click();
    await checkButton.click();
    const helpButton = page.getByRole('button', { name: 'Help' });
    await expect(helpButton).toBeVisible();
    const helpIconGroup = helpButton.getByRole('group', {
      includeHidden: false
    });
    await expect(helpIconGroup).toBeHidden();
  });
});
Repository: freeCodeCamp/freeCodeCamp
File: e2e/help-button.spec.ts (TypeScript)

Code before:

test.describe('help-button tests for a page with a reset and help button', () => {
  test('should not be present before the user checks their code three times', async ({
    page
  }) => {
    await page.goto(
      'learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-8'
    );
    await expect(page.getByTestId('get-help-button')).toBeHidden();
  });

  test('should be present after the user checks their code three times', async ({
    page
  }) => {
    await page.goto(
      'learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-8'
    );
    const checkButton = page.getByTestId('lowerJaw-check-button');
    await checkButton.click();
    await checkButton.click();
    await checkButton.click();
    await expect(page.getByText(translations.buttons.help)).toBeVisible();
  });
  test('icon should be invisible to screen-reader', async ({ page }) => {
    await page.goto(
      'learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-8'
    );
    const checkButton = page.getByTestId('lowerJaw-check-button');
    await checkButton.click();
    await checkButton.click();
    await checkButton.click();
    const helpButton = page.getByText(translations.buttons.help);
    const helpIconGroup = helpButton.getByRole('group', {
      includeHidden: false
    });
    await expect(helpIconGroup).toBeHidden();
  });
});


Review comment (performance):
I think we should merge this assertion into the "should be present..." case above. Tests like this are perfectly fine if we are writing unit tests, but with e2e it's a little too expensive with the setup and teardown time.

Code after:
test.describe('help-button tests for a page with a reset and help button', () => {
  test('should not be present before the user checks their code three times', async ({
    page
  }) => {
    await page.goto(
      'learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-8'
    );
    await expect(page.getByRole('button', { name: 'Help' })).toBeHidden();
  });

  test('should be present after the user checks their code three times', async ({
    page
  }) => {
    await page.goto(
      'learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-8'
    );
    const checkButton = page.getByTestId('lowerJaw-check-button');
    await checkButton.click();
    await checkButton.click();
    await checkButton.click();
    const helpButton = page.getByRole('button', { name: 'Help' });
    await expect(helpButton).toBeVisible();
    const helpIconGroup = helpButton.getByRole('group', {
      includeHidden: false
    });
    await expect(helpIconGroup).toBeHidden();
  });
});