utils#calculateTotalInvestment TypeScript Examples

The following examples show how to use utils#calculateTotalInvestment. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From exevo-pan with The Unlicense 4 votes vote down vote up
describe('<CharacterModal />', () => {
  beforeEach(() => {
    mockedFetch.mockClear()
    scrollIntoViewMock.mockClear()
    mockOnClose.mockClear()
    setup.setTimeout()
  })

  test.each(characterList)(
    'should render every element correctly',
    (character) => {
      const {
        outfits,
        storeOutfits,
        mounts,
        storeMounts,
        storeItems,
        charms,
        charmInfo,
        hirelings,
        achievementPoints,
      } = character

      renderWithProviders(
        <CharacterModal characterData={character} onClose={mockOnClose} />,
      )

      const totalInvestment = formatNumberWithCommas(
        calculateTotalInvestment(character),
      )

      if (totalInvestment === '0') {
        expect(screen.queryByText(totalInvestment)).not.toBeInTheDocument()
      } else {
        expect(
          screen.getByText(`${totalInvestment} Tibia Coins`, { exact: false }),
        ).toBeInTheDocument()
      }

      expect(
        screen.getByText(
          `Outfits ${tabCounter(outfits.length, storeOutfits.length)}`,
          { exact: false },
        ),
      ).toBeInTheDocument()

      expect(
        screen.getByText(
          `Mounts ${tabCounter(mounts.length, storeMounts.length)}`,
          { exact: false },
        ),
      ).toBeInTheDocument()

      if (storeItems.length > 0) {
        expect(
          screen.getByText(`Store Items (${storeItems.length})`, {
            exact: false,
          }),
        ).toBeInTheDocument()
      } else {
        expect(
          screen.queryByText(`Store Items (${storeItems.length})`, {
            exact: false,
          }),
        ).not.toBeInTheDocument()
      }

      expect(screen.getByText('Charms:', { exact: false }).textContent).toEqual(
        `Charms: ${charms.length}/19 (${formatNumberWithCommas(
          charmInfo.total,
        )} total points,${formatNumberWithCommas(charmInfo.unspent)} unspent)`,
      )

      expect(
        screen.getByText('Hirelings:', { exact: false }).textContent,
      ).toEqual(
        `Hirelings: ${hirelings.count} (${hirelings.jobs}/4 jobs, ${hirelings.outfits} outfits)`,
      )

      expect(
        screen.getByText(
          `Achievement points: ${formatNumberWithCommas(achievementPoints)}`,
          {
            exact: false,
          },
        ),
      ).toBeInTheDocument()
    },
  )

  test('if a sprite is not found, it should call `NotifyErrorClient`', async () => {
    const [character] = characterList

    const { rerender } = renderWithProviders(
      <CharacterModal
        characterData={{ ...character, storeMounts: [] }}
        onClose={mockOnClose}
      />,
    )

    expect(mockedFetch).toHaveBeenCalledTimes(0)

    rerender(
      <CharacterModal
        characterData={{
          ...character,
          storeMounts: ['weird mount'],
        }}
        onClose={mockOnClose}
      />,
    )

    await waitFor(() => expect(mockedFetch).toHaveBeenCalledTimes(1))
  })

  test('should call `onClose` handler', () => {
    const [character] = characterList
    renderWithProviders(
      <CharacterModal characterData={character} onClose={mockOnClose} />,
    )

    expect(mockOnClose).toHaveBeenCalledTimes(0)

    userEvent.click(screen.getByRole('button', { name: 'Close dialog' }))
    expect(mockOnClose).toHaveBeenCalledTimes(1)
  })

  test('should be tabbable', () => {
    const [character] = characterList
    renderWithProviders(
      <CharacterModal characterData={character} onClose={mockOnClose} />,
    )

    const [tab1, tab2] = screen.getAllByRole('tab')
    expect(scrollIntoViewMock).toHaveBeenCalledTimes(0)

    expect(tab1).toHaveAttribute('aria-selected', 'true')
    expect(tab2).toHaveAttribute('aria-selected', 'false')

    userEvent.click(tab2)
    expect(tab1).toHaveAttribute('aria-selected', 'false')
    expect(tab2).toHaveAttribute('aria-selected', 'true')
    expect(scrollIntoViewMock).toHaveBeenCalledTimes(1)
  })
})
Example #2
Source File: index.tsx    From exevo-pan with The Unlicense 4 votes vote down vote up
CharacterModal = ({
  characterData,
  onClose,
  past = false,
}: CharacterModalProps) => {
  const {
    id,
    sex,
    outfitId,
    nickname,
    level,
    vocationId,
    serverData,
    transfer,
    auctionEnd,
    hasBeenBidded,
    currentBid,
    items,
    skills,
    hirelings,
    charmInfo,
    preySlot,
    huntingSlot,
    storeItems,
    imbuements,
    charms,
    quests,
    outfits,
    mounts,
    storeOutfits,
    storeMounts,
    achievementPoints,
  } = characterData

  const {
    translations: { common },
  } = useTranslations()

  const checkboxRecords = useMemo(() => checkStore(storeItems), [])

  const tcInvested = useMemo(
    () => formatNumberWithCommas(calculateTotalInvestment(characterData)),
    [characterData],
  )

  const tabRef = useRef<HTMLDivElement>(null)
  const isDesktop = useIsDesktop()

  const handleTabChange = useCallback(() => {
    if (!isDesktop) {
      tabRef.current?.scrollIntoView({
        block: 'start',
      })
    }
  }, [isDesktop])

  return (
    <Dialog
      isOpen
      onClose={onClose}
      className={clsx(
        styles.wrapper,
        'w-full max-w-[var(--cardMaxMobileWidth)] p-[var(--lateralMargin)] outline-none md:w-fit md:max-w-[calc(100%-80px)]',
      )}
    >
      <Head
        id={id}
        outfitId={outfitId}
        nickname={nickname}
        level={level}
        vocationId={vocationId}
        serverName={serverData.serverName}
      />

      <div className="custom-scrollbar -mx-[var(--lateralMargin)] h-[var(--gridMobileHeight)] overflow-y-auto px-[var(--lateralMargin)] md:h-[var(--cardFixedHeight)]">
        <S.Spacer className="w-full md:flex md:gap-6">
          <S.Spacer className="md:z-4 h-fit pt-1.5 md:sticky md:top-0 md:min-w-[280px] md:max-w-fit md:shrink-0">
            <InfoGrid>
              <Textbox.Server
                serverData={serverData}
                nickname={nickname}
                transfer={transfer}
                placement="bottom"
              />
              <Textbox.Pvp serverData={serverData} />
              <Textbox.AuctionEnd auctionEnd={auctionEnd} past={past} />
              <Textbox.AuctionBid
                hasBeenBidded={hasBeenBidded}
                currentBid={currentBid}
                past={past}
              />
            </InfoGrid>

            <CharacterItems items={items} />

            <S.Section border>
              <CharacterSkills skills={skills} />
            </S.Section>

            <S.TooltipSection>
              <ImbuementsTooltip placement="top-start" items={imbuements} />
              <CharmsTooltip
                placement="top-start"
                items={charms}
                charmInfo={charmInfo}
              />
              <QuestsTooltip placement="top-start" items={quests} />
              <Hirelings hirelingsInfo={hirelings} />
              <Achievements achievementPoints={achievementPoints} />
            </S.TooltipSection>
          </S.Spacer>

          <S.Spacer className="h-fit w-full">
            <S.Section border className="z-3">
              <div
                title={`${common.CharacterCard.tcInvested.prefix} ${tcInvested} ${common.CharacterCard.tcInvested.suffix}`}
                className="text-tsm flex items-center gap-[5px]"
              >
                <Icons.TibiaCoin />{' '}
                {common.CharacterCard.CharacterModal.totalInvested}:{' '}
                <strong
                  className={clsx(
                    tcInvested === '0'
                      ? 'font-normal'
                      : 'text-primaryHighlight',
                  )}
                >
                  {tcInvested} Tibia Coins
                </strong>
              </div>

              <div className="grid grid-flow-col grid-rows-3 gap-2 md:max-w-[400px]">
                <Checkbox
                  label="Training Dummy"
                  checked={checkboxRecords.dummy}
                />
                <Checkbox
                  label="Gold pouch"
                  checked={checkboxRecords.goldPouch}
                />
                <Checkbox label="Hirelings" checked={hirelings.count > 0} />
                <Checkbox
                  label="Charm expansion"
                  checked={charmInfo.expansion}
                />
                <Checkbox label="Prey Slot" checked={preySlot} />
                <Checkbox label="Hunting Task Slot" checked={huntingSlot} />
                <Checkbox
                  label="Imbuement Shrine"
                  checked={checkboxRecords.imbuementShrine}
                />
                <Checkbox
                  label="Reward Shrine"
                  checked={checkboxRecords.rewardShrine}
                />
                <Checkbox label="Mailbox" checked={checkboxRecords.mailbox} />
              </div>
            </S.Section>

            <Tabs.Group
              className="min-h-[var(--gridMobileHeight)] md:min-h-[unset]"
              style={{ display: 'block', overflow: 'unset' }}
              onChange={handleTabChange}
              ref={tabRef}
            >
              <Tabs.Panel
                label={
                  <>
                    <OutfitIcon />
                    Outfits {tabCounter(outfits.length, storeOutfits.length)}
                  </>
                }
              >
                <S.SpriteSection>
                  {outfits.map(({ name, type }) => (
                    <SpriteBox
                      key={name}
                      offset
                      auctionId={id}
                      name={name}
                      sex={sex}
                      src={resolvers.outfit(name, sex, type)}
                      type={type}
                      checkRareOutfit
                    />
                  ))}
                </S.SpriteSection>

                {storeOutfits.length > 0 && (
                  <>
                    <S.SpriteSectionDivisor>
                      Store outfits ({storeOutfits.length})
                    </S.SpriteSectionDivisor>
                    <S.SpriteSection>
                      {storeOutfits.map(({ name, type }) => (
                        <SpriteBox
                          key={name}
                          offset
                          auctionId={id}
                          name={name}
                          sex={sex}
                          src={resolvers.storeOutfit(name, sex, type)}
                        />
                      ))}
                    </S.SpriteSection>
                  </>
                )}
              </Tabs.Panel>

              {mounts.length + storeMounts.length > 0 && (
                <Tabs.Panel
                  label={
                    <>
                      <MountIcon />
                      Mounts {tabCounter(mounts.length, storeMounts.length)}
                    </>
                  }
                >
                  <S.SpriteSection>
                    {mounts.map((name) => (
                      <SpriteBox
                        key={name}
                        offset
                        auctionId={id}
                        name={name}
                        sex={sex}
                        src={resolvers.mount(name)}
                        checkRareMount
                      />
                    ))}
                  </S.SpriteSection>

                  {storeMounts.length > 0 && (
                    <>
                      <S.SpriteSectionDivisor>
                        Store mounts ({storeMounts.length})
                      </S.SpriteSectionDivisor>
                      <S.SpriteSection>
                        {storeMounts.map((name) => (
                          <SpriteBox
                            key={name}
                            offset
                            auctionId={id}
                            name={name}
                            sex={sex}
                            src={resolvers.storeMount(name)}
                          />
                        ))}
                      </S.SpriteSection>
                    </>
                  )}
                </Tabs.Panel>
              )}

              {storeItems.length > 0 && (
                <Tabs.Panel
                  label={
                    <>
                      <StoreIcon />
                      Store Items ({storeItems.length})
                    </>
                  }
                >
                  <S.SpriteSection>
                    {storeItems.map(({ name, amount }, childIndex) => (
                      <SpriteBox
                        // eslint-disable-next-line react/no-array-index-key
                        key={`${childIndex}-${name}`}
                        auctionId={id}
                        name={name}
                        amount={amount}
                        sex={sex}
                        src={resolvers.storeItem(name)}
                      />
                    ))}
                  </S.SpriteSection>
                </Tabs.Panel>
              )}
            </Tabs.Group>
          </S.Spacer>
        </S.Spacer>
      </div>
    </Dialog>
  )
}
Example #3
Source File: index.tsx    From exevo-pan with The Unlicense 4 votes vote down vote up
describe('<CharacterCard />', () => {
  test.each(characterList)('should write every info correctly', (character) => {
    renderWithProviders(<CharacterCard characterData={character} />)

    expect(screen.getByText(character.nickname)).toBeInTheDocument()

    expect(
      screen.getByText(
        `Level ${character.level} - ${vocation.getFullName(
          character.vocationId,
          character.level,
        )}`,
      ),
    ).toBeInTheDocument()

    expect(
      screen.getByAltText(character.serverData.serverLocation.string),
    ).toBeInTheDocument()

    expect(
      screen.getByText(character.serverData.serverName),
    ).toBeInTheDocument()

    expect(
      screen.getByLabelText(
        character.transfer
          ? 'Regular World Transfer available'
          : 'Regular World Transfer NOT available',
      ),
    ).toBeInTheDocument()

    expect(
      screen.getByText(character.serverData.pvpType.string),
    ).toBeInTheDocument()

    expect(
      screen.getByText(character.hasBeenBidded ? 'Current Bid' : 'Minimum Bid'),
    ).toBeInTheDocument()

    expect(
      screen.getByText(formatNumberWithCommas(character.currentBid)),
    ).toBeInTheDocument()

    expect(screen.queryAllByAltText('Featured item')).toHaveLength(
      character.items.length,
    )

    character.items.forEach((itemId) => {
      const [, tier] = itemId.toString().split('.')
      if (tier) {
        const [first] = screen.queryAllByTitle(`tier ${tier}`)
        expect(first).toBeInTheDocument()
      }
    })

    expect(
      screen.getByText(
        `Imbuements: ${character.imbuements.length}/${imbuement.tokens.length}`,
      ),
    ).toBeInTheDocument()

    expect(
      screen.getByText(
        `Charms: ${character.charms.length}/${charm.tokens.length}`,
      ),
    ).toBeInTheDocument()

    expect(
      screen.getByText(
        `Quests: ${character.quests.length}/${quest.tokens.length}`,
      ),
    ).toBeInTheDocument()

    const charmCheckbox = screen.getByRole('checkbox', {
      name: 'Charm Expansion',
    })
    if (character.charmInfo.expansion) {
      expect(charmCheckbox).toBeChecked()
    } else {
      expect(charmCheckbox).not.toBeChecked()
    }

    const preyCheckbox = screen.getByRole('checkbox', {
      name: 'Prey Slot',
    })
    if (character.preySlot) {
      expect(preyCheckbox).toBeChecked()
    } else {
      expect(preyCheckbox).not.toBeChecked()
    }

    const totalInvestment = formatNumberWithCommas(
      calculateTotalInvestment(character),
    )

    if (totalInvestment === '0') {
      expect(screen.queryByText(totalInvestment)).not.toBeInTheDocument()
    } else {
      expect(
        screen.getByText(totalInvestment, { exact: false }),
      ).toBeInTheDocument()
    }
  })

  test.each(characterList)(
    `should render a different bid label for ${routes.BAZAAR_HISTORY} route`,
    (character) => {
      renderWithProviders(<CharacterCard characterData={character} past />)
      expect(
        screen.getByText(
          character.hasBeenBidded ? 'Auction Successful' : 'Auction Failed',
        ),
      ).toBeInTheDocument()
    },
  )

  test.each(characterList)(
    `should render highlighted card correctly`,
    (character) => {
      renderWithProviders(
        <CharacterCard characterData={character} highlighted />,
      )

      expect(screen.getByText('Highlight your auction!')).toBeInTheDocument()
    },
  )

  test('the character card should be able to be expanded', () => {
    const [character] = characterList
    renderWithProviders(<CharacterCard characterData={character} expandable />)

    const expandButton = screen.getByRole('button', {
      name: 'Expand for full auction details',
    })

    expect(screen.queryByRole('dialog')).not.toBeInTheDocument()

    userEvent.click(expandButton)
    expect(screen.getByRole('dialog')).toBeInTheDocument()

    userEvent.click(screen.getByRole('button', { name: 'Close dialog' }))

    expect(screen.queryByRole('dialog')).not.toBeInTheDocument()
  })
})
Example #4
Source File: index.tsx    From exevo-pan with The Unlicense 4 votes vote down vote up
CharacterCard = ({
  characterData,
  highlighted = false,
  lazyRender = false,
  expandable = false,
  past = false,
  ...props
}: CharacterCardProps) => {
  const {
    translations: { common },
  } = useTranslations()

  const {
    id,
    nickname,
    outfitId,
    level,
    vocationId,
    serverData,
    transfer,
    auctionEnd,
    hasBeenBidded,
    currentBid,
    items,
    skills,
    imbuements,
    charms,
    quests,
    charmInfo,
    preySlot,
  } = characterData

  const tcInvested = useMemo(
    () => formatNumberWithCommas(calculateTotalInvestment(characterData)),
    [characterData],
  )

  const ref = useRef<HTMLDivElement>()

  const [isExpanded, setExpanded] = useState(false)

  const expandCard = useCallback(() => setExpanded(true), [])
  const handleKeyPress = useCallback(
    (event: React.KeyboardEvent) => {
      if (checkKeyboardTrigger(event.code)) expandCard()
    },
    [expandCard],
  )

  return (
    <>
      <S.Wrapper
        ref={ref as React.RefObject<HTMLDivElement>}
        highlighted={highlighted}
        role={expandable ? 'button' : undefined}
        tabIndex={expandable ? 1 : undefined}
        aria-label={expandable ? common.CharacterCard.expand : undefined}
        onClick={expandable ? expandCard : undefined}
        onKeyPress={expandable ? handleKeyPress : undefined}
        {...props}
      >
        <Head
          id={id}
          outfitId={outfitId}
          nickname={nickname}
          level={level}
          vocationId={vocationId}
          serverName={serverData.serverName}
          highlighted={highlighted}
        >
          {highlighted && <TagButton />}
        </Head>

        <S.Body lazy={lazyRender}>
          <S.InfoGrid>
            <Textbox.Server
              serverData={serverData}
              nickname={nickname}
              transfer={transfer}
            />
            <Textbox.Pvp serverData={serverData} />
            <Textbox.AuctionEnd auctionEnd={auctionEnd} past={past} />
            <Textbox.AuctionBid
              hasBeenBidded={hasBeenBidded}
              currentBid={currentBid}
              past={past}
            />
          </S.InfoGrid>

          <CharacterItems items={items} />

          <CharacterSkills skills={skills} />

          <S.FlexFooter>
            <S.FlexColumn>
              <ImbuementsTooltip items={imbuements} />
              <CharmsTooltip items={charms} />
              <QuestsTooltip items={quests} />
            </S.FlexColumn>

            <S.FlexColumn storeColumn>
              <S.Checkbox
                label="Charm Expansion"
                checked={charmInfo.expansion}
              />

              <S.Checkbox label="Prey Slot" checked={preySlot} />

              {tcInvested !== '0' && (
                <div
                  className="flex items-center justify-between gap-1.5"
                  title={`${common.CharacterCard.tcInvested.prefix} ${tcInvested} ${common.CharacterCard.tcInvested.suffix}`}
                >
                  <S.CheckboxContainer>
                    <S.Icons.TibiaCoin />
                  </S.CheckboxContainer>
                  <S.Strong>
                    {tcInvested} {common.CharacterCard.tcInvested.invested}
                  </S.Strong>
                </div>
              )}
            </S.FlexColumn>
          </S.FlexFooter>
        </S.Body>

        <SpecialTags character={characterData} />
      </S.Wrapper>
      {isExpanded && (
        <CharacterModal
          characterData={characterData}
          onClose={() => setExpanded(false)}
          past={past}
        />
      )}
    </>
  )
}