카테고리 없음

15주차 (3)

jaeoun0238 2025. 2. 6. 00:51
describe('updateCardOrder', () => { it('should update card order', async () => { const userId = 1; const columnId = 1; const cardId = 1; const targetCardId = 2; const column = { id: columnId, board: { id: 99 } }; const cards = [ { id: 1, lexo: LexoRank.middle().toString() }, { id: 2, lexo: LexoRank.middle().genNext().toString() }, ]; const targetCard = { id: targetCardId, lexo: LexoRank.middle().genNext().toString(), }; const updatedCard = { id: cardId, lexo: LexoRank.parse(targetCard.lexo).genNext().toString(), }; mockColumnRepository.findOne.mockResolvedValue(column); mockMemberRepository.findOne.mockResolvedValue({ boardId: column.board.id, userId, }); mockCardRepository.find.mockResolvedValue(cards); mockCardRepository.findOne .mockResolvedValueOnce(cards[0]) .mockResolvedValueOnce(targetCard) .mockResolvedValueOnce(updatedCard); mockCardRepository.update.mockResolvedValue(updatedCard); const result = await service.updateCardOrder( userId, columnId, cardId, targetCardId, ); expect(result).toEqual(updatedCard); }); });

const generateString = () => crypto.randomUUID(); 라는 오류가 발생했습니다.

crypto 객체가 정의되지 않았기 때문에 "crypto is not defined" 인 상태가 된것인데..!

 

const crypto = require('crypto');

이코드를 사용하면 해결이 가능했습니다.

 

const crypto = require('crypto'); 를 사용하면 해결되는 이유

 

NestJS는 기본적으로 CommonJS (CJS) 환경을 사용한다.

require('crypto')는 CommonJS 환경에서 올바르게 동작한다.

import * as crypto from 'crypto';를 사용하려면 TypeScript와 Node.js를 ES 모듈 방식으로 설정해야 하는데,

기본적으로 CommonJS로 설정되어 있기 때문에 오류가 발생할 수 있다.

 

이번에 맡은 부분을 jest를 사용해보면서 정말 많은 고난이 있었습니다ㅜㅜ 처음사용해보는거라 그런지 익숙하지 않아서 어려움이 많았는데 service.ts파일에서
findOne 의 갯수를 확인하고 이를 service.spec.ts 파일에서도 그대로 적용해야한다.

  async updateCardOrder(
    userId: number,
    columnId: number,
    cardId: number,
    targetCardId: number,
  ): Promise<Card> {
    const column = await this.columnRepository.findOne({
      where: { id: columnId },
      relations: ['board'],
    });

    const checkMember = await this.memberRepository.findOne({
      where: { userId: userId, boardId: column.board.id },
    });

    if (!checkMember) {
      throw new NotFoundException(
        '카드을 변경할 수 있는 권한이 존재하지 않습니다.',
      );
    }

    const cards = await this.cardRepository.find({
      where: { columnId },
      order: { lexo: 'DESC' },
    });

    const card = await this.cardRepository.findOne({ where: { id: cardId } });
    const targetCard = await this.cardRepository.findOne({
      where: { id: targetCardId },
    });

    const CardIndex = cards.findIndex((card) => card.id === cardId);
    const targetCardIndex = cards.findIndex((card) => card.id === targetCardId);

    //-------------------------------------------------------------

    if (targetCardIndex < CardIndex) {
      const targetNextCardIndex = targetCardIndex - 1;

      if (!card || !targetCard) {
        throw new BadRequestException('카드가 존재하지 않습니다.');
      }

      const currentRank = LexoRank.parse(card.lexo);
      const targetRank = LexoRank.parse(targetCard.lexo);
      const targetNextCard = cards[targetNextCardIndex];

      if (targetNextCardIndex < 0) {
        let lexoRank: LexoRank;
        lexoRank = LexoRank.parse(targetCard.lexo.toString()).genNext(); // 현재 카드 다음 랭크

        await this.cardRepository.update(
          { id: cardId, columnId },
          { lexo: lexoRank.toString() },
        );

        return await this.cardRepository.findOne({ where: { id: cardId } });
      }
      const newRank = LexoRank.parse(targetNextCard.lexo).between(targetRank); // 현재 카드와 타켓 카드 사이의 랭크

      await this.cardRepository.update(
        { id: cardId, columnId },
        { lexo: newRank.toString() },
      );

      return await this.cardRepository.findOne({ where: { id: cardId } });
    } else {
      const maxIndex: number = cards.length - 1;

      if (targetCardIndex === maxIndex) {
        let lexoRank: LexoRank;
        lexoRank = LexoRank.parse(targetCard.lexo.toString()).genPrev(); // 현재 카드 다음 랭크

        await this.cardRepository.update(
          { id: cardId, columnId },
          { lexo: lexoRank.toString() },
        );

        return await this.cardRepository.findOne({ where: { id: cardId } }); // 여기서부터 cardRepository를 사용하는 findOne의 갯수 확인
      }

      const targetNextCardIndex = targetCardIndex + 1;

      // const existingCard = await this.cardRepository.findOne({ where: { id: targetCardId }, order: { lexo: "DESC" } })

      if (!card || !targetCard) {
        throw new BadRequestException('카드가 존재하지 않습니다.');
      }

      const currentRank = LexoRank.parse(card.lexo);
      const targetRank = LexoRank.parse(targetCard.lexo);
      const targetNextCard = cards[targetNextCardIndex];

      if (targetNextCardIndex === maxIndex) {
        let lexoRank: LexoRank;
        lexoRank = LexoRank.parse(targetCard.lexo.toString()).genPrev(); // 현재 카드 다음 랭크

        await this.cardRepository.update(
          { id: cardId, columnId },
          { lexo: lexoRank.toString() },
        );

        return await this.cardRepository.findOne({ where: { id: cardId } });
      }
      const newRank = LexoRank.parse(targetNextCard.lexo).between(targetRank); // 현재 카드와 타켓 카드 사이의 랭크

      await this.cardRepository.update(
        { id: cardId, columnId },
        { lexo: newRank.toString() },
      );

      return await this.cardRepository.findOne({ where: { id: cardId } });
    }
  }

 

findOne를 잘살펴보면

mockCardRepository.findOne
        .mockResolvedValueOnce(cards[0])
        .mockResolvedValueOnce(targetCard)
        .mockResolvedValueOnce(updatedCard);

 

원래의 서비스 파일에서 findOne를 3번 사용했기때문에 CardRepository를 사용하는 3가지를 한번에 묶어서 사용해줘야 오류가 나지 않는다!!!