@prisma/client#User TypeScript Examples

The following examples show how to use @prisma/client#User. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: userData.decorator.ts    From amplication with Apache License 2.0 6 votes vote down vote up
/**
 * Access the user data from the request object i.e `req.user`.
 */
function userFactory(ctx: ExecutionContext): User {
  const contextType = ctx.getType();
  if (contextType === "http") {
    // do something that is only important in the context of regular HTTP requests (REST)
    const { user } = ctx.switchToHttp().getRequest();
    return user;
  } else if (contextType === "rpc") {
    // do something that is only important in the context of Microservice requests
    throw new Error("Rpc context is not implemented yet");
  } else if (contextType === "ws") {
    // do something that is only important in the context of Websockets requests
    throw new Error("Websockets context is not implemented yet");
  } else if (ctx.getType<GqlContextType>() === "graphql") {
    // do something that is only important in the context of GraphQL requests
    const gqlExecutionContext = GqlExecutionContext.create(ctx);
    return gqlExecutionContext.getContext().req.user;
  }
  throw new Error("Invalid context");
}
Example #2
Source File: auth.service.spec.ts    From amplication with Apache License 2.0 6 votes vote down vote up
EXAMPLE_USER: User = {
  id: 'exampleUser',
  createdAt: new Date(),
  updatedAt: new Date(),
  accountId: EXAMPLE_ACCOUNT.id,
  workspaceId: EXAMPLE_WORKSPACE_ID,
  isOwner: true,
  deletedAt: null
}
Example #3
Source File: [id].tsx    From next-crud with MIT License 6 votes vote down vote up
UserCreate: NextPage<IProps> = ({ user }) => {
  const toast = useToast()
  const { replace } = useRouter()
  const queryClient = useQueryClient()

  const onSubmit = async (values: IFormValues) => {
    try {
      const userData = await fetch(`/api/users/${user.id}`, {
        method: 'PUT',
        body: JSON.stringify(values),
        headers: {
          'Content-Type': 'application/json',
        },
      }).then((res) => res.json())
      toast({
        status: 'success',
        description: 'User successfully updated',
        duration: 2000,
      })
      replace('/users')
      queryClient.setQueryData<
        InfiniteData<TPaginationResult<User>> | undefined
      >('users', (data) => {
        const page = data?.pages.find((page) =>
          page.data.some((userElem) => userElem.id === user.id)
        )
        if (page) {
          const elemIdx = page.data.findIndex((data) => data.id === user.id)
          page.data[elemIdx] = userData
        }

        return data
      })
    } catch (e) {
      toast({
        status: 'error',
        description: 'Failed to update user',
        duration: 2000,
      })
    }
  }

  return (
    <Layout title={user.username} backRoute="/users">
      <VStack spacing={4} width="100%">
        <Heading>User edition</Heading>
        <UserForm
          initialValues={{ username: user.username }}
          onSubmit={onSubmit}
        />
      </VStack>
    </Layout>
  )
}
Example #4
Source File: auth.service.spec.ts    From amplication with Apache License 2.0 6 votes vote down vote up
EXAMPLE_OTHER_USER: User = {
  id: 'exampleOtherUser',
  createdAt: new Date(),
  updatedAt: new Date(),
  accountId: EXAMPLE_ACCOUNT.id,
  workspaceId: EXAMPLE_WORKSPACE.id,
  isOwner: true,
  deletedAt: null
}
Example #5
Source File: [...nextcrud].ts    From next-crud with MIT License 6 votes vote down vote up
handler = NextCrud({
  adapter: new PrismaAdapter<User | Post, ModelName>({
    prismaClient: prisma,
  }),
  swagger: {
    title: 'My API CRUD',
    apiUrl: process.env.API_URL as string,
    config: {
      User: {
        tag: {
          name: 'Users',
        },
      },
      Post: {
        tag: {
          name: 'Posts',
        },
      },
    },
  },
})
Example #6
Source File: db.test.ts    From fullstack-starterkit with MIT License 6 votes vote down vote up
describe('DB Test Suite', () => {
  test('User should be created', async () => {
    const input: User = createUserInput();
    const user = await prisma.user.create({ data: input });
    expect(user.id).toBe(input.id);
  });

  test('Post should be created', async () => {
    const input: Post = createPostInput();
    const post = await prisma.post.create({ data: input });
    expect(post.id).toBe(input.id);
  });
});
Example #7
Source File: getUser.ts    From fullstack-starterkit with MIT License 6 votes vote down vote up
async function getUser(_: Parent, args: QueryGetUserArgs, context: Context): Promise<GetUserResult> {
  const { prisma } = context;
  const { input } = args;
  const { id }: GetUserInput = input;

  const user: User | null = await prisma.user.findUnique({ where: { id } });

  return { user };
}
Example #8
Source File: node-uptimes.service.ts    From ironfish-api with Mozilla Public License 2.0 6 votes vote down vote up
async getWithClient(
    user: User,
    client: BasePrismaClient,
  ): Promise<NodeUptime | null> {
    return client.nodeUptime.findUnique({
      where: {
        user_id: user.id,
      },
    });
  }
