ronantakizawa/codereview-bench huggingface dataset:
Repository: freeCodeCamp/freeCodeCamp
File: api/src/utils/common-challenge-functions.ts (TypeScript)

Code before:
  // head: string;
  // tail: string;
  // seed: string;
  // id: string;
  // history: string[];

  // This value is present in prisma schema
  path?: string | null;
};

export type CompletedChallenge = {
  id: string;
  solution?: string | null;
  githubLink?: string | null;
  challengeType?: number | null;
  completedDate: number;
  isManuallyApproved?: boolean | null;
  files?: CompletedChallengeFile[];
};

/**
 * Helper function to save a user's challenge data. Used in challenge
 * submission endpoints.
 *
 * @param challengeId The id of the submitted challenge.
 * @param user The existing user record.
 * @param challenge The saveble challenge.
 * @returns Saved challenges.
 */
export function saveUserChallengeData(
  challengeId: string,
  user: user,
  challenge: Omit<SavedChallenge, 'lastSavedDate'>
) {
  const challengeToSave: SavedChallenge = {
    id: challengeId,
    lastSavedDate: Date.now(),
    files: challenge.files?.map(file =>
      pick(file, ['contents', 'key', 'name', 'ext', 'history'])
    ) as SavedChallengeFile[]
  };

  const savedIndex = user.savedChallenges.findIndex(
    ({ id }) => challengeId === id
  );

  if (savedIndex >= 0) {
    user.savedChallenges[savedIndex] = challengeToSave;
  } else {
    user.savedChallenges.push(challengeToSave);
  }

Review comment (suggestion):
```suggestion
 * @param savedChallenges The user's saved challenges.
```

Code after:
  // head: string;
  // tail: string;
  // seed: string;
  // id: string;
  // history: string[];

  // This value is present in prisma schema
  path?: string | null;
};

export type CompletedChallenge = {
  id: string;
  solution?: string | null;
  githubLink?: string | null;
  challengeType?: number | null;
  completedDate: number;
  isManuallyApproved?: boolean | null;
  files?: CompletedChallengeFile[];
};

/**
 * Helper function to save a user's challenge data. Used in challenge
 * submission endpoints.
 *
 * @param challengeId The id of the submitted challenge.
 * @param savedChallenges The user's saved challenges array.
 * @param challenge The saveble challenge.
 * @returns Update or push the saved challenges.
 */
export function saveUserChallengeData(
  challengeId: string,
  savedChallenges: SavedChallenge[],
  challenge: Omit<SavedChallenge, 'lastSavedDate'>
) {
  const challengeToSave: SavedChallenge = {
    id: challengeId,
    lastSavedDate: Date.now(),
    files: challenge.files?.map(file =>
      pick(file, ['contents', 'key', 'name', 'ext', 'history'])
    )
  };

  const savedIndex = savedChallenges.findIndex(({ id }) => challengeId === id);

  if (savedIndex >= 0) {
    savedChallenges[savedIndex] = challengeToSave;
  } else {
    savedChallenges.push(challengeToSave);
  }

  return savedChallenges;
Repository: freeCodeCamp/freeCodeCamp
File: api/src/utils/common-challenge-functions.ts (TypeScript)

Code before:
  files?: CompletedChallengeFile[];
};

/**
 * Helper function to save a user's challenge data. Used in challenge
 * submission endpoints.
 *
 * @param challengeId The id of the submitted challenge.
 * @param user The existing user record.
 * @param challenge The saveble challenge.
 * @returns Saved challenges.
 */
export function saveUserChallengeData(
  challengeId: string,
  user: user,
  challenge: Omit<SavedChallenge, 'lastSavedDate'>
) {
  const challengeToSave: SavedChallenge = {
    id: challengeId,
    lastSavedDate: Date.now(),
    files: challenge.files?.map(file =>
      pick(file, ['contents', 'key', 'name', 'ext', 'history'])
    ) as SavedChallengeFile[]
  };

  const savedIndex = user.savedChallenges.findIndex(
    ({ id }) => challengeId === id
  );

  if (savedIndex >= 0) {
    user.savedChallenges[savedIndex] = challengeToSave;
  } else {
    user.savedChallenges.push(challengeToSave);
  }

  return user.savedChallenges;
}

