diff --git a/.github/workflows/css-linting.yml b/.github/workflows/css-linting.yml index fae3b66..48b333a 100644 --- a/.github/workflows/css-linting.yml +++ b/.github/workflows/css-linting.yml @@ -20,4 +20,4 @@ jobs: - name: Install dependencies run: sudo npm install - name: Run tests - run: sudo npm run lintCSS \ No newline at end of file + run: sudo npm run lint-css \ No newline at end of file diff --git a/.github/workflows/html-linting.yml b/.github/workflows/html-linting.yml index ab68590..c24292b 100644 --- a/.github/workflows/html-linting.yml +++ b/.github/workflows/html-linting.yml @@ -20,4 +20,4 @@ jobs: - name: Install dependencies run: sudo npm install - name: Run tests - run: sudo npm run lintHTML + run: sudo npm run lint-html diff --git a/.github/workflows/js-linting.yml b/.github/workflows/js-linting.yml index f3aafaf..b642926 100644 --- a/.github/workflows/js-linting.yml +++ b/.github/workflows/js-linting.yml @@ -22,4 +22,4 @@ jobs: - name: Install dependencies run: sudo npm install - name: Run tests - run: sudo npm run lint \ No newline at end of file + run: sudo npm run lint-js \ No newline at end of file diff --git a/.stylelintrc.json b/.stylelintrc.json index 2f1eeda..76eba38 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -1,3 +1,4 @@ { - "extends": "stylelint-config-standard" + "extends": "stylelint-config-standard", + "ignore": ["inside-parens", "param", "value"] } \ No newline at end of file diff --git a/README.md b/README.md index 4d9849e..4a2b1cf 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ -# cse110-fa22-group29 -[Team Page Link](https://github.com/cse110-fa22-group29/cse110-fa22-group29/blob/main/admin/team.md) \ No newline at end of file +# cse110-fa22-group29 + +[Team Page Link](https://github.com/cse110-fa22-group29/cse110-fa22-group29/blob/main/admin/team.md) + +[Food Journal](https://cse110-fa22-group29.github.io/cse110-fa22-group29/) \ No newline at end of file diff --git a/admin/cipipeline/phase1.md b/admin/cipipeline/phase1.md index 046ee84..ccb48f0 100644 --- a/admin/cipipeline/phase1.md +++ b/admin/cipipeline/phase1.md @@ -31,6 +31,9 @@ So far the features listed below have been completed to some degree: - Linting (JS) - Implemented: ction triggers on any PR, uses eslint to perform style enforcement on all JS components - ToDo: trigger workflow only on certain PRs which relate to JS code +- Linting (HTML) + - Implemented: action triggers on any PR, uses HTMLhint to perform style enforcement on all HTML components +- Linting (CSS) + - Implemented: action triggers on any PR, uses Stylelint to perform style enforcement on all CSS components - -## Planned Features and Timeline \ No newline at end of file +## Planned Features and Timeline diff --git a/admin/meetings/111722-sprint2meeting1.md b/admin/meetings/111722-sprint2meeting1.md new file mode 100644 index 0000000..01b31d9 --- /dev/null +++ b/admin/meetings/111722-sprint2meeting1.md @@ -0,0 +1,47 @@ +# Meeting Minutes (11/07/2022) +## Team 29: Hackers1995 +## Meeting Topic: First Sprint +Meeting notes for the first sprint + +## Attendance +1. Rhea Bhutada +2. George Dubinin +3. Gavyn Ezell +4. Henry Feng +5. Kara Hoagland +6. Marc Reta +7. Sanjit Joseph +8. Daniel Hernandez +9. Arthur Lu +10. Isaac Otero + +## Meeting Details +- When: 11/17/2022 at 11:30PM +- Where: Design & Innovation Building + +## Agenda: +- ### Old/Unresolved Business + - N/A +- ### New Business + - Second sprint commences! + - Focus on design progress for the project showoff + - Cuisine vs Tag identifiers for reviews (both?) + - localStorage will hold: + - list of active IDs which is updated for very create operation. An ID uniquely identifies a review + - value, "nextId" denoting the index of the next available slot for an Id + - entries for every single review (javascript object) + - a list for every tag that denotes which Ids belong to reviews containing this tag + + End2end tests will rely on specific html element names which include the following: + - "create-btn" (located on homepage and used to create a new review) + - "submit-btn" (located on form and used to post review) + - "update-btn" (located on a specific review page) + - "delete-btn" (located on a specific review page) + - "tag-add-btn" (located on the review create form) +- ### Next Meeting's Business + +## Decisions Made +- + +## End Time +- 11/17/2022 at 1:00PM \ No newline at end of file diff --git a/admin/meetings/112022-sprint2meeting3.md b/admin/meetings/112022-sprint2meeting3.md new file mode 100644 index 0000000..fdbaca0 --- /dev/null +++ b/admin/meetings/112022-sprint2meeting3.md @@ -0,0 +1,36 @@ +# Meeting Minutes (11/20/2022) +## Team 29: Hackers1995 +## Meeting Topic: Second Sprint Meeting 3 + + +## Attendance +1. Rhea Bhutada +2. George Dubinin +3. Gavyn Ezell +4. Henry Feng +5. Kara Hoagland +6. Marc Reta +7. Sanjit Joseph +8. Daniel Hernandez +9. Arthur Lu +10. Isaac Otero + +## Meeting Details +- When: 11/20/2022 at 1:00PM +- Where: CSE Building Second Floor + +## Agenda: +- ### Old/Unresolved Business + - N/A +- ### New Business + - Planning for the Agile Steam Status Video + - *Present the status of your software* + - *Description of current challenges to development* + - *Preview of the next sprint and what to look forward to* +- ### Next Meeting's Business + +## Decisions Made +- + +## End Time +- 11/20/2022 at 3:00PM \ No newline at end of file diff --git a/package.json b/package.json index 5dfc756..be9a691 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,11 @@ "type": "module", "scripts": { "test": "mocha --recursive --require mock-local-storage './{,!(node_modules)/**}/*.test.js'", - "lint": "eslint **/*.js", - "fix-style": "eslint --fix **/*.js", - "lintHTML": "htmlhint '**/*.html'", - "lintCSS": "stylelint '**/*.css'", + "lint-js": "eslint **/*.js", + "fix-js": "eslint --fix **/*.js", + "lint-html": "htmlhint **/*.html", + "lint-css": "stylelint **/*.css", + "fix-css": "stylelint --fix **/*.css", "http-server": "http-server source" }, "devDependencies": { diff --git a/source/CreatePage.html b/source/CreatePage.html index 99fc09c..0388673 100644 --- a/source/CreatePage.html +++ b/source/CreatePage.html @@ -14,42 +14,56 @@ - + + -
-
- Pic: - Choose Input type: +
+ logo +

