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

@@ -11,6 +11,7 @@ import { useState } from 'react';
import { SelectFormField, TextInputFormField } from '~/app/_components/Form/Fields';
import { usePathname, useRouter } from 'next/navigation';
import { SelectItem } from '~/components/ui/select';
import FormMutationContextProvider from '~/app/_components/Form/Components/MutationProvider';
export default function CreateUpdateCvCategoryForm(params: { className?: string, entity?: IterableElement<RouterOutputs['category']['select']> }) {
const schemas = entitySchemas('cvCategory')
const [id, setId] = useState<string | undefined>(params.entity ? params.entity.id : undefined)
@@ -33,22 +34,25 @@ export default function CreateUpdateCvCategoryForm(params: { className?: string,
createMutation.mutate(values)
}
return (
<FormScaffold
form={form}
createMutation={createMutation}
updateMutation={updateMutation}
deleteMutation={deleteMutation}
onSubmit={onSubmit}
title='Category'
id={id}
className={params.className}
>
<TextInputFormField control={form.control} name='name' label='Name' />
<SelectFormField control={form.control} name='layoutPosition' label='Layout Position' placeholder={form.getValues().layoutPosition == null ? undefined : form.getValues().layoutPosition}>
{schemas.insert.shape.layoutPosition.unwrap().unwrap().options.map((o) => (
<SelectItem key={o} value={o}> {o} </SelectItem>
))}
</SelectFormField>
</FormScaffold>
<FormMutationContextProvider value={{
createMutation:createMutation,
updateMutation:updateMutation,
deleteMutation:deleteMutation
}}>
<FormScaffold
form={form}
onSubmit={onSubmit}
title='Category'
id={id}
className={params.className}
>
<TextInputFormField control={form.control} name='name' label='Name' />
<SelectFormField control={form.control} name='layoutPosition' label='Layout Position' placeholder={form.getValues().layoutPosition == null ? undefined : form.getValues().layoutPosition}>
{schemas.insert.shape.layoutPosition.unwrap().unwrap().options.map((o) => (
<SelectItem key={o} value={o}> {o} </SelectItem>
))}
</SelectFormField>
</FormScaffold>
</FormMutationContextProvider>
)
}

View File

@@ -13,6 +13,7 @@ import { FormScaffold } from '~/app/_components/Form/Components';
import { useState } from 'react';
import { SelectFormField, TextInputFormField, MdeFormField, CalenderFormField, BooleanFormField } from '~/app/_components/Form/Fields'
import { usePathname, useRouter } from 'next/navigation';
import {FormMutationContextProvider, type FormCreateMutationInterface} from '~/app/_components/Form/Components/MutationProvider';
export default function CreateUpdateCvEntryForm(params: { className?: string, entity?: IterableElement<RouterOutputs['entry']['select']>, isUpdate?: boolean }) {
const [id, setId] = useState<string | undefined>(params.entity ? params.entity.id : undefined)
const { theme } = useTheme()
@@ -42,11 +43,16 @@ export default function CreateUpdateCvEntryForm(params: { className?: string, en
createMutation.mutate(values)
}
return (
//todo
// solved by: strictFunctionTypes: false
// sadge
<FormMutationContextProvider value={{
createMutation:createMutation,
updateMutation:updateMutation,
deleteMutation:deleteMutation
}}>
<FormScaffold
form={form}
createMutation={createMutation}
updateMutation={updateMutation}
deleteMutation={deleteMutation}
onSubmit={onSubmit}
title='Entry'
id={id}
@@ -56,7 +62,7 @@ export default function CreateUpdateCvEntryForm(params: { className?: string, en
{
categoriesSuccess ?
<>
{categories.map((c) => {
{categories?.map((c) => {
return (<SelectItem key={c.id} value={c.id}> {c.name} </SelectItem>)
})}
</> :
@@ -69,5 +75,6 @@ export default function CreateUpdateCvEntryForm(params: { className?: string, en
<CalenderFormField control={form.control} name='toTime' label='To Date' />
<BooleanFormField control={form.control} name='hideDates' label='Hide Dates' />
</FormScaffold>
</FormMutationContextProvider>
)
}

View File

@@ -1,8 +1,7 @@
'use server'
import { expect, test } from 'vitest'
import { render, screen } from '@testing-library/react'
import CreateUpdateProjectForm from './CreateUpdateProjectForm'
import TrpcProvider from '~/../test/trpc/vitest.trpcProvider.mock'
import TrpcProvider from '~/app/_trpc/TrpcProvider'
test('CreateUpdateProjectForm', () => {
render(
@@ -10,6 +9,4 @@ test('CreateUpdateProjectForm', () => {
<CreateUpdateProjectForm/>
</TrpcProvider>
)
let options = screen.getAllByRole('combobox')
console.log(options)
})

View File

@@ -12,12 +12,11 @@ import { SelectFormField, TextInputFormField } from '~/app/_components/Form/Fiel
import { FormScaffold } from '~/app/_components/Form/Components';
import { usePathname, useRouter } from 'next/navigation';
import { makeUseRelationShipWithNameIndex } from '~/lib/hooks';
import { FormMutationContextProvider } from '~/app/_components/Form/Components/MutationProvider';
export default function CreateUpdateProjectForm(params: { className?: string, entity?: IterableElement<RouterOutputs['project']['select']> }) {
const [id, setId] = useState<string|undefined>(params.entity ? params.entity.id : undefined)
const [id, setId] = useState<string | undefined>(params.entity ? params.entity.id : undefined)
const schemas = entitySchemas('project')
console.log('using trpc')
const { data:stacks,id:stackId, name:stackName,success:stacksSuccess, error:stackError } = makeUseRelationShipWithNameIndex('stackItems')(trpc.techStack.select.useQuery({}),id,(items) => {return items ? items.join('-') : ""})
console.log(stackError)
const { data: stacks, id: stackId, name: stackName, success: stacksSuccess, error: stackError } = makeUseRelationShipWithNameIndex('stackItems')(trpc.techStack.select.useQuery({}), id, (items) => { return items ? items.join('-') : "" })
const form = useForm<z.infer<typeof schemas.insert>>({
resolver: zodResolver(schemas.insert),
defaultValues: {
@@ -40,38 +39,42 @@ export default function CreateUpdateProjectForm(params: { className?: string, en
createMutation.mutate(values)
}
return (
<FormScaffold
form={form}
createMutation={createMutation}
updateMutation={updateMutation}
deleteMutation={deleteMutation}
onSubmit={onSubmit}
title='Project'
id={id}
className={params.className}
>
<SelectFormField control={form.control} name='stackId' label='Stack' defaultValue={stackId} placeholder={stackName} >
{
stacksSuccess ?
<>
{stacks?.map((stack) => {
return (<SelectItem key={stack.id} value={stack.id}> {stack.stackItems ? stack.stackItems.join("-") : "Empty Stack"} </SelectItem>)
})}
</> :
<SelectItem key='placeholder' value="placeholder" />
}
</SelectFormField>
<TextInputFormField control={form.control} name='title' label='Title' />
<SelectFormField control={form.control} name='sourceType' label='Source Type' defaultValue={'open'} placeholder='open' >
<SelectItem value="open"> open </SelectItem>
<SelectItem value="closed"> closed </SelectItem>
</SelectFormField>
<TextInputFormField control={form.control} label='Source Link' name='sourceLink' />
<SelectFormField control={form.control} name='releaseStatus' label='Release Status' defaultValue={'unreleased'} placeholder='unreleased' >
<SelectItem value="released"> released </SelectItem>
<SelectItem value="unreleased"> unreleased </SelectItem>
</SelectFormField>
<TextInputFormField control={form.control} label='Release Link' name='releaseLink' />
</FormScaffold>
<FormMutationContextProvider value={
{
createMutation: createMutation,
updateMutation: updateMutation,
deleteMutation: deleteMutation
}}>
<FormScaffold
form={form}
onSubmit={onSubmit}
title='Project'
id={id}
className={params.className}
>
<SelectFormField control={form.control} name='stackId' label='Stack' defaultValue={stackId} placeholder={stackName} >
{
stacksSuccess ?
<>
{stacks?.map((stack) => {
return (<SelectItem key={stack.id} value={stack.id}> {stack.stackItems ? stack.stackItems.join("-") : "Empty Stack"} </SelectItem>)
})}
</> :
<SelectItem key='placeholder' value="placeholder" />
}
</SelectFormField>
<TextInputFormField control={form.control} name='title' label='Title' />
<SelectFormField control={form.control} name='sourceType' label='Source Type' defaultValue={'open'} placeholder='open' >
<SelectItem value="open"> open </SelectItem>
<SelectItem value="closed"> closed </SelectItem>
</SelectFormField>
<TextInputFormField control={form.control} label='Source Link' name='sourceLink' />
<SelectFormField control={form.control} name='releaseStatus' label='Release Status' defaultValue={'unreleased'} placeholder='unreleased' >
<SelectItem value="released"> released </SelectItem>
<SelectItem value="unreleased"> unreleased </SelectItem>
</SelectFormField>
<TextInputFormField control={form.control} label='Release Link' name='releaseLink' />
</FormScaffold>
</FormMutationContextProvider>
)
}

View File

@@ -0,0 +1,55 @@
import { test, assert, expect } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { userEvent } from '@testing-library/user-event'
import CreateUpdateStackForm from './CreateUpdateForm'
import TrpcProvider from '~/app/_trpc/TrpcProvider'
import { servTrpc } from '~/app/_trpc/ServerClient'
import { db } from '~/server/db'
import { sql } from 'drizzle-orm'
test('CreateUpdateProjectForm',async () => {
const user = userEvent.setup()
// console.log("db direct:" ,db.query.techStack.findMany());
render(
<TrpcProvider>
<CreateUpdateStackForm/>
</TrpcProvider>
)
const trigger = screen.getByTestId("multiboolean-popover-trigger")
fireEvent.click(trigger)
const content = screen.getAllByTestId("multiboolean-checkbox")
const checkfirst = content.at(0)
const checkSecond = content.at(1)
assert.notEqual(checkfirst,undefined)
assert.notEqual(checkSecond,undefined)
await user.click(checkfirst as HTMLElement)
await user.click(checkSecond as HTMLElement)
// TODO use findby: https://testing-library.com/docs/dom-testing-library/api-async because component has async effects and conditional rendering
// this shit just doesnt work
// https://github.com/jsdom/jsdom/issues/1937 why ? who knows
const submitButton = screen.getByTestId('form-submit')
screen.debug(submitButton)
// waitFor(() => {
// if ((submitButton as HTMLButtonElement).type != 'submit') {
// console.log("button isn submit")
// throw new Error('submit button props pending');
// }
// })
await user.click(submitButton)
screen.debug()
//TODO find out why the fuck this is timing out
await waitFor(() => {
screen.getByTestId('submitted')
},{timeout:3000})
let res
await waitFor(async () => {
return new Promise(async (resolve,reject) => {
res = await db.execute(sql`SELECT * from "gregorlohaus.com_tech_stack";`)
if (res.rows.length < 1) {
reject(false)
} else {
resolve(true)
}
})
},{timeout:3000})
console.log(res)
})

View File

@@ -2,19 +2,16 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
import { z } from "zod";
import { Form } from "~/components/ui/form";
import { trpc } from "~/app/_trpc/Client";
import { Button } from "~/components/ui/button";
import * as Card from '~/components/ui/card'
import type { IterableElement } from 'type-fest'
import { stackItemEnum } from "~/server/db/schema";
import { stackItemEnum } from "~/server/dbschema/schema";
import type { RouterOutputs } from '~/server/routers/_app';
import { entitySchemas, makeOnSuccess } from '~/lib/utils';
import { useState } from 'react';
import { MultiBooleanFormField } from "~/app/_components/Form/Fields"
import { DependentFormMessaage, FormScaffold } from '~/app/_components/Form/Components';
import DependentText from '~/app/_components/DependentText';
import { FormScaffold } from '~/app/_components/Form/Components';
import { usePathname, useRouter } from 'next/navigation';
import { FormMutationContextProvider } from '~/app/_components/Form/Components/MutationProvider';
export default function CreateUpdateStackForm(params: { className?: string, entity?: IterableElement<RouterOutputs['techStack']['select']> }) {
const schemas = entitySchemas('techStack')
@@ -25,6 +22,7 @@ export default function CreateUpdateStackForm(params: { className?: string, enti
stackItems: params.entity ? params.entity.stackItems : [],
}
})
const [submitted, setSubmitted] = useState(false)
const [id, setId] = useState<string | undefined>(params.entity ? params.entity.id : undefined)
let path = usePathname()
let router = useRouter()
@@ -32,22 +30,25 @@ export default function CreateUpdateStackForm(params: { className?: string, enti
const updateMutation = trpc.techStack.update.useMutation({ onSuccess: makeOnSuccess('update', form) })
const deleteMutation = trpc.techStack.delete.useMutation({ onSuccess: makeOnSuccess('delete', form, undefined, path, router) })
function onSubmit(values: z.infer<typeof schemas.insert>) {
setSubmitted(true)
params.entity ?
updateMutation.mutate(values) :
createMutation.mutate(values)
createMutation.mutate(values);
}
return (
<FormScaffold
form={form}
createMutation={createMutation}
updateMutation={updateMutation}
deleteMutation={deleteMutation}
onSubmit={onSubmit}
title='Entry'
id={id}
className={params.className}
>
<MultiBooleanFormField control={form.control} name='stackItems' label='Stack Items' options={stackItemEnum.enumValues} defaultValues={params.entity?.stackItems} />
</FormScaffold>
<>
<div data-testid={submitted ? "submitted" : ""}/>
<FormMutationContextProvider value={{ createMutation: createMutation, updateMutation: updateMutation, deleteMutation: deleteMutation }}>
<FormScaffold
form={form}
onSubmit={onSubmit}
title='Entry'
id={id}
className={params.className}
>
<MultiBooleanFormField control={form.control} name='stackItems' label='Stack Items' options={stackItemEnum.enumValues} defaultValues={params.entity?.stackItems ?? [""]} />
</FormScaffold>
</FormMutationContextProvider>
</>
)
}