/**
 * Helper function to update a user's challenge data. Used in challenge
 * submission endpoints.
 *
 * @deprecated Create specific functions for each submission endpoint.
 * @param fastify The Fastify instance.
 * @param user The existing user record.
 * @param challengeId The id of the submitted challenge.
 * @param _completedChallenge The challenge submission.
 * @param timezone The user's timezone.
 * @returns Information about the update.
 */
export async function updateUserChallengeData(

Review comment (suggestion):
```suggestion
  const savedIndex = savedChallenges.findIndex(
```

Code after:
  files?: CompletedChallengeFile[];
};

/**
 * Helper function to save a user's challenge data. Used in challenge
 * submission endpoints.
 *
 * @param challengeId The id of the submitted challenge.
 * @param savedChallenges The user's saved challenges array.
 * @param challenge The saveble challenge.
 * @returns Update or push the saved challenges.
 */
export function saveUserChallengeData(
  challengeId: string,
  savedChallenges: SavedChallenge[],
  challenge: Omit<SavedChallenge, 'lastSavedDate'>
) {
  const challengeToSave: SavedChallenge = {
    id: challengeId,
    lastSavedDate: Date.now(),
    files: challenge.files?.map(file =>
      pick(file, ['contents', 'key', 'name', 'ext', 'history'])
    )
  };

  const savedIndex = savedChallenges.findIndex(({ id }) => challengeId === id);

  if (savedIndex >= 0) {
    savedChallenges[savedIndex] = challengeToSave;
  } else {
    savedChallenges.push(challengeToSave);
  }

  return savedChallenges;
}

/**
 * Helper function to update a user's challenge data. Used in challenge
 * submission endpoints.
 *
 * @deprecated Create specific functions for each submission endpoint.
 * @param fastify The Fastify instance.
 * @param user The existing user record.
 * @param challengeId The id of the submitted challenge.
 * @param _completedChallenge The challenge submission.
 * @param timezone The user's timezone.
 * @returns Information about the update.
 */
export async function updateUserChallengeData(
  fastify: FastifyInstance,
  user: user,
Repository: freeCodeCamp/freeCodeCamp
File: api/src/utils/error-formatting.ts (TypeScript)

Code before:
  message: string;
};

// TODO(Post-MVP): Normalize error responses (either msg or messge, not both)
type CodeRoadError = {
  type: 'error';
  msg: string;
};

const getError = (errors: ErrorObject[]): ErrorObject => {
  // This is a guard against accidentally enabling allErrors in ajv and making
  // the server more vulnerable to DOS.
  const error = errors[0];
  if (!error || errors.length !== 1) {
    throw new Error(
      'Bad Argument: the array of errors must have exactly one element.'
    );
  }
  return error;
};

/**
 * Format validation errors for /project-completed.
 *
 * @param errors An array of validation errors.
 * @param message Unqiue message for the function.
 * @returns Formatted errors that can be used in the response.
 */
export const formatProjectCompletedValidation = (
  errors: ErrorObject[],
  message?: FormattedError['message']
): FormattedError => {
  const error = getError(errors);

  return error.instancePath === '' &&
    error.params.missingProperty === 'solution'
    ? {
        type: 'error',
        message:
          'You have not provided the valid links for us to inspect your work.'
      }
    : {
        type: 'error',
        message:
          message ?? 'That does not appear to be a valid challenge submission.'
      };
};

