From c351e050228688ebdb6257f8f07bc0f201ac7529 Mon Sep 17 00:00:00 2001 From: Jane Moroz Date: Tue, 29 Aug 2023 14:03:38 +0300 Subject: [PATCH 001/127] feat: add "my team" table --- src/app/myteam/components/TeamRow.tsx | 31 ++++++++++ src/app/myteam/components/TeamTable.css | 11 ++++ src/app/myteam/components/TeamTable.tsx | 75 +++++++++++++++++++++++++ src/app/myteam/components/index.ts | 2 + src/app/myteam/index.ts | 1 + src/app/myteam/page.tsx | 7 +++ 6 files changed, 127 insertions(+) create mode 100644 src/app/myteam/components/TeamRow.tsx create mode 100644 src/app/myteam/components/TeamTable.css create mode 100644 src/app/myteam/components/TeamTable.tsx create mode 100644 src/app/myteam/components/index.ts create mode 100644 src/app/myteam/index.ts create mode 100644 src/app/myteam/page.tsx diff --git a/src/app/myteam/components/TeamRow.tsx b/src/app/myteam/components/TeamRow.tsx new file mode 100644 index 00000000..4a2ee296 --- /dev/null +++ b/src/app/myteam/components/TeamRow.tsx @@ -0,0 +1,31 @@ +import React from "react"; + +interface TeamMember { + name: string; + discordId: string; + averageHour: number; + location: string; + timeZone: string; + email: string; + position: string; +} + +interface TeamRowProps { + teamMemeber: TeamMember; +} + +function TeamRow({ teamMemeber }: TeamRowProps) { + return ( + + {teamMemeber.name} + {teamMemeber.discordId} + {teamMemeber.averageHour} + {teamMemeber.location} + {teamMemeber.timeZone} + {teamMemeber.email} + {teamMemeber.position} + + ); +} + +export default TeamRow; diff --git a/src/app/myteam/components/TeamTable.css b/src/app/myteam/components/TeamTable.css new file mode 100644 index 00000000..d372f08a --- /dev/null +++ b/src/app/myteam/components/TeamTable.css @@ -0,0 +1,11 @@ +.table { + @apply border-separate; +} + +.table :where(thead, tbody) :where(tr:not(:last-child)), .table :where(thead, tbody) :where(tr:first-child:last-child) { + @apply border-none; +} + +.table :where(thead) { + @apply mb-10; +} \ No newline at end of file diff --git a/src/app/myteam/components/TeamTable.tsx b/src/app/myteam/components/TeamTable.tsx new file mode 100644 index 00000000..ec568bd7 --- /dev/null +++ b/src/app/myteam/components/TeamTable.tsx @@ -0,0 +1,75 @@ +import "./TeamTable.css"; + +import { TeamRow } from "."; + +const data = [ + { + id: "1", + name: "Danney Trieu", + discordId: "danneytrieuwork#2558", + averageHour: 10, + location: "Denver, CO, USA", + timeZone: "MDT", + email: "danney@gmail.com", + position: "Product Owner", + }, + { + id: "2", + name: "Jane Morez", + discordId: "Jan_morez#2341", + averageHour: 15, + location: "Las Vegas, NY, USA", + timeZone: "PDT", + email: "jane@gmail.com", + position: "Back-end Developer", + }, + { + id: "3", + name: "Kayla Montre", + discordId: "KaylaMon#5678", + averageHour: 12, + location: "Las Vegas, NY, USA", + timeZone: "PDT", + email: "kayla@gmail.com", + position: "UX/UI Designer", + }, + { + id: "4", + name: "Jackson Pez", + discordId: "jackson#2558", + averageHour: 10, + location: "Denver, CO, USA", + timeZone: "MDT", + email: "jackson@gmail.com", + position: "Front-end Developer", + }, +]; + +function TeamTable() { + return ( +
+ + {/* head */} + + + + + + + + + + + + + {/* rows */} + {data.map((teamMemeber) => ( + + ))} + +
NameDiscord IDAverage Hour/SprintLocationTime ZoneEmailPosition
+
+ ); +} + +export default TeamTable; diff --git a/src/app/myteam/components/index.ts b/src/app/myteam/components/index.ts new file mode 100644 index 00000000..2e1afbb7 --- /dev/null +++ b/src/app/myteam/components/index.ts @@ -0,0 +1,2 @@ +export { default as TeamTable } from "./TeamTable"; +export { default as TeamRow } from "./TeamRow"; diff --git a/src/app/myteam/index.ts b/src/app/myteam/index.ts new file mode 100644 index 00000000..5a517cce --- /dev/null +++ b/src/app/myteam/index.ts @@ -0,0 +1 @@ +export { default as MyTeamPage } from "./page"; diff --git a/src/app/myteam/page.tsx b/src/app/myteam/page.tsx new file mode 100644 index 00000000..b4921ada --- /dev/null +++ b/src/app/myteam/page.tsx @@ -0,0 +1,7 @@ +import { TeamTable } from "./components"; + +function MyTeamPage() { + return ; +} + +export default MyTeamPage; From 2776ae044d63b72fa9e15755e80a1ebbddd14183 Mon Sep 17 00:00:00 2001 From: Jane Moroz Date: Fri, 1 Sep 2023 10:53:36 +0300 Subject: [PATCH 002/127] style: remove unnecessary style file --- src/app/myteam/components/TeamTable.css | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 src/app/myteam/components/TeamTable.css diff --git a/src/app/myteam/components/TeamTable.css b/src/app/myteam/components/TeamTable.css deleted file mode 100644 index d372f08a..00000000 --- a/src/app/myteam/components/TeamTable.css +++ /dev/null @@ -1,11 +0,0 @@ -.table { - @apply border-separate; -} - -.table :where(thead, tbody) :where(tr:not(:last-child)), .table :where(thead, tbody) :where(tr:first-child:last-child) { - @apply border-none; -} - -.table :where(thead) { - @apply mb-10; -} \ No newline at end of file From dbb67eff996d1050cef277cd1aaec70828c4f0fa Mon Sep 17 00:00:00 2001 From: Jane Moroz Date: Fri, 1 Sep 2023 10:55:09 +0300 Subject: [PATCH 003/127] feat: move data to 'fixture' folder --- src/app/myteam/components/TeamRow.tsx | 12 +---- src/app/myteam/components/TeamTable.tsx | 52 ++----------------- src/app/myteam/components/fixtures/MyTeam.ts | 53 ++++++++++++++++++++ 3 files changed, 58 insertions(+), 59 deletions(-) create mode 100644 src/app/myteam/components/fixtures/MyTeam.ts diff --git a/src/app/myteam/components/TeamRow.tsx b/src/app/myteam/components/TeamRow.tsx index 4a2ee296..50113581 100644 --- a/src/app/myteam/components/TeamRow.tsx +++ b/src/app/myteam/components/TeamRow.tsx @@ -1,14 +1,4 @@ -import React from "react"; - -interface TeamMember { - name: string; - discordId: string; - averageHour: number; - location: string; - timeZone: string; - email: string; - position: string; -} +import { TeamMember } from "./fixtures/MyTeam"; interface TeamRowProps { teamMemeber: TeamMember; diff --git a/src/app/myteam/components/TeamTable.tsx b/src/app/myteam/components/TeamTable.tsx index ec568bd7..42b19a2d 100644 --- a/src/app/myteam/components/TeamTable.tsx +++ b/src/app/myteam/components/TeamTable.tsx @@ -1,56 +1,12 @@ -import "./TeamTable.css"; - +import { teamMembers } from "./fixtures/MyTeam"; import { TeamRow } from "."; -const data = [ - { - id: "1", - name: "Danney Trieu", - discordId: "danneytrieuwork#2558", - averageHour: 10, - location: "Denver, CO, USA", - timeZone: "MDT", - email: "danney@gmail.com", - position: "Product Owner", - }, - { - id: "2", - name: "Jane Morez", - discordId: "Jan_morez#2341", - averageHour: 15, - location: "Las Vegas, NY, USA", - timeZone: "PDT", - email: "jane@gmail.com", - position: "Back-end Developer", - }, - { - id: "3", - name: "Kayla Montre", - discordId: "KaylaMon#5678", - averageHour: 12, - location: "Las Vegas, NY, USA", - timeZone: "PDT", - email: "kayla@gmail.com", - position: "UX/UI Designer", - }, - { - id: "4", - name: "Jackson Pez", - discordId: "jackson#2558", - averageHour: 10, - location: "Denver, CO, USA", - timeZone: "MDT", - email: "jackson@gmail.com", - position: "Front-end Developer", - }, -]; - function TeamTable() { return (
- +
{/* head */} - + @@ -63,7 +19,7 @@ function TeamTable() { {/* rows */} - {data.map((teamMemeber) => ( + {teamMembers.map((teamMemeber) => ( ))} diff --git a/src/app/myteam/components/fixtures/MyTeam.ts b/src/app/myteam/components/fixtures/MyTeam.ts new file mode 100644 index 00000000..5982bc79 --- /dev/null +++ b/src/app/myteam/components/fixtures/MyTeam.ts @@ -0,0 +1,53 @@ +export interface TeamMember { + id: string; + name: string; + discordId: string; + averageHour: number; + location: string; + timeZone: string; + email: string; + position: string; +} + +export const teamMembers: TeamMember[] = [ + { + id: "1", + name: "Danney Trieu", + discordId: "danneytrieuwork#2558", + averageHour: 10, + location: "Denver, CO, USA", + timeZone: "MDT", + email: "danney@gmail.com", + position: "Product Owner", + }, + { + id: "2", + name: "Jane Morez", + discordId: "Jan_morez#2341", + averageHour: 15, + location: "Las Vegas, NY, USA", + timeZone: "PDT", + email: "jane@gmail.com", + position: "Back-end Developer", + }, + { + id: "3", + name: "Kayla Montre", + discordId: "KaylaMon#5678", + averageHour: 12, + location: "Las Vegas, NY, USA", + timeZone: "PDT", + email: "kayla@gmail.com", + position: "UX/UI Designer", + }, + { + id: "4", + name: "Jackson Pez", + discordId: "jackson#2558", + averageHour: 10, + location: "Denver, CO, USA", + timeZone: "MDT", + email: "jackson@gmail.com", + position: "Front-end Developer", + }, +]; From 9bbc2a626c8afd77f9c0aa28ba18d240ba91d398 Mon Sep 17 00:00:00 2001 From: Jane Moroz Date: Fri, 1 Sep 2023 11:00:09 +0300 Subject: [PATCH 004/127] style: fix colors --- src/app/myteam/components/TeamRow.tsx | 2 +- src/app/myteam/components/TeamTable.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/myteam/components/TeamRow.tsx b/src/app/myteam/components/TeamRow.tsx index 50113581..e560457c 100644 --- a/src/app/myteam/components/TeamRow.tsx +++ b/src/app/myteam/components/TeamRow.tsx @@ -7,7 +7,7 @@ interface TeamRowProps { function TeamRow({ teamMemeber }: TeamRowProps) { return ( - + diff --git a/src/app/myteam/components/TeamTable.tsx b/src/app/myteam/components/TeamTable.tsx index 42b19a2d..a4f42f20 100644 --- a/src/app/myteam/components/TeamTable.tsx +++ b/src/app/myteam/components/TeamTable.tsx @@ -4,9 +4,9 @@ import { TeamRow } from "."; function TeamTable() { return (
-
Name Discord ID
{teamMemeber.name}{teamMemeber.name} {teamMemeber.discordId} {teamMemeber.averageHour} {teamMemeber.location}
+
{/* head */} - + @@ -17,7 +17,7 @@ function TeamTable() { - + {/* rows */} {teamMembers.map((teamMemeber) => ( From bf92d96c62497b4238c82deb57e850861284c5e2 Mon Sep 17 00:00:00 2001 From: Timothy Russo Date: Tue, 5 Sep 2023 12:55:35 +0200 Subject: [PATCH 005/127] feat: folder structure --- src/app/sidebar/components/Sidebar.tsx | 0 src/app/sidebar/index.ts | 0 src/app/sidebar/page.tsx | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/app/sidebar/components/Sidebar.tsx create mode 100644 src/app/sidebar/index.ts create mode 100644 src/app/sidebar/page.tsx diff --git a/src/app/sidebar/components/Sidebar.tsx b/src/app/sidebar/components/Sidebar.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/sidebar/index.ts b/src/app/sidebar/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/app/sidebar/page.tsx b/src/app/sidebar/page.tsx new file mode 100644 index 00000000..e69de29b From c9e648a64601277c959e60d023f5148716ccfdab Mon Sep 17 00:00:00 2001 From: Timothy Russo Date: Wed, 6 Sep 2023 08:59:55 +0200 Subject: [PATCH 006/127] feat: add basic sidebar --- src/app/sidebar/components/Sidebar.tsx | 32 ++++++++++++++++++++++++++ src/app/sidebar/components/index.ts | 0 2 files changed, 32 insertions(+) create mode 100644 src/app/sidebar/components/index.ts diff --git a/src/app/sidebar/components/Sidebar.tsx b/src/app/sidebar/components/Sidebar.tsx index e69de29b..7d781249 100644 --- a/src/app/sidebar/components/Sidebar.tsx +++ b/src/app/sidebar/components/Sidebar.tsx @@ -0,0 +1,32 @@ +import { ArrowRightOnRectangleIcon, ArrowLeftOnRectangleIcon } from "@heroicons/react/24/solid"; + +export default function Sidebar() { + return ( +
+ +
+ {/* Page content here */} +
+ +
+
+
+ + +
+
+ ); +} diff --git a/src/app/sidebar/components/index.ts b/src/app/sidebar/components/index.ts new file mode 100644 index 00000000..e69de29b From 005d147142f520ad345e138e772919174d645f30 Mon Sep 17 00:00:00 2001 From: Timothy Russo Date: Wed, 6 Sep 2023 09:09:38 +0200 Subject: [PATCH 007/127] feat: update file structure --- src/app/sidebar/components/Sidebar.tsx | 6 ++++-- src/app/sidebar/components/index.ts | 1 + src/app/sidebar/index.ts | 1 + src/app/sidebar/page.tsx | 5 +++++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/app/sidebar/components/Sidebar.tsx b/src/app/sidebar/components/Sidebar.tsx index 7d781249..096d6f96 100644 --- a/src/app/sidebar/components/Sidebar.tsx +++ b/src/app/sidebar/components/Sidebar.tsx @@ -1,4 +1,7 @@ -import { ArrowRightOnRectangleIcon, ArrowLeftOnRectangleIcon } from "@heroicons/react/24/solid"; +import { + ArrowRightOnRectangleIcon, + ArrowLeftOnRectangleIcon, +} from "@heroicons/react/24/solid"; export default function Sidebar() { return ( @@ -25,7 +28,6 @@ export default function Sidebar() { Sidebar Item 2 - ); diff --git a/src/app/sidebar/components/index.ts b/src/app/sidebar/components/index.ts index e69de29b..c3c64060 100644 --- a/src/app/sidebar/components/index.ts +++ b/src/app/sidebar/components/index.ts @@ -0,0 +1 @@ +export { default as Sidebar } from "./Sidebar"; diff --git a/src/app/sidebar/index.ts b/src/app/sidebar/index.ts index e69de29b..df9f273f 100644 --- a/src/app/sidebar/index.ts +++ b/src/app/sidebar/index.ts @@ -0,0 +1 @@ +export { default as SidebarPage } from "./page"; diff --git a/src/app/sidebar/page.tsx b/src/app/sidebar/page.tsx index e69de29b..18d74e5e 100644 --- a/src/app/sidebar/page.tsx +++ b/src/app/sidebar/page.tsx @@ -0,0 +1,5 @@ +import { Sidebar } from "./components"; + +export default function SidebarPage() { + return ; +} From 022bebfa6d2d28c093fce43ccf9960144a4abac5 Mon Sep 17 00:00:00 2001 From: Jane Moroz Date: Wed, 6 Sep 2023 12:01:09 +0300 Subject: [PATCH 008/127] fix: rename folder 'myteam' to 'my-team' --- src/app/{myteam => my-team}/components/TeamRow.tsx | 0 src/app/{myteam => my-team}/components/TeamTable.tsx | 0 src/app/{myteam => my-team}/components/fixtures/MyTeam.ts | 0 src/app/{myteam => my-team}/components/index.ts | 0 src/app/{myteam => my-team}/index.ts | 0 src/app/{myteam => my-team}/page.tsx | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename src/app/{myteam => my-team}/components/TeamRow.tsx (100%) rename src/app/{myteam => my-team}/components/TeamTable.tsx (100%) rename src/app/{myteam => my-team}/components/fixtures/MyTeam.ts (100%) rename src/app/{myteam => my-team}/components/index.ts (100%) rename src/app/{myteam => my-team}/index.ts (100%) rename src/app/{myteam => my-team}/page.tsx (100%) diff --git a/src/app/myteam/components/TeamRow.tsx b/src/app/my-team/components/TeamRow.tsx similarity index 100% rename from src/app/myteam/components/TeamRow.tsx rename to src/app/my-team/components/TeamRow.tsx diff --git a/src/app/myteam/components/TeamTable.tsx b/src/app/my-team/components/TeamTable.tsx similarity index 100% rename from src/app/myteam/components/TeamTable.tsx rename to src/app/my-team/components/TeamTable.tsx diff --git a/src/app/myteam/components/fixtures/MyTeam.ts b/src/app/my-team/components/fixtures/MyTeam.ts similarity index 100% rename from src/app/myteam/components/fixtures/MyTeam.ts rename to src/app/my-team/components/fixtures/MyTeam.ts diff --git a/src/app/myteam/components/index.ts b/src/app/my-team/components/index.ts similarity index 100% rename from src/app/myteam/components/index.ts rename to src/app/my-team/components/index.ts diff --git a/src/app/myteam/index.ts b/src/app/my-team/index.ts similarity index 100% rename from src/app/myteam/index.ts rename to src/app/my-team/index.ts diff --git a/src/app/myteam/page.tsx b/src/app/my-team/page.tsx similarity index 100% rename from src/app/myteam/page.tsx rename to src/app/my-team/page.tsx From 800484894e6e35660e3ed24c9406e8d327749fed Mon Sep 17 00:00:00 2001 From: Jane Moroz Date: Wed, 6 Sep 2023 12:31:42 +0300 Subject: [PATCH 009/127] fix: fix eslint error --- src/app/tech-stack/components/TechStackContainer.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/app/tech-stack/components/TechStackContainer.tsx b/src/app/tech-stack/components/TechStackContainer.tsx index 97e0e6d6..44bad1f4 100644 --- a/src/app/tech-stack/components/TechStackContainer.tsx +++ b/src/app/tech-stack/components/TechStackContainer.tsx @@ -4,8 +4,10 @@ import { TechStackCard } from "."; export default function TechStackContainer() { return ( -
-
    +
    +
      {Object.keys(techStack).map((cardType, index) => (
    • Date: Wed, 6 Sep 2023 12:48:15 +0300 Subject: [PATCH 010/127] style: use colors from tailwind config --- src/app/globals.css | 1 + src/app/my-team/components/TeamTable.tsx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index cc294bc0..273d332d 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -5,6 +5,7 @@ ::-webkit-scrollbar { width: 4px; + height: 6px } ::-webkit-scrollbar-track { diff --git a/src/app/my-team/components/TeamTable.tsx b/src/app/my-team/components/TeamTable.tsx index a4f42f20..81cd1dc1 100644 --- a/src/app/my-team/components/TeamTable.tsx +++ b/src/app/my-team/components/TeamTable.tsx @@ -3,8 +3,8 @@ import { TeamRow } from "."; function TeamTable() { return ( -
      -
Name Discord IDPosition
+
+
{/* head */} From 390b6681e94b02d3aab18d2f17392e5c3f3c73c9 Mon Sep 17 00:00:00 2001 From: Jane Moroz Date: Wed, 6 Sep 2023 13:48:26 +0300 Subject: [PATCH 011/127] feat: add "Edit" button --- src/app/my-team/components/TeamRow.tsx | 19 ++++++++++++++++++- src/app/my-team/components/TeamTable.tsx | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/app/my-team/components/TeamRow.tsx b/src/app/my-team/components/TeamRow.tsx index e560457c..f7f4cd59 100644 --- a/src/app/my-team/components/TeamRow.tsx +++ b/src/app/my-team/components/TeamRow.tsx @@ -1,4 +1,9 @@ +import { PencilSquareIcon } from "@heroicons/react/24/solid"; import { TeamMember } from "./fixtures/MyTeam"; +import { Button } from "@/components"; + +// Temp: +const currentUserId = "1"; interface TeamRowProps { teamMemeber: TeamMember; @@ -9,7 +14,19 @@ function TeamRow({ teamMemeber }: TeamRowProps) { - + diff --git a/src/app/my-team/components/TeamTable.tsx b/src/app/my-team/components/TeamTable.tsx index 81cd1dc1..50abf626 100644 --- a/src/app/my-team/components/TeamTable.tsx +++ b/src/app/my-team/components/TeamTable.tsx @@ -3,7 +3,7 @@ import { TeamRow } from "."; function TeamTable() { return ( -
+
{teamMemeber.name} {teamMemeber.discordId}{teamMemeber.averageHour} +
+ {teamMemeber.averageHour} + {teamMemeber.id === currentUserId && ( + + )} +
+
{teamMemeber.location} {teamMemeber.timeZone} {teamMemeber.email}
{/* head */} From 6ec6fae14813c8206c9a9f0ba2d48dc6ad703cda Mon Sep 17 00:00:00 2001 From: Jane Moroz Date: Thu, 7 Sep 2023 13:35:13 +0300 Subject: [PATCH 012/127] fix: move temp variable to TeamTable --- src/app/my-team/components/TeamRow.tsx | 8 +++----- src/app/my-team/components/TeamTable.tsx | 9 ++++++++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/app/my-team/components/TeamRow.tsx b/src/app/my-team/components/TeamRow.tsx index f7f4cd59..764c6ce3 100644 --- a/src/app/my-team/components/TeamRow.tsx +++ b/src/app/my-team/components/TeamRow.tsx @@ -2,14 +2,12 @@ import { PencilSquareIcon } from "@heroicons/react/24/solid"; import { TeamMember } from "./fixtures/MyTeam"; import { Button } from "@/components"; -// Temp: -const currentUserId = "1"; - interface TeamRowProps { teamMemeber: TeamMember; + currentUserId: string; } -function TeamRow({ teamMemeber }: TeamRowProps) { +function TeamRow({ teamMemeber, currentUserId }: TeamRowProps) { return ( @@ -20,7 +18,7 @@ function TeamRow({ teamMemeber }: TeamRowProps) { {teamMemeber.id === currentUserId && ( diff --git a/src/app/my-team/components/TeamTable.tsx b/src/app/my-team/components/TeamTable.tsx index 50abf626..aa526e4d 100644 --- a/src/app/my-team/components/TeamTable.tsx +++ b/src/app/my-team/components/TeamTable.tsx @@ -1,6 +1,9 @@ import { teamMembers } from "./fixtures/MyTeam"; import { TeamRow } from "."; +// Temp: +const currentUserId = "1"; + function TeamTable() { return (
@@ -20,7 +23,11 @@ function TeamTable() {
{/* rows */} {teamMembers.map((teamMemeber) => ( - + ))}
{teamMemeber.name}
From 62d7c774327e8f687e538289ec36ac6996511b66 Mon Sep 17 00:00:00 2001 From: Jane Moroz Date: Thu, 7 Sep 2023 13:46:21 +0300 Subject: [PATCH 013/127] fix: fix typo --- src/app/my-team/components/TeamRow.tsx | 20 ++++++++++---------- src/app/my-team/components/TeamTable.tsx | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/app/my-team/components/TeamRow.tsx b/src/app/my-team/components/TeamRow.tsx index 764c6ce3..87670637 100644 --- a/src/app/my-team/components/TeamRow.tsx +++ b/src/app/my-team/components/TeamRow.tsx @@ -3,19 +3,19 @@ import { TeamMember } from "./fixtures/MyTeam"; import { Button } from "@/components"; interface TeamRowProps { - teamMemeber: TeamMember; + teamMember: TeamMember; currentUserId: string; } -function TeamRow({ teamMemeber, currentUserId }: TeamRowProps) { +function TeamRow({ teamMember, currentUserId }: TeamRowProps) { return ( - {teamMemeber.name} - {teamMemeber.discordId} + {teamMember.name} + {teamMember.discordId}
- {teamMemeber.averageHour} - {teamMemeber.id === currentUserId && ( + {teamMember.averageHour} + {teamMember.id === currentUserId && ( diff --git a/src/app/directory/components/fixtures/MyTeam.ts b/src/app/directory/components/fixtures/MyTeam.ts index 5982bc79..297d2e56 100644 --- a/src/app/directory/components/fixtures/MyTeam.ts +++ b/src/app/directory/components/fixtures/MyTeam.ts @@ -14,7 +14,7 @@ export const teamMembers: TeamMember[] = [ id: "1", name: "Danney Trieu", discordId: "danneytrieuwork#2558", - averageHour: 10, + averageHour: 0, location: "Denver, CO, USA", timeZone: "MDT", email: "danney@gmail.com", @@ -24,7 +24,7 @@ export const teamMembers: TeamMember[] = [ id: "2", name: "Jane Morez", discordId: "Jan_morez#2341", - averageHour: 15, + averageHour: 0, location: "Las Vegas, NY, USA", timeZone: "PDT", email: "jane@gmail.com", From 3c6ab074fee9764979c8acd1d2ae58010158ea48 Mon Sep 17 00:00:00 2001 From: Dan Ko Date: Sat, 9 Sep 2023 03:12:37 -0400 Subject: [PATCH 026/127] remove object curly newline eslint rule to resolve issue with prettier formatting --- .eslintrc.json | 72 +++++++++++++++++++++++++++++++-------- src/components/Banner.tsx | 2 -- 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index d26019a2..033991d5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -8,7 +8,10 @@ "ecmaVersion": "latest", "sourceType": "module" }, - "plugins": ["@typescript-eslint", "import"], + "plugins": [ + "@typescript-eslint", + "import" + ], "extends": [ "plugin:import/recommended", "plugin:import/typescript", @@ -28,19 +31,32 @@ "error", { "selector": "interface", - "format": ["PascalCase"] + "format": [ + "PascalCase" + ] } ], "react/function-component-definition": [ 2, - { "namedComponents": "function-declaration" } + { + "namedComponents": "function-declaration" + } + ], + "react/destructuring-assignment": [ + 2, + "always" ], - "react/destructuring-assignment": [2, "always"], "react/button-has-type": 2, "react/no-array-index-key": 2, "import/order": 2, - "semi": [2, "always"], - "quotes": [2, "double"], + "semi": [ + 2, + "always" + ], + "quotes": [ + 2, + "double" + ], "prefer-destructuring": [ 2, { @@ -57,19 +73,45 @@ "enforceForRenamedProperties": false } ], - "object-curly-spacing": [2, "always"], - "arrow-body-style": [2, "as-needed"], - "arrow-parens": [2, "always"], + "object-curly-spacing": [ + 2, + "always" + ], + "arrow-body-style": [ + 2, + "as-needed" + ], + "arrow-parens": [ + 2, + "always" + ], "space-infix-ops": 2, - "arrow-spacing": [2, { "before": true, "after": true }], - "no-unused-vars": [2, { "args": "all", "argsIgnorePattern": "_" }], + "arrow-spacing": [ + 2, + { + "before": true, + "after": true + } + ], + "no-unused-vars": [ + 2, + { + "args": "all", + "argsIgnorePattern": "_" + } + ], "guard-for-in": 2, "no-await-in-loop": 2, - "indent": [2, 2], - "object-curly-newline": [2, { "minProperties": 4, "consistent": true }], + "indent": [ + 2, + 2 + ], "brace-style": 2, "no-multiple-empty-lines": 2, - "eol-last": [2, "always"], + "eol-last": [ + 2, + "always" + ], "no-nested-ternary": 2 } -} +} \ No newline at end of file diff --git a/src/components/Banner.tsx b/src/components/Banner.tsx index 023c7022..3d03615d 100644 --- a/src/components/Banner.tsx +++ b/src/components/Banner.tsx @@ -7,8 +7,6 @@ interface BannerProps { description: string; } -// eslint and prettier conflicting again. object-curly-newline -// eslint-disable-next-line function Banner({ image, alt, title, description }: BannerProps) { return (
From 8a26d1eb218921cd8e7a450084b4904cc9e9b26a Mon Sep 17 00:00:00 2001 From: Mark Linn Date: Sat, 9 Sep 2023 10:01:55 +0200 Subject: [PATCH 027/127] trial workflow --- .github/workflows/preview.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 56c484af..7918c2fa 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -6,7 +6,7 @@ on: workflow_dispatch: push: branches: - - premium-strip + [main, dev] jobs: deploy: From dd62b155335098f2473eca0b83a874e7e9a28e5e Mon Sep 17 00:00:00 2001 From: Jane Moroz Date: Sat, 9 Sep 2023 14:01:08 +0300 Subject: [PATCH 028/127] style: change row gap --- src/app/directory/components/TeamRow.module.css | 7 +++++++ src/app/directory/components/TeamTable.tsx | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 src/app/directory/components/TeamRow.module.css diff --git a/src/app/directory/components/TeamRow.module.css b/src/app/directory/components/TeamRow.module.css new file mode 100644 index 00000000..e23e65e9 --- /dev/null +++ b/src/app/directory/components/TeamRow.module.css @@ -0,0 +1,7 @@ +.table :where(td) { + @apply py-1; +} + +.table :where(th) { + @apply pb-6; +} \ No newline at end of file diff --git a/src/app/directory/components/TeamTable.tsx b/src/app/directory/components/TeamTable.tsx index 87722bab..636991f3 100644 --- a/src/app/directory/components/TeamTable.tsx +++ b/src/app/directory/components/TeamTable.tsx @@ -1,3 +1,4 @@ +import styles from "./TeamRow.module.css"; import { teamMembers } from "./fixtures/MyTeam"; import { TeamRow } from "."; @@ -7,7 +8,9 @@ const currentUserId = "1"; function TeamTable() { return (
- +
{/* head */} From 254f3a9e5ed6754341f9a76d062358eec4bd5198 Mon Sep 17 00:00:00 2001 From: Mark Linn Date: Sat, 9 Sep 2023 13:17:40 +0200 Subject: [PATCH 029/127] add: run workflow on pr --- .github/workflows/preview.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 7918c2fa..9ec6ab12 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -3,10 +3,9 @@ env: VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} on: - workflow_dispatch: - push: + pull_request: branches: - [main, dev] + - dev jobs: deploy: From 4ba6c6e1a59483b61356f3722b6902a8420ae6fc Mon Sep 17 00:00:00 2001 From: Mark Linn Date: Sat, 9 Sep 2023 13:18:55 +0200 Subject: [PATCH 030/127] chore: remove vercel preview workflow --- .github/workflows/preview.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .github/workflows/preview.yml diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml deleted file mode 100644 index 9ec6ab12..00000000 --- a/.github/workflows/preview.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Deploy to Vercel Preview -env: - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} -on: - pull_request: - branches: - - dev - -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: install Vercel CLI - run: npm install --global vercel@latest - - name: pull Vercel environment information - run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} - - name: build project artifacts - run: vercel build --token=${{ secrets.VERCEL_TOKEN }} - - name: deploy preview + assign beta domain - run: | - OUTPUT=$(du --inodes -d 5 .vercel/output) - echo "$OUTPUT" - LAST=$(echo "$OUTPUT" | tail -n 1) - PERCENTAGE=$(echo "$LAST" | awk 'BEGIN {maxtotal=15000} { printf "%.2f%%", ($1/maxtotal*100) }') - echo "Vercel file usage percentage" >> $GITHUB_STEP_SUMMARY - echo "$PERCENTAGE" >> $GITHUB_STEP_SUMMARY - du -h -d 3 .vercel/output/functions/en - vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} > domain.txt - vercel alias --scope ${{ secrets.VERCEL_TEAM_ID }} --token ${{ secrets.VERCEL_TOKEN }} set `cat domain.txt` biodrop-preview.vercel.app \ No newline at end of file From e4467ff447fd8380e47d7ab3ce94f533e39d1485 Mon Sep 17 00:00:00 2001 From: Mark Linn Date: Sat, 9 Sep 2023 18:09:31 +0200 Subject: [PATCH 031/127] chore: updating workflow to run cypress only on PRs to Main --- .github/workflows/test.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cba9c810..446ecd62 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v2 with: - node-version: "18" # current LTS (we have 16 in Docker) + node-version: "18" - name: Install dependencies run: yarn install @@ -27,4 +27,9 @@ jobs: run: yarn test - name: Run Cypress tests - run: yarn cypress + run: | + if [[ ${{ github.event.pull_request.base.ref }} == 'main' ]]; then + yarn cypress + else + echo "Skipping Cypress tests for non-main branch." + fi From 11f3906d8af3d369a25542ff3deb6470e4b0f8e1 Mon Sep 17 00:00:00 2001 From: Dan Ko Date: Sat, 9 Sep 2023 12:12:44 -0400 Subject: [PATCH 032/127] add cypress script to pre-push hook --- .husky/pre-push | 1 + 1 file changed, 1 insertion(+) diff --git a/.husky/pre-push b/.husky/pre-push index 07c67d33..c2162796 100644 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -3,3 +3,4 @@ yarn prettier yarn lint +yarn cypress From 7df5ba4051b4687fa8c09421ce4bd8822bbcad9a Mon Sep 17 00:00:00 2001 From: Timothy Russo Date: Sun, 10 Sep 2023 12:47:09 +0200 Subject: [PATCH 033/127] feat: add basic structure for the sidebar --- src/app/sidebar/components/Sidebar.tsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/app/sidebar/components/Sidebar.tsx b/src/app/sidebar/components/Sidebar.tsx index 14410383..535630cf 100644 --- a/src/app/sidebar/components/Sidebar.tsx +++ b/src/app/sidebar/components/Sidebar.tsx @@ -1,6 +1,16 @@ +"use client"; + +import { useState } from "react"; + export default function Sidebar() { + const [expand, setExpand] = useState(false); + return ( -
+
  • @@ -10,7 +20,11 @@ export default function Sidebar() {
-
+
From 9c2540d1c7744ce46a36b5fe15c7330347d58f9b Mon Sep 17 00:00:00 2001 From: Timothy Russo Date: Sun, 10 Sep 2023 15:00:10 +0200 Subject: [PATCH 034/127] feat: buttons layout --- src/app/sidebar/components/Sidebar.tsx | 89 +++++++++++++++++++++----- src/components/navbar/Navbar.tsx | 2 +- 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/src/app/sidebar/components/Sidebar.tsx b/src/app/sidebar/components/Sidebar.tsx index 535630cf..6987f6b0 100644 --- a/src/app/sidebar/components/Sidebar.tsx +++ b/src/app/sidebar/components/Sidebar.tsx @@ -1,30 +1,89 @@ "use client"; import { useState } from "react"; +import { + RectangleGroupIcon, + ChartBarIcon, + BookmarkSquareIcon, + RocketLaunchIcon, + ArrowRightOnRectangleIcon, + ArrowLeftOnRectangleIcon, +} from "@heroicons/react/24/solid"; +import { Button } from "@/components"; export default function Sidebar() { const [expand, setExpand] = useState(false); return (
-
-
    -
  • -
  • -
  • -
  • +
    +
      + + + +
    -
    -
    - + > + {expand ? ( + + ) : ( + + )} +
diff --git a/src/components/navbar/Navbar.tsx b/src/components/navbar/Navbar.tsx index 290403bd..ab0ade2e 100644 --- a/src/components/navbar/Navbar.tsx +++ b/src/components/navbar/Navbar.tsx @@ -6,7 +6,7 @@ const notificationCount = 4; export default function Navbar() { return ( -
-
+ ); } From 8d31db92e2e1a91c242b978f67d7356ba7068d67 Mon Sep 17 00:00:00 2001 From: Jane Moroz Date: Mon, 11 Sep 2023 13:34:47 +0300 Subject: [PATCH 036/127] style: remove hover effects from the edit btn --- src/app/directory/components/TeamRow.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/directory/components/TeamRow.tsx b/src/app/directory/components/TeamRow.tsx index b14775c0..77c146af 100644 --- a/src/app/directory/components/TeamRow.tsx +++ b/src/app/directory/components/TeamRow.tsx @@ -13,12 +13,12 @@ function TeamRow({ teamMember, currentUserId }: TeamRowProps) {
{teamMember.name} {teamMember.discordId} -
+
{teamMember.averageHour === 0 ? "Add hours" : teamMember.averageHour} {teamMember.id === currentUserId && ( From d804f16b9834107bd00a8cbd2fff9ac7f322edac Mon Sep 17 00:00:00 2001 From: Jane Moroz Date: Mon, 11 Sep 2023 13:56:13 +0300 Subject: [PATCH 037/127] feat: test --- src/components/ModeToggle.tsx | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/components/ModeToggle.tsx diff --git a/src/components/ModeToggle.tsx b/src/components/ModeToggle.tsx new file mode 100644 index 00000000..de2ca03e --- /dev/null +++ b/src/components/ModeToggle.tsx @@ -0,0 +1,5 @@ +export default function ModeToggle() { + return ( +
ModeToggle
+ ); +} \ No newline at end of file From 4ca8226f548c7dd9b2482abf5d704f14f4afc84e Mon Sep 17 00:00:00 2001 From: Daniel Ko Date: Mon, 11 Sep 2023 22:21:37 -0400 Subject: [PATCH 038/127] Create LICENSE --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. From 8e68f0f287e8928a59f7ee2765ee1b4d615eab68 Mon Sep 17 00:00:00 2001 From: Timothy Russo Date: Tue, 12 Sep 2023 08:49:13 +0200 Subject: [PATCH 039/127] feat: refactor the sidebar code --- src/app/sidebar/components/Sidebar.tsx | 62 +++++++++++++------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/src/app/sidebar/components/Sidebar.tsx b/src/app/sidebar/components/Sidebar.tsx index 7b40934f..2581fe5a 100644 --- a/src/app/sidebar/components/Sidebar.tsx +++ b/src/app/sidebar/components/Sidebar.tsx @@ -11,64 +11,66 @@ import { } from "@heroicons/react/24/solid"; import { Button } from "@/components"; +enum Pages { + DASHBOARD = "Dashboard", + ASSESSMENT = "Assessment", + RESOURCES = "Resources", + MY_VOYAGE = "My Voyage" +} + export default function Sidebar() { - const [expand, setExpand] = useState(false); + const [expand, setExpand] = useState(false); + const [selectedButton, setSelectedButton] = useState(); + + const buttonStyles = `${expand ? "w-[230px] flex justify-start pl-[24px] transition-all" : "w-[50px]"} h-[50px] text-black capitalize border-none`; + + const getButtonBackgroundStyle = (page: Pages) => selectedButton === page ? "bg-neutral-content" : "bg-white"; + const getDisplayText = (page: Pages) => expand ? page : ""; + return (
element in various ways - .should("have.text", "Column content") - .should("contain", "Column content") - .should("have.html", "Column content") - // chai-jquery uses "is()" to check if element matches selector - .should("match", "td") - // to match text content against a regular expression - // first need to invoke jQuery method text() - // and then match using regular expression - .invoke("text") - .should("match", /column content/i); - - // a better way to check element's text content against a regular expression - // is to use "cy.contains" - // https://on.cypress.io/contains - cy.get(".assertion-table") - .find("tbody tr:last") - // finds first element with text content matching regular expression - .contains("td", /column content/i) - .should("be.visible"); - - // for more information about asserting element's text - // see https://on.cypress.io/using-cypress-faq#How-do-I-get-an-element’s-text-contents - }); - - it(".and() - chain multiple assertions together", () => { - // https://on.cypress.io/and - cy.get(".assertions-link") - .should("have.class", "active") - .and("have.attr", "href") - .and("include", "cypress.io"); - }); - }); - - describe("Explicit Assertions", () => { - // https://on.cypress.io/assertions - it("expect - make an assertion about a specified subject", () => { - // We can use Chai's BDD style assertions - expect(true).to.be.true; - const o = { foo: "bar" }; - - expect(o).to.equal(o); - expect(o).to.deep.equal({ foo: "bar" }); - // matching text using regular expression - expect("FooBar").to.match(/bar$/i); - }); - - it("pass your own callback function to should()", () => { - // Pass a function to should that can have any number - // of explicit assertions within it. - // The ".should(cb)" function will be retried - // automatically until it passes all your explicit assertions or times out. - cy.get(".assertions-p") - .find("p") - .should(($p) => { - // https://on.cypress.io/$ - // return an array of texts from all of the p's - const texts = $p.map((i, el) => Cypress.$(el).text()); - - // jquery map returns jquery object - // and .get() convert this to simple array - const paragraphs = texts.get(); - - // array should have length of 3 - expect(paragraphs, "has 3 paragraphs").to.have.length(3); - - // use second argument to expect(...) to provide clear - // message with each assertion - expect(paragraphs, "has expected text in each paragraph").to.deep.eq([ - "Some text from first p", - "More text from second p", - "And even more text from third p", - ]); - }); - }); - - it("finds element by class name regex", () => { - cy.get(".docs-header") - .find("div") - // .should(cb) callback function will be retried - .should(($div) => { - expect($div).to.have.length(1); - - const className = $div[0].className; - - expect(className).to.match(/heading-/); - }) - // .then(cb) callback is not retried, - // it either passes or fails - .then(($div) => { - expect($div, "text content").to.have.text("Introduction"); - }); - }); - - it("can throw any error", () => { - cy.get(".docs-header") - .find("div") - .should(($div) => { - if ($div.length !== 1) { - // you can throw your own errors - throw new Error("Did not find 1 element"); - } - - const className = $div[0].className; - - if (!className.match(/heading-/)) { - throw new Error(`Could not find class "heading-" in ${className}`); - } - }); - }); - - it("matches unknown text between two elements", () => { - /** - * Text from the first element. - * @type {string} - */ - let text; - - /** - * Normalizes passed text, - * useful before comparing text with spaces and different capitalization. - * @param {string} s Text to normalize - */ - const normalizeText = (s) => s.replace(/\s/g, "").toLowerCase(); - - cy.get(".two-elements") - .find(".first") - .then(($first) => { - // save text from the first element - text = normalizeText($first.text()); - }); - - cy.get(".two-elements") - .find(".second") - .should(($div) => { - // we can massage text before comparing - const secondText = normalizeText($div.text()); - - expect(secondText, "second text").to.equal(text); - }); - }); - - it("assert - assert shape of an object", () => { - const person = { - name: "Joe", - age: 20, - }; - - assert.isObject(person, "value is object"); - }); - - it("retries the should callback until assertions pass", () => { - cy.get("#random-number").should(($div) => { - const n = parseFloat($div.text()); - - expect(n).to.be.gte(1).and.be.lte(10); - }); - }); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/connectors.cy.js b/cypress/e2e/2-advanced-examples/connectors.cy.js deleted file mode 100644 index aaabcd13..00000000 --- a/cypress/e2e/2-advanced-examples/connectors.cy.js +++ /dev/null @@ -1,96 +0,0 @@ -/// - -context("Connectors", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/commands/connectors"); - }); - - it(".each() - iterate over an array of elements", () => { - // https://on.cypress.io/each - cy.get(".connectors-each-ul>li").each(($el, index, $list) => { - console.log($el, index, $list); - }); - }); - - it(".its() - get properties on the current subject", () => { - // https://on.cypress.io/its - cy.get(".connectors-its-ul>li") - // calls the 'length' property yielding that value - .its("length") - .should("be.gt", 2); - }); - - it(".invoke() - invoke a function on the current subject", () => { - // our div is hidden in our script.js - // $('.connectors-div').hide() - cy.get(".connectors-div").should("be.hidden"); - - // https://on.cypress.io/invoke - // call the jquery method 'show' on the 'div.container' - cy.get(".connectors-div").invoke("show"); - - cy.get(".connectors-div").should("be.visible"); - }); - - it(".spread() - spread an array as individual args to callback function", () => { - // https://on.cypress.io/spread - const arr = ["foo", "bar", "baz"]; - - cy.wrap(arr).spread((foo, bar, baz) => { - expect(foo).to.eq("foo"); - expect(bar).to.eq("bar"); - expect(baz).to.eq("baz"); - }); - }); - - describe(".then()", () => { - it("invokes a callback function with the current subject", () => { - // https://on.cypress.io/then - cy.get(".connectors-list > li").then(($lis) => { - expect($lis, "3 items").to.have.length(3); - expect($lis.eq(0), "first item").to.contain("Walk the dog"); - expect($lis.eq(1), "second item").to.contain("Feed the cat"); - expect($lis.eq(2), "third item").to.contain("Write JavaScript"); - }); - }); - - it("yields the returned value to the next command", () => { - cy.wrap(1) - .then((num) => { - expect(num).to.equal(1); - - return 2; - }) - .then((num) => { - expect(num).to.equal(2); - }); - }); - - it("yields the original subject without return", () => { - cy.wrap(1) - .then((num) => { - expect(num).to.equal(1); - // note that nothing is returned from this callback - }) - .then((num) => { - // this callback receives the original unchanged value 1 - expect(num).to.equal(1); - }); - }); - - it("yields the value yielded by the last Cypress command inside", () => { - cy.wrap(1) - .then((num) => { - expect(num).to.equal(1); - // note how we run a Cypress command - // the result yielded by this Cypress command - // will be passed to the second ".then" - cy.wrap(2); - }) - .then((num) => { - // this callback receives the value yielded by "cy.wrap(2)" - expect(num).to.equal(2); - }); - }); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/cookies.cy.js b/cypress/e2e/2-advanced-examples/cookies.cy.js deleted file mode 100644 index d497107e..00000000 --- a/cypress/e2e/2-advanced-examples/cookies.cy.js +++ /dev/null @@ -1,122 +0,0 @@ -/// - -context("Cookies", () => { - beforeEach(() => { - Cypress.Cookies.debug(true); - - cy.visit("https://example.cypress.io/commands/cookies"); - - // clear cookies again after visiting to remove - // any 3rd party cookies picked up such as cloudflare - cy.clearCookies(); - }); - - it("cy.getCookie() - get a browser cookie", () => { - // https://on.cypress.io/getcookie - cy.get("#getCookie .set-a-cookie").click(); - - // cy.getCookie() yields a cookie object - cy.getCookie("token").should("have.property", "value", "123ABC"); - }); - - it("cy.getCookies() - get browser cookies for the current domain", () => { - // https://on.cypress.io/getcookies - cy.getCookies().should("be.empty"); - - cy.get("#getCookies .set-a-cookie").click(); - - // cy.getCookies() yields an array of cookies - cy.getCookies() - .should("have.length", 1) - .should((cookies) => { - // each cookie has these properties - expect(cookies[0]).to.have.property("name", "token"); - expect(cookies[0]).to.have.property("value", "123ABC"); - expect(cookies[0]).to.have.property("httpOnly", false); - expect(cookies[0]).to.have.property("secure", false); - expect(cookies[0]).to.have.property("domain"); - expect(cookies[0]).to.have.property("path"); - }); - }); - - it("cy.getAllCookies() - get all browser cookies", () => { - // https://on.cypress.io/getallcookies - cy.getAllCookies().should("be.empty"); - - cy.setCookie("key", "value"); - cy.setCookie("key", "value", { domain: ".example.com" }); - - // cy.getAllCookies() yields an array of cookies - cy.getAllCookies() - .should("have.length", 2) - .should((cookies) => { - // each cookie has these properties - expect(cookies[0]).to.have.property("name", "key"); - expect(cookies[0]).to.have.property("value", "value"); - expect(cookies[0]).to.have.property("httpOnly", false); - expect(cookies[0]).to.have.property("secure", false); - expect(cookies[0]).to.have.property("domain"); - expect(cookies[0]).to.have.property("path"); - - expect(cookies[1]).to.have.property("name", "key"); - expect(cookies[1]).to.have.property("value", "value"); - expect(cookies[1]).to.have.property("httpOnly", false); - expect(cookies[1]).to.have.property("secure", false); - expect(cookies[1]).to.have.property("domain", ".example.com"); - expect(cookies[1]).to.have.property("path"); - }); - }); - - it("cy.setCookie() - set a browser cookie", () => { - // https://on.cypress.io/setcookie - cy.getCookies().should("be.empty"); - - cy.setCookie("foo", "bar"); - - // cy.getCookie() yields a cookie object - cy.getCookie("foo").should("have.property", "value", "bar"); - }); - - it("cy.clearCookie() - clear a browser cookie", () => { - // https://on.cypress.io/clearcookie - cy.getCookie("token").should("be.null"); - - cy.get("#clearCookie .set-a-cookie").click(); - - cy.getCookie("token").should("have.property", "value", "123ABC"); - - // cy.clearCookies() yields null - cy.clearCookie("token").should("be.null"); - - cy.getCookie("token").should("be.null"); - }); - - it("cy.clearCookies() - clear browser cookies for the current domain", () => { - // https://on.cypress.io/clearcookies - cy.getCookies().should("be.empty"); - - cy.get("#clearCookies .set-a-cookie").click(); - - cy.getCookies().should("have.length", 1); - - // cy.clearCookies() yields null - cy.clearCookies(); - - cy.getCookies().should("be.empty"); - }); - - it("cy.clearAllCookies() - clear all browser cookies", () => { - // https://on.cypress.io/clearallcookies - cy.getAllCookies().should("be.empty"); - - cy.setCookie("key", "value"); - cy.setCookie("key", "value", { domain: ".example.com" }); - - cy.getAllCookies().should("have.length", 2); - - // cy.clearAllCookies() yields null - cy.clearAllCookies(); - - cy.getAllCookies().should("be.empty"); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/cypress_api.cy.js b/cypress/e2e/2-advanced-examples/cypress_api.cy.js deleted file mode 100644 index 2d5e7bf3..00000000 --- a/cypress/e2e/2-advanced-examples/cypress_api.cy.js +++ /dev/null @@ -1,197 +0,0 @@ -/// - -context("Cypress APIs", () => { - context("Cypress.Commands", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/cypress-api"); - }); - - // https://on.cypress.io/custom-commands - - it(".add() - create a custom command", () => { - Cypress.Commands.add( - "console", - { - prevSubject: true, - }, - (subject, method) => { - // the previous subject is automatically received - // and the commands arguments are shifted - - // allow us to change the console method used - method = method || "log"; - - // log the subject to the console - console[method]("The subject is", subject); - - // whatever we return becomes the new subject - // we don't want to change the subject so - // we return whatever was passed in - return subject; - }, - ); - - cy.get("button") - .console("info") - .then(($button) => { - // subject is still $button - }); - }); - }); - - context("Cypress.Cookies", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/cypress-api"); - }); - - // https://on.cypress.io/cookies - it(".debug() - enable or disable debugging", () => { - Cypress.Cookies.debug(true); - - // Cypress will now log in the console when - // cookies are set or cleared - cy.setCookie("fakeCookie", "123ABC"); - cy.clearCookie("fakeCookie"); - cy.setCookie("fakeCookie", "123ABC"); - cy.clearCookie("fakeCookie"); - cy.setCookie("fakeCookie", "123ABC"); - }); - }); - - context("Cypress.arch", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/cypress-api"); - }); - - it("Get CPU architecture name of underlying OS", () => { - // https://on.cypress.io/arch - expect(Cypress.arch).to.exist; - }); - }); - - context("Cypress.config()", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/cypress-api"); - }); - - it("Get and set configuration options", () => { - // https://on.cypress.io/config - let myConfig = Cypress.config(); - - expect(myConfig).to.have.property("animationDistanceThreshold", 5); - expect(myConfig).to.have.property("baseUrl", null); - expect(myConfig).to.have.property("defaultCommandTimeout", 4000); - expect(myConfig).to.have.property("requestTimeout", 5000); - expect(myConfig).to.have.property("responseTimeout", 30000); - expect(myConfig).to.have.property("viewportHeight", 660); - expect(myConfig).to.have.property("viewportWidth", 1000); - expect(myConfig).to.have.property("pageLoadTimeout", 60000); - expect(myConfig).to.have.property("waitForAnimations", true); - - expect(Cypress.config("pageLoadTimeout")).to.eq(60000); - - // this will change the config for the rest of your tests! - Cypress.config("pageLoadTimeout", 20000); - - expect(Cypress.config("pageLoadTimeout")).to.eq(20000); - - Cypress.config("pageLoadTimeout", 60000); - }); - }); - - context("Cypress.dom", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/cypress-api"); - }); - - // https://on.cypress.io/dom - it(".isHidden() - determine if a DOM element is hidden", () => { - let hiddenP = Cypress.$(".dom-p p.hidden").get(0); - let visibleP = Cypress.$(".dom-p p.visible").get(0); - - // our first paragraph has css class 'hidden' - expect(Cypress.dom.isHidden(hiddenP)).to.be.true; - expect(Cypress.dom.isHidden(visibleP)).to.be.false; - }); - }); - - context("Cypress.env()", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/cypress-api"); - }); - - // We can set environment variables for highly dynamic values - - // https://on.cypress.io/environment-variables - it("Get environment variables", () => { - // https://on.cypress.io/env - // set multiple environment variables - Cypress.env({ - host: "veronica.dev.local", - api_server: "http://localhost:8888/v1/", - }); - - // get environment variable - expect(Cypress.env("host")).to.eq("veronica.dev.local"); - - // set environment variable - Cypress.env("api_server", "http://localhost:8888/v2/"); - expect(Cypress.env("api_server")).to.eq("http://localhost:8888/v2/"); - - // get all environment variable - expect(Cypress.env()).to.have.property("host", "veronica.dev.local"); - expect(Cypress.env()).to.have.property( - "api_server", - "http://localhost:8888/v2/", - ); - }); - }); - - context("Cypress.log", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/cypress-api"); - }); - - it("Control what is printed to the Command Log", () => { - // https://on.cypress.io/cypress-log - }); - }); - - context("Cypress.platform", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/cypress-api"); - }); - - it("Get underlying OS name", () => { - // https://on.cypress.io/platform - expect(Cypress.platform).to.be.exist; - }); - }); - - context("Cypress.version", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/cypress-api"); - }); - - it("Get current version of Cypress being run", () => { - // https://on.cypress.io/version - expect(Cypress.version).to.be.exist; - }); - }); - - context("Cypress.spec", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/cypress-api"); - }); - - it("Get current spec information", () => { - // https://on.cypress.io/spec - // wrap the object so we can inspect it easily by clicking in the command log - cy.wrap(Cypress.spec).should("include.keys", [ - "name", - "relative", - "absolute", - ]); - }); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/files.cy.js b/cypress/e2e/2-advanced-examples/files.cy.js deleted file mode 100644 index d161b309..00000000 --- a/cypress/e2e/2-advanced-examples/files.cy.js +++ /dev/null @@ -1,87 +0,0 @@ -/// - -/// JSON fixture file can be loaded directly using -// the built-in JavaScript bundler -const requiredExample = require("../../fixtures/example"); - -context("Files", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/commands/files"); - - // load example.json fixture file and store - // in the test context object - cy.fixture("example.json").as("example"); - }); - - it("cy.fixture() - load a fixture", () => { - // https://on.cypress.io/fixture - - // Instead of writing a response inline you can - // use a fixture file's content. - - // when application makes an Ajax request matching "GET **/comments/*" - // Cypress will intercept it and reply with the object in `example.json` fixture - cy.intercept("GET", "**/comments/*", { fixture: "example.json" }).as( - "getComment", - ); - - // we have code that gets a comment when - // the button is clicked in scripts.js - cy.get(".fixture-btn").click(); - - cy.wait("@getComment") - .its("response.body") - .should("have.property", "name") - .and("include", "Using fixtures to represent data"); - }); - - it("cy.fixture() or require - load a fixture", function () { - // we are inside the "function () { ... }" - // callback and can use test context object "this" - // "this.example" was loaded in "beforeEach" function callback - expect(this.example, "fixture in the test context").to.deep.equal( - requiredExample, - ); - - // or use "cy.wrap" and "should('deep.equal', ...)" assertion - cy.wrap(this.example).should("deep.equal", requiredExample); - }); - - it("cy.readFile() - read file contents", () => { - // https://on.cypress.io/readfile - - // You can read a file and yield its contents - // The filePath is relative to your project's root. - cy.readFile(Cypress.config("configFile")).then((config) => { - expect(config).to.be.an("string"); - }); - }); - - it("cy.writeFile() - write to a file", () => { - // https://on.cypress.io/writefile - - // You can write to a file - - // Use a response from a request to automatically - // generate a fixture file for use later - cy.request("https://jsonplaceholder.cypress.io/users").then((response) => { - cy.writeFile("cypress/fixtures/users.json", response.body); - }); - - cy.fixture("users").should((users) => { - expect(users[0].name).to.exist; - }); - - // JavaScript arrays and objects are stringified - // and formatted into text. - cy.writeFile("cypress/fixtures/profile.json", { - id: 8739, - name: "Jane", - email: "jane@example.com", - }); - - cy.fixture("profile").should((profile) => { - expect(profile.name).to.eq("Jane"); - }); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/location.cy.js b/cypress/e2e/2-advanced-examples/location.cy.js deleted file mode 100644 index 6f797f14..00000000 --- a/cypress/e2e/2-advanced-examples/location.cy.js +++ /dev/null @@ -1,34 +0,0 @@ -/// - -context("Location", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/commands/location"); - }); - - it("cy.hash() - get the current URL hash", () => { - // https://on.cypress.io/hash - cy.hash().should("be.empty"); - }); - - it("cy.location() - get window.location", () => { - // https://on.cypress.io/location - cy.location().should((location) => { - expect(location.hash).to.be.empty; - expect(location.href).to.eq( - "https://example.cypress.io/commands/location", - ); - expect(location.host).to.eq("example.cypress.io"); - expect(location.hostname).to.eq("example.cypress.io"); - expect(location.origin).to.eq("https://example.cypress.io"); - expect(location.pathname).to.eq("/commands/location"); - expect(location.port).to.eq(""); - expect(location.protocol).to.eq("https:"); - expect(location.search).to.be.empty; - }); - }); - - it("cy.url() - get the current URL", () => { - // https://on.cypress.io/url - cy.url().should("eq", "https://example.cypress.io/commands/location"); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/misc.cy.js b/cypress/e2e/2-advanced-examples/misc.cy.js deleted file mode 100644 index fc6df9aa..00000000 --- a/cypress/e2e/2-advanced-examples/misc.cy.js +++ /dev/null @@ -1,106 +0,0 @@ -/// - -context("Misc", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/commands/misc"); - }); - - it(".end() - end the command chain", () => { - // https://on.cypress.io/end - - // cy.end is useful when you want to end a chain of commands - // and force Cypress to re-query from the root element - cy.get(".misc-table").within(() => { - // ends the current chain and yields null - cy.contains("Cheryl").click().end(); - - // queries the entire table again - cy.contains("Charles").click(); - }); - }); - - it("cy.exec() - execute a system command", () => { - // execute a system command. - // so you can take actions necessary for - // your test outside the scope of Cypress. - // https://on.cypress.io/exec - - // we can use Cypress.platform string to - // select appropriate command - // https://on.cypress/io/platform - cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`); - - // on CircleCI Windows build machines we have a failure to run bash shell - // https://github.com/cypress-io/cypress/issues/5169 - // so skip some of the tests by passing flag "--env circle=true" - const isCircleOnWindows = - Cypress.platform === "win32" && Cypress.env("circle"); - - if (isCircleOnWindows) { - cy.log("Skipping test on CircleCI"); - - return; - } - - // cy.exec problem on Shippable CI - // https://github.com/cypress-io/cypress/issues/6718 - const isShippable = - Cypress.platform === "linux" && Cypress.env("shippable"); - - if (isShippable) { - cy.log("Skipping test on ShippableCI"); - - return; - } - - cy.exec("echo Jane Lane").its("stdout").should("contain", "Jane Lane"); - - if (Cypress.platform === "win32") { - cy.exec(`print ${Cypress.config("configFile")}`) - .its("stderr") - .should("be.empty"); - } else { - cy.exec(`cat ${Cypress.config("configFile")}`) - .its("stderr") - .should("be.empty"); - - cy.exec("pwd").its("code").should("eq", 0); - } - }); - - it("cy.focused() - get the DOM element that has focus", () => { - // https://on.cypress.io/focused - cy.get(".misc-form").find("#name").click(); - cy.focused().should("have.id", "name"); - - cy.get(".misc-form").find("#description").click(); - cy.focused().should("have.id", "description"); - }); - - context("Cypress.Screenshot", function () { - it("cy.screenshot() - take a screenshot", () => { - // https://on.cypress.io/screenshot - cy.screenshot("my-image"); - }); - - it("Cypress.Screenshot.defaults() - change default config of screenshots", function () { - Cypress.Screenshot.defaults({ - blackout: [".foo"], - capture: "viewport", - clip: { x: 0, y: 0, width: 200, height: 200 }, - scale: false, - disableTimersAndAnimations: true, - screenshotOnRunFailure: true, - onBeforeScreenshot() {}, - onAfterScreenshot() {}, - }); - }); - }); - - it("cy.wrap() - wrap an object", () => { - // https://on.cypress.io/wrap - cy.wrap({ foo: "bar" }) - .should("have.property", "foo") - .and("include", "bar"); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/navigation.cy.js b/cypress/e2e/2-advanced-examples/navigation.cy.js deleted file mode 100644 index 2bdae554..00000000 --- a/cypress/e2e/2-advanced-examples/navigation.cy.js +++ /dev/null @@ -1,56 +0,0 @@ -/// - -context("Navigation", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io"); - cy.get(".navbar-nav").contains("Commands").click(); - cy.get(".dropdown-menu").contains("Navigation").click(); - }); - - it("cy.go() - go back or forward in the browser's history", () => { - // https://on.cypress.io/go - - cy.location("pathname").should("include", "navigation"); - - cy.go("back"); - cy.location("pathname").should("not.include", "navigation"); - - cy.go("forward"); - cy.location("pathname").should("include", "navigation"); - - // clicking back - cy.go(-1); - cy.location("pathname").should("not.include", "navigation"); - - // clicking forward - cy.go(1); - cy.location("pathname").should("include", "navigation"); - }); - - it("cy.reload() - reload the page", () => { - // https://on.cypress.io/reload - cy.reload(); - - // reload the page without using the cache - cy.reload(true); - }); - - it("cy.visit() - visit a remote url", () => { - // https://on.cypress.io/visit - - // Visit any sub-domain of your current domain - - // Pass options to the visit - cy.visit("https://example.cypress.io/commands/navigation", { - timeout: 50000, // increase total time for the visit to resolve - onBeforeLoad(contentWindow) { - // contentWindow is the remote page's window object - expect(typeof contentWindow === "object").to.be.true; - }, - onLoad(contentWindow) { - // contentWindow is the remote page's window object - expect(typeof contentWindow === "object").to.be.true; - }, - }); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/network_requests.cy.js b/cypress/e2e/2-advanced-examples/network_requests.cy.js deleted file mode 100644 index 0d49015f..00000000 --- a/cypress/e2e/2-advanced-examples/network_requests.cy.js +++ /dev/null @@ -1,184 +0,0 @@ -/// - -context("Network Requests", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/commands/network-requests"); - }); - - // Manage HTTP requests in your app - - it("cy.request() - make an XHR request", () => { - // https://on.cypress.io/request - cy.request("https://jsonplaceholder.cypress.io/comments").should( - (response) => { - expect(response.status).to.eq(200); - // the server sometimes gets an extra comment posted from another machine - // which gets returned as 1 extra object - expect(response.body) - .to.have.property("length") - .and.be.oneOf([500, 501]); - expect(response).to.have.property("headers"); - expect(response).to.have.property("duration"); - }, - ); - }); - - it("cy.request() - verify response using BDD syntax", () => { - cy.request("https://jsonplaceholder.cypress.io/comments").then( - (response) => { - // https://on.cypress.io/assertions - expect(response).property("status").to.equal(200); - expect(response) - .property("body") - .to.have.property("length") - .and.be.oneOf([500, 501]); - expect(response).to.include.keys("headers", "duration"); - }, - ); - }); - - it("cy.request() with query parameters", () => { - // will execute request - // https://jsonplaceholder.cypress.io/comments?postId=1&id=3 - cy.request({ - url: "https://jsonplaceholder.cypress.io/comments", - qs: { - postId: 1, - id: 3, - }, - }) - .its("body") - .should("be.an", "array") - .and("have.length", 1) - .its("0") // yields first element of the array - .should("contain", { - postId: 1, - id: 3, - }); - }); - - it("cy.request() - pass result to the second request", () => { - // first, let's find out the userId of the first user we have - cy.request("https://jsonplaceholder.cypress.io/users?_limit=1") - .its("body") // yields the response object - .its("0") // yields the first element of the returned list - // the above two commands its('body').its('0') - // can be written as its('body.0') - // if you do not care about TypeScript checks - .then((user) => { - expect(user).property("id").to.be.a("number"); - // make a new post on behalf of the user - cy.request("POST", "https://jsonplaceholder.cypress.io/posts", { - userId: user.id, - title: "Cypress Test Runner", - body: "Fast, easy and reliable testing for anything that runs in a browser.", - }); - }) - // note that the value here is the returned value of the 2nd request - // which is the new post object - .then((response) => { - expect(response).property("status").to.equal(201); // new entity created - expect(response).property("body").to.contain({ - title: "Cypress Test Runner", - }); - - // we don't know the exact post id - only that it will be > 100 - // since JSONPlaceholder has built-in 100 posts - expect(response.body) - .property("id") - .to.be.a("number") - .and.to.be.gt(100); - - // we don't know the user id here - since it was in above closure - // so in this test just confirm that the property is there - expect(response.body).property("userId").to.be.a("number"); - }); - }); - - it("cy.request() - save response in the shared test context", () => { - // https://on.cypress.io/variables-and-aliases - cy.request("https://jsonplaceholder.cypress.io/users?_limit=1") - .its("body") - .its("0") // yields the first element of the returned list - .as("user") // saves the object in the test context - .then(function () { - // NOTE 👀 - // By the time this callback runs the "as('user')" command - // has saved the user object in the test context. - // To access the test context we need to use - // the "function () { ... }" callback form, - // otherwise "this" points at a wrong or undefined object! - cy.request("POST", "https://jsonplaceholder.cypress.io/posts", { - userId: this.user.id, - title: "Cypress Test Runner", - body: "Fast, easy and reliable testing for anything that runs in a browser.", - }) - .its("body") - .as("post"); // save the new post from the response - }) - .then(function () { - // When this callback runs, both "cy.request" API commands have finished - // and the test context has "user" and "post" objects set. - // Let's verify them. - expect(this.post, "post has the right user id") - .property("userId") - .to.equal(this.user.id); - }); - }); - - it("cy.intercept() - route responses to matching requests", () => { - // https://on.cypress.io/intercept - - let message = "whoa, this comment does not exist"; - - // Listen to GET to comments/1 - cy.intercept("GET", "**/comments/*").as("getComment"); - - // we have code that gets a comment when - // the button is clicked in scripts.js - cy.get(".network-btn").click(); - - // https://on.cypress.io/wait - cy.wait("@getComment") - .its("response.statusCode") - .should("be.oneOf", [200, 304]); - - // Listen to POST to comments - cy.intercept("POST", "**/comments").as("postComment"); - - // we have code that posts a comment when - // the button is clicked in scripts.js - cy.get(".network-post").click(); - cy.wait("@postComment").should(({ request, response }) => { - expect(request.body).to.include("email"); - expect(request.headers).to.have.property("content-type"); - expect(response && response.body).to.have.property( - "name", - "Using POST in cy.intercept()", - ); - }); - - // Stub a response to PUT comments/ **** - cy.intercept( - { - method: "PUT", - url: "**/comments/*", - }, - { - statusCode: 404, - body: { error: message }, - headers: { "access-control-allow-origin": "*" }, - delayMs: 500, - }, - ).as("putComment"); - - // we have code that puts a comment when - // the button is clicked in scripts.js - cy.get(".network-put").click(); - - cy.wait("@putComment"); - - // our 404 statusCode logic in scripts.js executed - cy.get(".network-put-comment").should("contain", message); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/querying.cy.js b/cypress/e2e/2-advanced-examples/querying.cy.js deleted file mode 100644 index 3bdef3e8..00000000 --- a/cypress/e2e/2-advanced-examples/querying.cy.js +++ /dev/null @@ -1,106 +0,0 @@ -/// - -context("Querying", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/commands/querying"); - }); - - // The most commonly used query is 'cy.get()', you can - // think of this like the '$' in jQuery - - it("cy.get() - query DOM elements", () => { - // https://on.cypress.io/get - - cy.get("#query-btn").should("contain", "Button"); - - cy.get(".query-btn").should("contain", "Button"); - - cy.get("#querying .well>button:first").should("contain", "Button"); - // ↲ - // Use CSS selectors just like jQuery - - cy.get('[data-test-id="test-example"]').should("have.class", "example"); - - // 'cy.get()' yields jQuery object, you can get its attribute - // by invoking `.attr()` method - cy.get('[data-test-id="test-example"]') - .invoke("attr", "data-test-id") - .should("equal", "test-example"); - - // or you can get element's CSS property - cy.get('[data-test-id="test-example"]') - .invoke("css", "position") - .should("equal", "static"); - - // or use assertions directly during 'cy.get()' - // https://on.cypress.io/assertions - cy.get('[data-test-id="test-example"]') - .should("have.attr", "data-test-id", "test-example") - .and("have.css", "position", "static"); - }); - - it("cy.contains() - query DOM elements with matching content", () => { - // https://on.cypress.io/contains - cy.get(".query-list").contains("bananas").should("have.class", "third"); - - // we can pass a regexp to `.contains()` - cy.get(".query-list").contains(/^b\w+/).should("have.class", "third"); - - cy.get(".query-list").contains("apples").should("have.class", "first"); - - // passing a selector to contains will - // yield the selector containing the text - cy.get("#querying") - .contains("ul", "oranges") - .should("have.class", "query-list"); - - cy.get(".query-button").contains("Save Form").should("have.class", "btn"); - }); - - it(".within() - query DOM elements within a specific element", () => { - // https://on.cypress.io/within - cy.get(".query-form").within(() => { - cy.get("input:first").should("have.attr", "placeholder", "Email"); - cy.get("input:last").should("have.attr", "placeholder", "Password"); - }); - }); - - it("cy.root() - query the root DOM element", () => { - // https://on.cypress.io/root - - // By default, root is the document - cy.root().should("match", "html"); - - cy.get(".query-ul").within(() => { - // In this within, the root is now the ul DOM element - cy.root().should("have.class", "query-ul"); - }); - }); - - it("best practices - selecting elements", () => { - // https://on.cypress.io/best-practices#Selecting-Elements - cy.get("[data-cy=best-practices-selecting-elements]").within(() => { - // Worst - too generic, no context - cy.get("button").click(); - - // Bad. Coupled to styling. Highly subject to change. - cy.get(".btn.btn-large").click(); - - // Average. Coupled to the `name` attribute which has HTML semantics. - cy.get("[name=submission]").click(); - - // Better. But still coupled to styling or JS event listeners. - cy.get("#main").click(); - - // Slightly better. Uses an ID but also ensures the element - // has an ARIA role attribute - cy.get("#main[role=button]").click(); - - // Much better. But still coupled to text content that may change. - cy.contains("Submit").click(); - - // Best. Insulated from all changes. - cy.get("[data-cy=submit]").click(); - }); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js b/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js deleted file mode 100644 index c4080a9b..00000000 --- a/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js +++ /dev/null @@ -1,213 +0,0 @@ -/// - -context("Spies, Stubs, and Clock", () => { - it("cy.spy() - wrap a method in a spy", () => { - // https://on.cypress.io/spy - cy.visit("https://example.cypress.io/commands/spies-stubs-clocks"); - - const obj = { - foo() {}, - }; - - const spy = cy.spy(obj, "foo").as("anyArgs"); - - obj.foo(); - - expect(spy).to.be.called; - }); - - it("cy.spy() retries until assertions pass", () => { - cy.visit("https://example.cypress.io/commands/spies-stubs-clocks"); - - const obj = { - /** - * Prints the argument passed - * @param x {any} - */ - foo(x) { - console.log("obj.foo called with", x); - }, - }; - - cy.spy(obj, "foo").as("foo"); - - setTimeout(() => { - obj.foo("first"); - }, 500); - - setTimeout(() => { - obj.foo("second"); - }, 2500); - - cy.get("@foo").should("have.been.calledTwice"); - }); - - it("cy.stub() - create a stub and/or replace a function with stub", () => { - // https://on.cypress.io/stub - cy.visit("https://example.cypress.io/commands/spies-stubs-clocks"); - - const obj = { - /** - * prints both arguments to the console - * @param a {string} - * @param b {string} - */ - foo(a, b) { - console.log("a", a, "b", b); - }, - }; - - const stub = cy.stub(obj, "foo").as("foo"); - - obj.foo("foo", "bar"); - - expect(stub).to.be.called; - }); - - it("cy.clock() - control time in the browser", () => { - // https://on.cypress.io/clock - - // create the date in UTC so its always the same - // no matter what local timezone the browser is running in - const now = new Date(Date.UTC(2017, 2, 14)).getTime(); - - cy.clock(now); - cy.visit("https://example.cypress.io/commands/spies-stubs-clocks"); - cy.get("#clock-div").click().should("have.text", "1489449600"); - }); - - it("cy.tick() - move time in the browser", () => { - // https://on.cypress.io/tick - - // create the date in UTC so its always the same - // no matter what local timezone the browser is running in - const now = new Date(Date.UTC(2017, 2, 14)).getTime(); - - cy.clock(now); - cy.visit("https://example.cypress.io/commands/spies-stubs-clocks"); - cy.get("#tick-div").click().should("have.text", "1489449600"); - - cy.tick(10000); // 10 seconds passed - cy.get("#tick-div").click().should("have.text", "1489449610"); - }); - - it("cy.stub() matches depending on arguments", () => { - // see all possible matchers at - // https://sinonjs.org/releases/latest/matchers/ - const greeter = { - /** - * Greets a person - * @param {string} name - */ - greet(name) { - return `Hello, ${name}!`; - }, - }; - - cy.stub(greeter, "greet") - .callThrough() // if you want non-matched calls to call the real method - .withArgs(Cypress.sinon.match.string) - .returns("Hi") - .withArgs(Cypress.sinon.match.number) - .throws(new Error("Invalid name")); - - expect(greeter.greet("World")).to.equal("Hi"); - expect(() => greeter.greet(42)).to.throw("Invalid name"); - expect(greeter.greet).to.have.been.calledTwice; - - // non-matched calls goes the actual method - expect(greeter.greet()).to.equal("Hello, undefined!"); - }); - - it("matches call arguments using Sinon matchers", () => { - // see all possible matchers at - // https://sinonjs.org/releases/latest/matchers/ - const calculator = { - /** - * returns the sum of two arguments - * @param a {number} - * @param b {number} - */ - add(a, b) { - return a + b; - }, - }; - - const spy = cy.spy(calculator, "add").as("add"); - - expect(calculator.add(2, 3)).to.equal(5); - - // if we want to assert the exact values used during the call - expect(spy).to.be.calledWith(2, 3); - - // let's confirm "add" method was called with two numbers - expect(spy).to.be.calledWith( - Cypress.sinon.match.number, - Cypress.sinon.match.number, - ); - - // alternatively, provide the value to match - expect(spy).to.be.calledWith( - Cypress.sinon.match(2), - Cypress.sinon.match(3), - ); - - // match any value - expect(spy).to.be.calledWith(Cypress.sinon.match.any, 3); - - // match any value from a list - expect(spy).to.be.calledWith(Cypress.sinon.match.in([1, 2, 3]), 3); - - /** - * Returns true if the given number is even - * @param {number} x - */ - const isEven = (x) => x % 2 === 0; - - // expect the value to pass a custom predicate function - // the second argument to "sinon.match(predicate, message)" is - // shown if the predicate does not pass and assertion fails - expect(spy).to.be.calledWith(Cypress.sinon.match(isEven, "isEven"), 3); - - /** - * Returns a function that checks if a given number is larger than the limit - * @param {number} limit - * @returns {(x: number) => boolean} - */ - const isGreaterThan = (limit) => (x) => x > limit; - - /** - * Returns a function that checks if a given number is less than the limit - * @param {number} limit - * @returns {(x: number) => boolean} - */ - const isLessThan = (limit) => (x) => x < limit; - - // you can combine several matchers using "and", "or" - expect(spy).to.be.calledWith( - Cypress.sinon.match.number, - Cypress.sinon - .match(isGreaterThan(2), "> 2") - .and(Cypress.sinon.match(isLessThan(4), "< 4")), - ); - - expect(spy).to.be.calledWith( - Cypress.sinon.match.number, - Cypress.sinon - .match(isGreaterThan(200), "> 200") - .or(Cypress.sinon.match(3)), - ); - - // matchers can be used from BDD assertions - cy.get("@add").should( - "have.been.calledWith", - Cypress.sinon.match.number, - Cypress.sinon.match(3), - ); - - // you can alias matchers for shorter test code - const { match: M } = Cypress.sinon; - - cy.get("@add").should("have.been.calledWith", M.number, M(3)); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/storage.cy.js b/cypress/e2e/2-advanced-examples/storage.cy.js deleted file mode 100644 index f9277940..00000000 --- a/cypress/e2e/2-advanced-examples/storage.cy.js +++ /dev/null @@ -1,116 +0,0 @@ -/// - -context("Local Storage / Session Storage", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/commands/storage"); - }); - // Although localStorage is automatically cleared - // in between tests to maintain a clean state - // sometimes we need to clear localStorage manually - - it("cy.clearLocalStorage() - clear all data in localStorage for the current origin", () => { - // https://on.cypress.io/clearlocalstorage - cy.get(".ls-btn") - .click() - .should(() => { - expect(localStorage.getItem("prop1")).to.eq("red"); - expect(localStorage.getItem("prop2")).to.eq("blue"); - expect(localStorage.getItem("prop3")).to.eq("magenta"); - }); - - // clearLocalStorage() yields the localStorage object - cy.clearLocalStorage().should((ls) => { - expect(ls.getItem("prop1")).to.be.null; - expect(ls.getItem("prop2")).to.be.null; - expect(ls.getItem("prop3")).to.be.null; - }); - - cy.get(".ls-btn") - .click() - .should(() => { - expect(localStorage.getItem("prop1")).to.eq("red"); - expect(localStorage.getItem("prop2")).to.eq("blue"); - expect(localStorage.getItem("prop3")).to.eq("magenta"); - }); - - // Clear key matching string in localStorage - cy.clearLocalStorage("prop1").should((ls) => { - expect(ls.getItem("prop1")).to.be.null; - expect(ls.getItem("prop2")).to.eq("blue"); - expect(ls.getItem("prop3")).to.eq("magenta"); - }); - - cy.get(".ls-btn") - .click() - .should(() => { - expect(localStorage.getItem("prop1")).to.eq("red"); - expect(localStorage.getItem("prop2")).to.eq("blue"); - expect(localStorage.getItem("prop3")).to.eq("magenta"); - }); - - // Clear keys matching regex in localStorage - cy.clearLocalStorage(/prop1|2/).should((ls) => { - expect(ls.getItem("prop1")).to.be.null; - expect(ls.getItem("prop2")).to.be.null; - expect(ls.getItem("prop3")).to.eq("magenta"); - }); - }); - - it("cy.getAllLocalStorage() - get all data in localStorage for all origins", () => { - // https://on.cypress.io/getalllocalstorage - cy.get(".ls-btn").click(); - - // getAllLocalStorage() yields a map of origins to localStorage values - cy.getAllLocalStorage().should((storageMap) => { - expect(storageMap).to.deep.equal({ - // other origins will also be present if localStorage is set on them - "https://example.cypress.io": { - prop1: "red", - prop2: "blue", - prop3: "magenta", - }, - }); - }); - }); - - it("cy.clearAllLocalStorage() - clear all data in localStorage for all origins", () => { - // https://on.cypress.io/clearalllocalstorage - cy.get(".ls-btn").click(); - - // clearAllLocalStorage() yields null - cy.clearAllLocalStorage().should(() => { - expect(sessionStorage.getItem("prop1")).to.be.null; - expect(sessionStorage.getItem("prop2")).to.be.null; - expect(sessionStorage.getItem("prop3")).to.be.null; - }); - }); - - it("cy.getAllSessionStorage() - get all data in sessionStorage for all origins", () => { - // https://on.cypress.io/getallsessionstorage - cy.get(".ls-btn").click(); - - // getAllSessionStorage() yields a map of origins to sessionStorage values - cy.getAllSessionStorage().should((storageMap) => { - expect(storageMap).to.deep.equal({ - // other origins will also be present if sessionStorage is set on them - "https://example.cypress.io": { - prop4: "cyan", - prop5: "yellow", - prop6: "black", - }, - }); - }); - }); - - it("cy.clearAllSessionStorage() - clear all data in sessionStorage for all origins", () => { - // https://on.cypress.io/clearallsessionstorage - cy.get(".ls-btn").click(); - - // clearAllSessionStorage() yields null - cy.clearAllSessionStorage().should(() => { - expect(sessionStorage.getItem("prop4")).to.be.null; - expect(sessionStorage.getItem("prop5")).to.be.null; - expect(sessionStorage.getItem("prop6")).to.be.null; - }); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/traversal.cy.js b/cypress/e2e/2-advanced-examples/traversal.cy.js deleted file mode 100644 index 2ee4b9bf..00000000 --- a/cypress/e2e/2-advanced-examples/traversal.cy.js +++ /dev/null @@ -1,116 +0,0 @@ -/// - -context("Traversal", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/commands/traversal"); - }); - - it(".children() - get child DOM elements", () => { - // https://on.cypress.io/children - cy.get(".traversal-breadcrumb") - .children(".active") - .should("contain", "Data"); - }); - - it(".closest() - get closest ancestor DOM element", () => { - // https://on.cypress.io/closest - cy.get(".traversal-badge").closest("ul").should("have.class", "list-group"); - }); - - it(".eq() - get a DOM element at a specific index", () => { - // https://on.cypress.io/eq - cy.get(".traversal-list>li").eq(1).should("contain", "siamese"); - }); - - it(".filter() - get DOM elements that match the selector", () => { - // https://on.cypress.io/filter - cy.get(".traversal-nav>li").filter(".active").should("contain", "About"); - }); - - it(".find() - get descendant DOM elements of the selector", () => { - // https://on.cypress.io/find - cy.get(".traversal-pagination") - .find("li") - .find("a") - .should("have.length", 7); - }); - - it(".first() - get first DOM element", () => { - // https://on.cypress.io/first - cy.get(".traversal-table td").first().should("contain", "1"); - }); - - it(".last() - get last DOM element", () => { - // https://on.cypress.io/last - cy.get(".traversal-buttons .btn").last().should("contain", "Submit"); - }); - - it(".next() - get next sibling DOM element", () => { - // https://on.cypress.io/next - cy.get(".traversal-ul") - .contains("apples") - .next() - .should("contain", "oranges"); - }); - - it(".nextAll() - get all next sibling DOM elements", () => { - // https://on.cypress.io/nextall - cy.get(".traversal-next-all") - .contains("oranges") - .nextAll() - .should("have.length", 3); - }); - - it(".nextUntil() - get next sibling DOM elements until next el", () => { - // https://on.cypress.io/nextuntil - cy.get("#veggies").nextUntil("#nuts").should("have.length", 3); - }); - - it(".not() - remove DOM elements from set of DOM elements", () => { - // https://on.cypress.io/not - cy.get(".traversal-disabled .btn") - .not("[disabled]") - .should("not.contain", "Disabled"); - }); - - it(".parent() - get parent DOM element from DOM elements", () => { - // https://on.cypress.io/parent - cy.get(".traversal-mark").parent().should("contain", "Morbi leo risus"); - }); - - it(".parents() - get parent DOM elements from DOM elements", () => { - // https://on.cypress.io/parents - cy.get(".traversal-cite").parents().should("match", "blockquote"); - }); - - it(".parentsUntil() - get parent DOM elements from DOM elements until el", () => { - // https://on.cypress.io/parentsuntil - cy.get(".clothes-nav") - .find(".active") - .parentsUntil(".clothes-nav") - .should("have.length", 2); - }); - - it(".prev() - get previous sibling DOM element", () => { - // https://on.cypress.io/prev - cy.get(".birds").find(".active").prev().should("contain", "Lorikeets"); - }); - - it(".prevAll() - get all previous sibling DOM elements", () => { - // https://on.cypress.io/prevall - cy.get(".fruits-list").find(".third").prevAll().should("have.length", 2); - }); - - it(".prevUntil() - get all previous sibling DOM elements until el", () => { - // https://on.cypress.io/prevuntil - cy.get(".foods-list") - .find("#nuts") - .prevUntil("#veggies") - .should("have.length", 3); - }); - - it(".siblings() - get all sibling DOM elements", () => { - // https://on.cypress.io/siblings - cy.get(".traversal-pills .active").siblings().should("have.length", 2); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/utilities.cy.js b/cypress/e2e/2-advanced-examples/utilities.cy.js deleted file mode 100644 index aa271b62..00000000 --- a/cypress/e2e/2-advanced-examples/utilities.cy.js +++ /dev/null @@ -1,109 +0,0 @@ -/// - -context("Utilities", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/utilities"); - }); - - it("Cypress._ - call a lodash method", () => { - // https://on.cypress.io/_ - cy.request("https://jsonplaceholder.cypress.io/users").then((response) => { - let ids = Cypress._.chain(response.body).map("id").take(3).value(); - - expect(ids).to.deep.eq([1, 2, 3]); - }); - }); - - it("Cypress.$ - call a jQuery method", () => { - // https://on.cypress.io/$ - let $li = Cypress.$(".utility-jquery li:first"); - - cy.wrap($li) - .should("not.have.class", "active") - .click() - .should("have.class", "active"); - }); - - it("Cypress.Blob - blob utilities and base64 string conversion", () => { - // https://on.cypress.io/blob - cy.get(".utility-blob").then(($div) => { - // https://github.com/nolanlawson/blob-util#imgSrcToDataURL - // get the dataUrl string for the javascript-logo - return Cypress.Blob.imgSrcToDataURL( - "https://example.cypress.io/assets/img/javascript-logo.png", - undefined, - "anonymous", - ).then((dataUrl) => { - // create an element and set its src to the dataUrl - let img = Cypress.$("", { src: dataUrl }); - - // need to explicitly return cy here since we are initially returning - // the Cypress.Blob.imgSrcToDataURL promise to our test - // append the image - $div.append(img); - - cy.get(".utility-blob img").click().should("have.attr", "src", dataUrl); - }); - }); - }); - - it("Cypress.minimatch - test out glob patterns against strings", () => { - // https://on.cypress.io/minimatch - let matching = Cypress.minimatch("/users/1/comments", "/users/*/comments", { - matchBase: true, - }); - - expect(matching, "matching wildcard").to.be.true; - - matching = Cypress.minimatch("/users/1/comments/2", "/users/*/comments", { - matchBase: true, - }); - - expect(matching, "comments").to.be.false; - - // ** matches against all downstream path segments - matching = Cypress.minimatch("/foo/bar/baz/123/quux?a=b&c=2", "/foo/**", { - matchBase: true, - }); - - expect(matching, "comments").to.be.true; - - // whereas * matches only the next path segment - - matching = Cypress.minimatch("/foo/bar/baz/123/quux?a=b&c=2", "/foo/*", { - matchBase: false, - }); - - expect(matching, "comments").to.be.false; - }); - - it("Cypress.Promise - instantiate a bluebird promise", () => { - // https://on.cypress.io/promise - let waited = false; - - /** - * @return Bluebird - */ - function waitOneSecond() { - // return a promise that resolves after 1 second - return new Cypress.Promise((resolve, reject) => { - setTimeout(() => { - // set waited to true - waited = true; - - // resolve with 'foo' string - resolve("foo"); - }, 1000); - }); - } - - cy.then(() => { - // return a promise to cy.then() that - // is awaited until it resolves - return waitOneSecond().then((str) => { - expect(str).to.eq("foo"); - expect(waited).to.be.true; - }); - }); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/viewport.cy.js b/cypress/e2e/2-advanced-examples/viewport.cy.js deleted file mode 100644 index 2d0644ab..00000000 --- a/cypress/e2e/2-advanced-examples/viewport.cy.js +++ /dev/null @@ -1,59 +0,0 @@ -/// - -context("Viewport", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/commands/viewport"); - }); - - it("cy.viewport() - set the viewport size and dimension", () => { - // https://on.cypress.io/viewport - - cy.get("#navbar").should("be.visible"); - cy.viewport(320, 480); - - // the navbar should have collapse since our screen is smaller - cy.get("#navbar").should("not.be.visible"); - cy.get(".navbar-toggle").should("be.visible").click(); - cy.get(".nav").find("a").should("be.visible"); - - // lets see what our app looks like on a super large screen - cy.viewport(2999, 2999); - - // cy.viewport() accepts a set of preset sizes - // to easily set the screen to a device's width and height - - // We added a cy.wait() between each viewport change so you can see - // the change otherwise it is a little too fast to see :) - - cy.viewport("macbook-15"); - cy.wait(200); - cy.viewport("macbook-13"); - cy.wait(200); - cy.viewport("macbook-11"); - cy.wait(200); - cy.viewport("ipad-2"); - cy.wait(200); - cy.viewport("ipad-mini"); - cy.wait(200); - cy.viewport("iphone-6+"); - cy.wait(200); - cy.viewport("iphone-6"); - cy.wait(200); - cy.viewport("iphone-5"); - cy.wait(200); - cy.viewport("iphone-4"); - cy.wait(200); - cy.viewport("iphone-3"); - cy.wait(200); - - // cy.viewport() accepts an orientation for all presets - // the default orientation is 'portrait' - cy.viewport("ipad-2", "portrait"); - cy.wait(200); - cy.viewport("iphone-4", "landscape"); - cy.wait(200); - - // The viewport will be reset back to the default dimensions - // in between tests (the default can be set in cypress.config.{js|ts}) - }); -}); diff --git a/cypress/e2e/2-advanced-examples/waiting.cy.js b/cypress/e2e/2-advanced-examples/waiting.cy.js deleted file mode 100644 index 7e9feeb0..00000000 --- a/cypress/e2e/2-advanced-examples/waiting.cy.js +++ /dev/null @@ -1,33 +0,0 @@ -/// - -context("Waiting", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/commands/waiting"); - }); - // BE CAREFUL of adding unnecessary wait times. - // https://on.cypress.io/best-practices#Unnecessary-Waiting - - // https://on.cypress.io/wait - it("cy.wait() - wait for a specific amount of time", () => { - cy.get(".wait-input1").type("Wait 1000ms after typing"); - cy.wait(1000); - cy.get(".wait-input2").type("Wait 1000ms after typing"); - cy.wait(1000); - cy.get(".wait-input3").type("Wait 1000ms after typing"); - cy.wait(1000); - }); - - it("cy.wait() - wait for a specific route", () => { - // Listen to GET to comments/1 - cy.intercept("GET", "**/comments/*").as("getComment"); - - // we have code that gets a comment when - // the button is clicked in scripts.js - cy.get(".network-btn").click(); - - // wait for GET comments/1 - cy.wait("@getComment") - .its("response.statusCode") - .should("be.oneOf", [200, 304]); - }); -}); diff --git a/cypress/e2e/2-advanced-examples/window.cy.js b/cypress/e2e/2-advanced-examples/window.cy.js deleted file mode 100644 index 9740ba04..00000000 --- a/cypress/e2e/2-advanced-examples/window.cy.js +++ /dev/null @@ -1,22 +0,0 @@ -/// - -context("Window", () => { - beforeEach(() => { - cy.visit("https://example.cypress.io/commands/window"); - }); - - it("cy.window() - get the global window object", () => { - // https://on.cypress.io/window - cy.window().should("have.property", "top"); - }); - - it("cy.document() - get the document object", () => { - // https://on.cypress.io/document - cy.document().should("have.property", "charset").and("eq", "UTF-8"); - }); - - it("cy.title() - get the title", () => { - // https://on.cypress.io/title - cy.title().should("include", "Kitchen Sink"); - }); -}); From 156b6afa35fbb7a4c9016d37064a5f70e623a9cc Mon Sep 17 00:00:00 2001 From: Dan Ko Date: Mon, 18 Sep 2023 19:47:01 -0400 Subject: [PATCH 067/127] adjust styles to make main page content adjust with sidebar --- src/app/layout.tsx | 9 +- src/app/page.tsx | 6 +- src/components/index.ts | 1 + src/components/navbar/Navbar.tsx | 2 +- src/components/sidebar/ExpandButton.tsx | 26 ++++ src/components/sidebar/PageButton.tsx | 51 ++++++++ src/components/sidebar/Sidebar.tsx | 136 ++++++++++++++++++++ src/components/sidebar/VoyagePageButton.tsx | 56 ++++++++ src/components/sidebar/VoyageStatus.tsx | 35 +++++ src/components/sidebar/index.ts | 4 + 10 files changed, 318 insertions(+), 8 deletions(-) create mode 100644 src/components/sidebar/ExpandButton.tsx create mode 100644 src/components/sidebar/PageButton.tsx create mode 100644 src/components/sidebar/Sidebar.tsx create mode 100644 src/components/sidebar/VoyagePageButton.tsx create mode 100644 src/components/sidebar/VoyageStatus.tsx create mode 100644 src/components/sidebar/index.ts diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f6ee4da7..ff79f8d9 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,7 +1,7 @@ import "./globals.css"; import type { Metadata } from "next"; import { Inter } from "next/font/google"; -import { StoreProvider, Navbar } from "@/components"; +import { StoreProvider, Navbar, Sidebar } from "@/components"; export const metadata: Metadata = { title: "Create Next App", @@ -23,8 +23,13 @@ export default function RootLayout({ return ( +
- {children} + + +
{children}
+
+
); diff --git a/src/app/page.tsx b/src/app/page.tsx index 8a077e13..ecbb0a8f 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -3,9 +3,5 @@ import { CounterPage } from "."; export default function Home() { - return ( -
- -
- ); + return ; } diff --git a/src/components/index.ts b/src/components/index.ts index 7c17c28d..154dce72 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -2,4 +2,5 @@ export { default as StoreProvider } from "./StoreProvider"; export { default as Avatar } from "./Avatar"; export { default as Button } from "./Button"; export { default as Banner } from "./Banner"; +export { default as Sidebar } from "./sidebar/Sidebar"; export * from "./navbar"; diff --git a/src/components/navbar/Navbar.tsx b/src/components/navbar/Navbar.tsx index f83d2fd5..18a732b3 100644 --- a/src/components/navbar/Navbar.tsx +++ b/src/components/navbar/Navbar.tsx @@ -5,7 +5,7 @@ const notificationCount = 4; export default function Navbar() { return ( -