can add suggestion comment + tests

This commit is contained in:
Kalle
2021-02-25 15:40:30 +02:00
parent b26b0bca50
commit 4d2908b9a8
9 changed files with 119 additions and 35 deletions

View File

@@ -30,7 +30,7 @@ const PlusHomePage: React.FC<PlusHomePageProps> = () => {
<>
{plusStatusData && plusStatusData.membershipTier && (
<SuggestionVouchModal
canSuggest={!ownSuggestion}
canSuggest={!suggestionsLoading && !ownSuggestion}
canVouch={!!plusStatusData.canVouchFor}
userPlusMembershipTier={plusStatusData.membershipTier}
/>
@@ -63,7 +63,7 @@ const PlusHomePage: React.FC<PlusHomePageProps> = () => {
<SubText mr={2}>+2</SubText> ({suggestionCounts.TWO})
</Flex>
</Radio>
<Radio value="THREE">
<Radio value="THREE" data-cy="plus-three-radio">
<Flex align="center">
<SubText mr={2}>+3</SubText> ({suggestionCounts.THREE})
</Flex>

View File

@@ -16,7 +16,7 @@ import useMutation from "hooks/useMutation";
import { getFullUsername } from "lib/strings";
import { Unpacked } from "lib/types";
import {
suggestionSchema,
resuggestionSchema,
SUGGESTION_DESCRIPTION_LIMIT,
} from "lib/validators/suggestion";
import { useState } from "react";
@@ -24,7 +24,7 @@ import { useForm } from "react-hook-form";
import { Suggestions } from "services/plus";
import * as z from "zod";
type FormData = z.infer<typeof suggestionSchema>;
type FormData = z.infer<typeof resuggestionSchema>;
const Suggestion = ({
suggestion,
@@ -34,19 +34,14 @@ const Suggestion = ({
canSuggest: boolean;
}) => {
const [showTextarea, setShowTextarea] = useState(false);
const { handleSubmit, errors, register, watch, control } = useForm<FormData>({
resolver: zodResolver(suggestionSchema),
defaultValues: {
// region doesn't matter as it is not updated after the first suggestion
region: "NA",
tier: suggestion.tier,
suggestedId: suggestion.suggestedUser.id,
},
const { handleSubmit, errors, register, watch } = useForm<FormData>({
resolver: zodResolver(resuggestionSchema),
});
const { onSubmit, sending } = useMutation({
route: "plus/suggestions",
mutationKey: "plus/suggestions",
successText: "Comment added",
onSuccess: () => setShowTextarea(false),
});
const watchDescription = watch("description", "");
@@ -92,23 +87,44 @@ const Suggestion = ({
size="sm"
onClick={() => setShowTextarea(!showTextarea)}
mt={4}
data-cy="comment-button"
>
Add comment
</Button>
)}
{showTextarea && (
<form onSubmit={handleSubmit(onSubmit)}>
<form
onSubmit={handleSubmit((values) =>
onSubmit({
...values,
// region doesn't matter as it is not updated after the first suggestion
region: "NA",
tier: suggestion.tier,
suggestedId: suggestion.suggestedUser.id,
})
)}
>
<FormControl isInvalid={!!errors.description}>
<FormLabel htmlFor="description" mt={4}>
Comment to suggestion
</FormLabel>
<Textarea name="description" ref={register} />
<Textarea
name="description"
ref={register}
data-cy="comment-textarea"
/>
<FormHelperText mb={4}>
{(watchDescription ?? "").length}/{SUGGESTION_DESCRIPTION_LIMIT}
</FormHelperText>
<FormErrorMessage>{errors.description?.message}</FormErrorMessage>
</FormControl>
<Button size="sm" mr={3} type="submit" isLoading={sending}>
<Button
size="sm"
mr={3}
type="submit"
isLoading={sending}
data-cy="submit-button"
>
<Trans>Save</Trans>
</Button>
<Button

View File

@@ -17,7 +17,7 @@ import {
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import {
suggestionSchema,
suggestionFullSchema,
SUGGESTION_DESCRIPTION_LIMIT,
} from "lib/validators/suggestion";
import * as z from "zod";
@@ -31,7 +31,7 @@ interface Props {
userPlusMembershipTier?: number;
}
type FormData = z.infer<typeof suggestionSchema>;
type FormData = z.infer<typeof suggestionFullSchema>;
const SuggestionVouchModal: React.FC<Props> = ({
canVouch,
@@ -40,10 +40,10 @@ const SuggestionVouchModal: React.FC<Props> = ({
}) => {
const [isOpen, setIsOpen] = useState(false);
const { handleSubmit, errors, register, watch, control } = useForm<FormData>({
resolver: zodResolver(suggestionSchema),
resolver: zodResolver(suggestionFullSchema),
});
const { onSubmit, sending } = useMutation({
onClose: () => setIsOpen(false),
onSuccess: () => setIsOpen(false),
route: "plus/suggestions",
mutationKey: "plus/suggestions",
successText: "New suggestion submitted",
@@ -64,7 +64,12 @@ const SuggestionVouchModal: React.FC<Props> = ({
return (
<>
<Button size="sm" mb={4} onClick={() => setIsOpen(true)}>
<Button
size="sm"
mb={4}
onClick={() => setIsOpen(true)}
data-cy="suggestion-button"
>
{getButtonText()}
</Button>
{isOpen && (
@@ -84,7 +89,7 @@ const SuggestionVouchModal: React.FC<Props> = ({
<Controller
name="tier"
control={control}
defaultValue={1}
defaultValue={userPlusMembershipTier}
render={({ value, onChange }) => (
<Select
value={value}
@@ -122,7 +127,11 @@ const SuggestionVouchModal: React.FC<Props> = ({
<FormControl>
<FormLabel mt={4}>Region</FormLabel>
<Select name="region" ref={register}>
<Select
name="region"
ref={register}
data-cy="region-select"
>
<option value="NA">NA</option>
<option value="EU">EU</option>
</Select>
@@ -136,7 +145,11 @@ const SuggestionVouchModal: React.FC<Props> = ({
<FormLabel htmlFor="description" mt={4}>
Description
</FormLabel>
<Textarea name="description" ref={register} />
<Textarea
name="description"
ref={register}
data-cy="description-textarea"
/>
<FormHelperText>
{(watchDescription ?? "").length}/
{SUGGESTION_DESCRIPTION_LIMIT}
@@ -147,7 +160,12 @@ const SuggestionVouchModal: React.FC<Props> = ({
</FormControl>
</ModalBody>
<ModalFooter>
<Button mr={3} type="submit" isLoading={sending}>
<Button
mr={3}
type="submit"
isLoading={sending}
data-cy="submit-button"
>
Save
</Button>
<Button onClick={() => setIsOpen(false)} variant="outline">

View File

@@ -14,10 +14,46 @@ context("Plus Voting History", () => {
});
context("Plus Home Page", () => {
beforeEach(() => {
cy.login("sendou");
it("can filter through suggestions not logged in", () => {
cy.visit("/plus");
cy.contains("yooo so cracked").dataCy("plus-three-radio").click();
cy.contains("yooo so cracked").should("not.exist");
});
it.only("correctly calculates voting percentage", () => {});
it("can submit new suggestion and persists with reload", () => {
cy.login("sendou");
cy.visit("/plus");
cy.dataCy("suggestion-button")
.click()
.get(".select__value-container")
.type("NZAP{enter}")
.dataCy("region-select")
.select("EU")
.dataCy("description-textarea")
.type("always trust in nzap")
.dataCy("submit-button")
.click();
cy.contains("always trust in nzap")
.reload()
.contains("always trust in nzap")
.dataCy("suggestion-button")
.should("not.exist");
});
it("can add comment to suggestion and toast shows", () => {
cy.login("sendou");
cy.visit("/plus");
cy.dataCy("comment-button")
.click()
.dataCy("comment-textarea")
.type("yes agreed")
.dataCy("submit-button")
.click();
cy.contains("Comment added");
cy.contains('"yes agreed" - Sendou#4059');
cy.dataCy("comment-button").should("not.exist");
});
});

View File

@@ -11,3 +11,7 @@ Cypress.Commands.add("login", (user: "sendou" | "nzap") => {
cy.intercept("/api/auth/session", u);
});
});
beforeEach(() => {
cy.exec("npm run seed");
});

View File

@@ -8,12 +8,12 @@ import { useUser } from "./common";
const useMutation = ({
route,
mutationKey,
onClose,
onSuccess,
successText,
}: {
route: string;
mutationKey: string;
onClose?: () => void;
onSuccess?: () => void;
successText: string;
}) => {
const toast = useToast();
@@ -42,7 +42,7 @@ const useMutation = ({
mutate("/api/" + mutationKey);
toast(getToastOptions(successText, "success"));
onClose?.();
onSuccess?.();
};
return { onSubmit, sending };

View File

@@ -2,9 +2,14 @@ import * as z from "zod";
export const SUGGESTION_DESCRIPTION_LIMIT = 500;
export const suggestionSchema = z.object({
const suggestionRootSchema = z.object({
description: z.string().max(SUGGESTION_DESCRIPTION_LIMIT).min(10),
});
export const suggestionFullSchema = suggestionRootSchema.extend({
suggestedId: z.number().int(),
tier: z.number().int().min(1).max(3),
region: z.enum(["NA", "EU"]),
});
export const resuggestionSchema = suggestionRootSchema;

View File

@@ -72,7 +72,7 @@ export const getPlusSuggestionsData = (): Prisma.PlusSuggestionCreateManyInput[]
description: "yooo so cracked",
region: "NA",
tier: 2,
suggestedId: 11,
suggestedId: 10,
suggesterId: 1,
},
];

View File

@@ -1,8 +1,8 @@
import { PlusSuggestion, Prisma } from "@prisma/client";
import { Prisma } from "@prisma/client";
import { UserError } from "lib/errors";
import { getPercentageFromCounts } from "lib/plus";
import { userBasicSelection } from "lib/prisma";
import { suggestionSchema } from "lib/validators/suggestion";
import { suggestionFullSchema } from "lib/validators/suggestion";
import prisma from "prisma/client";
export type PlusStatus = Prisma.PromiseReturnType<typeof getPlusStatus>;
@@ -178,7 +178,10 @@ const addSuggestion = async ({
data: unknown;
userId: number;
}) => {
const parsedData = { ...suggestionSchema.parse(data), suggesterId: userId };
const parsedData = {
...suggestionFullSchema.parse(data),
suggesterId: userId,
};
const [suggestions, plusStatuses] = await Promise.all([
prisma.plusSuggestion.findMany({}),
prisma.plusStatus.findMany({}),
@@ -203,6 +206,8 @@ const addSuggestion = async ({
(status) => status.userId === userId
);
console.log({ suggesterPlusStatus, parsedData });
if (
!suggesterPlusStatus ||
!suggesterPlusStatus.membershipTier ||