/**
 * Format validation errors for /coderoad-challenge-completed.
 *

Review comment (suggestion):
```suggestion
```
I'll tidy this up in another PR, but let's keep this function simple for now.

Code after:
  message: string;
};

// TODO(Post-MVP): Normalize error responses (either msg or messge, not both)
type CodeRoadError = {
  type: 'error';
  msg: string;
};

const getError = (errors: ErrorObject[]): ErrorObject => {
  // This is a guard against accidentally enabling allErrors in ajv and making
  // the server more vulnerable to DOS.
  const error = errors[0];
  if (!error || errors.length !== 1) {
    throw new Error(
      'Bad Argument: the array of errors must have exactly one element.'
    );
  }
  return error;
};

/**
 * Format validation errors for /project-completed.
 *
 * @param errors An array of validation errors.
 * @returns Formatted errors that can be used in the response.
 */
export const formatProjectCompletedValidation = (
  errors: ErrorObject[]
): FormattedError => {
  const error = getError(errors);

  return error.instancePath === '' &&
    error.params.missingProperty === 'solution'
    ? {
        type: 'error',
        message:
          'You have not provided the valid links for us to inspect your work.'
      }
    : {
        type: 'error',
        message: 'That does not appear to be a valid challenge submission.'
      };
};

/**
 * Format validation errors for /coderoad-challenge-completed.
 *
 * @param errors An array of validation errors.
 * @returns Formatted errors that can be used in the response.
 */
Repository: freeCodeCamp/freeCodeCamp
File: api/src/schemas.ts (TypeScript)

Code before:
          'That does not appear to be a valid challenge submission.'
        )
      }),
      500: Type.Object({
        type: Type.Literal('danger'),
        message: Type.Literal(
          'Oops! Something went wrong. Please try again in a moment or contact support@freecodecamp.org if the error persists.'
        )
      })
    }
  },
  saveChallenge: {
    body: saveChallengeBody,
    response: {
      200: Type.Object({
        savedChallenges: Type.Array(
          Type.Intersect([
            saveChallengeBody,
            Type.Object({ lastSavedDate: Type.Number() })
          ])
        )
      }),
      403: Type.Object({
        type: Type.Literal('error'),
        message: Type.Literal('That challenge type is not savable.')
      }),
      500: Type.Object({
        type: Type.Literal('danger'),
        message: Type.Literal(
          'Oops! Something went wrong. Please try again in a moment or contact support@freecodecamp.org if the error persists.'
        )
      })
    }
  }
};


Review comment (suggestion):
```suggestion
      403: Type.Literal('That challenge type is not savable.'),
```
See above.

Code after:
          'That does not appear to be a valid challenge submission.'
        )
      }),
      500: Type.Object({
        type: Type.Literal('danger'),
        message: Type.Literal(
          'Oops! Something went wrong. Please try again in a moment or contact support@freecodecamp.org if the error persists.'
        )
      })
    }
  },
  saveChallenge: {
    body: saveChallengeBody,
    response: {
      200: Type.Object({
        savedChallenges: Type.Array(
          Type.Intersect([
            saveChallengeBody,
            Type.Object({ lastSavedDate: Type.Number() })
          ])
        )
      }),
      403: Type.Literal('That challenge type is not savable.'),
      500: Type.Object({
        type: Type.Literal('danger'),
        message: Type.Literal(
          'Oops! Something went wrong. Please try again in a moment or contact support@freecodecamp.org if the error persists.'
        )
      })
    }
  }
};
Repository: freeCodeCamp/freeCodeCamp
File: client/src/components/landing/components/faq.tsx (TypeScript)

Code before:
import React from 'react';
import { Col, Row } from '@freecodecamp/react-bootstrap';
import { useTranslation } from 'react-i18next';
import { Spacer } from '../../helpers';
import BigCallToAction from './big-call-to-action';

interface FaqItem {
  question: string;
  answer: string[];
}

