test setup lackin
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
import { DeleteIcon } from "lucide-react";
|
||||
import type { UseTRPCMutationOptions, UseTRPCMutationResult } from "node_modules/@trpc/react-query/dist/getQueryKey.d-CruH3ncI.mjs";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import { useFormMutationContext } from "./MutationProvider";
|
||||
|
||||
export default function DeleteButton<TD, TE, TV, TC>(params: { mutation: UseTRPCMutationResult<TD, TE, TV, TC>, id?: string }) {
|
||||
export default function DeleteButton(params: { id?: string }) {
|
||||
const ctx = useFormMutationContext()
|
||||
if (ctx == undefined) {
|
||||
throw new Error('Dependent form message needs populates form mutations context')
|
||||
}
|
||||
if (params.id) {
|
||||
return (
|
||||
<Button variant='destructive' onClick={() => params.mutation.mutate(({ id: params.id } as TV))}>
|
||||
<Button variant='destructive' onClick={() => ctx.deleteMutation.mutate(({ id: params.id ? params.id : "" }))}>
|
||||
<DeleteIcon />
|
||||
</Button>
|
||||
)
|
||||
|
||||
@@ -4,22 +4,16 @@ import { DependentFormMessaage, SubmitButton, DeleteButton } from '~/app/_compon
|
||||
import type { FieldValues, SubmitHandler, UseFormReturn } from 'react-hook-form';
|
||||
import type { ReactNode } from 'react';
|
||||
import DependentText from '../../DependentText';
|
||||
import type { UseTRPCMutationResult } from 'node_modules/@trpc/react-query/dist/getQueryKey.d-CruH3ncI.mjs';
|
||||
interface Error {
|
||||
message: string
|
||||
}
|
||||
export default function FormScaffold<T extends FieldValues, TD, TE extends Error, TV, TC, TTD, TTE extends Error, TTV, TTC, TTTD, TTTE extends Error, TTTV, TTTC>(params: {
|
||||
|
||||
export default function FormScaffold<T extends FieldValues,>(params: {
|
||||
form: UseFormReturn<T>,
|
||||
onSubmit: SubmitHandler<T>,
|
||||
createMutation: UseTRPCMutationResult<TD, TE, TV, TC>,
|
||||
updateMutation: UseTRPCMutationResult<TTD, TTE, TTV, TTC>,
|
||||
deleteMutation: UseTRPCMutationResult<TTTD, TTTE, TTTV, TTTC>,
|
||||
title: string,
|
||||
children: ReactNode,
|
||||
children?: ReactNode,
|
||||
id?: string,
|
||||
className?: string
|
||||
}) {
|
||||
const { form, onSubmit, createMutation, deleteMutation, updateMutation, title, id, className, children } = params
|
||||
const { form, onSubmit, title, id, className, children } = params
|
||||
return (
|
||||
<Card.Card className={className ? className : "w-5/6 lg:w-1/2"}>
|
||||
<Card.CardHeader>
|
||||
@@ -32,12 +26,13 @@ export default function FormScaffold<T extends FieldValues, TD, TE extends Error
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="space-y-8"
|
||||
data-testid="form"
|
||||
>
|
||||
{children}
|
||||
<SubmitButton id={id} />
|
||||
<SubmitButton id={id} />
|
||||
<div className='flex flex-row justify-between'>
|
||||
<DependentFormMessaage falseStatus={createMutation.status} trueStatus={updateMutation.status} falseError={createMutation.error} trueError={updateMutation.error} bool={id ? true : false} />
|
||||
<DeleteButton mutation={deleteMutation} id={id} />
|
||||
<DependentFormMessaage bool={id ? true : false} />
|
||||
<DeleteButton id={id} />
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import { FormMessage } from "~/components/ui/form";
|
||||
import { useFormMutationContext } from "./MutationProvider";
|
||||
|
||||
interface Error {
|
||||
message: string
|
||||
}
|
||||
|
||||
export default function DependentFormMessaage( params: {trueStatus: string, falseStatus: string, falseError?: Error|null, trueError?:Error|null, bool: boolean} ) {
|
||||
export default function DependentFormMessaage( params: {bool: boolean} ) {
|
||||
const ctx = useFormMutationContext()
|
||||
if (ctx == undefined) {
|
||||
throw new Error('Dependent form message needs populates form mutations context')
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{
|
||||
params.bool ?
|
||||
<FormMessage className={params.trueStatus == "success" ? "text-green-500" : "text-red-500"}>
|
||||
{params.trueError ? params.trueError.message : params.trueStatus}
|
||||
<FormMessage className={ctx.updateMutation.status == "success" ? "text-green-500" : "text-red-500"}>
|
||||
{ctx.updateMutation.error ? ctx.updateMutation.error.message : ctx.updateMutation.status}
|
||||
</FormMessage> :
|
||||
<FormMessage className={params.falseStatus == "success" ? "text-green-500" : "text-red-500"}>
|
||||
{params.falseError ? params.falseError.message : params.falseStatus}
|
||||
<FormMessage className={ctx.createMutation.status == "success" ? "text-green-500" : "text-red-500"}>
|
||||
{ctx.createMutation.error ? ctx.createMutation.error.message : ctx.createMutation.status}
|
||||
</FormMessage>
|
||||
}
|
||||
</>
|
||||
|
||||
33
src/app/_components/Form/Components/MutationProvider.tsx
Normal file
33
src/app/_components/Form/Components/MutationProvider.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { UseTRPCMutationResult } from "node_modules/@trpc/react-query/dist/getQueryKey.d-CruH3ncI.mjs";
|
||||
import { createContext, useContext, type ReactNode } from "react";
|
||||
|
||||
interface ToString {
|
||||
toString: () => string
|
||||
message: string
|
||||
}
|
||||
|
||||
|
||||
export interface MutationInterface {
|
||||
mutate: (params:{id:string}) => void
|
||||
error: ToString | null
|
||||
status: "error" | "idle" | "pending" | "success"
|
||||
}
|
||||
|
||||
type FormMutationContext = {
|
||||
createMutation: MutationInterface,
|
||||
updateMutation: MutationInterface,
|
||||
deleteMutation: MutationInterface
|
||||
}
|
||||
|
||||
const FormMutationContext = createContext<FormMutationContext|undefined>(undefined)
|
||||
export function useFormMutationContext() {
|
||||
return useContext(FormMutationContext)
|
||||
}
|
||||
|
||||
export function FormMutationContextProvider(params: {children: ReactNode, value: FormMutationContext}) {
|
||||
return (
|
||||
<FormMutationContext.Provider value={params.value}>
|
||||
{params.children}
|
||||
</FormMutationContext.Provider>
|
||||
)
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import DependentText from "../../DependentText";
|
||||
|
||||
export default function SubmitButton(params: {id?:string}) {
|
||||
return (
|
||||
<Button type="submit">
|
||||
<Button submit={true}>
|
||||
<DependentText bool={params.id?true:false} true='Update' false='Create' />
|
||||
</Button>
|
||||
)
|
||||
|
||||
@@ -21,10 +21,8 @@ function InnerMultiBooleanFormField(params: { options: string[], onChange: (arg0
|
||||
}
|
||||
const onCheckedItemChange = (key: string) => {
|
||||
return function onCheckedChange(checked: CheckedState) {
|
||||
console.log(key,checked)
|
||||
let state = context.checkedValues;
|
||||
if (checked === "indeterminate") {
|
||||
console.log('checked was intermediate')
|
||||
return
|
||||
} else {
|
||||
state[key] = checked
|
||||
@@ -36,7 +34,6 @@ function InnerMultiBooleanFormField(params: { options: string[], onChange: (arg0
|
||||
stateArr.push(key)
|
||||
}
|
||||
}
|
||||
console.log('calling field on change with:', stateArr)
|
||||
params.onChange(stateArr)
|
||||
}
|
||||
}
|
||||
@@ -53,7 +50,7 @@ function InnerMultiBooleanFormField(params: { options: string[], onChange: (arg0
|
||||
<FormItem key={opt}>
|
||||
<div className="flex flex-row justify-between py-2 border-b-1">
|
||||
<FormLabel>{opt}</FormLabel>
|
||||
<Checkbox checked={checked(opt)} onCheckedChange={onCheckedItemChange(opt)} />
|
||||
<Checkbox data-testid="multiboolean-checkbox" checked={checked(opt)} onCheckedChange={onCheckedItemChange(opt)} />
|
||||
</div>
|
||||
</FormItem>
|
||||
))
|
||||
@@ -71,14 +68,14 @@ export default function MultiBooleanFormField<T extends FieldValues>(params: { c
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<PopoverTrigger data-testid="multiboolean-popover-trigger" asChild>
|
||||
<Button variant={'ghost'}>
|
||||
<FormLabel>{params.label}</FormLabel>
|
||||
<ChevronDownIcon/>
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<FormControl>
|
||||
<PopoverContent>
|
||||
<PopoverContent data-testid="multiboolean-content">
|
||||
<MultiBooleanFieldContext.Provider value={{checkedValues: checkedValues, setCheckedValue: setCheckedValues}}>
|
||||
<InnerMultiBooleanFormField onChange={field.onChange} options={params.options} />
|
||||
</MultiBooleanFieldContext.Provider>
|
||||
|
||||
19
src/app/_components/Test/TestingTest.client.test.tsx
Normal file
19
src/app/_components/Test/TestingTest.client.test.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import TestingTest from "./TestingTest";
|
||||
import { test } from 'vitest'
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import { userEvent } from '@testing-library/user-event'
|
||||
import { FormMutationContextProvider } from "../Form/Components/MutationProvider";
|
||||
|
||||
test('TestingTest', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(
|
||||
<TestingTest/>
|
||||
)
|
||||
const submitButton = screen.getByTestId('form-submit')
|
||||
screen.debug()
|
||||
user.click(submitButton)
|
||||
await waitFor(() => {
|
||||
screen.getByTestId('submitted')
|
||||
})
|
||||
screen.debug()
|
||||
})
|
||||
33
src/app/_components/Test/TestingTest.tsx
Normal file
33
src/app/_components/Test/TestingTest.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import { useForm } from "react-hook-form";
|
||||
import { FormScaffold } from "../Form/Components";
|
||||
import z from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useState } from "react";
|
||||
import { FormMutationContextProvider } from "../Form/Components/MutationProvider";
|
||||
|
||||
export default function TestingTest() {
|
||||
const schema = z.object({ text: z.string() })
|
||||
const [submitted, setSubmitted] = useState(false)
|
||||
const fakeMutation = {
|
||||
error: {message: "test"},
|
||||
status: "idle" as const,
|
||||
mutate: (_:{id:string}) => {}
|
||||
}
|
||||
const form = useForm<z.infer<typeof schema>>({
|
||||
resolver: zodResolver(schema),
|
||||
defaultValues: {
|
||||
text: ""
|
||||
}
|
||||
})
|
||||
const onSubmit = (_: z.infer<typeof schema>) => {
|
||||
setSubmitted(true)
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<div data-testid={submitted ? "submitted" : "unsubmitted"} />
|
||||
<FormMutationContextProvider value={{ createMutation: fakeMutation, updateMutation: fakeMutation, deleteMutation: fakeMutation }}>
|
||||
<FormScaffold form={form} onSubmit={onSubmit} title="Testing Test" />
|
||||
</FormMutationContextProvider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user