diff --git a/restapi/products/Product.ts b/restapi/products/Product.ts
index 22aafeac..763c735d 100644
--- a/restapi/products/Product.ts
+++ b/restapi/products/Product.ts
@@ -32,6 +32,11 @@ export const product = new Schema(
type: String,
required: false,
},
+ category: {
+ type:String,
+ required: true,
+ enum: ['Clothes', 'Decoration', 'Electronics', 'Miscellaneous']
+ }
},
{
versionKey: false,
diff --git a/restapi/products/ProductController.ts b/restapi/products/ProductController.ts
index 4672a410..58e281bc 100644
--- a/restapi/products/ProductController.ts
+++ b/restapi/products/ProductController.ts
@@ -84,3 +84,31 @@ export const updateProduct: RequestHandler = async (req, res) => {
res.status(403).json();
}
};
+
+export const filterAndOrderBy: RequestHandler = async (req, res) => {
+ let mode = req.params.mode;
+ const category = req.params.category;
+ let products;
+
+ if (
+ category !== "Clothes" &&
+ category !== "Decoration" &&
+ category !== "Electronics" &&
+ category !== "Miscellaneous"
+ ) {
+ if (mode !== "asc" && mode !== "desc") {
+ products = await productModel.find();
+ } else {
+ products = await productModel.find().sort({ price: mode });
+ }
+ } else {
+ if (mode !== "asc" && mode !== "desc") {
+ products = await productModel.find({ category: category });
+ } else {
+ products = await productModel
+ .find({ category: category })
+ .sort({ price: mode });
+ }
+ }
+ return res.json(products);
+};
diff --git a/restapi/products/ProductRoutes.ts b/restapi/products/ProductRoutes.ts
index 9c1256cb..ccd6567b 100644
--- a/restapi/products/ProductRoutes.ts
+++ b/restapi/products/ProductRoutes.ts
@@ -1,7 +1,7 @@
-import express, { Request, Response, Router } from "express";
+import express, { Router } from "express";
+import multer from "../utils/multer";
import * as ProdctController from "./ProductController";
-import multer from "../utils/multer";
const api: Router = express.Router();
@@ -9,6 +9,8 @@ api.get("/products", ProdctController.getProducts);
api.get("/products/findByCode/:code", ProdctController.getProduct);
+api.get('/products/filter&order/:category&:mode', ProdctController.filterAndOrderBy)
+
api.post("/products", multer.single("image"), ProdctController.createProduct);
api.post("/products/delete/:code", ProdctController.deleteProduct);
diff --git a/restapi/products/product.http b/restapi/products/product.http
index 4bcfacde..125dfe74 100644
--- a/restapi/products/product.http
+++ b/restapi/products/product.http
@@ -3,7 +3,7 @@
GET {{url}}/products/list
###
-GET {{url}}/products/findByCode/1
+GET {{url}}/products/findByCode/0007
###
POST {{url}}/products/create
@@ -21,9 +21,15 @@ Content-Type: application/json
DELETE {{url}}/products/delete/1
###
-POST {{url}}/products/update/1347
+POST {{url}}/products/update/0045
Content-Type: application/json
{
- "name": "Camiseta del Sporting chacho"
+ "category": "Miscellaneous"
}
+
+###
+GET {{url}}/products/order/desc
+
+###
+GET {{url}}/products/filter&order/Electronics&asc
diff --git a/restapi/tests/orders.test.ts b/restapi/tests/orders.test.ts
index 531cffb0..d4bafd5c 100644
--- a/restapi/tests/orders.test.ts
+++ b/restapi/tests/orders.test.ts
@@ -71,6 +71,7 @@ describe("orders", () => {
"Do you wanna show your friends that you are THE GREATEST IMPOSTER? Then this shirt is for you!",
stock: 1,
image: "0001.png",
+ category: "Clothes",
},
],
date: new Date(),
diff --git a/restapi/tests/products.test.ts b/restapi/tests/products.test.ts
index fc0637b4..b7266c78 100644
--- a/restapi/tests/products.test.ts
+++ b/restapi/tests/products.test.ts
@@ -71,6 +71,7 @@ describe("prodcuts", () => {
name: "Super SUS T-Shirt",
price: 9.5,
image: "0001.png",
+ category: "Clothes",
})
);
});
@@ -91,6 +92,7 @@ describe("prodcuts", () => {
price: 0.99,
description: "Another test product",
stock: 0,
+ category: "Clothes",
});
expect(response.statusCode).toBe(403);
});
@@ -110,6 +112,7 @@ describe("prodcuts", () => {
price: 0.99,
description: "Another test product",
stock: 0,
+ category: "Clothes",
});
expect(response.statusCode).toBe(200);
expect(response.body.name).toBe("testProduct");
@@ -128,6 +131,7 @@ describe("prodcuts", () => {
price: 0.99,
description: "A failure insert test product",
stock: 0,
+ category: "Clothes",
});
expect(response.statusCode).toBe(409);
});
@@ -144,6 +148,23 @@ describe("prodcuts", () => {
expect(response.statusCode).toBe(412);
});
+ it("Can't create a product with incorrect or missing category", async () => {
+ let userToken = await getToken();
+ const response: Response = await request(app)
+ .post("/products")
+ .set("token", userToken)
+ .set("email", "test")
+ .send({
+ code: uuidv4(),
+ name: "testFailProduct",
+ price: 0.99,
+ description: "A failure insert test product",
+ stock: 0,
+ category: "Nothing",
+ });
+ expect(response.statusCode).toBe(412);
+ });
+
it("Can update a product correctly", async () => {
let userToken = await getToken();
const response: Response = await request(app)
@@ -151,23 +172,25 @@ describe("prodcuts", () => {
.set("token", userToken)
.set("email", "test")
.send({
- stock: 1000,
+ stock: 10,
});
expect(response.statusCode).toBe(200);
- expect(response.body.stock).toBe(1000);
+ expect(response.body.stock).toBe(10);
});
it("Can't update a product without being admin or manager", async () => {
- const token: Response = await request(app).post("/users/requestToken/").send({
- email: "test1",
- password: "test",
- });
+ const token: Response = await request(app)
+ .post("/users/requestToken/")
+ .send({
+ email: "test1",
+ password: "test",
+ });
const response: Response = await request(app)
.post("/products/update/" + productCode)
.set("token", token.body)
.set("email", "test1")
.send({
- stock: 1000,
+ stock: 10,
});
expect(response.statusCode).toBe(403);
});
@@ -176,7 +199,7 @@ describe("prodcuts", () => {
const response: Response = await request(app)
.post("/products/update/" + productCode)
.send({
- stock: 1000,
+ stock: 10,
});
expect(response.statusCode).toBe(403);
});
@@ -197,6 +220,53 @@ describe("prodcuts", () => {
.send();
expect(response.statusCode).toBe(403);
});
+
+ /*
+ Testing filtering and ordering products
+ */
+ it("Can filter by category", async () => {
+ const response: Response = await request(app)
+ .get("/products/filter&order/Electronics&A")
+ .send();
+ expect(response.statusCode).toBe(200);
+ expect(response.body).toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({ category: "Electronics" }),
+ ])
+ );
+ });
+
+ it("Can filter by category and order by price", async () => {
+ const response: Response = await request(app)
+ .get("/products/filter&order/Electronics&asc")
+ .send();
+ expect(response.statusCode).toBe(200);
+ expect(response.body).toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({ category: "Electronics" }),
+ ])
+ );
+ expect(response.body[0].price).toBe(20.99);
+ });
+
+ it("Can order by price", async () => {
+ const response: Response = await request(app)
+ .get("/products/filter&order/Category&asc")
+ .send();
+ expect(response.statusCode).toBe(200);
+ expect(response.body[0].price).toBe(1.99);
+ });
+
+ it("Check normal order when 'wrong' input", async () => {
+ const response: Response = await request(app)
+ .get("/products/filter&order/a&a")
+ .send();
+ expect(response.statusCode).toBe(200);
+ expect(response.body[0].price).toBe(12.95);
+ expect(response.body[0].code).toBe("1234");
+ expect(response.body[1].price).toBe(9.5);
+ expect(response.body[1].code).toBe("0001");
+ });
});
async function getToken() {
diff --git a/restapi/utils/PDFHelper.ts b/restapi/utils/PDFHelper.ts
index 86104829..96c6db5f 100644
--- a/restapi/utils/PDFHelper.ts
+++ b/restapi/utils/PDFHelper.ts
@@ -1,5 +1,5 @@
import { orderModel } from "../orders/Order";
-import { userModel } from "../users/User";
+import { sendInvoiceEmail } from "./emailSender";
const fs = require("fs");
const PDFGenerator = require("pdfkit");
@@ -11,7 +11,7 @@ export const createPDF = async (code: string) => {
const orderFound = await orderModel.findOne({
orderCode: code,
});
- const user = await userModel.findOne({ email: orderFound.userEmail });
+ /*const user = await userModel.findOne({ email: orderFound.userEmail });
const invoiceData = {
addresses: {
shipping: {
@@ -29,27 +29,17 @@ export const createPDF = async (code: string) => {
};
const ig = new InvoiceGenerator(invoiceData);
- ig.generate();
-
- /*var html = fs.readFileSync(process.cwd() + "/utils/template.html", "utf-8");
+ ig.generate();*/
+ var html = fs.readFileSync(process.cwd() + "/utils/template.html", "utf-8");
const parse = require("node-html-parser").parse;
- const options: CreateOptions = {
- format: "A4",
- orientation: "portrait",
- };
-
- const orderFound = await orderModel.findOne({
- orderCode: code,
- });
-
const root = parse(html);
const body = root.querySelector("body");
let aux =
'' +
'' +
'
DeDe
' +
- '
' +
+ '
' +
"
" +
"" +
"" +
@@ -146,12 +136,5 @@ export const createPDF = async (code: string) => {
body.insertAdjacentHTML("beforeend", aux);
- pdf
- .create(root.toString(), options)
- .toFile("./pdf/" + orderFound.orderCode + ".pdf", function (err, res) {
- if (err) console.log(err);
- else {
- sendInvoiceEmail(orderFound.userEmail, orderFound.orderCode);
- }
- });*/
+ sendInvoiceEmail(orderFound.userEmail, orderFound.orderCode, root.toString());
};
diff --git a/restapi/utils/emailSender.ts b/restapi/utils/emailSender.ts
index 0fa4f7e6..49ee0923 100644
--- a/restapi/utils/emailSender.ts
+++ b/restapi/utils/emailSender.ts
@@ -1,4 +1,3 @@
-
const nodemailer = require("nodemailer");
const { v4: uuidv4 } = require("uuid");
const fs = require("fs");
@@ -12,10 +11,11 @@ sgMail.setApiKey(
export const sendInvoiceEmail: Function = (
email: string,
- orderCode: string
+ orderCode: string,
+ message: string
) => {
- const pathToAttachment = `${__dirname}/pdf/` + orderCode + ".pdf";
- const attachment = fs.readFileSync(pathToAttachment).toString("base64");
+ /*const pathToAttachment = `${__dirname}/pdf/` + orderCode + ".pdf";
+ const attachment = fs.readFileSync(pathToAttachment).toString("base64");*/
const mailOptions = {
to: email,
@@ -23,20 +23,24 @@ export const sendInvoiceEmail: Function = (
subject: "DeDe Order Invoice",
html:
"Thank you for trusting in DeDe and buying with us.
Here you have the receipt of your purchase." +
- "
We hope to see you soon :)
",
- attachments: [
+ "
We hope to see you soon :)
" +
+ message,
+ /*attachments: [
{
content: attachment,
filename: orderCode + ".pdf",
type: "application/pdf",
disposition: "attachment",
},
- ],
+ ],*/
};
sgMail.send(mailOptions);
};
-export const sendVerificationEmail: Function = async (email: string, uniqueString: string) => {
+export const sendVerificationEmail: Function = async (
+ email: string,
+ uniqueString: string
+) => {
const currentUrl = "http://localhost:5000";
const mailOptions = {
diff --git a/webapp/src/api/api.ts b/webapp/src/api/api.ts
index 07d96049..97510551 100644
--- a/webapp/src/api/api.ts
+++ b/webapp/src/api/api.ts
@@ -1,7 +1,9 @@
-import { Order, Review, User, Product } from "../shared/shareddtypes";
+import { Order, Product, Review, User } from "../shared/shareddtypes";
const apiEndPoint = process.env.REACT_APP_API_URI || "http://localhost:5000";
+// USERS
+
export async function addUser(user: User): Promise {
let response = await fetch(apiEndPoint + "/users", {
method: "POST",
@@ -44,6 +46,8 @@ export async function getUser(userEmail: String): Promise {
return response.json();
}
+// PRODUCTS
+
export async function getProducts(): Promise {
let response = await fetch(apiEndPoint + "/products/");
return response.json();
@@ -56,35 +60,6 @@ export async function getProduct(productCode: string): Promise {
return response.json();
}
-export async function getPlaces(
- x: number,
- y: number,
- radiusMeters: number,
- maxResults: number
-): Promise {
- const url =
- "https://api.geoapify.com/v2/places?categories=commercial&filter=circle:" +
- x +
- "," +
- y +
- "," +
- radiusMeters +
- "&bias=proximity:" +
- x +
- "," +
- y +
- "&limit=" +
- maxResults +
- "&apiKey=" +
- process.env.REACT_APP_GEOAPIFY_KEY;
-
- let places;
- await fetch(url, {
- method: "GET",
- }).then((response) => (places = response.json()));
- return places;
-}
-
export async function updateProduct(product: Product) {
await fetch(apiEndPoint + "/products/update/" + product.code, {
method: "POST",
@@ -133,6 +108,20 @@ export async function deleteProduct(code: string) {
});
}
+// Mode must be desc or asc. If not default order
+// Category must be Clothes, Decoration, Elecrtonics or Miscellaneous. If not all categories
+export async function filterProductsByCategory(
+ category: string,
+ mode: string
+): Promise {
+ let response = await fetch(
+ apiEndPoint + "/products/filter&order/" + category + "&" + mode
+ );
+ return response.json();
+}
+
+// ORDERS
+
export async function createOrder(body: any) {
await fetch(apiEndPoint + "/orders", {
method: "POST",
@@ -182,6 +171,8 @@ export async function getOrders(): Promise {
return response.json();
}
+// REVIEWS
+
export async function getReviewsByCode(code: string): Promise {
let response = await fetch(apiEndPoint + "/reviews/listByCode/" + code);
return response.json();
@@ -215,3 +206,34 @@ export async function addReview(review: Review): Promise {
return true;
} else return false;
}
+
+// PLACES
+
+export async function getPlaces(
+ x: number,
+ y: number,
+ radiusMeters: number,
+ maxResults: number
+): Promise {
+ const url =
+ "https://api.geoapify.com/v2/places?categories=commercial&filter=circle:" +
+ x +
+ "," +
+ y +
+ "," +
+ radiusMeters +
+ "&bias=proximity:" +
+ x +
+ "," +
+ y +
+ "&limit=" +
+ maxResults +
+ "&apiKey=" +
+ process.env.REACT_APP_GEOAPIFY_KEY;
+
+ let places;
+ await fetch(url, {
+ method: "GET",
+ }).then((response) => (places = response.json()));
+ return places;
+}
diff --git a/webapp/src/components/checkout/Checkout.tsx b/webapp/src/components/checkout/Checkout.tsx
index 5db9b03d..2769a806 100644
--- a/webapp/src/components/checkout/Checkout.tsx
+++ b/webapp/src/components/checkout/Checkout.tsx
@@ -1,21 +1,21 @@
-import * as React from "react";
-
import Container from "@mui/material/Container";
import Paper from "@mui/material/Paper";
-import Stepper from "@mui/material/Stepper";
import Step from "@mui/material/Step";
import StepLabel from "@mui/material/StepLabel";
+import Stepper from "@mui/material/Stepper";
import Typography from "@mui/material/Typography";
-
+import * as React from "react";
import { updateProduct } from "../../api/api";
-import { CartItem } from "../../shared/shareddtypes";
import { saveOrder } from "../../helpers/ShoppingCartHelper";
-
-import ShippingAddress from "./ShippingAddress";
-import ShippingMethod from "./ShippingMethod";
-import Review from "./Review";
+import { CartItem } from "../../shared/shareddtypes";
import Billing from "./Billing";
import OrderConfirmation from "./OrderConfirmation";
+import Review from "./Review";
+import ShippingAddress from "./ShippingAddress";
+import ShippingMethod from "./ShippingMethod";
+
+
+
function getSteps() {
return ["Address", "Shipping method", "Review", "Billing", "Confirm"];
@@ -59,7 +59,7 @@ export default function Checkout(props: any) {
props.productsCart,
costs,
props.userEmail,
- "Get address not implemented yet"
+ address
);
props.deleteCart();
};
diff --git a/webapp/src/components/dashboard/products/DeleteProduct.tsx b/webapp/src/components/dashboard/products/DeleteProduct.tsx
index 0fe25b4c..ce4f93eb 100644
--- a/webapp/src/components/dashboard/products/DeleteProduct.tsx
+++ b/webapp/src/components/dashboard/products/DeleteProduct.tsx
@@ -1,23 +1,20 @@
-import React, { useState } from "react";
-
import {
- Box,
- Card,
+ Alert, Box, Button, Card,
Container,
MenuItem,
Paper,
Snackbar,
Stack,
styled,
- TextField,
- Alert,
- Button,
+ TextField
} from "@mui/material";
-
+import React, { useState } from "react";
import { deleteProduct } from "../../../api/api";
import { checkImageExists } from "../../../helpers/ImageHelper";
import { NotificationType, Product } from "../../../shared/shareddtypes";
+
+
const DEF_IMAGE: string = require("../../../images/not-found.png");
const Img = styled("img")({
@@ -39,6 +36,7 @@ export default function DeleteProduct(props: DeleteProductProps): JSX.Element {
const [description, setDescription] = useState("");
const [stock, setStock] = useState("");
const [price, setPrice] = useState("");
+ const [category, setCategory] = useState("");
const [dialogOpen, setDialogOpen] = useState(0);
const [image, setImage] = useState(DEF_IMAGE);
const [notification, setNotification] = useState({
@@ -54,6 +52,7 @@ export default function DeleteProduct(props: DeleteProductProps): JSX.Element {
setCode(p.code);
setName(p.name);
setDescription(p.description);
+ setCategory(p.category)
setPrice(p.price.toString());
setStock(p.stock.toString());
setImage(checkImageExists(p.image));
@@ -87,6 +86,7 @@ export default function DeleteProduct(props: DeleteProductProps): JSX.Element {
setCode("");
setName("");
setDescription("");
+ setCategory("")
setStock("");
setPrice("");
setImage(DEF_IMAGE);
@@ -114,7 +114,7 @@ export default function DeleteProduct(props: DeleteProductProps): JSX.Element {
>
{products.map((product) => (
))}
@@ -163,6 +163,18 @@ export default function DeleteProduct(props: DeleteProductProps): JSX.Element {
variant="outlined"
/>
+ setCategory(event.target.value)}
+ />
+
(DEF_IMAGE);
const getCode = async () => {
@@ -76,6 +76,7 @@ export default function UploadImage(props: UploadProductProps): JSX.Element {
setDescription("");
setStock("");
setPrice("");
+ setCategory("");
};
const checkFields = () => {
@@ -99,6 +100,7 @@ export default function UploadImage(props: UploadProductProps): JSX.Element {
description: description,
price: Number(price),
stock: Number(stock),
+ category: category,
});
if (created) {
emptyFields();
@@ -184,6 +186,32 @@ export default function UploadImage(props: UploadProductProps): JSX.Element {
onChange={(event) => setDescription(event.target.value)}
/>
+ setCategory(event.target.value)}
+ >
+
+
+
+
+
+
{
- item.product.stock = item.amount;
- orderProducts.push(item.product);
+ let p: Product = {
+ code: item.product.code,
+ name: item.product.name,
+ description: item.product.description,
+ price: item.product.price,
+ stock: item.amount,
+ image: item.product.image,
+ category: item.product.category
+ };
+ orderProducts.push(p);
});
let order: Order = {
diff --git a/webapp/src/shared/shareddtypes.ts b/webapp/src/shared/shareddtypes.ts
index cb973ef0..17ae53da 100644
--- a/webapp/src/shared/shareddtypes.ts
+++ b/webapp/src/shared/shareddtypes.ts
@@ -16,6 +16,14 @@ export type Product = {
price: number;
stock: number;
image: string;
+ category: string;
+};
+
+export const ProductCategories = {
+ Clothes: "Clothes",
+ Decoration: "Decoration",
+ Electronics: "Electronics",
+ Misccellaneous: "Miscellaneous",
};
export type NotificationType = {
diff --git a/webapp/src/tests/cart/ShoppingCart.test.tsx b/webapp/src/tests/cart/ShoppingCart.test.tsx
index 9ed394cd..e1ea2d0e 100644
--- a/webapp/src/tests/cart/ShoppingCart.test.tsx
+++ b/webapp/src/tests/cart/ShoppingCart.test.tsx
@@ -1,7 +1,7 @@
import { render } from "@testing-library/react";
+import { BrowserRouter as Router } from "react-router-dom";
import ShoppingCart from "../../components/cart/ShoppingCart";
import { CartItem } from "../../shared/shareddtypes";
-import { BrowserRouter as Router } from "react-router-dom";
//Test for the ShoppingCart component, receives a list of cart items and it is rendered properly.
test("A list of two cart items is rendered", async () => {
@@ -14,6 +14,7 @@ test("A list of two cart items is rendered", async () => {
price: 10,
stock: 20,
image: "",
+ category: 'Electronics'
},
amount: 1,
},
@@ -25,6 +26,7 @@ test("A list of two cart items is rendered", async () => {
price: 15,
stock: 10,
image: "",
+ category: 'Clothes'
},
amount: 2,
},
diff --git a/webapp/src/tests/cart/ShoppingCartTable.test.tsx b/webapp/src/tests/cart/ShoppingCartTable.test.tsx
index ddb9b1f2..0aab086b 100644
--- a/webapp/src/tests/cart/ShoppingCartTable.test.tsx
+++ b/webapp/src/tests/cart/ShoppingCartTable.test.tsx
@@ -13,6 +13,7 @@ test("A list of two cart items is rendered", async () => {
price: 10,
stock: 20,
image: "",
+ category: 'Electronics'
},
amount: 1,
},
@@ -24,6 +25,7 @@ test("A list of two cart items is rendered", async () => {
price: 15,
stock: 10,
image: "",
+ category: 'Clothes'
},
amount: 2,
},
@@ -73,6 +75,7 @@ test("A list of one cart item with amount 0 is not rendered", async () => {
price: 10,
stock: 20,
image: "",
+ category: 'Electronics'
},
amount: 0,
},
@@ -102,6 +105,7 @@ test("The increment button is disabled when the amount is equal or higher to the
price: 10,
stock: 20,
image: "",
+ category: 'Electronics'
},
amount: 20,
},
@@ -130,6 +134,7 @@ test("Increment and decrement buttons work well.", async () => {
price: 10,
stock: 20,
image: "",
+ category: 'Electronics'
},
amount: 1,
},
diff --git a/webapp/src/tests/products/ProductBox.test.tsx b/webapp/src/tests/products/ProductBox.test.tsx
index 5e176ea5..6facf9d5 100644
--- a/webapp/src/tests/products/ProductBox.test.tsx
+++ b/webapp/src/tests/products/ProductBox.test.tsx
@@ -1,9 +1,8 @@
-import React from "react";
-
import { fireEvent, render } from "@testing-library/react";
-import ProductBox from "../../components/products/ProductBox";
-import { Product, CartItem } from "../../shared/shareddtypes";
import { BrowserRouter as Router } from "react-router-dom";
+import ProductBox from "../../components/products/ProductBox";
+import { CartItem, Product } from "../../shared/shareddtypes";
+
test("A product is rendered", async () => {
const product: Product = {
@@ -13,6 +12,7 @@ test("A product is rendered", async () => {
price: 10,
stock: 20,
image: "",
+ category: 'Electronics'
};
const { getByText, container } = render(
@@ -41,6 +41,7 @@ test("A product is added to the cart", async () => {
price: 10,
stock: 20,
image: "",
+ category: 'Electronics'
};
const cart: CartItem[] = [];
@@ -69,6 +70,7 @@ test("URL to product details works", async () => {
price: 10,
stock: 20,
image: "",
+ category: 'Electronics'
};
const cart: CartItem[] = [];
diff --git a/webapp/src/tests/products/ProductDetails.test.tsx b/webapp/src/tests/products/ProductDetails.test.tsx
index 9eb6d2d9..7750d5ef 100644
--- a/webapp/src/tests/products/ProductDetails.test.tsx
+++ b/webapp/src/tests/products/ProductDetails.test.tsx
@@ -1,6 +1,6 @@
-import { fireEvent, prettyDOM, render } from "@testing-library/react";
+import { fireEvent, render } from "@testing-library/react";
import ProductDetails from "../../components/products/ProductDetails";
-import { Product, CartItem } from "../../shared/shareddtypes";
+import { Product } from "../../shared/shareddtypes";
//Test that the product details page renders correctly
test("Renders product details page", () => {
@@ -11,6 +11,7 @@ test("Renders product details page", () => {
price: 9.99,
stock: 15,
image: "",
+ category: 'Electronics'
};
const { getByText, getAllByText } = render(
@@ -38,6 +39,7 @@ test("Adds product to cart", () => {
price: 9.99,
stock: 15,
image: "",
+ category: 'Electronics'
};
const onAdd = jest.fn();
diff --git a/webapp/src/tests/products/ProductList.test.tsx b/webapp/src/tests/products/ProductList.test.tsx
index 41aaa987..f6770cc3 100644
--- a/webapp/src/tests/products/ProductList.test.tsx
+++ b/webapp/src/tests/products/ProductList.test.tsx
@@ -1,9 +1,8 @@
-import React from "react";
-
-import { fireEvent, render } from "@testing-library/react";
+import { render } from "@testing-library/react";
+import { BrowserRouter as Router } from "react-router-dom";
import ProductList from "../../components/products/ProductList";
import { Product } from "../../shared/shareddtypes";
-import { BrowserRouter as Router } from "react-router-dom";
+
test("A list of products is rendered", async () => {
const products: Product[] = [
@@ -14,6 +13,7 @@ test("A list of products is rendered", async () => {
price: 10,
stock: 20,
image: "",
+ category: 'Electronics'
},
{
code: "9998",
@@ -22,6 +22,7 @@ test("A list of products is rendered", async () => {
price: 15,
stock: 10,
image: "",
+ category: 'Electronics'
},
];