Repository: freeCodeCamp/freeCodeCamp
File: e2e/donate-page-default.spec.ts (TypeScript)

Code before:

  test('should display donation page benefit 3', async () => {
    const donateText3 = page.getByTestId(pageElements.donateText3);
    await expect(donateText3).toHaveText(translations.donate['why-donate-2']);
  });

  test('should render the campers image in desktop browsers', async ({
    isMobile
  }) => {
    const figure = page.getByTestId(pageElements.campersImage);

    if (isMobile) {
      await expect(figure).not.toBeVisible();
      return;
    }

    await expect(figure).toBeVisible();
  });

  test('should display the faq heading', async () => {
    const faqHead = page.getByTestId(pageElements.faqHeading);
    await expect(faqHead).toHaveText(translations.donate.faq);
  });

  test('should display the faq list with buttons', async () => {
    for (let i = 0; i < frequentlyAskedQuestions.length; i++) {
      const frequentlyAskedQuestion = page.getByRole('button', {
        name: frequentlyAskedQuestions[i]
      });
      await frequentlyAskedQuestion.isVisible();
      await frequentlyAskedQuestion.click();
      const frequentlyAskedAnswer = frequentlyAskedAnswers[i];
      if (Array.isArray(frequentlyAskedAnswer)) {
        for (const answer of frequentlyAskedAnswer) {
          await page.getByText(answer).isVisible();
        }
      } else {
        await page.getByText(frequentlyAskedAnswer).isVisible();
      }
      await frequentlyAskedQuestion.click();
    }
  });
});


Review comment (performance):
This abstraction does make the test shorter to write, but it is quite hard to read and understand due to the nested array structure.

IMHO, we should keep the tests explicit and straight-forward as much as possible. DRY production code can speed up developer velocity, but DRY test code can slow us down. And production code can have all kind of abstractions because there are unit tests covering the expected behaviors, but we don't have any defense mechanisms for tests.

So in this case, we could just:

```ts
const faqOne = page.getByRole('button', { name:  'faqOne' });

await expect(faqOne).isVisible();
await faqOne.click();
await expect(page.getByText('answer')).toBeVisible();

const faqTwo = page.getByRole('button', { name:  'faqTwo' });
// ...
```

Code after:

    const faq4 = page.getByRole('button', {
      name: translations.donate['how-one-time']
    });
    await expect(faq4).toBeVisible();
    await faq4.click();
    await expect(
      page.getByText(
        "If you'd prefer to make one-time donations, you can support freeCodeCamp's mission whenever you have cash to spare. You can use this link to donate whatever amount feels right through PayPal."
      )
    ).toBeVisible();
    await expect(
      page.getByText(translations.donate['wire-transfer'])
    ).toBeVisible();
    await faq4.click();

    const faq5 = page.getByRole('button', {
      name: translations.donate['does-crypto']
    });
    await expect(faq5).toBeVisible();
    await faq5.click();
    await expect(
      page.getByText(translations.donate['yes-cryptocurrency'])
    ).toBeVisible();
    await faq5.click();

    const faq6 = page.getByRole('button', {
      name: translations.donate['can-check']
    });
    await expect(faq6).toBeVisible();
    await faq6.click();
    await expect(
      page.getByText(translations.donate['yes-check'])
    ).toBeVisible();
    await expect(page.getByText('Free Code Camp, Inc.')).toBeVisible();
    await expect(page.getByText('3905 Hedgcoxe Rd')).toBeVisible();
    await expect(page.getByText('PO Box 250352')).toBeVisible();
    await expect(page.getByText('Plano, TX 75025')).toBeVisible();
    await faq6.click();

    const faq7 = page.getByRole('button', {
      name: translations.donate['how-matching-gift']
    });
    await expect(faq7).toBeVisible();
    await faq7.click();
    await expect(
      page.getByText(translations.donate['employers-vary'])
    ).toBeVisible();
    await expect(
      page.getByText(translations.donate['some-volunteer'])
    ).toBeVisible();