Skip to content

Commit

Permalink
Merge pull request #78 from CMU-17-356/testing_customer
Browse files Browse the repository at this point in the history
Added success notification for adding to cart, added id selectors to …
  • Loading branch information
ananyabhat authored Mar 25, 2022
2 parents 887129d + 873645c commit 535e593
Show file tree
Hide file tree
Showing 9 changed files with 1,493 additions and 267 deletions.
72 changes: 72 additions & 0 deletions backend/tests/place_order.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import puppeteer from "puppeteer";

jest.setTimeout(90 * 1000);

describe("Placing an order", () => {
let browser;
let page;

beforeAll(async () => {
browser = await puppeteer.launch();
page = await browser.newPage();
await page.goto("http://localhost:3000/customer");
});

it("contains the donut card", async () => {
await page.waitForSelector("#JellyCard");
const text = await page.$eval("#JellyCard", (e) => e.textContent);
expect(text).toContain("Jelly");
});

it("can add donut to cart", async() => {
await page.click('#JellyAddBtn');
await page.waitForSelector('#addedAlert');
const text = await page.$eval("#addedAlert", (e) => e.textContent);
expect(text).toContain("Added Jelly donut to cart!");
});

it("can continue to cart", async() => {
const [response] = await Promise.all([
page.click('#continueToCart'),
page.waitForNavigation()
]);
});

it("can show correct cart order headings", async () => {
const data = await page.$$eval('#order-items-table thead tr th', tds => tds.map((td) => {
return td.innerText;
}));
expect(data).toEqual(['Donut', 'Price']);
});

// it("can show correct cart items", async () => {
// const data = await page.$$eval('#order-items-table tbody tr td', tds => tds.map((td) => {
// return td.innerText;
// }));
// expect(data).toEqual(['Jelly', '2.5']);
// });

it("can show correct payment details", async () => {
const rawData = await page.$$eval('#payment-details-table tbody tr', tds => tds.map((td) => {
return td.innerText;
}));
const data = rawData.map(el => el.split("\t"));
expect(data).toEqual([
[ 'Subtotal', '2.50' ],
[ 'Fees & Estimated Tax', '0.18' ],
[ 'Total', '2.67' ]
]);
});

it("can continue to track order", async() => {
const [response] = await Promise.all([
page.click('#continueToTrackOrder'),
page.waitForNavigation()
]);
});

afterAll(async() => {
browser.close();
});

});
4 changes: 3 additions & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ function App() {
<ResponsiveAppBar></ResponsiveAppBar>
<Routes>
<Route path="/customer" element={<CustomerMenu />} />
<Route path="/order" element={<TrackOrder />} />
<Route path="/trackorder" element={<TrackOrder />}>
<Route path=":id" element={<TrackOrder />} />
</Route>
<Route path="/cart" element={<Cart />} />
<Route path='/login' element={<Login />} />
<Route path='/register' element={<CustomerSignUp />}/>
Expand Down
145 changes: 100 additions & 45 deletions frontend/src/components/Customer/Cart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,69 +8,126 @@ import { Link } from 'react-router-dom';
import DonutInterface from '../Dronut/Donut';
import DroneInterface from '../Drone/Drone';
import { customerItems } from '../Customer/CustomerMenu';
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';



export interface Order {
_id: number;
_id: string;
first_name: string;
last_name: string;
drone: DroneInterface;
items: Array<DonutInterface>;
price: number;
}
export default function Cart() {
function subtotal(items: readonly DonutInterface[]) {
console.log("items: ", items);
return items.map(({ price }) => price).reduce((sum, i) => sum + i, 0);
}
const TAX_RATE = 0.07;

function calculatePaymentDetails(items) {
const invoiceSubtotal = subtotal(customerItems.items);
const invoiceTaxes = TAX_RATE * invoiceSubtotal;
const invoiceTotal = invoiceTaxes + invoiceSubtotal;
return [invoiceSubtotal, invoiceTaxes, invoiceTotal];
}

let [submitted, setSubmitted] = useState<boolean>(false);

const [id, setID] = useState("623d350aff5d5564185ce960");
const navigate = useNavigate();


function getID() {
fetch('/orders').then((resp) => {
return resp.json() as Promise<Array<Order>>;
}).then((response: Array<Order>) => {
const ids = response.map((order: Order) => order._id);
console.log(ids);
console.log(ids[0]);
setID(ids[0]);
console.log("id:", id);
});
}

useEffect(() => {if (submitted) {
getID();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [submitted]);

function submitOrder() {
// const response = await fetch('/customers/'+customerItems.customerId).then((res) => res.json());
const [invoiceSubtotal, invoiceTaxes, invoiceTotal] = calculatePaymentDetails(customerItems.items);
// console.log(response);
// const newOrder = {
// "customer": customerItems.customerId,
// "drone": {"battery_life": 10, "critical": false},
// "location": {
// "street_address": response.addresses[0].street_address ,
// "city": response.addresses[0].city,
// "state": response.addresses[0].state,
// "zipcode": response.addresses[0].zipcode
// },
// "items": customerItems.items,
// "total": invoiceTotal,
// "status": "Preparing"
// };

const newOrder = {
"customer": "623cc0716c8375d16ebc1afe",
"drone": {"battery_life": 10, "critical": false},
"location": {
"street_address": "error" ,
"city": "error",
"state": "error",
"zipcode": "error"
},
"items": customerItems.items,
"total": invoiceTotal,
"status": "Preparing"
};
console.log("newOrder: ",newOrder);

fetch('/orders', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(newOrder)
}).then((resp) => {
// alert('Order submitted!');
let path = '/trackorder/' + id.toString();
navigate(path);
}, (err) => {
alert('Unexpected error submitting order.');
});

}


async function handlePlaceOrder() {
const response = await fetch('/customers/'+customerItems.customerId).then((res) => res.json());

const newOrder = {
"customer": customerItems.customerId,
"drone": {"battery_life": 10, "critical": false},
"location": {
"street_address": response.addresses[0].street_address,
"city": response.addresses[0].city,
"state": response.addresses[0].state,
"zipcode": response.addresses[0].zipcode
},
"items": customerItems.items,
"total": invoiceTotal,
"status": "Preparing"
};
console.log("newOrder: ",newOrder);

fetch('/orders', {
method: 'POST',
body: JSON.stringify(newOrder),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
useEffect(() => {
if (submitted) {
submitOrder();
}
});

}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [submitted]);

function ccyFormat(num: number) {
return `${num.toFixed(2)}`;
}

function subtotal(items: readonly DonutInterface[]) {
console.log("items: ", items);
return items.map(({ price }) => price).reduce((sum, i) => sum + i, 0);
}

const TAX_RATE = 0.07;
const invoiceSubtotal = subtotal(customerItems.items);
const invoiceTaxes = TAX_RATE * invoiceSubtotal;
const invoiceTotal = invoiceTaxes + invoiceSubtotal;

function OrderedItems() {
console.log(customerItems);
return (
<Box sx={{ width: '100%' }}>
<Paper sx={{ width: '100%', mb: 2 }}>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<Table id="order-items-table" sx={{ minWidth: 650 }} >
<TableHead>
<TableRow>
<TableCell>Donut</TableCell>
Expand Down Expand Up @@ -129,9 +186,10 @@ function DeliveryOptions(){
}

function PaymentDetails(){
const [invoiceSubtotal, invoiceTaxes, invoiceTotal] = calculatePaymentDetails(customerItems.items);
return(
<TableContainer component={Paper}>
<Table aria-label="spanning table">
<Table aria-label="spanning table" id="payment-details-table">
<Typography gutterBottom variant="h6" sx={{margin: 2}}>
Payment Details
</Typography>
Expand Down Expand Up @@ -170,18 +228,15 @@ function CartContent(){
<PaymentDetails />
</CardContent>
</Card>
<Button
<Button id="continueToTrackOrder"
variant="contained"
color="secondary"
component={Link}
to={'/order'}
onClick={() => handlePlaceOrder()}
onClick={() => setSubmitted(true)}
sx={{mt: 2}}>Place Order</Button>
</Container>
);
}

export default function Cart() {
return (
<main>
<CartContent />
Expand Down
44 changes: 37 additions & 7 deletions frontend/src/components/Customer/CustomerMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
import { Box, Button, Container, CssBaseline, Typography } from '@mui/material';
import React from 'react';
import {
Alert,
Box,
Button,
Card,
CardActions,
CardContent,
CardMedia,
Container,
CssBaseline,
Grid,
Snackbar,
Typography
} from '@mui/material';
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import DonutInterface from '../Dronut/Donut';
import DonutList from '../Dronut/DonutList';
Expand Down Expand Up @@ -27,13 +40,25 @@ const donuts: Array<DonutInterface> = [];


function Menu() {

const handleClose = (event?: React.SyntheticEvent | Event, reason?: string) => {
if (reason === 'clickaway') {
return;
}

setOpen(false);
};

const [open, setOpen] = React.useState(false);
const [snackMessage, setSnackMessage] = React.useState("");

function handleAddItem(item) {
console.log(item);
console.log(donuts);
donuts.push(item);
console.log(donuts);
customerItems.items.push(item);
setSnackMessage(`Added ${item.flavor} donut to cart!`);
setOpen(true);
}

async function handleCustomerCart(){
console.log("logged User: ",loggedUser);

Expand All @@ -52,7 +77,6 @@ function Menu() {
}else{
customerItems.customerId = loggedUser._id;
}
customerItems.items=donuts;
console.log(customerItems)
}

Expand All @@ -62,7 +86,13 @@ function Menu() {
{/* End hero unit */}
<DonutList onClick={handleAddItem} text="Add to cart" />
</Container>
<Button color="secondary" component={Link} to={'/cart'} onClick={handleCustomerCart}>
<Snackbar open={open} autoHideDuration={6000} onClose={handleClose}>
<Alert id="addedAlert" onClose={handleClose} severity="success" sx={{ width: '100%' }}>
{snackMessage}
</Alert>
</Snackbar>
<Button id="continueToCart"
color="secondary" component={Link} to={'/cart'} onClick={handleCustomerCart}>
Continue to Cart
</Button>
</main>
Expand Down
Loading

0 comments on commit 535e593

Please sign in to comment.