如何根据作为 props 传递的条件来测试 React 组件

问题描述 投票:0回答:1

所以我试图测试我的代码,但我的测试失败了,因为它无法根据条件找到一些元素

这是我想要测试的 Options.tsx 文件

这是我遇到的错误

✓ 当 showoprion 为 true 时显示更多水平图标(36 毫秒) ✕ 当 noteId 存在且不在笔记内时显示移动到、笔记删除和文件夹选择按钮(64 毫秒) ✕ 当存在folderId 和deleteOptions 时显示文件夹删除、编辑按钮(31 毫秒)

● 选项组件 › 当 noteId 存在且不在笔记内时,显示移动到、笔记删除和文件夹选择按钮

TestingLibraryElementError: Unable to find an accessible element with the role "button" and name "Move to"

● 选项组件 › 当存在folderId 和deleteOptions 时显示文件夹删除、编辑按钮

TestingLibraryElementError: Unable to find an accessible element with the role "button" and name "Delete Folder"

选项.tsx

import React, { useState } from 'react'
import {
    DropdownMenu,
    DropdownMenuContent,
    DropdownMenuItem,
    DropdownMenuTrigger,
  } from "@/components/ui/dropdown-menu"
  import { useMutation, useQuery } from "convex/react";
  import { toast } from "sonner";
  
  import { api } from "../../../../convex/_generated/api";
  import { MoreHorizontal, Plus} from 'lucide-react'
import { Id } from '../../../../convex/_generated/dataModel';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from "@/components/ui/select"
  
import {
    Dialog,
    DialogClose,
    DialogContent,
    DialogDescription,
    DialogHeader,
    DialogTitle,
    DialogTrigger,
} from "@/components/ui/dialog"
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { useRouter } from 'next/navigation';


type Props = {}

