Fixes the CRUD client helpers (#2098)

This commit is contained in:
Mihovil Ilakovac 2024-07-02 09:44:03 +02:00 committed by GitHub
parent 78c9db996a
commit 320f40327a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 259 additions and 47 deletions

View File

@ -1,7 +1,7 @@
{{={= =}=}}
import { useAction, useQuery } from "wasp/client/operations";
import { createAction } from "../operations/actions/core.js";
import { createQuery } from "../operations/queries/core.js";
import { makeUseActionFor, makeUseQueryFor } from "./operationsHelpers.js";
import {
{=# operations.Get =}
GetQueryResolved,
@ -55,41 +55,31 @@ function createCrud() {
{=# operations.Get =}
get: {
query: crudGetQuery,
useQuery(args: Parameters<GetQueryResolved>[0]) {
return useQuery(crudGetQuery, args);
}
useQuery: makeUseQueryFor(crudGetQuery)
},
{=/ operations.Get =}
{=# operations.GetAll =}
getAll: {
query: crudGetAllQuery,
useQuery() {
return useQuery(crudGetAllQuery);
}
useQuery: makeUseQueryFor(crudGetAllQuery)
},
{=/ operations.GetAll =}
{=# operations.Create =}
create: {
action: crudCreateAction,
useAction() {
return useAction(crudCreateAction);
}
useAction: makeUseActionFor(crudCreateAction)
},
{=/ operations.Create =}
{=# operations.Update =}
update: {
action: crudUpdateAction,
useAction() {
return useAction(crudUpdateAction);
}
useAction: makeUseActionFor(crudUpdateAction)
},
{=/ operations.Update =}
{=# operations.Delete =}
delete: {
action: crudDeleteAction,
useAction() {
return useAction(crudDeleteAction);
}
useAction: makeUseActionFor(crudDeleteAction)
},
{=/ operations.Delete =}
}

View File

@ -0,0 +1,21 @@
import { useAction, useQuery } from "../operations"
import type { Query, Action } from "../operations/rpc"
import type { Tail } from "../../universal/types"
// PRIVATE API
export function makeUseQueryFor<Input, Output>(
query: Query<Input, Output>
) {
return (
...rest: Tail<Parameters<typeof useQuery<Input, Output>>>
) => useQuery<Input, Output>(query, ...rest);
}
// PRIVATE API
export function makeUseActionFor<Input = unknown, Output = unknown>(
action: Action<Input, Output>
) {
return (
...rest: Tail<Parameters<typeof useAction<Input, Output>>>
) => useAction<Input, Output>(action, ...rest);
}

View File

@ -29,3 +29,7 @@ export type _Awaited<T> = T extends Promise<infer V>
// consideration.
export type _ReturnType<T extends (...args: never[]) => unknown> =
T extends (...args: never[]) => infer R ? R : never
// Returns elements of an array except the first one.
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -333,7 +333,7 @@
"file",
"../out/sdk/wasp/universal/types.ts"
],
"8ef378c1447289104856ec1a92931fd1280c0f8d0a8463008674e93bd798b884"
"791cb40cb5c405ade34d46770a8178353257e8d2351a877b6ca5e88aafb0ec13"
],
[
[

View File

@ -3,3 +3,4 @@ export type Expand<T> = T extends (...args: infer A) => infer R ? (...args: A) =
} : never;
export type _Awaited<T> = T extends Promise<infer V> ? _Awaited<V> : T;
export type _ReturnType<T extends (...args: never[]) => unknown> = T extends (...args: never[]) => infer R ? R : never;
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -29,3 +29,7 @@ export type _Awaited<T> = T extends Promise<infer V>
// consideration.
export type _ReturnType<T extends (...args: never[]) => unknown> =
T extends (...args: never[]) => infer R ? R : never
// Returns elements of an array except the first one.
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -3,3 +3,4 @@ export type Expand<T> = T extends (...args: infer A) => infer R ? (...args: A) =
} : never;
export type _Awaited<T> = T extends Promise<infer V> ? _Awaited<V> : T;
export type _ReturnType<T extends (...args: never[]) => unknown> = T extends (...args: never[]) => infer R ? R : never;
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -29,3 +29,7 @@ export type _Awaited<T> = T extends Promise<infer V>
// consideration.
export type _ReturnType<T extends (...args: never[]) => unknown> =
T extends (...args: never[]) => infer R ? R : never
// Returns elements of an array except the first one.
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -333,7 +333,7 @@
"file",
"../out/sdk/wasp/universal/types.ts"
],
"8ef378c1447289104856ec1a92931fd1280c0f8d0a8463008674e93bd798b884"
"791cb40cb5c405ade34d46770a8178353257e8d2351a877b6ca5e88aafb0ec13"
],
[
[

View File

@ -3,3 +3,4 @@ export type Expand<T> = T extends (...args: infer A) => infer R ? (...args: A) =
} : never;
export type _Awaited<T> = T extends Promise<infer V> ? _Awaited<V> : T;
export type _ReturnType<T extends (...args: never[]) => unknown> = T extends (...args: never[]) => infer R ? R : never;
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -29,3 +29,7 @@ export type _Awaited<T> = T extends Promise<infer V>
// consideration.
export type _ReturnType<T extends (...args: never[]) => unknown> =
T extends (...args: never[]) => infer R ? R : never
// Returns elements of an array except the first one.
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -35,6 +35,7 @@ waspComplexTest/.wasp/out/sdk/wasp/client/auth/index.ts
waspComplexTest/.wasp/out/sdk/wasp/client/auth/ui.ts
waspComplexTest/.wasp/out/sdk/wasp/client/config.ts
waspComplexTest/.wasp/out/sdk/wasp/client/crud/index.ts
waspComplexTest/.wasp/out/sdk/wasp/client/crud/operationsHelpers.ts
waspComplexTest/.wasp/out/sdk/wasp/client/crud/tasks.ts
waspComplexTest/.wasp/out/sdk/wasp/client/index.ts
waspComplexTest/.wasp/out/sdk/wasp/client/operations/actions/core.ts
@ -148,6 +149,9 @@ waspComplexTest/.wasp/out/sdk/wasp/dist/client/config.js.map
waspComplexTest/.wasp/out/sdk/wasp/dist/client/crud/index.d.ts
waspComplexTest/.wasp/out/sdk/wasp/dist/client/crud/index.js
waspComplexTest/.wasp/out/sdk/wasp/dist/client/crud/index.js.map
waspComplexTest/.wasp/out/sdk/wasp/dist/client/crud/operationsHelpers.d.ts
waspComplexTest/.wasp/out/sdk/wasp/dist/client/crud/operationsHelpers.js
waspComplexTest/.wasp/out/sdk/wasp/dist/client/crud/operationsHelpers.js.map
waspComplexTest/.wasp/out/sdk/wasp/dist/client/crud/tasks.d.ts
waspComplexTest/.wasp/out/sdk/wasp/dist/client/crud/tasks.js
waspComplexTest/.wasp/out/sdk/wasp/dist/client/crud/tasks.js.map

View File

@ -209,12 +209,19 @@
],
"ca3b06b6c04c38c69523f435f6a15e9984414b440648708ea7227cd619b2f918"
],
[
[
"file",
"../out/sdk/wasp/client/crud/operationsHelpers.ts"
],
"2da35a3b387e026ada345f21f78b75170423696828fa0981b1900e5660d650e9"
],
[
[
"file",
"../out/sdk/wasp/client/crud/tasks.ts"
],
"2114cf0cc99408b1bb501f8a278c90239349744f3593a9cd2f80cbea0b1fbbe3"
"4947286d60b6652052edd7bc47230481a27ce5cbaa62ed62bac727576ececa43"
],
[
[
@ -746,7 +753,7 @@
"file",
"../out/sdk/wasp/universal/types.ts"
],
"8ef378c1447289104856ec1a92931fd1280c0f8d0a8463008674e93bd798b884"
"791cb40cb5c405ade34d46770a8178353257e8d2351a877b6ca5e88aafb0ec13"
],
[
[

View File

@ -0,0 +1,21 @@
import { useAction, useQuery } from "../operations"
import type { Query, Action } from "../operations/rpc"
import type { Tail } from "../../universal/types"
// PRIVATE API
export function makeUseQueryFor<Input, Output>(
query: Query<Input, Output>
) {
return (
...rest: Tail<Parameters<typeof useQuery<Input, Output>>>
) => useQuery<Input, Output>(query, ...rest);
}
// PRIVATE API
export function makeUseActionFor<Input = unknown, Output = unknown>(
action: Action<Input, Output>
) {
return (
...rest: Tail<Parameters<typeof useAction<Input, Output>>>
) => useAction<Input, Output>(action, ...rest);
}

View File

@ -1,6 +1,6 @@
import { useAction, useQuery } from "wasp/client/operations";
import { createAction } from "../operations/actions/core.js";
import { createQuery } from "../operations/queries/core.js";
import { makeUseActionFor, makeUseQueryFor } from "./operationsHelpers.js";
import {
GetQueryResolved,
GetAllQueryResolved,
@ -23,21 +23,15 @@ function createCrud() {
return {
get: {
query: crudGetQuery,
useQuery(args: Parameters<GetQueryResolved>[0]) {
return useQuery(crudGetQuery, args);
}
useQuery: makeUseQueryFor(crudGetQuery)
},
getAll: {
query: crudGetAllQuery,
useQuery() {
return useQuery(crudGetAllQuery);
}
useQuery: makeUseQueryFor(crudGetAllQuery)
},
create: {
action: crudCreateAction,
useAction() {
return useAction(crudCreateAction);
}
useAction: makeUseActionFor(crudCreateAction)
},
}
}

View File

@ -0,0 +1,5 @@
import type { Query, Action } from "../operations/rpc";
export declare function makeUseQueryFor<Input, Output>(query: Query<Input, Output>): (queryFnArgs?: Input, options?: any) => import("@tanstack/react-query").UseQueryResult<Output, Error>;
export declare function makeUseActionFor<Input = unknown, Output = unknown>(action: Action<Input, Output>): (actionOptions?: {
optimisticUpdates: import("../operations").OptimisticUpdateDefinition<Input, any>[];
}) => [Input] extends [never] ? (args?: unknown) => Promise<Output> : [Input] extends [void] ? () => Promise<Output> : (args: Input) => Promise<Output>;

View File

@ -0,0 +1,10 @@
import { useAction, useQuery } from "../operations";
// PRIVATE API
export function makeUseQueryFor(query) {
return (...rest) => useQuery(query, ...rest);
}
// PRIVATE API
export function makeUseActionFor(action) {
return (...rest) => useAction(action, ...rest);
}
//# sourceMappingURL=operationsHelpers.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"operationsHelpers.js","sourceRoot":"","sources":["../../../client/crud/operationsHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAInD,cAAc;AACd,MAAM,UAAU,eAAe,CAC7B,KAA2B;IAE3B,OAAO,CACL,GAAG,IAAsD,EACzD,EAAE,CAAC,QAAQ,CAAgB,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,cAAc;AACd,MAAM,UAAU,gBAAgB,CAC9B,MAA6B;IAE7B,OAAO,CACL,GAAG,IAAuD,EAC1D,EAAE,CAAC,SAAS,CAAgB,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;AACjD,CAAC"}

View File

@ -2,7 +2,7 @@ import { GetQueryResolved, GetAllQueryResolved } from 'wasp/server/crud/tasks';
export declare const tasks: {
get: {
query: import("../operations/queries/core.js").QueryFor<GetQueryResolved>;
useQuery(args: Parameters<GetQueryResolved>[0]): import("@tanstack/react-query").UseQueryResult<import("@prisma/client/runtime/index.js").GetResult<{
useQuery: (queryFnArgs?: import(".prisma/client").Prisma.TaskWhereUniqueInput, options?: any) => import("@tanstack/react-query").UseQueryResult<import("@prisma/client/runtime/index.js").GetResult<{
id: number;
description: string;
isDone: boolean;
@ -10,7 +10,7 @@ export declare const tasks: {
};
getAll: {
query: import("../operations/queries/core.js").QueryFor<GetAllQueryResolved>;
useQuery(): import("@tanstack/react-query").UseQueryResult<(import("@prisma/client/runtime/index.js").GetResult<{
useQuery: (queryFnArgs?: {}, options?: any) => import("@tanstack/react-query").UseQueryResult<(import("@prisma/client/runtime/index.js").GetResult<{
id: number;
description: string;
isDone: boolean;
@ -22,7 +22,9 @@ export declare const tasks: {
description: string;
isDone: boolean;
}, unknown> & {}>;
useAction(): (args: import(".prisma/client").Prisma.TaskCreateInput) => Promise<import("@prisma/client/runtime/index.js").GetResult<{
useAction: (actionOptions?: {
optimisticUpdates: import("../operations/hooks.js").OptimisticUpdateDefinition<import(".prisma/client").Prisma.TaskCreateInput, any>[];
}) => (args: import(".prisma/client").Prisma.TaskCreateInput) => Promise<import("@prisma/client/runtime/index.js").GetResult<{
id: number;
description: string;
isDone: boolean;

View File

@ -1,6 +1,6 @@
import { useAction, useQuery } from "wasp/client/operations";
import { createAction } from "../operations/actions/core.js";
import { createQuery } from "../operations/queries/core.js";
import { makeUseActionFor, makeUseQueryFor } from "./operationsHelpers.js";
function createCrud() {
const crudGetQuery = createQuery('tasks/get', ['Task']);
const crudGetAllQuery = createQuery('tasks/get-all', ['Task']);
@ -8,21 +8,15 @@ function createCrud() {
return {
get: {
query: crudGetQuery,
useQuery(args) {
return useQuery(crudGetQuery, args);
}
useQuery: makeUseQueryFor(crudGetQuery)
},
getAll: {
query: crudGetAllQuery,
useQuery() {
return useQuery(crudGetAllQuery);
}
useQuery: makeUseQueryFor(crudGetAllQuery)
},
create: {
action: crudCreateAction,
useAction() {
return useAction(crudCreateAction);
}
useAction: makeUseActionFor(crudCreateAction)
},
};
}

View File

@ -1 +1 @@
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../../client/crud/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAO5D,SAAS,UAAU;IACf,MAAM,YAAY,GAAG,WAAW,CAC5B,WAAW,EACX,CAAC,MAAM,CAAC,CACX,CAAA;IACD,MAAM,eAAe,GAAG,WAAW,CAC/B,eAAe,EACf,CAAC,MAAM,CAAC,CACX,CAAA;IACD,MAAM,gBAAgB,GAAG,YAAY,CACjC,cAAc,EACd,CAAC,MAAM,CAAC,CACX,CAAA;IACD,OAAO;QACH,GAAG,EAAE;YACD,KAAK,EAAE,YAAY;YACnB,QAAQ,CAAC,IAAqC;gBAC1C,OAAO,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YACxC,CAAC;SACJ;QACD,MAAM,EAAE;YACJ,KAAK,EAAE,eAAe;YACtB,QAAQ;gBACJ,OAAO,QAAQ,CAAC,eAAe,CAAC,CAAC;YACrC,CAAC;SACJ;QACD,MAAM,EAAE;YACJ,MAAM,EAAE,gBAAgB;YACxB,SAAS;gBACL,OAAO,SAAS,CAAC,gBAAgB,CAAC,CAAC;YACvC,CAAC;SACJ;KACJ,CAAA;AACL,CAAC;AAED,aAAa;AACb,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC"}
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../../client/crud/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAO3E,SAAS,UAAU;IACf,MAAM,YAAY,GAAG,WAAW,CAC5B,WAAW,EACX,CAAC,MAAM,CAAC,CACX,CAAA;IACD,MAAM,eAAe,GAAG,WAAW,CAC/B,eAAe,EACf,CAAC,MAAM,CAAC,CACX,CAAA;IACD,MAAM,gBAAgB,GAAG,YAAY,CACjC,cAAc,EACd,CAAC,MAAM,CAAC,CACX,CAAA;IACD,OAAO;QACH,GAAG,EAAE;YACD,KAAK,EAAE,YAAY;YACnB,QAAQ,EAAE,eAAe,CAAC,YAAY,CAAC;SAC1C;QACD,MAAM,EAAE;YACJ,KAAK,EAAE,eAAe;YACtB,QAAQ,EAAE,eAAe,CAAC,eAAe,CAAC;SAC7C;QACD,MAAM,EAAE;YACJ,MAAM,EAAE,gBAAgB;YACxB,SAAS,EAAE,gBAAgB,CAAC,gBAAgB,CAAC;SAChD;KACJ,CAAA;AACL,CAAC;AAED,aAAa;AACb,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC"}

View File

@ -3,3 +3,4 @@ export type Expand<T> = T extends (...args: infer A) => infer R ? (...args: A) =
} : never;
export type _Awaited<T> = T extends Promise<infer V> ? _Awaited<V> : T;
export type _ReturnType<T extends (...args: never[]) => unknown> = T extends (...args: never[]) => infer R ? R : never;
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -29,3 +29,7 @@ export type _Awaited<T> = T extends Promise<infer V>
// consideration.
export type _ReturnType<T extends (...args: never[]) => unknown> =
T extends (...args: never[]) => infer R ? R : never
// Returns elements of an array except the first one.
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -389,7 +389,7 @@
"file",
"../out/sdk/wasp/universal/types.ts"
],
"8ef378c1447289104856ec1a92931fd1280c0f8d0a8463008674e93bd798b884"
"791cb40cb5c405ade34d46770a8178353257e8d2351a877b6ca5e88aafb0ec13"
],
[
[

View File

@ -3,3 +3,4 @@ export type Expand<T> = T extends (...args: infer A) => infer R ? (...args: A) =
} : never;
export type _Awaited<T> = T extends Promise<infer V> ? _Awaited<V> : T;
export type _ReturnType<T extends (...args: never[]) => unknown> = T extends (...args: never[]) => infer R ? R : never;
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -29,3 +29,7 @@ export type _Awaited<T> = T extends Promise<infer V>
// consideration.
export type _ReturnType<T extends (...args: never[]) => unknown> =
T extends (...args: never[]) => infer R ? R : never
// Returns elements of an array except the first one.
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -333,7 +333,7 @@
"file",
"../out/sdk/wasp/universal/types.ts"
],
"8ef378c1447289104856ec1a92931fd1280c0f8d0a8463008674e93bd798b884"
"791cb40cb5c405ade34d46770a8178353257e8d2351a877b6ca5e88aafb0ec13"
],
[
[

View File

@ -3,3 +3,4 @@ export type Expand<T> = T extends (...args: infer A) => infer R ? (...args: A) =
} : never;
export type _Awaited<T> = T extends Promise<infer V> ? _Awaited<V> : T;
export type _ReturnType<T extends (...args: never[]) => unknown> = T extends (...args: never[]) => infer R ? R : never;
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -29,3 +29,7 @@ export type _Awaited<T> = T extends Promise<infer V>
// consideration.
export type _ReturnType<T extends (...args: never[]) => unknown> =
T extends (...args: never[]) => infer R ? R : never
// Returns elements of an array except the first one.
export type Tail<T extends [unknown, ...unknown[]]> = T extends [unknown, ...infer R] ? R : never;

View File

@ -0,0 +1,39 @@
import { useState } from 'react'
import { AuthUser } from 'wasp/auth'
import { Tasks } from 'wasp/client/crud'
export function CrudTestPage({ user }: { user: AuthUser }) {
const { data: tasks } = Tasks.getAll.useQuery({ filter: 'special filter ' })
const createTask = Tasks.create.useAction()
const [newTaskDescription, setNewTaskDescription] = useState('')
return (
<div>
<h1>Tasks</h1>
<div>
<input
type="text"
value={newTaskDescription}
onChange={(e) => setNewTaskDescription(e.target.value)}
/>
<button
onClick={() =>
createTask({
user: { connect: { id: user.id } },
description: newTaskDescription,
isDone: false,
})
}
>
Create task
</button>
</div>
<ul>
{tasks?.map((task) => (
<li key={task.id}>{task.description}</li>
))}
</ul>
</div>
)
}

View File

@ -0,0 +1,22 @@
import { Task } from 'wasp/entities'
import { HttpError } from 'wasp/server'
import { Tasks } from 'wasp/server/crud'
export const getAllFilteredTasks: Tasks.GetAllQuery<
{ filter: string } | void,
Task[]
> = (args, context) => {
if (!context.user) {
throw new HttpError(401, 'Unauthorized')
}
return context.entities.Task.findMany({
where: {
description: {
contains: args ? args.filter : '',
},
user: {
id: context.user.id,
},
},
})
}

View File

@ -115,6 +115,12 @@ page TaskPage {
component: import Task from "@src/client/pages/Task.tsx"
}
route CrudRoute { path: "/crud", to: Crud }
page Crud {
component: import { CrudTestPage } from "@src/client/pages/CrudTest.tsx",
authRequired: true
}
route CatchAllRoute { path: "*", to: CatchAllPage }
page CatchAllPage {
component: import { CatchAllPage } from "@src/client/pages/CatchAll"
@ -215,3 +221,13 @@ job mySpecialScheduledJob {
}
}
}
crud Tasks {
entity: Task,
operations: {
getAll: {
overrideFn: import { getAllFilteredTasks } from "@src/server/crud"
},
create: {}
}
}

View File

@ -0,0 +1,50 @@
import { test, expect } from "@playwright/test";
test.describe("CRUD test", () => {
const randomEmail = `test${Math.random().toString(36).substring(7)}@test.com`;
const password = "12345678";
test.describe.configure({ mode: "serial" });
test.beforeAll(async ({ browser }) => {
const page = await browser.newPage();
// Sign up
await page.goto("/signup");
await page.waitForSelector("text=Create a new account");
await page.locator("input[type='email']").fill(randomEmail);
await page.locator("input[type='password']").fill(password);
await page.locator("button").click();
});
test("CRUD with override works", async ({ page }) => {
await page.goto("/login");
await page.waitForSelector("text=Log in to your account");
await page.locator("input[type='email']").fill(randomEmail);
await page.locator("input[type='password']").fill(password);
await page.getByRole("button", { name: "Log in" }).click();
await page.waitForSelector("text=Profile page");
await page.goto("/crud");
await page.waitForSelector("text=Tasks");
await createTask(page, "special filter 1");
await createTask(page, "special filter 2");
await createTask(page, "something else");
await expect(page.locator("body")).toContainText("special filter 1");
await expect(page.locator("body")).toContainText("special filter 2");
await expect(page.locator("li[text='something else']")).not.toBeVisible();
});
});
async function createTask(page: any, description: string) {
await page.locator("input[type='text']").fill(description);
await page.getByText("Create task").click();
}

View File

@ -22,13 +22,15 @@ genNewClientCrudApi spec =
if areThereAnyCruds
then
sequence
[ genCrudIndex spec cruds
[ genCrudIndex spec cruds,
genFileCopy [relfile|client/crud/operationsHelpers.ts|]
]
<++> genCrudOperations spec cruds
else return []
where
cruds = getCruds spec
areThereAnyCruds = not $ null cruds
genFileCopy = return . C.mkTmplFd
genCrudIndex :: AppSpec -> [(String, AS.Crud.Crud)] -> Generator FileDraft
genCrudIndex spec cruds = return $ C.mkTmplFdWithData [relfile|client/crud/index.ts|] tmplData