Example #9
Source File: userData.decorator.ts    From amplication with Apache License 2.0 5 votes vote down vote up
UserData = createParamDecorator<undefined, ExecutionContext, User>(
  (data, ctx: ExecutionContext) => userFactory(ctx)
)
Example #10
Source File: Post.ts    From fullstack-starterkit with MIT License 5 votes vote down vote up
Post = {
  author: async (parent: Parent, _: Args, context: Context): Promise<User | null> => {
    const { id } = parent;
    const { prisma } = context;

    return prisma.post.findUnique({ where: { id } }).author();
  }
}
Example #11
Source File: node-uptimes.service.ts    From ironfish-api with Mozilla Public License 2.0 5 votes vote down vote up
async get(user: User): Promise<NodeUptime | null> {
    return this.getWithClient(user, this.prisma);
  }
Example #12
Source File: node-uptimes.service.ts    From ironfish-api with Mozilla Public License 2.0 5 votes vote down vote up
async addUptime(user: User): Promise<NodeUptime> {
    const now = new Date();

    const lastCheckinCutoff = new Date();
    lastCheckinCutoff.setHours(now.getHours() - NODE_UPTIME_CHECKIN_HOURS);

    const uptime = await this.prisma.$transaction(async (prisma) => {
      await prisma.$executeRawUnsafe(
        `SELECT pg_advisory_xact_lock(HASHTEXT($1));`,
        user.id,
      );

      let uptime = await this.getWithClient(user, prisma);
      if (uptime && uptime.last_checked_in >= lastCheckinCutoff) {
        return uptime;
      }

      uptime = await prisma.nodeUptime.upsert({
        where: {
          user_id: user.id,
        },
        update: {
          last_checked_in: now.toISOString(),
          total_hours: {
            increment: 1,
          },
        },
        create: {
          user_id: user.id,
          last_checked_in: now.toISOString(),
          total_hours: 0,
        },
      });

      return uptime;
    });

    if (uptime.total_hours >= NODE_UPTIME_CREDIT_HOURS) {
      const userId = user.id;
      await this.graphileWorkerService.addJob(
        GraphileWorkerPattern.CREATE_NODE_UPTIME_EVENT,
        { userId, occurredAt: now },
        { queueName: `update_node_uptime_for_${userId}` },
      );
    }

    return uptime;
  }