const Faq = (): JSX.Element => {
  const { t } = useTranslation();
  const faqItems: FaqItem[] = t('landing.faqs', { returnObjects: true });

  return (
    <Row className='landing-faq'>
      <Col sm={8} smOffset={2} xs={10} xsOffset={1}>
        <h1 className='big-heading'>{t('landing.faq')}</h1>
        <Spacer size='medium' />
        {faqItems.map((faq, i) => (
          <div data-test-label='landing-page-faq' key={i}>
            <h3>{faq.question}</h3>
            {faq.answer.map((answer, i) => (
              <p key={i}>{answer}</p>
            ))}
            <Spacer size='small' />
            <Spacer size='small' />
          </div>
        ))}
        <h3>{t('landing.happy-coding')}</h3>
        <Spacer size='medium' />
        <BigCallToAction />
        <Spacer size='large' />
      </Col>
    </Row>
  );
};


Review comment (suggestion):
we can stop returning objects and the explicit type, if we give more context to the `t` function.

```suggestion
  const faqItems = t<string, string & FaqItem[]>('landing.faqs');
```

Code after:
import React from 'react';
import { Col } from '@freecodecamp/react-bootstrap';
import { useTranslation } from 'react-i18next';
import { Spacer } from '../../helpers';
import BigCallToAction from './big-call-to-action';

interface FaqItem {
  question: string;
  answer: string[];
}

const Faq = (): JSX.Element => {
  const { t } = useTranslation();
  const faqItems = t<string, string & FaqItem[]>('landing.faqs');

  return (
    <Col sm={8} smOffset={2} xs={10} xsOffset={1}>
      <h1 className='big-heading'>{t('landing.faq')}</h1>
      <Spacer size='small' />
      {faqItems.map((faq, i) => (
        <div data-test-label='landing-page-faq' key={i}>
          <p className='faq-question'>{faq.question}</p>
          {faq.answer.map((answer, i) => (
            <p key={i}>{answer}</p>
          ))}
          <Spacer size='small' />
        </div>
      ))}
      <h3>{t('learn.read-this.p12')}</h3>
      <Spacer size='medium' />
      <BigCallToAction />
      <Spacer size='large' />
    </Col>
  );
};

Faq.displayName = 'Faq';
export default Faq;
Repository: freeCodeCamp/freeCodeCamp
File: client/src/components/landing/components/faq.tsx (TypeScript)

Code before:
const Faq = (): JSX.Element => {
  const { t } = useTranslation();
  const faqItems: FaqItem[] = t('landing.faqs', { returnObjects: true });

  return (
    <Row className='landing-faq'>
      <Col sm={8} smOffset={2} xs={10} xsOffset={1}>
        <h1 className='big-heading'>{t('landing.faq')}</h1>
        <Spacer size='medium' />
        {faqItems.map((faq, i) => (
          <div data-test-label='landing-page-faq' key={i}>
            <h3>{faq.question}</h3>
            {faq.answer.map((answer, i) => (
              <p key={i}>{answer}</p>
            ))}
            <Spacer size='small' />
            <Spacer size='small' />
          </div>
        ))}
        <h3>{t('landing.happy-coding')}</h3>
        <Spacer size='medium' />
        <BigCallToAction />
        <Spacer size='large' />
      </Col>
    </Row>
  );
};

Faq.displayName = 'Faq';
export default Faq;


Review comment (suggestion):
We don't need the row element, the className. and if you are okay with making the answer one string, we can remove extra map higher function.

```suggestion
  return (
    <Col sm={8} smOffset={2} xs={10} xsOffset={1}>
      <h2 className='big-heading'>{t('landing.faq')}</h2>
      <Spacer size='medium' />
      {faqItems.map((faq, i) => (
        <div data-test-label='landing-page-faq' key={i}>
          <p className='faq-question'>{faq.question}</p>
          <p>{faq.answer}</p>
          <Spacer size='xSmall' />
        </div>
      ))}
      <p>{t('learn.read-this.p12')}</p>
      <Spacer size='medium' />
      <BigCallToAction />
      <Spacer size='large' />
    </Col>
  );
```