const Options = ({
    folder = true,
    folderId,
    deleteOptions = false,
    showOption = false,
    note = true,
    noteId,
}:{
    folder?:boolean,
    folderId?:Id<"folder">
    deleteOptions?:boolean
    showOption:boolean
    note?:boolean
    noteId?:Id<"note">
}) => {
    const folders = useQuery(api.folder.getAllFolders,{});
    const createfolder = useMutation(api.folder.create);
    const createnote = useMutation(api.note.create);
    const deletefolder = useMutation(api.folder.deleteFolder)
    const deletenote = useMutation(api.note.deleteNote)
    const movenote = useMutation(api.note.moveNote)
    const updatefoldertitle = useMutation(api.folder.updateTitleFolder)
    const updatenotetitle = useMutation(api.note.updateTitleNote)
    const [selectedFolder, setSelectedFolder] = useState<Id<"folder">>()
    const [title, setTitle] = useState<string>("")
    console.log(selectedFolder)
    const router = useRouter()

    const handleCreateFolder = () => {
      const promise = createfolder({ title: "Untitled" })
        .then((documentId) => router.push(`/folder/${documentId}`))
  
      toast.promise(promise, {
        loading: "Creating a new folder...",
        success: "New folder created!",
        error: "Failed to create a new folder."
      });
    };
    const handleCreateNote = () => {
      const promise = createnote({ title: "Untitled", folderId: folderId })
        .then((documentId) => router.push(`/notes/${documentId}`))
  
      toast.promise(promise, {
        loading: "Creating a new note...",
        success: "New note created!",
        error: "Failed to create a new note."
      });
    };

    const handleDeleteFolder = () => {
        if(!folderId) return
        const promise = deletefolder({folderId:folderId})
        toast.promise(promise, {
            loading: "Deleting the  folder ...",
            success: "Deleted folder successfully",
            error: "Failed to delete folder"
        });
    }
    const handleDeleteNote = () => {
        if(!noteId) return
        const promise = deletenote({noteId})
        .then(() => router.push(`/notes`))
        toast.promise(promise, {
            loading: "Deleting the  note ...",
            success: "Deleted note successfully",
            error: "Failed to delete note"
        });
    }

    const handleMoveNote = () => {
        if(!noteId || !selectedFolder) return
        const promise = movenote({noteId, folderId:selectedFolder})

        toast.promise(promise, {
            loading: "Moving note ...",
            success: "Moved note successfully",
            error: "Failed to move note"
        });
    }

    const handleEditFolder = () => {
        if(!folderId) return
        const promise = updatefoldertitle({folderId:folderId, title})
        toast.promise(promise, {
            loading: "updating the  folder title ...",
            success: "updated folder title successfully",
            error: "Failed to update folder title"
        });
    }
    const handleEditNote = () => {
        if(!noteId) return
        const promise = updatenotetitle({noteId, title})
        toast.promise(promise, {
            loading: "updating the  note title ...",
            success: "updated note title successfully",
            error: "Failed to update note title"
        });
    }
  return (
    <div className='px-3'>
        <DropdownMenu>
          <DropdownMenuTrigger role='more-options' className='cursor-pointer hover:bg-primary/10 p-1 rounded-md'>
            <span className={`${showOption ? "" :"invisible"}`}>
             <MoreHorizontal size={18}/>
            </span>
          </DropdownMenuTrigger>
          <DropdownMenuContent className='max-w-[250px] min-w-[180px]'>
            <DropdownMenuItem className={`${folder ? "" : "hidden"}`} onClick={handleCreateFolder}>Add Folder</DropdownMenuItem>
            <DropdownMenuItem className={`${note ? "" : "hidden"}`} onClick={handleCreateNote}>Add Note</DropdownMenuItem>
            {(note === false && noteId) && (
                <div>
                    <Dialog>
                        <DialogTrigger className='w-full text-left text-sm p-1 px-2 hover:bg-primary/10 rounded'>Move to</DialogTrigger>
                        <DialogContent>
                            <DialogHeader>
                            <DialogTitle className='text-base mb-2'>Select Folder</DialogTitle>
                            <Select onValueChange={(event) => setSelectedFolder(event as Id<"folder">)}>
                                <SelectTrigger className="w-full">
                                    <SelectValue placeholder="Folder" />
                                </SelectTrigger>
                                <SelectContent>
                                    {folders?.map((foldera) => (
                                        <SelectItem key={foldera._id} value={foldera._id}>{foldera.title}</SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                            </DialogHeader>
                            <DialogClose onClick={handleMoveNote}><Button className='w-full'>Move</Button></DialogClose>
                        </DialogContent>
                    </Dialog>
                </div>
            )}
            {(deleteOptions && folderId) && (
                <div>
                <DropdownMenuItem  onClick={handleDeleteFolder}>Delete Folder</DropdownMenuItem>
                <div>
                    <Dialog >
                        <DialogTrigger className='w-full text-left text-sm p-1 px-2 hover:bg-primary/10 rounded'>Edi Folder</DialogTrigger>
                        <DialogContent>
                            <DialogHeader>
                            <DialogTitle className='text-base mb-2'>Folder Title</DialogTitle>
                            <Input onChange={(e) => setTitle(e.target.value)} placeholder='title' />
                            </DialogHeader>
                            <DialogClose onClick={handleEditFolder}><Button className='w-full'>Save</Button></DialogClose>
                        </DialogContent>
                    </Dialog>
                </div>
                </div>
            )}
            {(deleteOptions && noteId) &&(
                <div>
                <DropdownMenuItem  onClick={handleDeleteNote}>Delete Note</DropdownMenuItem>
                <div>
                    <Dialog >
                        <DialogTrigger className='w-full text-left text-sm p-1 px-2 hover:bg-primary/10 rounded'>Edit Note</DialogTrigger>
                        <DialogContent>
                            <DialogHeader>
                            <DialogTitle className='text-base mb-2'>Note Title</DialogTitle>
                            <Input onChange={(e) => setTitle(e.target.value)}  placeholder='title' />
                            </DialogHeader>
                            <DialogClose onClick={handleEditNote}><Button className='w-full'>Save</Button></DialogClose>
                        </DialogContent>
                    </Dialog>
                </div>
                </div>
            )}
          </DropdownMenuContent>
        </DropdownMenu>
        
    </div>
  )
}

export default Options






选项.test.tsx

import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import Options from '@/app/(notes)/_components/options';
import { Id } from '../../convex/_generated/dataModel';
import { MoreHorizontal } from 'lucide-react';

jest.mock('convex/react', () => ({
  useMutation: jest.fn(),
  useQuery: jest.fn(),
}));

jest.mock('next/navigation', () => ({
    useRouter: jest.fn(),
  }));

  describe('Options component', () => {
    it('show morehorizontal icon when showoprion is true', () => {
      // Mock useRouter implementation
      const enabledProps: { showOption:boolean} = {
        showOption:true
      };
  
      // Render the component
      render(<Options deleteOptions {...enabledProps} />);
      const Icon = render(<MoreHorizontal size={18} />)
      expect(Icon).toBeTruthy()

      expect(screen.queryByRole('button', { name: 'Move to' })).not.toBeInTheDocument()

      expect(screen.queryByRole('button', { name: 'Delete Note' })).not.toBeInTheDocument()

      expect(screen.queryByRole('button', { name: 'Edit Note' })).not.toBeInTheDocument()

      expect(screen.queryByRole('button', { name: 'Delete Folder' })).not.toBeInTheDocument()

      expect(screen.queryByRole('button', { name: 'Edit Folder' })).not.toBeInTheDocument()
    });

    it('show move to and Note Delete and Folder Select button when noteId is present and when we are not inside the note', () => {
        const enabledProps: { showOption:boolean, noteId:Id<'note'>,note:boolean, deleteOptions:boolean} = {
          showOption:true,
          noteId:'id' as Id<'note'>,
          note:false,
          deleteOptions:true
        };
      
        // Render the component
        render(<Options  showOption deleteOptions note noteId={'id' as Id<'note'>} />);
        
        console.log(document.body.innerHTML);
      
          expect(screen.getByRole('button', { name: 'Move to' })).toBeInTheDocument();
          expect(screen.getByRole('button', { name: 'Select Folder' })).toBeInTheDocument();
          expect(screen.getByRole('button', { name: 'Delete Note' })).toBeInTheDocument();
      });      

    it('show Folder Delete , edit button when folderId and deleteOptions is present ', () => {
      const enabledProps1: { showOption:boolean, folderId:Id<'folder'>,deleteOptions:boolean} = {
        showOption:true,
        folderId:'id' as Id<'folder'>,
        deleteOptions:false
      };
  
      // Render the component
      render(<Options  {...enabledProps1} />);
            expect(screen.getByRole('button', { name: 'Delete Folder' })).toBeInTheDocument()
            expect(screen.getByRole('button', { name: 'Delete Folder' })).toBeInTheDocument()
    });
  });

所以,我尝试等待或直接传递道具,但没有任何作用

reactjs typescript next.js jestjs react-testing-library
1个回答
0
投票

代码太多。尝试更具体一点

© www.soinside.com 2019 - 2024. All rights reserved.