test setup lackin

This commit is contained in:
2025-09-03 22:04:56 +02:00
parent 869cc07fdd
commit 276c3dd75f
35 changed files with 629 additions and 285 deletions

View File

@@ -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>
)

View File

@@ -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>

View File

@@ -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>
}
</>

View 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>
)
}

View File

@@ -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>
)

View File

@@ -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>

View 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()
})

View 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>
</>
)
}