ronantakizawa/codereview-bench huggingface dataset:
Repository: freeCodeCamp/freeCodeCamp
File: api/src/db/prisma.ts (TypeScript)

Code before:
import fp from 'fastify-plugin';
import { FastifyPluginAsync } from 'fastify';
import { PrismaClient } from '@prisma/client';

// importing MONGOHQ_URL so we can mock it in testing.
import { MONGOHQ_URL } from '../utils/env';

declare module 'fastify' {
  interface FastifyInstance {
    prisma: ReturnType<typeof getExtendedClient>;
  }
}

const prismaPlugin: FastifyPluginAsync = fp(async (server, _options) => {
  const prisma = getExtendedClient();

  await prisma.$connect();

  server.decorate('prisma', prisma);

  server.addHook('onClose', async server => {
    await server.prisma.$disconnect();
  });
});

// TODO: It would be nice to split this up into multiple update functions,
//       but the types are a pain.
// TODO: Multiple extended clients can be used for different restrictions (e.g. session vs non-session users)
// TODO: Could be used to add other _easily forgotten_ fields like `progressTimestamp`
function getExtendedClient() {
  const prisma = new PrismaClient({
    datasources: {
      db: {
        url: MONGOHQ_URL
      }

Review comment (suggestion):
```suggestion
    prisma: ReturnType<typeof extendClient>;
```
See below

Code after:
import fp from 'fastify-plugin';
import { FastifyPluginAsync } from 'fastify';
import { PrismaClient } from '@prisma/client';

// importing MONGOHQ_URL so we can mock it in testing.
import { MONGOHQ_URL } from '../utils/env';

declare module 'fastify' {
  interface FastifyInstance {
    prisma: ReturnType<typeof extendClient>;
  }
}

const prismaPlugin: FastifyPluginAsync = fp(async (server, _options) => {
  const prisma = extendClient(
    new PrismaClient({
      datasources: {
        db: {
          url: MONGOHQ_URL
        }
      }
    })
  );

  await prisma.$connect();

  server.decorate('prisma', prisma);

  server.addHook('onClose', async server => {
    await server.prisma.$disconnect();
  });
});

// TODO: It would be nice to split this up into multiple update functions,
//       but the types are a pain.
Repository: freeCodeCamp/freeCodeCamp
File: api/src/db/prisma.ts (TypeScript)

Code before:
import fp from 'fastify-plugin';
import { FastifyPluginAsync } from 'fastify';
import { PrismaClient } from '@prisma/client';

// importing MONGOHQ_URL so we can mock it in testing.
import { MONGOHQ_URL } from '../utils/env';

declare module 'fastify' {
  interface FastifyInstance {
    prisma: ReturnType<typeof getExtendedClient>;
  }
}

const prismaPlugin: FastifyPluginAsync = fp(async (server, _options) => {
  const prisma = getExtendedClient();

  await prisma.$connect();

  server.decorate('prisma', prisma);

  server.addHook('onClose', async server => {
    await server.prisma.$disconnect();
  });
});

// TODO: It would be nice to split this up into multiple update functions,
//       but the types are a pain.
// TODO: Multiple extended clients can be used for different restrictions (e.g. session vs non-session users)
// TODO: Could be used to add other _easily forgotten_ fields like `progressTimestamp`
function getExtendedClient() {
  const prisma = new PrismaClient({
    datasources: {
      db: {
        url: MONGOHQ_URL
      }
    }
  }).$extends({
    query: {
      user: {
        async update({ args, query }) {

Review comment (suggestion):
```suggestion
  const prisma = extendClient(
    new PrismaClient({
      datasources: {
        db: {
          url: MONGOHQ_URL
        }
      }
    })
  );
```
Separates the concerns a bit

Code after:
import fp from 'fastify-plugin';
import { FastifyPluginAsync } from 'fastify';
import { PrismaClient } from '@prisma/client';

// importing MONGOHQ_URL so we can mock it in testing.
import { MONGOHQ_URL } from '../utils/env';

declare module 'fastify' {
  interface FastifyInstance {
    prisma: ReturnType<typeof extendClient>;
  }
}

const prismaPlugin: FastifyPluginAsync = fp(async (server, _options) => {
  const prisma = extendClient(
    new PrismaClient({
      datasources: {
        db: {
          url: MONGOHQ_URL
        }
      }
    })
  );

  await prisma.$connect();

  server.decorate('prisma', prisma);

  server.addHook('onClose', async server => {
    await server.prisma.$disconnect();
  });
});

// TODO: It would be nice to split this up into multiple update functions,
//       but the types are a pain.
// TODO: Multiple extended clients can be used for different restrictions (e.g. session vs non-session users)
// TODO: Could be used to add other _easily forgotten_ fields like `progressTimestamp`
function extendClient(prisma: PrismaClient) {
  return prisma.$extends({
    query: {
Repository: freeCodeCamp/freeCodeCamp
File: api/src/db/prisma.ts (TypeScript)

Code before:
  server.decorate('prisma', prisma);

  server.addHook('onClose', async server => {
    await server.prisma.$disconnect();
  });
});

// TODO: It would be nice to split this up into multiple update functions,
//       but the types are a pain.
// TODO: Multiple extended clients can be used for different restrictions (e.g. session vs non-session users)
// TODO: Could be used to add other _easily forgotten_ fields like `progressTimestamp`
function extendClient(prisma: PrismaClient) {
  return prisma.$extends({
    query: {
      user: {
        async update({ args, query }) {
          args.data.updateCount = { increment: 1 };
          return query(args);
        },
        async updateMany({ args, query }) {
          args.data.updateCount = { increment: 1 };
          return query(args);
        },
        async upsert({ args, query }) {
          args.update.updateCount = { increment: 1 };
          args.create.updateCount = 0;
          return query(args);
        },
        async create({ args, query }) {
          args.data.updateCount = 0;
          return query(args);
        },
        async createMany({ args, query }) {
          const data = args.data;
          if (Array.isArray(data)) {
            data.forEach(data => {
              data.updateCount = 0;
            });
          } else {
            data.updateCount = 0;
          }

          return query(args);
        }
        // NOTE: raw ops are untouched, as it is meant to be a direct passthrough to mongodb
        // async findRaw({ model, operation, args, query }) {}
        // async aggregateRaw({ model, operation, args, query }) {}
      }
    }
  });
}

Review comment (suggestion):
```suggestion
```
No need, we have a default value of 0.

Code after:
  server.decorate('prisma', prisma);

  server.addHook('onClose', async server => {
    await server.prisma.$disconnect();
  });
});

// TODO: It would be nice to split this up into multiple update functions,
//       but the types are a pain.
// TODO: Multiple extended clients can be used for different restrictions (e.g. session vs non-session users)
// TODO: Could be used to add other _easily forgotten_ fields like `progressTimestamp`
function extendClient(prisma: PrismaClient) {
  return prisma.$extends({
    query: {
      user: {
        async update({ args, query }) {
          args.data.updateCount = { increment: 1 };
          return query(args);
        },
        async updateMany({ args, query }) {
          args.data.updateCount = { increment: 1 };
          return query(args);
        },
        async upsert({ args, query }) {
          args.update.updateCount = { increment: 1 };
          return query(args);
        }
        // NOTE: raw ops are untouched, as it is meant to be a direct passthrough to mongodb
        // async findRaw({ model, operation, args, query }) {}
        // async aggregateRaw({ model, operation, args, query }) {}
      }
    }
  });
}

export default prismaPlugin;
Repository: freeCodeCamp/freeCodeCamp
File: client/src/components/helpers/button-link.tsx (TypeScript)

Code before:
import React, { useMemo } from 'react';
import { Link as GatsbyLink } from 'gatsby';
import { Button } from '@freecodecamp/ui';

export type ButtonSize = 'small' | 'medium' | 'large';

interface Props extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
  children: React.ReactNode;
  href: string;
  external?: boolean;
  className?: string;
  size?: ButtonSize;
  onClick?: React.MouseEventHandler<HTMLAnchorElement>;
  block?: boolean;
  download?: string;
  target?: React.HTMLAttributeAnchorTarget;
  disabled?: boolean;
}

/**
 * ButtonLink is a link that looks like a button.
 * The component renders:
 * - Internal link with Gatsby's Link component
 * - External link with freecodecamp/ui's Button component,
 *   which renders a plain `<a>` if it receives an `href`.
 * NOTE: We probably want to move this component to @freecodecamp/ui.
 */
export const ButtonLink = ({
  className,
  external,
  children,
  href,

Review comment (suggestion):
The props interface is based on that of the Button component: https://github.com/freeCodeCamp/ui/blob/884b6ca3e6a685a793b4b88f3e0fbb14000c3dfb/src/button/types.ts#L7-L17.

Code after:
import React from 'react';
import { Link as GatsbyLink } from 'gatsby';
import { Button } from '@freecodecamp/ui';

export type ButtonSize = 'small' | 'medium' | 'large';

interface Props extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
  children: React.ReactNode;
  href: string;
  className?: string;
  size?: ButtonSize;
  onClick?: React.MouseEventHandler<HTMLAnchorElement>;
  block?: boolean;
  download?: string;
  target?: React.HTMLAttributeAnchorTarget;
  disabled?: boolean;
}

/**
 * ButtonLink is a link that looks like a button.
 * The component renders:
 * - Internal link with Gatsby's Link component
 * - External link with freecodecamp/ui's Button component,
 *   which renders a plain `<a>` if it receives an `href`.
 * NOTE: We probably want to move this component to @freecodecamp/ui.
 */
export const ButtonLink = ({
  className,
  children,
  href,
  target,
  download,
Repository: freeCodeCamp/freeCodeCamp
File: client/src/components/helpers/button-link.tsx (TypeScript)

Code before:
  block,
  disabled
}: Props) => {
  // We only need to compute the styles of `size` and `block` for Gatsby Link.
  // freecodecamp/ui's Button already has the logic implemented.
  const gatsbyLinkCls = useMemo(() => {
    const cls = ['btn'];

    if (block) {
      cls.push('btn-block');
    }

    // The 'btn' class contains the base button styles as well as the `medium` variant styles.
    // So we only need to handle `large` and `small`.
    if (size === 'large') {
      cls.push('btn-lg');
    } else if (size === 'small') {
      cls.push('btn-sm');
    }

    if (className) {
      cls.push(className);
    }

    return cls.join(' ');
  }, [size, block, className]);

  // Links cannot be disabled. So if `disabled` is true, we render a `<button>` instead.
  if (disabled) {
    return (
      <Button
        variant='primary'
        className={className}
        size={size}
        block={block}
        disabled
      >
        {children}
      </Button>
    );
  }

  if (target === '_blank' || download) {
    return (
      <Button
        variant='primary'
        className={className}
        href={href}
        target={target}
        onClick={onClick}
        download={download}

Review comment (performance):
```suggestion
  const cls = ['btn'];
  if (block) cls.push('btn-block');

  // The 'btn' class contains the base button styles as well as the `medium` variant styles.
  // So we only need to handle `large` and `small`.
  if (size === 'large') cls.push('btn-lg');
  if (size === 'small') cls.push('btn-sm');
  if (className) cls.push(className);

  const gatsbyLinkCls = cls.join(' ');
```
Is a memo useful here? None of this is expensive. Also, Naomi would disapprove, but dropping the `{}` cleans this up a ton.

Code after:
  block,
  disabled
}: Props) => {
  // We only need to compute the styles of `size` and `block` for Gatsby Link.
  // freecodecamp/ui's Button already has the logic implemented.
  const cls = ['btn'];
  if (block) cls.push('btn-block');
  // The 'btn' class contains the base button styles as well as the `medium` variant styles.
  // So we only need to handle `large` and `small`.
  if (size === 'large') cls.push('btn-lg');
  if (size === 'small') cls.push('btn-sm');
  if (className) cls.push(className);
  const gatsbyLinkCls = cls.join(' ');

  // Links cannot be disabled. So if `disabled` is true,
  // we pass the prop to `Button` in order to render a `<button>` instead of an `<a>`.
  if (disabled || target === '_blank' || download) {
    return (
      <Button
        variant='primary'
        className={className}
        href={href}
        target={target}
        onClick={onClick}
        download={download}
        size={size}
        block={block}
        disabled={disabled}
      >
        {children}
      </Button>
    );
  }

  return (
    <GatsbyLink
      className={gatsbyLinkCls}
      to={href}
      target={target}
      onClick={onClick}
    >
      {children}
    </GatsbyLink>
  );
};
Repository: freeCodeCamp/freeCodeCamp
File: client/src/components/helpers/button-link.tsx (TypeScript)

Code before:
  href,
  target,
  download,
  onClick,
  size = 'medium',
  block,
  disabled
}: Props) => {
  // We only need to compute the styles of `size` and `block` for Gatsby Link.
  // freecodecamp/ui's Button already has the logic implemented.
  const gatsbyLinkCls = useMemo(() => {
    const cls = ['btn'];

    if (block) {
      cls.push('btn-block');
    }

    // The 'btn' class contains the base button styles as well as the `medium` variant styles.
    // So we only need to handle `large` and `small`.
    if (size === 'large') {
      cls.push('btn-lg');
    } else if (size === 'small') {
      cls.push('btn-sm');
    }

    if (className) {
      cls.push(className);
    }

    return cls.join(' ');
  }, [size, block, className]);

  // Links cannot be disabled. So if `disabled` is true, we render a `<button>` instead.
  if (disabled) {
    return (
      <Button
        variant='primary'
        className={className}
        size={size}
        block={block}
        disabled
      >
        {children}
      </Button>
    );
  }

  if (target === '_blank' || download) {
    return (
      <Button
        variant='primary'

Review comment (suggestion):
```suggestion
        className={className}
        disabled
```
See above.

Code after:
  href,
  target,
  download,
  onClick,
  size = 'medium',
  block,
  disabled
}: Props) => {
  // We only need to compute the styles of `size` and `block` for Gatsby Link.
  // freecodecamp/ui's Button already has the logic implemented.
  const cls = ['btn'];
  if (block) cls.push('btn-block');
  // The 'btn' class contains the base button styles as well as the `medium` variant styles.
  // So we only need to handle `large` and `small`.
  if (size === 'large') cls.push('btn-lg');
  if (size === 'small') cls.push('btn-sm');
  if (className) cls.push(className);
  const gatsbyLinkCls = cls.join(' ');

  // Links cannot be disabled. So if `disabled` is true,
  // we pass the prop to `Button` in order to render a `<button>` instead of an `<a>`.
  if (disabled || target === '_blank' || download) {
    return (
      <Button
        variant='primary'
        className={className}
        href={href}
        target={target}
        onClick={onClick}
        download={download}
        size={size}
        block={block}
        disabled={disabled}
      >
        {children}
      </Button>
    );
  }

  return (
    <GatsbyLink
      className={gatsbyLinkCls}
      to={href}
      target={target}
      onClick={onClick}
    >
      {children}
    </GatsbyLink>
  );
};
Repository: freeCodeCamp/freeCodeCamp
File: client/src/utils/ajax.ts (TypeScript)

Code before:
  ChallengeFile,
  ChallengeFiles,
  CompletedChallenge,
  GenerateExamResponseWithData,
  SavedChallenge,
  SavedChallengeFile,
  SurveyResults,
  User
} from '../redux/prop-types';
import { DonationDuration } from '../../../shared/config/donation-settings';

const { apiLocation } = envData;

const base = apiLocation;

const defaultOptions: RequestInit = {
  credentials: 'include'
};

// csrf_token is passed to the client as a cookie. The client must send
// this back as a header.
function getCSRFToken() {
  const token =
    typeof window !== 'undefined' ? cookies.get('csrf_token') : null;

  console.log(token);
  return token ?? '';
}

export interface ResponseWithData<T> {
  response: Response;
  data: T;
}

// TODO: Might want to handle flash messages as close to the request as possible
// to make use of the Response object (message, status, etc)
async function get<T>(path: string): Promise<ResponseWithData<T>> {
  const response = await fetch(`${base}${path}`, {
    ...defaultOptions,
    headers: { 'CSRF-Token': getCSRFToken() }
  });

  return combineDataWithResponse(response);
}

async function combineDataWithResponse<T>(response: Response) {
  const data = (await response.json()) as T;
  return { response, data };
}

export function post<T = void>(

Review comment (suggestion):
```suggestion
```

Seeing a variable called `token` get logged is scary no matter how harmless it really is 😅 

Code after:
  ChallengeFile,
  ChallengeFiles,
  CompletedChallenge,
  GenerateExamResponseWithData,
  SavedChallenge,
  SavedChallengeFile,
  SurveyResults,
  User
} from '../redux/prop-types';
import { DonationDuration } from '../../../shared/config/donation-settings';

const { apiLocation } = envData;

const base = apiLocation;

const defaultOptions: RequestInit = {
  credentials: 'include'
};

// csrf_token is passed to the client as a cookie. The client must send
// this back as a header.
function getCSRFToken() {
  const token =
    typeof window !== 'undefined' ? cookies.get('csrf_token') : null;
  return token ?? '';
}

export interface ResponseWithData<T> {
  response: Response;
  data: T;
}

// TODO: Might want to handle flash messages as close to the request as possible
// to make use of the Response object (message, status, etc)
async function get<T>(path: string): Promise<ResponseWithData<T>> {
  const response = await fetch(`${base}${path}`, {
    ...defaultOptions,
    headers: { 'CSRF-Token': getCSRFToken() }
  });

  return combineDataWithResponse(response);
}

async function combineDataWithResponse<T>(response: Response) {
  const data = (await response.json()) as T;
  return { response, data };
}

export function post<T = void>(
  path: string,
  body: unknown
Repository: freeCodeCamp/freeCodeCamp
File: e2e/report-user.spec.ts (TypeScript)

Code before:

test.beforeEach(async () => {
  await deleteAllEmails();
});

test('should be possible to report a user from their profile page', async ({
  page,
  isMobile
}) => {
  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();

  // On mobile, the texarea is the first element due to the searchbox not being present
  await page
    .getByRole('textbox')
    .nth(isMobile ? 0 : 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'
  );

  await expect(async () => {
    const emails = await getAllEmails();
    expect(emails.items).toHaveLength(1);
    expect(getSubject(getFirstEmail(emails))).toBe(
      "Abuse Report : Reporting twaha's profile."
    );
  }).toPass();
});


Review comment (bug):
The removal of `<div role='textbox'>` caused this test to fail as the number of textboxes on the screen has changed.

I updated the test to look for the specific textbox, rather than relying on other textboxes in the DOM.

Code after:

test.beforeEach(async () => {
  await deleteAllEmails();
});

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', { name: 'What would you like to report?' })
    .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'
  );

  await expect(async () => {
    const emails = await getAllEmails();
    expect(emails.items).toHaveLength(1);
    expect(getSubject(getFirstEmail(emails))).toBe(
      "Abuse Report : Reporting twaha's profile."
    );
  }).toPass();
});
Repository: freeCodeCamp/freeCodeCamp
File: client/utils/gatsby/page-loading.ts (TypeScript)

Code before:
// Gatsby's Link component has the following features:
// - When a Link component is in the viewport, Gatsby starts a low-priority request for the linked page's resources
// - When a Link component is hovered, Gatsby starts a high-priority request for the linked page's resources
//
// These functions are to mimic those behaviors to help cover cases
// where we want to preload a page but we don't show the link of the page on the screen.
//
// Refs:
// - https://v3.gatsbyjs.com/docs/reference/built-in-components/gatsby-link/#link-drives-gatsbys-fast-page-navigation
// - https://github.com/gatsbyjs/gatsby/discussions/20568#discussioncomment-104944

// Ref: https://github.com/gatsbyjs/gatsby/blob/721e9d1cf4a53604cddb7901003046bd3649836c/packages/gatsby-link/src/index.js#L74-L79
export const lowPriorityPreload = (path: string | null) => {
  if (!window.___loader) return;

  if (path) {
    window.___loader.enqueue(path);
  }
};

// Ref: https://github.com/gatsbyjs/gatsby/blob/721e9d1cf4a53604cddb7901003046bd3649836c/packages/gatsby-link/src/index.js#L150-L155
export const highPriorityPreload = (path: string | null) => {
  if (!window.___loader) return;

  if (path) {
    window.___loader.hovering(path);
  }
};


Review comment (bug):
Gatsby doc uses the term "prefetch" and "preload" interchangeably. Technically they are different, but since they can easily be mixed up, I'm just naming the functions `lowPriorityPreload` and `highPriorityPreload` instead.

Also: https://stackoverflow.com/questions/52764401/what-are-the-differences-between-html-preload-and-prefetch

Code after:
/**
 * The function is useful in cases where we want to preload a page
 * but the link of the page isn't rendered on the screen.
 * For more details, see https://github.com/freeCodeCamp/freeCodeCamp/pull/55472.
 */
export const preloadPage = (path: string | null) => {
  if (!window.___loader || !path) return;

  window.___loader.hovering(path);
};