Food Journal

+ +
+
+

New Entry

+ + +
+ Pic: + Choose Input type: - -
-
- - Meal: - - -
- + Source: + + + +
+
+ Meal: + + +
Rating: @@ -59,24 +73,25 @@
-
- Other Info: - -
+ + + \ No newline at end of file diff --git a/source/ReviewDetails.html b/source/ReviewDetails.html index 609af99..1faf942 100644 --- a/source/ReviewDetails.html +++ b/source/ReviewDetails.html @@ -77,7 +77,7 @@ - + diff --git a/source/assets/images/icons/Grouppink.png b/source/assets/images/icons/Grouppink.png new file mode 100644 index 0000000..d4f1d14 Binary files /dev/null and b/source/assets/images/icons/Grouppink.png differ diff --git a/source/assets/images/icons/Logo.png b/source/assets/images/icons/Logo.png new file mode 100644 index 0000000..0f5cf77 Binary files /dev/null and b/source/assets/images/icons/Logo.png differ diff --git a/source/assets/images/icons/favicon.ico b/source/assets/images/icons/favicon.ico new file mode 100644 index 0000000..e0dd9ea Binary files /dev/null and b/source/assets/images/icons/favicon.ico differ diff --git a/source/assets/scripts/appTestHelpers.js b/source/assets/scripts/appTestHelpers.js new file mode 100644 index 0000000..12fd3c3 --- /dev/null +++ b/source/assets/scripts/appTestHelpers.js @@ -0,0 +1,76 @@ +import {strict as assert} from "node:assert"; + +/** + * Fills out a create or update review form + * @param {Object} page the page object which contains the create or update form + * @param {Object} review review data to input into the form + */ +export async function setReviewForm(page, review) { + + // Set text fields + await page.$eval("#imgAlt", (el, value) => el.value = value, review.imgAlt); + await page.$eval("#mealName", (el, value) => el.value = value, review.mealName); + await page.$eval("#comments", (el, value) => el.value = value, review.comments); + await page.$eval("#restaurant", (el, value) => el.value = value, review.restaurant); + + // Get all tag elements and click them to delete them + let tag_items = await page.$$(".tag"); + if(tag_items !== null){ + for(let i = 0; i < tag_items.length; i++){ + await tag_items[i].click(); + } + } + + // Get the button needed to add new tags + let tag_btn = await page.$("#tag-add-btn"); + for(let i = 0; i < review.tags.length; i++){ + await page.$eval("#tag-form", (el, value) => el.value = value, review.tags[i]); + await tag_btn.click(); + } + + // Select a new rating + let rating_select = await page.$(`#s${review.rating}-select`); + await rating_select.click({delay: 100}); +} + +/** + * Tests a page or shadowDOM for correct element text, src, or alt values + * @param {Object} root page or shodowDOM to test + * @param {string} prefix prefix character for element IDs + * @param {Object} expected values for eahc element + */ +export async function checkCorrectness(root, prefix, expected){ + // Get the review image and check src and alt + let img = await root.$(`#${prefix}-mealImg`); + let imgSrc = await img.getProperty("src"); + let imgAlt = await img.getProperty("alt"); + // Check src and alt + assert.strictEqual(await imgSrc.jsonValue(), expected.imgSrc); + assert.strictEqual(await imgAlt.jsonValue(), expected.imgAlt); + + // Get the title, comment, and restaurant + let title = await root.$(`#${prefix}-mealName`); + let title_text = await title.getProperty("innerText"); + let comment = await root.$(`#${prefix}-comments`); + let comment_text = await comment.getProperty("innerText"); + let restaurant = await root.$(`#${prefix}-restaurant`); + let restaurant_text = await restaurant.getProperty("innerText"); + + // Check title, comment, and restaurant + assert.strictEqual(await title_text.jsonValue(), expected.mealName); + assert.strictEqual(await comment_text.jsonValue(), expected.comments); + assert.strictEqual(await restaurant_text.jsonValue(), expected.restaurant); + + // Check tags + let tags = await root.$$(".tag"); + assert.strictEqual(await tags.length, expected.tags.length); + for(let i = 0; i < expected.tags.length; i++){ + let tag_text = await tags[i].getProperty("innerText"); + assert.strictEqual(await tag_text.jsonValue(), expected.tags[i]); + } + + // Check stars + let stars = await root.$(`#${prefix}-rating`); + let stars_src = await stars.getProperty("src"); + assert.strictEqual(await stars_src.jsonValue(), expected.rating); +} \ No newline at end of file diff --git a/source/assets/scripts/main.e2e.test.js b/source/assets/scripts/main.e2e.test.js index 482f67c..38b5f3c 100644 --- a/source/assets/scripts/main.e2e.test.js +++ b/source/assets/scripts/main.e2e.test.js @@ -1,7 +1,8 @@ import {strict as assert} from "node:assert"; import {describe, it, before, after} from "mocha"; import puppeteer from "puppeteer-core"; -import { exit } from "node:process"; +import {exit} from "node:process"; +import {setReviewForm, checkCorrectness} from "./appTestHelpers.js"; describe("test App end to end", async () => { @@ -17,7 +18,8 @@ describe("test App end to end", async () => { root = false; } - browser = await puppeteer.launch({args: root ? ['--no-sandbox'] : undefined}); + //browser = await puppeteer.launch({headless: false, slowMo: 250, args: root ? ['--no-sandbox'] : undefined}); + browser = await puppeteer.launch({args: root ? ["--no-sandbox"] : undefined}); page = await browser.newPage(); try{ await page.goto("http://localhost:8080", {timeout: 1000}); @@ -35,346 +37,210 @@ describe("test App end to end", async () => { }); }); - describe("test create 1 new review", async () => { - it("create 1 new review", async () => { - // Click the button to show update form - let create_btn = await page.$("#create-btn"); - await create_btn.click(); - await page.waitForNavigation(); + describe("test CRUD on simple inputs and default image", () => { - // Set text fields - await page.$eval("#mealImg", el => el.value = "sample src"); - await page.$eval("#imgAlt", el => el.value = "sample alt"); - await page.$eval("#mealName", el => el.value = "sample name"); - await page.$eval("#comments", el => el.value = "sample comment"); - await page.$eval("#restaurant", el => el.value = "sample restaurant"); + describe("test create 1 new review", async () => { + it("create 1 new review", async () => { + // Click the button to create a new review + let create_btn = await page.$("#create-btn"); + await create_btn.click(); + await page.waitForNavigation(); - // Get the button needed to add new tags - let tag_btn = await page.$("#tag-add-btn"); - for(let i = 0; i < 5; i++){ - await page.$eval("#tag-form", (el, value) => el.value = `tag ${value}`, i); - await tag_btn.click(); - } + // create a new review + let review = { + imgAlt: "sample alt", + mealName: "sample name", + comments: "sample comment", + restaurant: "sample restaurant", + tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], + rating: 1 + }; + await setReviewForm(page, review); - // Select a new rating of 1 star - let rating_select = await page.$("#s1-select"); - await rating_select.click({delay: 100}); + // Click the save button to save updates + let save_btn = await page.$("#save-btn"); + await save_btn.click(); + await page.waitForNavigation(); + }); - // Click the save button to save updates - let save_btn = await page.$("#save-btn"); - await save_btn.click(); - await page.waitForNavigation(); + it("check details page", async () => { + // check the details page for correctness + let expected = { + imgSrc: "http://localhost:8080/assets/images/icons/plate_with_cutlery.png", + imgAlt: "sample alt", + mealName: "sample name", + comments: "sample comment", + restaurant: "sample restaurant", + tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], + rating: "http://localhost:8080/assets/images/icons/1-star.svg" + }; + await checkCorrectness(page, "d", expected); + }); + + it("check home page", async () => { + // Click the button to return to the home page + let home_btn = await page.$("#home-btn"); + home_btn.click(); + await page.waitForNavigation(); + + // Get the review card again and get its shadowRoot + let review_card = await page.$("review-card"); + let shadowRoot = await review_card.getProperty("shadowRoot"); + + let expected = { + imgSrc: "http://localhost:8080/assets/images/icons/plate_with_cutlery.png", + imgAlt: "sample alt", + mealName: "sample name", + comments: "sample comment", + restaurant: "sample restaurant", + tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], + rating: "http://localhost:8080/assets/images/icons/1-star.svg" + }; + await checkCorrectness(shadowRoot, "a", expected); + }); }); - it("check details page", async () => { - // Get the review image and check src and alt - let img = await page.$("#d-mealImg"); - let imgSrc = await img.getProperty("src"); - let imgAlt = await img.getProperty("alt"); - // Check src and alt - assert.strictEqual(await imgSrc.jsonValue(), "sample src"); - assert.strictEqual(await imgAlt.jsonValue(), "sample alt"); + describe("test read 1 review after refresh", async () => { + it("refresh page", async () => { + // Reload the page + await page.reload({ waitUntil: ["networkidle0", "domcontentloaded"] }); + }); - // Get the title, comment, and restaurant - let title = await page.$("#d-mealName"); - let title_text = await title.getProperty("innerText"); - let comment = await page.$("#d-comments"); - let comment_text = await comment.getProperty("innerText"); - let restaurant = await page.$("#d-restaurant"); - let restaurant_text = await restaurant.getProperty("innerText"); + it("check details page", async () => { + // click review card + let review_card = await page.$("review-card"); + await review_card.click(); + await page.waitForNavigation(); - // Check title, comment, and restaurant - assert.strictEqual(await title_text.jsonValue(), "sample name"); - assert.strictEqual(await comment_text.jsonValue(), "sample comment"); - assert.strictEqual(await restaurant_text.jsonValue(), "sample restaurant"); + // check the details page for correctness + let expected = { + imgSrc: "http://localhost:8080/assets/images/icons/plate_with_cutlery.png", + imgAlt: "sample alt", + mealName: "sample name", + comments: "sample comment", + restaurant: "sample restaurant", + tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], + rating: "http://localhost:8080/assets/images/icons/1-star.svg" + }; + await checkCorrectness(page, "d", expected); + }); - // Check tags - let tags = page.$(".tag"); - for(let i = 0; i < tags.length; i++){ - let tag_text = await tags[i].getProperty("innerText"); - assert.strictEqual(await tag_text.jsonValue(), `tag -${i}`); - } + it("check home page", async () => { + // Click the button to return to the home page + let home_btn = await page.$("#home-btn"); + home_btn.click(); + await page.waitForNavigation(); - // Check stars - let stars = await page.$("#d-rating"); - let stars_src = await stars.getProperty("src"); - assert.strictEqual(await stars_src.jsonValue(), "./assets/images/icons/5-star.svg"); - }); - - it("check home page", async () => { - // Click the button to return to the home page - let home_btn = await page.$("#home-btn"); - home_btn.click(); - await page.waitForNavigation(); + // Get the review card again and get its shadowRoot + let review_card = await page.$("review-card"); + let shadowRoot = await review_card.getProperty("shadowRoot"); - // Get the review card again and get its shadowRoot - let review_card = await page.$("review-card"); - let shadowRoot = await review_card.getProperty("shadowRoot"); - - // Get the review image and check src and alt - let img = await shadowRoot.$("#a-mealImg"); - let imgSrc = await img.getProperty("src"); - let imgAlt = await img.getProperty("alt"); - // Check src and alt - assert.strictEqual(await imgSrc.jsonValue(), "sample src"); - assert.strictEqual(await imgAlt.jsonValue(), "sample alt"); - - // Get the title, comment, and restaurant - let title = await shadowRoot.$("#a-mealName"); - let title_text = await title.getProperty("innerText"); - let comment = await shadowRoot.$("#a-comments"); - let comment_text = await comment.getProperty("innerText"); - let restaurant = await shadowRoot.$("#a-restaurant"); - let restaurant_text = await restaurant.getProperty("innerText"); - // Check title, comment, and restaurant - assert.strictEqual(await title_text.jsonValue(), "sample name"); - assert.strictEqual(await comment_text.jsonValue(), "sample comment"); - assert.strictEqual(await restaurant_text.jsonValue(), "sample restaurant"); - - // Check tags - let tags = shadowRoot.$(".tag"); - for(let i = 0; i < tags.length; i++){ - let tag_text = await tags[i].getProperty("innerText"); - assert.strictEqual(await tag_text.jsonValue(), `tag -${i}`); - } - - // Check stars - let stars = await shadowRoot.$("#a-rating"); - let stars_src = await stars.getProperty("src"); - assert.strictEqual(await stars_src.jsonValue(), "./assets/images/icons/5-star.svg"); - }); - }); - - describe("test read 1 review after refresh", async () => { - it("refresh page", async () => { - // Reload the page - await page.reload({ waitUntil: ["networkidle0", "domcontentloaded"] }); + // check the details page for correctness + let expected = { + imgSrc: "http://localhost:8080/assets/images/icons/plate_with_cutlery.png", + imgAlt: "sample alt", + mealName: "sample name", + comments: "sample comment", + restaurant: "sample restaurant", + tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], + rating: "http://localhost:8080/assets/images/icons/1-star.svg" + }; + await checkCorrectness(shadowRoot, "a", expected); + }); }); - it("check details page", async () => { - // click review card - let review_card = await page.$("review-card"); - console.log(JSON.stringify(review_card)); - await review_card.click(); - await page.waitForNavigation(); + describe("test update 1 review", async () => { - // Get the review image and check src and alt - let img = await page.$("#d-mealImg"); - let imgSrc = await img.getProperty("src"); - let imgAlt = await img.getProperty("alt"); - // Check src and alt - assert.strictEqual(await imgSrc.jsonValue(), "sample src"); - assert.strictEqual(await imgAlt.jsonValue(), "sample alt"); + it("update 1 review", async () => { - // Get the title, comment, and restaurant - let title = await page.$("#d-mealName"); - let title_text = await title.getProperty("innerText"); - let comment = await page.$("#d-comments"); - let comment_text = await comment.getProperty("innerText"); - let restaurant = await page.$("#d-restaurant"); - let restaurant_text = await restaurant.getProperty("innerText"); + // Get the only review card and click it + let review_card = await page.$("review-card"); + await review_card.click(); + await page.waitForNavigation(); - // Check title, comment, and restaurant - assert.strictEqual(await title_text.jsonValue(), "sample name"); - assert.strictEqual(await comment_text.jsonValue(), "sample comment"); - assert.strictEqual(await restaurant_text.jsonValue(), "sample restaurant"); + // Click the button to show update form + let update_btn = await page.$("#update-btn"); + await update_btn.click(); - // Check tags - let tags = page.$(".tag"); - for(let i = 0; i < tags.length; i++){ - let tag_text = await tags[i].getProperty("innerText"); - assert.strictEqual(await tag_text.jsonValue(), `tag -${i}`); - } + // create a new review + let review = { + imgAlt: "updated alt", + mealName: "updated name", + comments: "updated comment", + restaurant: "updated restaurant", + tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"], + rating: 5 + }; + await setReviewForm(page, review); + + // Click the save button to save updates + let save_btn = await page.$("#save-btn"); + await save_btn.click(); + await page.waitForNavigation(); + }); + + it("check details page", async () => { + // check the details page for correctness + let expected = { + imgSrc: "http://localhost:8080/assets/images/icons/plate_with_cutlery.png", + imgAlt: "updated alt", + mealName: "updated name", + comments: "updated comment", + restaurant: "updated restaurant", + tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"], + rating: "http://localhost:8080/assets/images/icons/5-star.svg" + }; + await checkCorrectness(page, "d", expected); + }); + + it("check home page", async () => { + // Click the button to return to the home page + let home_btn = await page.$("#home-btn"); + home_btn.click(); + await page.waitForNavigation(); + + // Get the review card again and get its shadowRoot + let review_card = await page.$("review-card"); + let shadowRoot = await review_card.getProperty("shadowRoot"); + + // check the details page for correctness + let expected = { + imgSrc: "http://localhost:8080/assets/images/icons/plate_with_cutlery.png", + imgAlt: "updated alt", + mealName: "updated name", + comments: "updated comment", + restaurant: "updated restaurant", + tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"], + rating: "http://localhost:8080/assets/images/icons/5-star.svg" + }; + await checkCorrectness(shadowRoot, "a", expected); + }); - // Check stars - let stars = await page.$("#d-rating"); - let stars_src = await stars.getProperty("src"); - assert.strictEqual(await stars_src.jsonValue(), "./assets/images/icons/5-star.svg"); }); - it("check home page", async () => { - // Click the button to return to the home page - let home_btn = await page.$("#home-btn"); - home_btn.click(); - await page.waitForNavigation(); + describe("test delete 1 review", async () => { + it("delete 1 review", async () => { + // Get the only review card and click it + let review_card = await page.$("review-card"); + await review_card.click(); + await page.waitForNavigation(); - // Get the review card again and get its shadowRoot - let review_card = await page.$("review-card"); - let shadowRoot = await review_card.getProperty("shadowRoot"); + page.on("dialog", async dialog => { + console.log(dialog.message()); + await dialog.accept(); + }); - // Get the review image and check src and alt - let img = await shadowRoot.$("#a-mealImg"); - let imgSrc = await img.getProperty("src"); - let imgAlt = await img.getProperty("alt"); - // Check src and alt - assert.strictEqual(await imgSrc.jsonValue(), "sample src"); - assert.strictEqual(await imgAlt.jsonValue(), "sample alt"); + // Get the delete button and click it + let delete_btn = await page.$("#delete-btn"); + await delete_btn.click(); + await page.waitForNavigation(); - // Get the title, comment, and restaurant - let title = await shadowRoot.$("#a-mealName"); - let title_text = await title.getProperty("innerText"); - let comment = await shadowRoot.$("#a-comments"); - let comment_text = await comment.getProperty("innerText"); - let restaurant = await shadowRoot.$("#a-restaurant"); - let restaurant_text = await restaurant.getProperty("innerText"); - // Check title, comment, and restaurant - assert.strictEqual(await title_text.jsonValue(), "sample name"); - assert.strictEqual(await comment_text.jsonValue(), "sample comment"); - assert.strictEqual(await restaurant_text.jsonValue(), "sample restaurant"); - - // Check tags - let tags = shadowRoot.$(".tag"); - for(let i = 0; i < tags.length; i++){ - let tag_text = await tags[i].getProperty("innerText"); - assert.strictEqual(await tag_text.jsonValue(), `tag -${i}`); - } - - // Check stars - let stars = await shadowRoot.$("#a-rating"); - let stars_src = await stars.getProperty("src"); - assert.strictEqual(await stars_src.jsonValue(), "./assets/images/icons/5-star.svg"); - }); - }); - - describe("test update 1 review", async () => { - - it("update 1 review", async () => { - - // Get the only review card and click it - let review_card = await page.$("review-card"); - console.log(JSON.stringify(review_card)); - await review_card.click(); - await page.waitForNavigation(); - - // Click the button to show update form - let update_btn = await page.$("#update-btn"); - await update_btn.click(); - - // Set text fields - await page.$eval("#mealImg", el => el.value = "updated src"); - await page.$eval("#imgAlt", el => el.value = "updated alt"); - await page.$eval("#mealName", el => el.value = "updated name"); - await page.$eval("#comments", el => el.value = "updated comment"); - await page.$eval("#restaurant", el => el.value = "updated restaurant"); - - // Get all tag elements and click them to delete them - let tag_items = await page.$$(".tag"); - for(let i = 0; i < tag_items.length; i++){ - await tag_items[i].click(); - } - - // Get the button needed to add new tags - let tag_btn = await page.$("#tag-add-btn"); - for(let i = 0; i < 5; i++){ - await page.$eval("#tag-form", (el, value) => el.value = `updated tag -${value}`, i); - await tag_btn.click(); - } - - // Select a new rating of 5 stars - let rating_select = await page.$("#s5-select"); - await rating_selects.click(); - - // Click the save button to save updates - let save_btn = await page.$("#save-btn"); - await save_btn.click(); - await page.waitForNavigation(); + // Check that the card was correctly removed (there should be no remaining cards) + review_card = await page.$("#review-card"); + assert.strictEqual(review_card, null); + }); }); - it("check details page", async () => { - // Get the review image and check src and alt - let img = await page.$("#d-mealImg"); - let imgSrc = await img.getProperty("src"); - let imgAlt = await img.getProperty("alt"); - // Check src and alt - assert.strictEqual(await imgSrc.jsonValue(), "updated src"); - assert.strictEqual(await imgAlt.jsonValue(), "updated alt"); - - // Get the title, comment, and restaurant - let title = await page.$("#d-mealName"); - let title_text = await title.getProperty("innerText"); - let comment = await page.$("#d-comments"); - let comment_text = await comment.getProperty("innerText"); - let restaurant = await page.$("#d-restaurant"); - let restaurant_text = await restaurant.getProperty("innerText"); - // Check title, comment, and restaurant - assert.strictEqual(await title_text.jsonValue(), "updated name"); - assert.strictEqual(await comment_text.jsonValue(), "updated comment"); - assert.strictEqual(await restaurant_text.jsonValue(), "updated restaurant"); - - // Check tags - let tags = page.$(".tag"); - for(let i = 0; i < tags.length; i++){ - let tag_text = await tags[i].getProperty("innerText"); - assert.strictEqual(await tag_text.jsonValue(), `updated tag -${i}`); - } - - // Check stars - let stars = await page.$("#d-rating"); - let stars_src = await stars.getProperty("src"); - assert.strictEqual(await stars_src.jsonValue(), "./assets/images/icons/1-star.svg"); - }); - - it("check home page", async () => { - // Click the button to return to the home page - let home_btn = await page.$("#home-btn"); - home_btn.click(); - await page.waitForNavigation(); - - // Get the review card again and get its shadowRoot - let review_card = await page.$("review-card"); - let shadowRoot = await review_card.getProperty("shadowRoot"); - - // Get the review image and check src and alt - let img = await shadowRoot.$("#a-mealImg"); - let imgSrc = await img.getProperty("src"); - let imgAlt = await img.getProperty("alt"); - // Check src and alt - assert.strictEqual(await imgSrc.jsonValue(), "updated src"); - assert.strictEqual(await imgAlt.jsonValue(), "updated alt"); - - // Get the title, comment, and restaurant - let title = await shadowRoot.$("#a-mealName"); - let title_text = await title.getProperty("innerText"); - let comment = await shadowRoot.$("#a-comments"); - let comment_text = await comment.getProperty("innerText"); - let restaurant = await shadowRoot.$("#a-restaurant"); - let restaurant_text = await restaurant.getProperty("innerText"); - // Check title, comment, and restaurant - assert.strictEqual(await title_text.jsonValue(), "updated name"); - assert.strictEqual(await comment_text.jsonValue(), "updated comment"); - assert.strictEqual(await restaurant_text.jsonValue(), "updated restaurant"); - - // Check tags - let tags = shadowRoot.$(".tag"); - for(let i = 0; i < tags.length; i++){ - let tag_text = await tags[i].getProperty("innerText"); - assert.strictEqual(await tag_text.jsonValue(), `tag -${i}`); - } - - // Check stars - let stars = await shadowRoot.$("#a-rating"); - let stars_src = await stars.getProperty("src"); - assert.strictEqual(await stars_src.jsonValue(), "./assets/images/icons/1-star.svg"); - }); - - }); - - describe("test delete 1 review", () => { - it("delete 1 review", async () => { - // Get the only review card and click it - let review_card = await page.$("review-card"); - await review_card.click(); - await page.waitForNavigation(); - - // Get the delete button and click it - let delete_btn = await page.$("#delete-btn"); - await delete_btn.click(); - await page.waitForNavigation(); - - // Check that the card was correctly removed (there should be no remaining cards) - review_card = await page.$("#review-card"); - assert.strictEqual(review_card, null); - }); }); after(async () => { diff --git a/source/assets/scripts/main.js b/source/assets/scripts/main.js index c402faf..38e182d 100644 --- a/source/assets/scripts/main.js +++ b/source/assets/scripts/main.js @@ -18,12 +18,12 @@ function init() { * @param {Array} reviews An array of reviews */ function addReviewsToDocument(reviews) { - let mainEl = document.querySelector("main"); + let box = document.getElementById("review-container"); reviews.forEach(review => { let newReview = document.createElement("review-card"); newReview.data = review; //TODO: want to append it to whatever the box is in layout - mainEl.append(newReview); + box.append(newReview); }); } diff --git a/source/index.html b/source/index.html index f273f02..f26633c 100644 --- a/source/index.html +++ b/source/index.html @@ -13,14 +13,39 @@ - + +
+ logo +

Food Journal

+
+ + +
+
+
+

Recent Reviews

+ CREATE + +
+
+
+
- + diff --git a/source/static/CreatePage.css b/source/static/CreatePage.css index c347a04..8d3a43e 100644 --- a/source/static/CreatePage.css +++ b/source/static/CreatePage.css @@ -1,83 +1,84 @@ /* CreatePage.css */ -* { - font-family: sans-serif; +body{ + background-color: #13323b; } -body { - height: 100%; - width: 100%; -} - -fieldset { - border: 2px solid rgb(214 214 214); - box-sizing: border-box; - display: block; - width: max-content; -} - -form button { - display: block; - margin-top: 5px; -} - -label[for="ingredients"] p { - margin: 0; -} - -label[for="numRatings"] { - margin: 10px 0 0; -} - -label[for^="rating"] { - padding-right: 10px; -} - -label:not([for^="rating"]) { - display: block; - margin-bottom: 5px; -} - -main { - column-gap: 10px; - display: flex; - flex-wrap: wrap; - height: auto; - max-width: 660px; - row-gap: 10px; - width: 100%; -} - -.tag-container { - display: flex; - flex-flow: row wrap; -} - -.tag { - background-color: grey; - border-radius: 7px; - color: white; - padding-right: 7px; - padding-left: 7px; - margin: 3px; -} - -.tag::before { - display: inline-block; - content: "x"; - height: 15px; - width: 15px; - margin-right: 4px; +h1 { text-align: center; - color: white; - cursor: pointer; +} +.Top-Bar{ + margin-top: -8cm; +} +.Top-Bar > img{ + position: relative; + top: 7.85cm; +} +.Top-Bar > h1{ + position: relative; + top: 2.2cm; + font-size: 3cm; + color: #EAA9BC + +} +.Top-Bar > form{ + position: relative; + left: 32cm; } -.tag:hover::before { - color: red; +.journal-form { + font-size: 120%; + width: 50%; + display: block; + margin: auto; + color: #ccb3bb; + border: 3px solid rgb(7, 0, 0); + background-color: #b52754; } -.danger { - background-color: rgb(254 171 171); - border-color: red; +.hidden, +.rating:not(:checked) > input { /* Hide radio circles while star rating */ + display: none; } + +/* Unchecked stars */ +.rating:not(:checked) > label { + /* Make stars line up sideways and not vertically */ + float: right; + + /* Hide label text */ + width: 1em; + overflow: hidden; + white-space: nowrap; + + /* Star default color and size */ + font-size: 200%; + line-height: 1.2; + color: #b3b3cc; +} + +.rating > label:active { + position: relative; +} + +.rating:not(:checked) > label::before { + content: "★"; +} + +/* Checked star color */ +.rating > input:checked ~ label { + color: #ffbf00; +} + +.rating:not(:checked) > label:hover, +.rating:not(:checked) > label:hover ~ label { + color: orangered; +} + +.rating > input:checked + label:hover, +.rating > input:checked ~ label:hover, +.rating > input:checked + label:hover ~ label, +.rating > input:checked ~ label:hover ~ label, +.rating > label:hover ~ input:checked ~ label { + color: orangered; +} \ No newline at end of file diff --git a/source/static/homepage.css b/source/static/homepage.css new file mode 100644 index 0000000..1aae749 --- /dev/null +++ b/source/static/homepage.css @@ -0,0 +1,65 @@ +/* homepage.css */ +/* Color*/ +body{ + background-color: #13323b; +} +.Top-Bar{ + margin-top: -8cm; +} +.Top-Bar > img{ + position: relative; + top: 7.5cm; +} +.Top-Bar > h1{ + position: relative; + left: 10.5cm; + top: 2.2cm; + font-size: 3cm; + color: #EAA9BC; + +} +.Top-Bar > form{ + position: relative; + left: 32cm; +} +.Review-boxes { + position: relative; +} + +.Review-boxes > h2 { + position: relative; + left: 10cm; + font-size: 1.5cm; + color: #EAA9BC; +} +.Review-boxes > input { + position: relative; + left: 20.34cm; + top: -3.5cm; +} + +.Filter-box{ + width:300px; + height:700px; + background: #8D4E62; + position: relative; + left: 29.5cm; + top: -5.5cm; +} +.review-container{ + display: flex; + position: relative; + top: -22cm; + left: 5cm; + max-width: 900px; + flex-wrap: wrap; +} +.review-container > div { + background-color: #f1f1f1; + width: 200px; + height: 200px; + margin: 10px; + text-align: center; + line-height: 75px; + font-size: 30px; + } \ No newline at end of file diff --git a/specs/adrs/111422-csslinting-stylelint.md b/specs/adrs/111422-csslinting-stylelint.md new file mode 100644 index 0000000..d35b025 --- /dev/null +++ b/specs/adrs/111422-csslinting-stylelint.md @@ -0,0 +1,19 @@ +# Use Stylelint for CSS linting framework + +- Status: accept +- Deciders: Arthur Lu, Marc Reta +- Date: 11 / 14 / 22 + +## Decision Drivers + +- Need linting to work with multiple style standards +- Need linting to be fast and informative + +## Considered Options + +- Stylelint +- Prettier + +## Decision Outcome + +Chosen Option: Stylelint for its easy installation and unopinionated. diff --git a/specs/adrs/111422-htmllinting-htmlhint.md b/specs/adrs/111422-htmllinting-htmlhint.md new file mode 100644 index 0000000..0bd3471 --- /dev/null +++ b/specs/adrs/111422-htmllinting-htmlhint.md @@ -0,0 +1,19 @@ +# Use HTMLhint for HTML linting framework + +- Status: accept +- Deciders: Arthur Lu, Marc Reta +- Date: 11 / 14 / 22 + +## Decision Drivers + +- Need linting to work with multiple style standards +- Need linting to be fast and informative + +## Considered Options + +- HTMLhint +- HTML-validate + +## Decision Outcome + +Chosen Option: HTMLhint for its low configuration complexity.