Example #13
Source File: auth.service.spec.ts    From amplication with Apache License 2.0 5 votes vote down vote up
EXAMPLE_ACCOUNT_WITH_CURRENT_USER: Account & { currentUser: User } = {
  ...EXAMPLE_ACCOUNT,
  currentUser: EXAMPLE_USER
}
Example #14
Source File: auth.service.spec.ts    From amplication with Apache License 2.0 5 votes vote down vote up
EXAMPLE_WORKSPACE: Workspace & { users: User[] } = {
  id: EXAMPLE_WORKSPACE_ID,
  name: 'Example Workspace',
  createdAt: new Date(),
  updatedAt: new Date(),
  users: [EXAMPLE_USER]
}
Example #15
Source File: deposits.upsert.service.spec.ts    From ironfish-api with Mozilla Public License 2.0 4 votes vote down vote up
describe('DepositsUpsertService', () => {
  let app: INestApplication;
  let depositHeadsService: DepositHeadsService;
  let depositsUpsertService: DepositsUpsertService;
  let graphileWorkerService: GraphileWorkerService;
  let prisma: PrismaService;
  let usersService: UsersService;

  let user1: User;
  let user2: User;
  let transaction1: DepositTransactionDto;
  let transaction2: DepositTransactionDto;

  beforeAll(async () => {
    app = await bootstrapTestApp();
    depositHeadsService = app.get(DepositHeadsService);
    depositsUpsertService = app.get(DepositsUpsertService);
    graphileWorkerService = app.get(GraphileWorkerService);
    prisma = app.get(PrismaService);
    usersService = app.get(UsersService);
    await app.init();

    user1 = await usersService.create({
      email: faker.internet.email(),
      graffiti: 'user1',
      country_code: faker.address.countryCode(),
    });

    user2 = await usersService.create({
      email: faker.internet.email(),
      graffiti: 'user2',
      country_code: faker.address.countryCode(),
    });

    transaction1 = transaction(
      [...notes([1, 2], user1.graffiti), ...notes([0.1, 3], user2.graffiti)],
      'transaction1Hash',
    );

    transaction2 = transaction(
      [...notes([0.05], user1.graffiti), ...notes([1], user2.graffiti)],
      'transaction2Hash',
    );
  });

  afterAll(async () => {
    await app.close();
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('bulkUpsert', () => {
    it('queues upsert deposit jobs for the payloads', async () => {
      const addJob = jest
        .spyOn(graphileWorkerService, 'addJob')
        .mockImplementation(jest.fn());

      const payload = {
        operations: [
          depositOperation(
            [transaction1],
            BlockOperation.CONNECTED,
            'block1Hash',
          ),
          depositOperation(
            [transaction2],
            BlockOperation.CONNECTED,
            'block2Hash',
          ),
        ],
      };

      await depositsUpsertService.bulkUpsert(payload.operations);

      expect(addJob).toHaveBeenCalledTimes(payload.operations.length);
      assert.ok(addJob.mock.calls);
      for (let i = 0; i < payload.operations.length; i++) {
        expect(addJob.mock.calls[i][0]).toBe(
          GraphileWorkerPattern.UPSERT_DEPOSIT,
        );
        expect(addJob.mock.calls[i][1]).toEqual(payload.operations[i]);
      }
    });
  });

  describe('upsert', () => {
    it('upserts new deposits and events', async () => {
      const payload = depositOperation(
        [transaction1, transaction2],
        BlockOperation.CONNECTED,
        'block1Hash',
      );

      await depositsUpsertService.upsert(payload);

      const user1Events = await prisma.event.findMany({
        where: {
          user_id: user1.id,
          type: EventType.SEND_TRANSACTION,
        },
      });

      const user2Events = await prisma.event.findMany({
        where: {
          user_id: user2.id,
          type: EventType.SEND_TRANSACTION,
        },
      });

      expect(user1Events).toHaveLength(1);
      expect(user2Events).toHaveLength(2);

      const user1Deposits = await prisma.deposit.findMany({
        where: {
          graffiti: user1.graffiti,
        },
      });

      const user2Deposits = await prisma.deposit.findMany({
        where: {
          graffiti: user2.graffiti,
        },
      });

      expect(user1Deposits).toHaveLength(2);
      expect(user2Deposits).toHaveLength(2);

      expect(user1Events[0].deposit_id).toEqual(user1Deposits[0].id);
      expect(user2Events[0].deposit_id).toEqual(user2Deposits[0].id);
      expect(user2Events[1].deposit_id).toEqual(user2Deposits[1].id);
    });

    describe('on DISCONNECTED operations', () => {
      it('removes events', async () => {
        const payload = depositOperation(
          [transaction2],
          BlockOperation.DISCONNECTED,
          'block1Hash',
        );

        await depositsUpsertService.upsert(payload);

        const user2Events = await prisma.event.findMany({
          where: {
            user_id: user2.id,
            type: EventType.SEND_TRANSACTION,
          },
        });

        const user1Deposits = await prisma.deposit.findMany({
          where: {
            graffiti: user1.graffiti,
          },
        });

        const user2Deposits = await prisma.deposit.findMany({
          where: {
            graffiti: user2.graffiti,
          },
        });

        expect(user2Events[0].points).toBe(1);
        expect(user2Events[1].points).toBe(0);
        expect(user2Events[1].deposit_id).toEqual(user2Deposits[1].id);
        expect(user2Deposits[1].amount).toEqual(1 * ORE_TO_IRON);

        expect(user1Deposits).toHaveLength(2);
        expect(user2Deposits).toHaveLength(2);

        expect(user1Deposits[1].main).toBe(false);
        expect(user2Deposits[1].main).toBe(false);
      });
    });

    it('updates the deposit head', async () => {
      const updateHead = jest
        .spyOn(depositHeadsService, 'upsert')
        .mockImplementation(jest.fn());

      const operation = depositOperation(
        [transaction1],
        BlockOperation.CONNECTED,
        'block1Hash',
      );
      await depositsUpsertService.upsert(operation);

      assert.ok(updateHead.mock.calls);
      expect(updateHead.mock.calls[0][0]).toBe(operation.block.hash);
    });

    describe('on FORK operations', () => {
      it('does not delete events on FORK operations', async () => {
        const transaction3 = transaction(
          [...notes([0.1], user2.graffiti)],
          'transaction3Hash',
        );

        const payload = depositOperation(
          [transaction3],
          BlockOperation.CONNECTED,
          'block3Hash',
        );

        await depositsUpsertService.upsert(payload);

        const user2EventsBefore = await prisma.event.findMany({
          where: {
            user_id: user2.id,
            type: EventType.SEND_TRANSACTION,
          },
        });

        const forkPayload = depositOperation(
          [transaction3],
          BlockOperation.FORK,
          'block3Hash',
        );

        await depositsUpsertService.upsert(forkPayload);

        const user2EventsAfter = await prisma.event.findMany({
          where: {
            user_id: user2.id,
            type: EventType.SEND_TRANSACTION,
          },
        });

        expect(user2EventsBefore).toEqual(user2EventsAfter);
      });
    });
  });

  const notes = (amounts: number[], graffiti: string) => {
    return amounts.map((amount) => {
      return { memo: graffiti, amount: amount * ORE_TO_IRON };
    });
  };

  const transaction = (notes: UpsertDepositsNoteDto[], hash?: string) => {
    return {
      hash: hash || uuid(),
      notes,
    };
  };

  const depositOperation = (
    transactions: DepositTransactionDto[],
    type: BlockOperation,
    hash?: string,
    previousBlockHash?: string,
    sequence?: number,
  ): UpsertDepositsOperationDto => {
    return {
      type,
      block: {
        hash: hash || uuid(),
        timestamp: new Date(),
        sequence: sequence || 0,
        previousBlockHash: previousBlockHash || uuid(),
      },
      transactions,
    };
  };
});
Example #16
Source File: auth.service.spec.ts    From amplication with Apache License 2.0 4 votes vote down vote up
describe('AuthService', () => {
  let service: AuthService;

  beforeEach(async () => {
    signMock.mockClear();
    createAccountMock.mockClear();
    setCurrentUserMock.mockClear();
    prismaAccountFindOneMock.mockClear();
    setPasswordMock.mockClear();
    hashPasswordMock.mockClear();
    validatePasswordMock.mockClear();
    findUsersMock.mockClear();
    createWorkspaceMock.mockClear();

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        {
          provide: AccountService,
          useClass: jest.fn(() => ({
            createAccount: createAccountMock,
            setCurrentUser: setCurrentUserMock,
            setPassword: setPasswordMock
          }))
        },
        {
          provide: PasswordService,
          useClass: jest.fn(() => ({
            hashPassword: hashPasswordMock,
            validatePassword: validatePasswordMock
          }))
        },
        {
          provide: UserService,
          useClass: jest.fn(() => ({
            findUsers: findUsersMock
          }))
        },
        {
          provide: WorkspaceService,
          useClass: jest.fn(() => ({
            createWorkspace: createWorkspaceMock
          }))
        },
        {
          provide: JwtService,
          useClass: jest.fn(() => ({
            sign: signMock
          }))
        },
        {
          provide: PrismaService,
          useClass: jest.fn(() => ({
            account: {
              findUnique: prismaAccountFindOneMock
            }
          }))
        },
        AuthService
      ],
      imports: []
    }).compile();

    service = module.get<AuthService>(AuthService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });

  it('sign ups for correct data', async () => {
    const result = await service.signup({
      email: EXAMPLE_ACCOUNT.email,
      password: EXAMPLE_ACCOUNT.password,
      firstName: EXAMPLE_ACCOUNT.firstName,
      lastName: EXAMPLE_ACCOUNT.lastName,
      workspaceName: EXAMPLE_WORKSPACE.name
    });
    expect(result).toBe(EXAMPLE_TOKEN);
    expect(createAccountMock).toHaveBeenCalledTimes(1);
    expect(createAccountMock).toHaveBeenCalledWith({
      data: {
        email: EXAMPLE_ACCOUNT.email,
        password: EXAMPLE_HASHED_PASSWORD,
        firstName: EXAMPLE_ACCOUNT.firstName,
        lastName: EXAMPLE_ACCOUNT.lastName
      }
    });
    expect(setCurrentUserMock).toHaveBeenCalledTimes(1);
    expect(setCurrentUserMock).toHaveBeenCalledWith(
      EXAMPLE_ACCOUNT.id,
      EXAMPLE_USER.id
    );
    expect(hashPasswordMock).toHaveBeenCalledTimes(1);
    expect(hashPasswordMock).toHaveBeenCalledWith(EXAMPLE_ACCOUNT.password);
    expect(createWorkspaceMock).toHaveBeenCalledTimes(1);
    expect(createWorkspaceMock).toHaveBeenCalledWith(EXAMPLE_ACCOUNT.id, {
      data: {
        name: EXAMPLE_WORKSPACE.name
      },
      include: {
        users: {
          include: {
            account: true,
            userRoles: true,
            workspace: true
          }
        }
      }
    });
    expect(signMock).toHaveBeenCalledTimes(1);
    expect(signMock).toHaveBeenCalledWith({
      accountId: EXAMPLE_ACCOUNT.id,
      workspaceId: EXAMPLE_WORKSPACE.id,
      roles: [EXAMPLE_USER_ROLE.role],
      userId: EXAMPLE_USER.id,
      type: EnumTokenType.User
    });
  });

  it('login for existing user', async () => {
    const result = await service.login(
      EXAMPLE_ACCOUNT.email,
      EXAMPLE_ACCOUNT.password
    );
    expect(result).toBe(EXAMPLE_TOKEN);
    expect(prismaAccountFindOneMock).toHaveBeenCalledTimes(1);
    expect(prismaAccountFindOneMock).toHaveBeenCalledWith({
      where: {
        email: EXAMPLE_ACCOUNT.email
      },
      include: {
        currentUser: {
          include: { account: true, workspace: true, userRoles: true }
        }
      }
    });
    expect(validatePasswordMock).toHaveBeenCalledTimes(1);
    expect(validatePasswordMock).toHaveBeenCalledWith(
      EXAMPLE_ACCOUNT.password,
      EXAMPLE_ACCOUNT.password
    );
    expect(signMock).toHaveBeenCalledTimes(1);
    expect(signMock).toHaveBeenCalledWith({
      accountId: EXAMPLE_ACCOUNT.id,
      workspaceId: EXAMPLE_WORKSPACE.id,
      roles: [EXAMPLE_USER_ROLE.role],
      userId: EXAMPLE_USER.id,
      type: EnumTokenType.User
    });
  });

  it('sets current workspace for existing user and existing workspace', async () => {
    const result = await service.setCurrentWorkspace(
      EXAMPLE_ACCOUNT.id,
      EXAMPLE_OTHER_WORKSPACE.id
    );
    expect(result).toBe(EXAMPLE_TOKEN);
    expect(findUsersMock).toHaveBeenCalledTimes(1);
    expect(findUsersMock).toHaveBeenCalledWith({
      where: {
        workspace: {
          id: EXAMPLE_OTHER_WORKSPACE.id
        },
        account: {
          id: EXAMPLE_ACCOUNT.id
        }
      },
      include: {
        account: true,
        workspace: true,
        userRoles: true
      },
      take: 1
    });
    expect(setCurrentUserMock).toHaveBeenCalledTimes(1);
    expect(setCurrentUserMock).toHaveBeenCalledWith(
      EXAMPLE_ACCOUNT.id,
      EXAMPLE_OTHER_AUTH_USER.id
    );
    expect(signMock).toHaveBeenCalledTimes(1);
    expect(signMock).toHaveBeenCalledWith({
      accountId: EXAMPLE_ACCOUNT.id,
      workspaceId: EXAMPLE_OTHER_WORKSPACE.id,
      roles: [EXAMPLE_USER_ROLE.role],
      userId: EXAMPLE_OTHER_AUTH_USER.id,
      type: EnumTokenType.User
    });
  });

  it('changes password for existing account', async () => {
    await service.changePassword(
      EXAMPLE_ACCOUNT,
      EXAMPLE_ACCOUNT.password,
      EXAMPLE_NEW_PASSWORD
    );
    expect(validatePasswordMock).toHaveBeenCalledTimes(1);
    expect(validatePasswordMock).toHaveBeenCalledWith(
      EXAMPLE_ACCOUNT.password,
      EXAMPLE_ACCOUNT.password
    );
    expect(hashPasswordMock).toHaveBeenCalledTimes(1);
    expect(hashPasswordMock).toHaveBeenCalledWith(EXAMPLE_NEW_PASSWORD);
    expect(setPasswordMock).toHaveBeenCalledTimes(1);
    expect(setPasswordMock).toHaveBeenCalledWith(
      EXAMPLE_ACCOUNT.id,
      EXAMPLE_NEW_HASHED_PASSWORD
    );
  });
});
Example #17
Source File: index.ts    From next-crud with MIT License 4 votes vote down vote up
describe('Prisma interraction', () => {
  beforeAll(async () => {
    await createSeedData()
  })
  let adapter: PrismaAdapter<User | Post, Prisma.ModelName>
  let handler: NextApiHandler<User | Post>

  beforeEach(() => {
    adapter = new PrismaAdapter<User | Post, Prisma.ModelName>({
      prismaClient: prisma,
      manyRelations: {
        [Prisma.ModelName.User]: [
          'post.author',
          'comment.post',
          'comment.author',
        ],
      },
    })
    handler = NextCrud({
      adapter,
      models: {
        [Prisma.ModelName.User]: {
          name: 'users',
        },
      },
    })
  })

  it('should get the list of users', async () => {
    const { res } = getMockRes()
    const req = getMockReq({
      url: '/api/users',
      method: 'GET',
    })

    const expectedResult = await prisma.user.findMany()

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should get a page based paginated users list', async () => {
    const { res } = getMockRes()
    const req = getMockReq({
      url: '/api/users?page=2&limit=2',
      method: 'GET',
    })

    const expectedResult = await prisma.user.findMany({
      skip: 2,
      take: 2,
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith({
      data: expectedResult,
      pagination: {
        total: 4,
        pageCount: 2,
        page: 2,
      },
    })
  })

  it('should get the user with first id', async () => {
    const user = await prisma.user.findFirst()

    const { res } = getMockRes()
    const req = getMockReq({
      url: `/api/users/${user.id}`,
      method: 'GET',
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(user)
  })

  it('should get the list of users with only their email', async () => {
    const { res } = getMockRes()
    const req = getMockReq({
      url: '/api/users?select=email',
      method: 'GET',
    })

    const expectedResult = await prisma.user.findMany({
      select: {
        email: true,
      },
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should get the list of users with only their email and posts', async () => {
    const { res } = getMockRes()
    const req = getMockReq({
      url: '/api/users?select=email,posts',
      method: 'GET',
    })

    const expectedResult = await prisma.user.findMany({
      select: {
        email: true,
        posts: true,
      },
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should get the list of users with only their email and posts ids', async () => {
    const { res } = getMockRes()
    const req = getMockReq({
      url: '/api/users?select=email,posts,posts.id',
      method: 'GET',
    })

    const expectedResult = await prisma.user.findMany({
      select: {
        email: true,
        posts: {
          select: {
            id: true,
          },
        },
      },
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should get the list of users with only their email, posts ids, comments and comments users', async () => {
    const { res } = getMockRes()
    const req = getMockReq({
      url: '/api/users?select=email,posts,posts.id,posts.comment,posts.comment.author',
      method: 'GET',
    })

    const expectedResult = await prisma.user.findMany({
      select: {
        email: true,
        posts: {
          select: {
            id: true,
            comment: {
              select: {
                author: true,
              },
            },
          },
        },
      },
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should return the first 2 users', async () => {
    const { res } = getMockRes()
    const req = getMockReq({
      url: '/api/users?limit=2',
      method: 'GET',
    })

    const expectedResult = await prisma.user.findMany({
      take: 2,
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should return 2 users after the first 2 ones', async () => {
    const { res } = getMockRes()
    const req = getMockReq({
      url: '/api/users?skip=2&limit=2',
      method: 'GET',
    })

    const expectedResult = await prisma.user.findMany({
      take: 2,
      skip: 2,
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should return 2 users based on a cursor', async () => {
    const firstUser = await prisma.user.findFirst()

    const { res } = getMockRes()
    const req = getMockReq({
      url: `/api/users?limit=2&cursor={"id":${firstUser.id}}`,
      method: 'GET',
    })

    const expectedResult = await prisma.user.findMany({
      take: 2,
      cursor: {
        id: firstUser.id,
      },
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should filter user by its email', async () => {
    const { res } = getMockRes()
    const req = getMockReq({
      url: `/api/users?where={"email":{"$eq":"[email protected]"}}`,
      method: 'GET',
    })

    const expectedResult = await prisma.user.findMany({
      where: {
        email: {
          equals: '[email protected]',
        },
      },
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should filter users where email does not match', async () => {
    const { res } = getMockRes()
    const req = getMockReq({
      url: `/api/users?where={"email":{"$neq":"[email protected]"}}`,
      method: 'GET',
    })

    const expectedResult = await prisma.user.findMany({
      where: {
        email: {
          not: '[email protected]',
        },
      },
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should filter users where email starts with john and ends with .com', async () => {
    const { res } = getMockRes()
    const req = getMockReq({
      url: `/api/users?where={"email":{"$and":{"$starts":"john", "$ends":".com"}}}`,
      method: 'GET',
    })

    const expectedResult = await prisma.user.findMany({
      where: {
        AND: [
          { email: { startsWith: 'john' } },
          { email: { endsWith: '.com' } },
        ],
      },
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should create a user', async () => {
    const { res } = getMockRes()
    const req = getMockReq({
      url: `/api/users`,
      method: 'POST',
      body: {
        email: '[email protected]',
      },
    })

    await handler(req, res)

    const expectedResult = await prisma.user.findFirst({
      where: {
        email: '[email protected]',
      },
    })

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should update a user', async () => {
    const user = await prisma.user.findFirst({
      where: {
        email: '[email protected]',
      },
    })
    const { res } = getMockRes()
    const req = getMockReq({
      url: `/api/users/${user.id}`,
      method: 'PATCH',
      body: {
        email: '[email protected]',
      },
    })

    await handler(req, res)

    const expectedResult = await prisma.user.findFirst({
      where: {
        email: '[email protected]',
      },
    })

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should update a user and respond with only its email', async () => {
    const user = await prisma.user.findFirst({
      where: {
        email: '[email protected]',
      },
    })
    const { res } = getMockRes()
    const req = getMockReq({
      url: `/api/users/${user.id}?select=email`,
      method: 'PATCH',
      body: {
        email: '[email protected]',
      },
    })

    await handler(req, res)

    const expectedResult = await prisma.user.findFirst({
      where: {
        email: '[email protected]',
      },
      select: {
        email: true,
      },
    })

    expect(res.send).toHaveBeenCalledWith(expectedResult)
  })

  it('should delete the previously created user', async () => {
    const user = await prisma.user.findFirst({
      where: {
        email: '[email protected]',
      },
    })
    const { res } = getMockRes()
    const req = getMockReq({
      url: `/api/users/${user.id}`,
      method: 'DELETE',
    })

    await handler(req, res)

    expect(res.send).toHaveBeenCalledWith(user)
  })

  afterAll(async () => {
    await prisma.comment.deleteMany()
    await prisma.post.deleteMany()
    await prisma.user.deleteMany()
    await prisma.$disconnect()
  })
})
Example #18
Source File: index.tsx    From next-crud with MIT License 4 votes vote down vote up
Users = () => {
  const { push } = useRouter()
  const { data, fetchNextPage, isFetching, hasNextPage, refetch } =
    useInfiniteQuery<TPaginationResult<User>>(
      'users',
      async ({ pageParam = 1 }) => {
        const data: TPaginationResult<User> = await fetch(
          `/api/users?page=${pageParam}`
        ).then((res) => res.json())

        return data
      },
      {
        getNextPageParam: (lastPage) => {
          const pagination = lastPage.pagination as TPaginationDataPageBased
          return pagination.page === pagination.pageCount
            ? undefined
            : pagination.page + 1
        },
      }
    )

  const allData = useMemo(() => {
    return data?.pages.flatMap((page) => page.data)
  }, [data])

  const onEditUser = (id: User['id']) => {
    push(`/users/${id}`)
  }

  const onDeleteUser = async (id: User['id']) => {
    await fetch(`/api/users/${id}`, {
      method: 'DELETE',
    })
    refetch()
  }

  return (
    <Layout title="Users" backRoute="/">
      <VStack spacing={6} width="100%">
        <Heading>Users</Heading>
        <Flex direction="row" justify="flex-end" width="100%">
          <Button
            colorScheme="green"
            leftIcon={<AddIcon color="white" />}
            onClick={() => push('/users/create')}
          >
            Create user
          </Button>
        </Flex>
        <VStack
          boxShadow="0px 2px 8px #ccc"
          p={4}
          borderRadius={6}
          width="100%"
          align="flex-start"
        >
          {!data && (
            <Stack width="100%">
              <Skeleton height="20px" />
              <Skeleton height="20px" />
              <Skeleton height="20px" />
            </Stack>
          )}
          {allData?.map((user) => (
            <UserListItem
              key={user.id}
              {...user}
              onEdit={onEditUser}
              onDelete={onDeleteUser}
            />
          ))}
        </VStack>
        <Button
          colorScheme="blue"
          onClick={() => fetchNextPage()}
          disabled={isFetching || !hasNextPage}
        >
          Load more
        </Button>
      </VStack>
    </Layout>
  )
}