About the headers, they indicate that these are a section for the screen readers, but the questions aren't sections, they are part of FAQ section, so to not confuse screen reader, we can use `p` elements, because the `details` don't give a good look and will require more work.

You can add the wanted styles in landing.css file https://github.com/freeCodeCamp/freeCodeCamp/blob/f5070cc68fa4caaaf668b65f4b05eb2d4bff055b/client/src/components/landing/landing.css#L1

```css
.faq-question {
  font-weight: bold;
  font-size: 1.25rem;
}
```

Code after:
const Faq = (): JSX.Element => {
  const { t } = useTranslation();
  const faqItems = t<string, string & FaqItem[]>('landing.faqs');

  return (
    <Col sm={8} smOffset={2} xs={10} xsOffset={1}>
      <h1 className='big-heading'>{t('landing.faq')}</h1>
      <Spacer size='small' />
      {faqItems.map((faq, i) => (
        <div data-test-label='landing-page-faq' key={i}>
          <p className='faq-question'>{faq.question}</p>
          {faq.answer.map((answer, i) => (
            <p key={i}>{answer}</p>
          ))}
          <Spacer size='small' />
        </div>
      ))}
      <h3>{t('learn.read-this.p12')}</h3>
      <Spacer size='medium' />
      <BigCallToAction />
      <Spacer size='large' />
    </Col>
  );
};

Faq.displayName = 'Faq';
export default Faq;
Repository: freeCodeCamp/freeCodeCamp
File: client/src/components/landing/components/faq.tsx (TypeScript)

Code before:
import React from 'react';
import { Col, Row } from '@freecodecamp/react-bootstrap';
import { useTranslation } from 'react-i18next';
import { Spacer } from '../../helpers';
import BigCallToAction from './big-call-to-action';

interface FaqItem {
  question: string;
  answer: string[];
}

