Repository: freeCodeCamp/freeCodeCamp
File: api/src/routes/user.test.ts (TypeScript)

Code before:
        await superPost('/account/delete');
        expect(await fastifyTestInstance.prisma.msUsername.count()).toBe(1);
      });

      test('POST deletes userTokens associated with the user', async () => {
        await fastifyTestInstance.prisma.userToken.createMany({
          data: tokenData
        });

        await superPost('/account/delete');

        const userTokens =
          await fastifyTestInstance.prisma.userToken.findMany();
        expect(userTokens).toHaveLength(1);
        expect(userTokens[0]?.userId).toBe(otherUserId);
      });

      test("POST deletes all the user's cookies", async () => {
        const res = await superPost('/account/delete');

        const setCookie = res.headers['set-cookie'];
        expect(setCookie).toEqual(
          expect.arrayContaining([
            'jwt_access_token=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure; SameSite=Lax',
            '_csrf=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure; SameSite=Lax',
            'csrf_token=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure; SameSite=Lax'
          ])
        );
        expect(setCookie).toHaveLength(3);
      });
    });

    describe('/account/reset-progress', () => {
      afterEach(async () => {
        await fastifyTestInstance.prisma.userToken.deleteMany({
          where: { OR: [{ userId: defaultUserId }, { userId: otherUserId }] }
        });
        await fastifyTestInstance.prisma.msUsername.deleteMany({
          where: { OR: [{ userId: defaultUserId }, { userId: otherUserId }] }
        });
      });
      test('POST returns 200 status code with empty object', async () => {
        await fastifyTestInstance.prisma.user.updateMany({
          where: { email: testUserData.email },
          data: modifiedProgressData
        });

        const response = await superPost('/account/reset-progress');

        const user = await fastifyTestInstance.prisma.user.findFirst({
          where: { email: testUserData.email }

Review comment (security):
Our current client cannot handle `httpOnly` `csrf_token`s:
https://github.com/ojeytonwilliams/freecodecamp/blob/ad0f272359a66440f7a1a6ca41c0b56c1b52b139/client/src/utils/ajax.ts#L26-L31

Also, how is the `csrf_token` `same_site=lax`? I thought the config made it `strict`?

Code after:
        await superPost('/account/delete');
        expect(await fastifyTestInstance.prisma.msUsername.count()).toBe(1);
      });

      test('POST deletes userTokens associated with the user', async () => {
        await fastifyTestInstance.prisma.userToken.createMany({
          data: tokenData
        });

        await superPost('/account/delete');

        const userTokens =
          await fastifyTestInstance.prisma.userToken.findMany();
        expect(userTokens).toHaveLength(1);
        expect(userTokens[0]?.userId).toBe(otherUserId);
      });

      test("POST deletes all the user's cookies", async () => {
        const res = await superPost('/account/delete');

        const setCookie = res.headers['set-cookie'];
        expect(setCookie).toEqual(
          expect.arrayContaining([
            expect.stringMatching(
              /^jwt_access_token=; Path=\/; Expires=Thu, 01 Jan 1970 00:00:00 GMT/
            ),
            expect.stringMatching(
              /^csrf_token=; Path=\/; Expires=Thu, 01 Jan 1970 00:00:00 GMT/
            ),
            expect.stringMatching(
              /^_csrf=; Path=\/; Expires=Thu, 01 Jan 1970 00:00:00 GMT/
            )
          ])
        );
        expect(setCookie).toHaveLength(3);
      });
    });

    describe('/account/reset-progress', () => {
      afterEach(async () => {
        await fastifyTestInstance.prisma.userToken.deleteMany({
          where: { OR: [{ userId: defaultUserId }, { userId: otherUserId }] }
        });
        await fastifyTestInstance.prisma.msUsername.deleteMany({
          where: { OR: [{ userId: defaultUserId }, { userId: otherUserId }] }
        });
      });
      test('POST returns 200 status code with empty object', async () => {
        await fastifyTestInstance.prisma.user.updateMany({
          where: { email: testUserData.email },
          data: modifiedProgressData