const Faq = (): JSX.Element => {
  const { t } = useTranslation();
  const faqItems: FaqItem[] = t('landing.faqs', { returnObjects: true });

  return (
    <Row className='landing-faq'>
      <Col sm={8} smOffset={2} xs={10} xsOffset={1}>
        <h1 className='big-heading'>{t('landing.faq')}</h1>
        <Spacer size='medium' />
        {faqItems.map((faq, i) => (
          <div data-test-label='landing-page-faq' key={i}>
            <h3>{faq.question}</h3>
            {faq.answer.map((answer, i) => (
              <p key={i}>{answer}</p>
            ))}
            <Spacer size='small' />

Review comment (suggestion):
```suggestion
import { Col } from '@freecodecamp/react-bootstrap';
```

Code after:
import React from 'react';
import { Col } from '@freecodecamp/react-bootstrap';
import { useTranslation } from 'react-i18next';
import { Spacer } from '../../helpers';
import BigCallToAction from './big-call-to-action';

interface FaqItem {
  question: string;
  answer: string[];
}

const Faq = (): JSX.Element => {
  const { t } = useTranslation();
  const faqItems = t<string, string & FaqItem[]>('landing.faqs');

  return (
    <Col sm={8} smOffset={2} xs={10} xsOffset={1}>
      <h1 className='big-heading'>{t('landing.faq')}</h1>
      <Spacer size='small' />
      {faqItems.map((faq, i) => (
        <div data-test-label='landing-page-faq' key={i}>
          <p className='faq-question'>{faq.question}</p>
          {faq.answer.map((answer, i) => (
            <p key={i}>{answer}</p>
          ))}
          <Spacer size='small' />
        </div>
Repository: freeCodeCamp/freeCodeCamp
File: api/jest.utils.ts (TypeScript)

Code before:
import request from 'supertest';

import { build } from './src/app';

declare global {
  // eslint-disable-next-line no-var
  var fastifyTestInstance: Awaited<ReturnType<typeof build>> | undefined;
}

export const getCsrfToken = (setCookies: string[]): string | undefined => {
  const csrfSetCookie = setCookies.find(str => str.includes('csrf_token'));
  const [csrfCookie] = csrfSetCookie?.split(';') ?? [];
  const [_key, csrfToken] = csrfCookie?.split('=') ?? [];

  return csrfToken;
};

export function superGet(endpoint: string): request.Test {
  return request(fastifyTestInstance?.server)
    .get(endpoint)
    .set('Origin', 'https://www.freecodecamp.org');
}

type Options = {
  sendCSRFToken: boolean;
};

// TODO: DRY out the superXs into a single superRequest function
export function superPut(
  endpoint: string,
  setCookies: string[],
  opts?: Options

Review comment (suggestion):
```suggestion
  var fastifyTestInstance: Awaited<ReturnType<typeof build>>;
```

Code after:
import request from 'supertest';

import { build } from './src/app';

type FastifyTestInstance = Awaited<ReturnType<typeof build>>;

declare global {
  // eslint-disable-next-line no-var
  var fastifyTestInstance: FastifyTestInstance;
}

type Options = {
  sendCSRFToken: boolean;
};

/* eslint-disable @typescript-eslint/naming-convention */
const requests = {
  GET: (resource: string) => request(fastifyTestInstance?.server).get(resource),
  POST: (resource: string) =>
    request(fastifyTestInstance?.server).post(resource),
  PUT: (resource: string) => request(fastifyTestInstance?.server).put(resource)
};
/* eslint-enable @typescript-eslint/naming-convention */

export const getCsrfToken = (setCookies: string[]): string | undefined => {
  const csrfSetCookie = setCookies.find(str => str.includes('csrf_token'));
  const [csrfCookie] = csrfSetCookie?.split(';') ?? [];
  const [_key, csrfToken] = csrfCookie?.split('=') ?? [];

  return csrfToken;
};
Repository: freeCodeCamp/freeCodeCamp
File: api/src/utils/default-user.ts (TypeScript)

Code before:
// TODO: audit this object to find out which properties need to be updated.
export const defaultUser = {
  about: '',
  acceptedPrivacyTerms: false,
  badges: {},
  completedChallenges: [],
  currentChallengeId: '',
  emailVerified: true,
  externalId: '',
  is2018DataVisCert: false,
  is2018FullStackCert: false,
  isApisMicroservicesCert: false,
  isBackEndCert: false,
  isBanned: false,
  isCheater: false,
  isDataAnalysisPyCertV7: false,
  isDataVisCert: false,
  isDonating: false,
  isFrontEndCert: false,
  isFrontEndLibsCert: false,
  isFullStackCert: false,
  isHonest: false,
  isInfosecCertV7: false,
  isInfosecQaCert: false,
  isJsAlgoDataStructCert: false,
  isMachineLearningPyCertV7: false,
  isQaCertV7: false,

Review comment (suggestion):
```suggestion
import { user } from "@prisma/client";

export const defaultUser: Omit<user, "id" | "email"> = {
```

I actually ran into something similar in one of my own projects - keeping a default record in sync with the schema. Found that enforcing a type helped! 

Code after:
// TODO: audit this object to find out which properties need to be updated.
import { type Prisma } from '@prisma/client';

export const defaultUser: Omit<Prisma.userCreateInput, 'email'> = {
  about: '',
  acceptedPrivacyTerms: false,
  completedChallenges: [],
  currentChallengeId: '',
  emailVerified: true, // this should be true until a user changes their email address
  externalId: '',
  is2018DataVisCert: false,
  is2018FullStackCert: false,
  isApisMicroservicesCert: false,
  isBackEndCert: false,
  isBanned: false,
  isCheater: false,
  isDataAnalysisPyCertV7: false,
  isDataVisCert: false,
  isDonating: false,
  isFrontEndCert: false,
  isFrontEndLibsCert: false,
  isFullStackCert: false,
  isHonest: false,
  isInfosecCertV7: false,
  isInfosecQaCert: false,
  isJsAlgoDataStructCert: false,
  isMachineLearningPyCertV7: false,