From 4b86e301f2d05294f73c859ab95384a6cb0da3c6 Mon Sep 17 00:00:00 2001
From: manisha <manisha_kanyal.scsebtech@galgotiasuniversity.edu.in>
Date: Jul 21 2021 14:19:08 +0000
Subject: fedora manual testing page implementation


---

diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..7a73a41
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,2 @@
+{
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 438f2b2..b9a180b 100644
--- a/package.json
+++ b/package.json
@@ -5,15 +5,18 @@
   "homepage": ".",
   "dependencies": {
     "@babel/runtime": "^7.14.0",
+    "clsx": "^1.1.1",
     "dateformat": "^3.0.3",
     "nanoid": "^3.1.22",
     "query-string": "^7.0.0",
     "ramda": "^0.27.1",
     "react": "^16.5.2",
+    "react-animate-on-scroll": "^2.1.5",
     "react-dom": "^16.5.2",
     "react-redux": "^7.2.1",
     "react-router-dom": "^5.2.0",
     "react-scripts": "^3.3.0",
+    "react-scroll": "^1.8.2",
     "react-step-wizard": "^5.3.6",
     "reactstrap": "^6.5.0",
     "redux": "^4.0.5",
diff --git a/src/index.css b/src/index.css
index f92ce94..780fc07 100644
--- a/src/index.css
+++ b/src/index.css
@@ -16,7 +16,7 @@ body {
   margin: 0;
   padding: 0;
   background-color: #fff;
-  padding-bottom: 10rem;
+  /* padding-bottom: 10rem; */
 }
 
 code {
@@ -113,6 +113,9 @@ ol.steps > li {
 
 .card {
   font-size: 0.9rem !important;
+}
+
+.cards {
   height: 100%;
 }
 
@@ -213,7 +216,7 @@ ol.steps > li {
 .disabled {
   pointer-events: none;
   cursor: default;
-  color: rgb(104, 102, 102);
+  color: #7d7c7c;
 }
 
 .enable {
@@ -225,3 +228,42 @@ ol.steps > li {
 .enable:hover {
   text-decoration: underline;
 }
+
+.overlay {
+  background-color: #fff;
+  color: #ddd;
+  transition: background-color 200ms linear;
+  transition: color 200ms linear;
+}
+
+.cardHeader {
+  background: rgb(165, 164, 164);
+}
+
+.manual-wrapper {
+  margin-top: 3em;
+  height: 70vh;
+}
+.color {
+  background-color: #84c48e;
+  color: white;
+}
+
+.btn-secondary.disabled,
+.btn-secondary:disabled {
+  color: rgb(90, 90, 90);
+  background-color: #6fb37a;
+}
+
+.sticky {
+  position: sticky;
+  top: 1em;
+}
+
+.scrollable-container {
+  position: relative;
+}
+
+.bottom-padding {
+  margin-bottom: 5px;
+}
diff --git a/src/landingpage/Blockers.js b/src/landingpage/Blockers.js
index 89efa98..22e1a9a 100644
--- a/src/landingpage/Blockers.js
+++ b/src/landingpage/Blockers.js
@@ -12,7 +12,7 @@ class Blockers extends Component {
   render() {
     if (this.props.data)
       return (
-        <Card>
+        <Card className="cards">
           <CardBody>
             <h1 className="text-center padded">
               Fedora {this.props.release} blockers and FEs{" "}
diff --git a/src/landingpage/Events.js b/src/landingpage/Events.js
index 3151841..811f07e 100644
--- a/src/landingpage/Events.js
+++ b/src/landingpage/Events.js
@@ -20,6 +20,7 @@ class Events extends Component {
       }
       return (
         <Event
+          key={meeting.link}
           date={date}
           month={month}
           time={time}
@@ -30,7 +31,7 @@ class Events extends Component {
       )
     })
     return (
-      <Card>
+      <Card className="cards">
         <CardBody>
           <h1 className="text-center padded">
             Meetings and testdays in the next 7 days{" "}
@@ -48,14 +49,14 @@ class Event extends Component {
     return (
       <Row>
         <Col md={6}>
-          <div class="d-flex flex-row align-items-center event">
-            <div class="d-flex flex-column align-items-center date">
-              <span class="month"> {this.props.month}</span>
-              <span class="day">{this.props.date}</span>
+          <div className="d-flex flex-row align-items-center event">
+            <div className="d-flex flex-column align-items-center date">
+              <span className="month"> {this.props.month}</span>
+              <span className="day">{this.props.date}</span>
             </div>
 
-            <div class="d-flex flex-column align-items-left">
-              <span class="title">
+            <div className="d-flex flex-column align-items-left">
+              <span className="title">
                 <a
                   className="events"
                   target="_blank"
@@ -64,7 +65,7 @@ class Event extends Component {
                   {this.props.summary}
                 </a>
               </span>
-              <span class="time">{this.props.time}</span>
+              <span className="time">{this.props.time}</span>
             </div>
           </div>
         </Col>
diff --git a/src/landingpage/Minutes.js b/src/landingpage/Minutes.js
index e2646db..7f82197 100644
--- a/src/landingpage/Minutes.js
+++ b/src/landingpage/Minutes.js
@@ -4,7 +4,7 @@ import { Card, CardBody } from "reactstrap"
 class Events extends Component {
   render() {
     return (
-      <Card className="mt-20">
+      <Card className="cards">
         <CardBody>
           <h1 className="text-center padded">Fedora QA Meeting Minutes</h1>
           <div className="events">
diff --git a/src/wizard/Manual.js b/src/wizard/Manual.js
new file mode 100644
index 0000000..3583336
--- /dev/null
+++ b/src/wizard/Manual.js
@@ -0,0 +1,105 @@
+import React, { useRef, useEffect, useState } from "react"
+import { useHistory, useLocation } from "react-router-dom"
+import queryString from "query-string"
+
+import Tab from "./manualTesting/Tab"
+
+const data = [
+  {
+    title: "Preperation",
+    description:
+      " Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISOLorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO",
+  },
+  {
+    title: "Installation",
+    description:
+      " Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISOLorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO",
+  },
+  {
+    title: "Testing",
+    description:
+      " Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISOLorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO",
+  },
+  {
+    title: "Reporting",
+    description:
+      " Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISOLorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO Lorem ipsum some clever text where to get ISO",
+  },
+]
+
+const addDetailsToData = (data) => {
+  return data.map(({ description, title }, index) => {
+    return {
+      title,
+      description,
+      id: `box${index + 1}`,
+      nextBox: data.length === index + 1 ? "final" : `box${index + 2}`,
+    }
+  })
+}
+
+const createVisibilityObject = (data) => {
+  const detailedData = addDetailsToData(data)
+  const visibility = {}
+  detailedData.forEach((item) => {
+    visibility[item.id] = 0
+  })
+  return visibility
+}
+
+const Manual = (props) => {
+  const [check, setCheck] = useState([])
+  const tabs = addDetailsToData(data) || []
+  const [visibility, setVisibility] = useState(createVisibilityObject(data) || {})
+
+  const location = useLocation()
+  const history = useHistory()
+  const params = queryString.parse(location.search)
+  const { tab = "box1" } = params
+
+  const ref = useRef()
+
+  const indexOfMaxValue = (arr) => {
+    return arr.reduce((acc, x, i, arr) => (x >= arr[acc] ? i : acc), 0)
+  }
+
+  const onNext = (box, currentBox) => {
+    if (box === "final") {
+      history.push("/wizard/few_hours/fedora_manual_testing/manual_testing")
+    } else {
+      history.push(`?tab=${box}`)
+    }
+
+    if (check.length - (check.indexOf(currentBox) + 1) >= 0 && check.indexOf(currentBox) !== -1) {
+      const currValue = check.slice(0, check.indexOf(currentBox))
+      setCheck([...currValue])
+    }
+
+    if (currentBox && !check.includes(currentBox)) {
+      setCheck([...check, currentBox])
+    }
+  }
+
+  useEffect(() => {
+    const maxIndex = indexOfMaxValue(Object.values(visibility))
+    history.push(`?tab=box${maxIndex + 1}`)
+  }, [history, visibility])
+
+  return (
+    <>
+      {tabs.map((item, index) => (
+        <div id={item.id} className="manual-wrapper" ref={ref} key={item.id}>
+          <Tab
+            check={check}
+            data={item}
+            hidden={item.id !== tab}
+            onNext={onNext}
+            setVisibility={setVisibility}
+          />
+        </div>
+      ))}
+    </>
+  )
+}
+
+export default Manual
diff --git a/src/wizard/Wizard.js b/src/wizard/Wizard.js
index 868ecd6..2459584 100644
--- a/src/wizard/Wizard.js
+++ b/src/wizard/Wizard.js
@@ -6,7 +6,6 @@ import { useDispatch, useSelector, shallowEqual } from "react-redux"
 import { loadWizardData } from "../actions/reduxActions"
 import WizardStepper from "./WizardStepper"
 import { useParams } from "react-router"
-
 import WizardNavigation from "./WizardNavigation"
 
 const Wizard = (props) => {
@@ -33,7 +32,7 @@ const Wizard = (props) => {
             <WizardNavigation step={step} />
             <WizardStepper step={step} />
 
-            {query.issues || query.action || query.provider === "fedora_easy_karma" ? (
+            {query.issues || query.provider === "fedora_easy_karma" ? (
               <Col md="12">
                 <h5 className="padded text-center">
                   None of the above looks interesting to you? We'd be happy if you looked around at{" "}
diff --git a/src/wizard/WizardNavigation.js b/src/wizard/WizardNavigation.js
index 2ff4d0f..0e97b99 100644
--- a/src/wizard/WizardNavigation.js
+++ b/src/wizard/WizardNavigation.js
@@ -73,15 +73,21 @@ function WizardNavigation(props) {
     createBreadcrumbItem(
       "Actions",
       step.slice(-1) > "4" ? "enable" : "disabled",
-      query.action
+      query.action === "manual_testing"
+        ? "Manual Testing"
+        : query.action === "beginner_guide"
+        ? "Beginner Guide"
+        : query.action
         ? getTags().filter((a) => a.toLowerCase() === decodeURIComponent(query.action))[0] ||
-            query.action.charAt(0).toUpperCase() + query.action.slice(1)
+          query.action.charAt(0).toUpperCase() + query.action.slice(1)
         : null
     ),
     createBreadcrumbItem(
       "Issues",
       step.slice(-1) > "5" ? "enable" : "disabled",
-      decodeURIComponent(query.issues)
+      query.action === "manual_testing" && query.issues
+        ? query.issues.charAt(0).toUpperCase() + query.issues.slice(1)
+        : decodeURIComponent(query.issues)
     ),
   ]
 
diff --git a/src/wizard/manualTesting/Intersection.js b/src/wizard/manualTesting/Intersection.js
new file mode 100644
index 0000000..c716321
--- /dev/null
+++ b/src/wizard/manualTesting/Intersection.js
@@ -0,0 +1,23 @@
+import { useState, useEffect } from "react"
+export function useOnScreen(ref) {
+  const [isIntersecting, setIntersecting] = useState(false)
+
+  const observer = new IntersectionObserver(
+    ([entry]) => {
+      setIntersecting(entry.intersectionRatio)
+    },
+    {
+      threshold: [0.01, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.99, 1.0],
+    }
+  )
+
+  useEffect(() => {
+    observer.observe(ref.current)
+
+    return () => {
+      observer.disconnect()
+    }
+  }, [observer, ref])
+
+  return isIntersecting
+}
diff --git a/src/wizard/manualTesting/Tab.js b/src/wizard/manualTesting/Tab.js
new file mode 100644
index 0000000..dcde5da
--- /dev/null
+++ b/src/wizard/manualTesting/Tab.js
@@ -0,0 +1,48 @@
+import React, { useEffect, useRef } from "react"
+import { Card, CardBody, CardText, Button, CardHeader } from "reactstrap"
+import { useOnScreen } from "./Intersection"
+import { Link } from "react-scroll"
+import clsx from "clsx"
+
+function Tab(props) {
+  const {
+    data: { title, description, nextBox, id },
+    hidden = false,
+    check,
+    onNext,
+    setVisibility,
+  } = props
+
+  const ref = useRef()
+  const visible = useOnScreen(ref)
+
+  useEffect(() => {
+    setVisibility((visibility) => ({ ...visibility, [id]: visible }))
+  }, [visible, setVisibility, id])
+
+  return (
+    <>
+      <Card className={hidden ? "sticky overlay card-container" : "sticky card-container "}>
+        <div className="scrollable-container" ref={ref}>
+          <CardHeader className={check.includes(id) ? "color" : "cardHeader"}>{title}</CardHeader>
+          <CardBody>
+            <CardText>{description}</CardText>
+            <Link smooth={true} to={nextBox} offset={-160} onClick={() => onNext(nextBox, id)}>
+              <Button
+                className={clsx({
+                  "bottom-padding": true,
+                  "float-right": true,
+                  color: check.includes(id),
+                  cardHeader: hidden,
+                })}>
+                <i className="fas fa-check"></i>
+              </Button>
+            </Link>
+          </CardBody>
+        </div>
+      </Card>
+    </>
+  )
+}
+
+export default Tab
diff --git a/src/wizard/step/Step1.js b/src/wizard/step/Step1.js
index 31e8d31..cd6ae98 100644
--- a/src/wizard/step/Step1.js
+++ b/src/wizard/step/Step1.js
@@ -15,33 +15,34 @@ const Step1 = (props) => {
       <Col sm="6">
         <Card
           className={
-            "clickable text-center" + (selectedItem === "Several_days" ? " card-selected" : "")
+            "cards clickable text-center" + (selectedItem === "few_hours" ? " card-selected" : "")
           }
           body
           type="btn"
           onClick={() => {
-            handleStep("several_days")
+            handleStep("few_hours")
           }}>
           <h1 className="padded">
-            Several Days <i className="fas fa-calendar-week"></i>
+            Few Hours <i className="fas fa-calendar-day"></i>
           </h1>
-          <CardText>Task that can take up to Several Days </CardText>
+          <CardText>Task that can take up to Few Hours </CardText>
         </Card>
       </Col>
       <Col sm="6">
         <Card
           className={
-            "clickable text-center" + (selectedItem === "few_hours" ? " card-selected" : "")
+            "cards clickable text-center" +
+            (selectedItem === "Several_days" ? " card-selected" : "")
           }
           body
           type="btn"
           onClick={() => {
-            handleStep("few_hours")
+            handleStep("several_days")
           }}>
           <h1 className="padded">
-            Few Hours <i className="fas fa-calendar-day"></i>
+            Several Days <i className="fas fa-calendar-week"></i>
           </h1>
-          <CardText>Task that can take up to Few Hours </CardText>
+          <CardText>Task that can take up to Several Days </CardText>
         </Card>
       </Col>
     </Row>
diff --git a/src/wizard/step/Step2.js b/src/wizard/step/Step2.js
index 2ae97ff..848190a 100644
--- a/src/wizard/step/Step2.js
+++ b/src/wizard/step/Step2.js
@@ -40,7 +40,7 @@ const Step2 = (props) => {
             <Col sm="6" key={item.provider}>
               <Card
                 className={
-                  "clickable text-center" +
+                  "cards clickable text-center" +
                   (selectedItem === item.provider ? " card-selected" : "")
                 }
                 onClick={() => {
@@ -64,7 +64,7 @@ const Step2 = (props) => {
             <Col sm="6" key={item.provider}>
               <Card
                 className={
-                  "clickable text-center" +
+                  "cards clickable text-center" +
                   (selectedItem === item.provider ? " card-selected" : "")
                 }
                 onClick={() => {
diff --git a/src/wizard/step/Step3.js b/src/wizard/step/Step3.js
index 7ca64bb..74787c8 100644
--- a/src/wizard/step/Step3.js
+++ b/src/wizard/step/Step3.js
@@ -1,6 +1,6 @@
 import React, { useState } from "react"
 import { shallowEqual, useSelector } from "react-redux"
-import { Card, CardBody, CardTitle, Col, Row, CardHeader } from "reactstrap"
+import { Card, CardBody, CardTitle, Col, Row, CardText } from "reactstrap"
 
 import FedoraEasyKarma from "../FedoraEasyKarma"
 import * as R from "ramda"
@@ -34,16 +34,6 @@ const Step3 = (props) => {
     return tags
   }
 
-  const getData2 = () => {
-    const getUniqueTags = R.pipe(
-      R.map((action) => action.extra_data.testtype),
-      R.flatten,
-      R.uniq
-    )
-    const tags = getUniqueTags(grouped["fedora_manual_testing"])
-    return tags
-  }
-
   const getLanguageIcon = (lang) => {
     switch (lang) {
       case "Python":
@@ -59,112 +49,34 @@ const Step3 = (props) => {
     }
   }
 
-  const getIcontestype = (item) => {
-    switch (item) {
-      case "Cloud":
-        return <i className="fas fa-cloud"></i>
-      case "Installation":
-        return <i className="fas fa-download"></i>
-      case "Desktop":
-        return <i className="fas fa-desktop"></i>
-      case "Server":
-        return <i className="fas fa-server"></i>
-      default:
-        return <i className="fab fa-fedora"></i>
-    }
-  }
-
-  const getTesttype = (testtype) => {
-    switch (testtype) {
-      case "Installation":
-        return (
-          <div className="text-left">
-            The <strong>Installation</strong> testcases generally deal with a part of the
-            installation procedure.
-            <br />
-            You will certainly need an installation ISO, and either a Virtual or Bare-metal machine
-            to run the test.
-            <br />
-            <i>Note:</i> some (not that many, though) of these testcases require Bare-metal
-            machine. Be sure to read the Description of the testcase carefully.
-          </div>
-        )
-
-      case "Desktop":
-        return (
-          <div className="text-left">
-            The <strong>Desktop</strong> testcases cover basic functionality of the desktop
-            environment.
-            <br />
-            You can either install Fedora onto clean Virtual or Bare-metal machine, or use a Live
-            image instead.
-          </div>
-        )
-
-      case "Base":
-        return (
-          <div className="text-left">
-            The <strong>Base</strong> testcases cover the system&#x27;s basic functionality just
-            after a clean installation.
-            <br />
-            Most times, you will be asked to perform a clean Fedora installation. You can use
-            either Virtual or Bare-metal machine.
-            <br />
-            <i>Pro tip:</i> using a snapshot of cleanly installed Virtual machine is just fine. No
-            need to reinstall for every testcase.
-          </div>
-        )
-
-      case "Server":
-        return (
-          <div className="text-left">
-            The <strong>Server</strong> testcases usually require multiple machines to test the
-            server-client behaviour, and might feel a bit advanced.
-          </div>
-        )
-
-      case "Cloud":
-        return (
-          <div className="text-left">
-            Even thought the <strong>Cloud</strong> testcases are best done in the specific
-            environments like EC2 or Openstack, you can also perform them locally using Testcloud.
-            <br />
-            Have a look at the{" "}
-            <a
-              target="_blank"
-              rel="noopener noreferrer"
-              href="https://fedoraproject.org/wiki/Test_Results:Fedora_Current_Cloud#Cloud_Provider_Setup">
-              Cloud provider setup
-            </a>{" "}
-            guides for more details.
-          </div>
-        )
-
-      default:
-        break
-    }
-  }
-
   return (
     <Row>
       {query.provider === "fedora_manual_testing" && (
         <>
-          {getData2().map((item) => (
-            <Col sm="6" className="card-container" key={item.toString()}>
-              <Card
-                onClick={() => {
-                  handleStep(item)
-                }}
-                className={
-                  "clickable text-center" + (selectedItem === item ? " card-selected" : "")
-                }>
-                <CardHeader className="title">
-                  {item} {getIcontestype(item)}{" "}
-                </CardHeader>
-                <CardBody>{getTesttype(item)}</CardBody>
-              </Card>
-            </Col>
-          ))}
+          <Col sm="6" className="card-container">
+            <Card
+              className="cards clickable text-center"
+              onClick={() => {
+                handleStep("beginner_guide")
+              }}>
+              <CardBody>
+                <h1 className="padded">I'm a complete beginner</h1>
+                <CardText> please guide to me this </CardText>
+              </CardBody>
+            </Card>
+          </Col>
+          <Col sm="6" className="card-container">
+            <Card
+              className="cards clickable text-center"
+              onClick={() => {
+                handleStep("manual_testing")
+              }}>
+              <CardBody>
+                <h1 className="padded">I've already done this</h1>
+                <CardText>Show me the test cases </CardText>
+              </CardBody>
+            </Card>
+          </Col>
         </>
       )}
 
@@ -183,7 +95,7 @@ const Step3 = (props) => {
             <Col sm="6" key={lang.toString()}>
               <Card
                 className={
-                  "clickable text-center" + (selectedItem === lang ? " card-selected" : "")
+                  "cards clickable text-center" + (selectedItem === lang ? " card-selected" : "")
                 }
                 onClick={() => {
                   handleStep(lang)
diff --git a/src/wizard/step/Step4.js b/src/wizard/step/Step4.js
index 08cc284..6b7b3ca 100644
--- a/src/wizard/step/Step4.js
+++ b/src/wizard/step/Step4.js
@@ -2,17 +2,26 @@ import React from "react"
 import { Row, Col, Card, CardBody, CardHeader } from "reactstrap"
 import { shallowEqual, useSelector } from "react-redux"
 import * as R from "ramda"
-import { FedoraManualTestingItem } from "../FedoraManualTesting"
 import { useHistory } from "react-router-dom"
+import Manual from "../Manual"
+
 const Step4 = (props) => {
   const { query } = props
 
   const history = useHistory()
 
   const handleChange = (option) => {
-    history.push(
-      `/wizard/${query.duration}/${query.provider}/${query.action}/${encodeURIComponent(option)}`
-    )
+    if (query.action === "manual_testing") {
+      history.push(
+        `/wizard/${query.duration}/${query.provider}/${query.action}/${encodeURIComponent(
+          option.toLowerCase()
+        )}`
+      )
+    } else {
+      history.push(
+        `/wizard/${query.duration}/${query.provider}/${query.action}/${encodeURIComponent(option)}`
+      )
+    }
   }
 
   const selectAction = (state) => state.wizard.all_actions
@@ -31,6 +40,16 @@ const Step4 = (props) => {
     return tags
   }
 
+  const getData2 = () => {
+    const getUniqueTags = R.pipe(
+      R.map((action) => action.extra_data.testtype),
+      R.flatten,
+      R.uniq
+    )
+    const tags = getUniqueTags(grouped2["fedora_manual_testing"])
+    return tags
+  }
+
   const getEasyfix = () => {
     const actions = R.filter(
       (a) =>
@@ -49,15 +68,90 @@ const Step4 = (props) => {
 
   const easyData = processData(getEasyfix() || [], "repo_fullname")
 
-  const getFedoraManualTesting = () => {
-    const actions = R.filter(
-      (a) =>
-        a.extra_data.testtype.includes(
-          query.action.charAt(0).toUpperCase() + query.action.slice(1)
-        ),
-      grouped2["fedora_manual_testing"]
-    )
-    return actions
+  const getIcontestype = (item) => {
+    switch (item) {
+      case "Cloud":
+        return <i className="fas fa-cloud"></i>
+      case "Installation":
+        return <i className="fas fa-download"></i>
+      case "Desktop":
+        return <i className="fas fa-desktop"></i>
+      case "Server":
+        return <i className="fas fa-server"></i>
+      default:
+        return <i className="fab fa-fedora"></i>
+    }
+  }
+
+  const getTesttype = (testtype) => {
+    switch (testtype) {
+      case "Installation":
+        return (
+          <div className="text-left">
+            The <strong>Installation</strong> testcases generally deal with a part of the
+            installation procedure.
+            <br />
+            You will certainly need an installation ISO, and either a Virtual or Bare-metal machine
+            to run the test.
+            <br />
+            <i>Note:</i> some (not that many, though) of these testcases require Bare-metal
+            machine. Be sure to read the Description of the testcase carefully.
+          </div>
+        )
+
+      case "Desktop":
+        return (
+          <div className="text-left">
+            The <strong>Desktop</strong> testcases cover basic functionality of the desktop
+            environment.
+            <br />
+            You can either install Fedora onto clean Virtual or Bare-metal machine, or use a Live
+            image instead.
+          </div>
+        )
+
+      case "Base":
+        return (
+          <div className="text-left">
+            The <strong>Base</strong> testcases cover the system&#x27;s basic functionality just
+            after a clean installation.
+            <br />
+            Most times, you will be asked to perform a clean Fedora installation. You can use
+            either Virtual or Bare-metal machine.
+            <br />
+            <i>Pro tip:</i> using a snapshot of cleanly installed Virtual machine is just fine. No
+            need to reinstall for every testcase.
+          </div>
+        )
+
+      case "Server":
+        return (
+          <div className="text-left">
+            The <strong>Server</strong> testcases usually require multiple machines to test the
+            server-client behaviour, and might feel a bit advanced.
+          </div>
+        )
+
+      case "Cloud":
+        return (
+          <div className="text-left">
+            Even thought the <strong>Cloud</strong> testcases are best done in the specific
+            environments like EC2 or Openstack, you can also perform them locally using Testcloud.
+            <br />
+            Have a look at the{" "}
+            <a
+              target="_blank"
+              rel="noopener noreferrer"
+              href="https://fedoraproject.org/wiki/Test_Results:Fedora_Current_Cloud#Cloud_Provider_Setup">
+              Cloud provider setup
+            </a>{" "}
+            guides for more details.
+          </div>
+        )
+
+      default:
+        break
+    }
   }
 
   return (
@@ -65,23 +159,32 @@ const Step4 = (props) => {
       {query.provider === "easyfix" &&
         Object.keys(easyData).map((key) => (
           <Col key={key} sm="6" className="card-container">
-            <Card className="clickable text-center" onClick={() => handleChange(key)}>
+            <Card className="cards clickable text-center" onClick={() => handleChange(key)}>
               <CardHeader className="title">{key}</CardHeader>
               <CardBody className="text-left">{easyData[key][0].extra_data.description}</CardBody>
             </Card>
           </Col>
         ))}
-      {query.provider === "fedora_manual_testing" &&
-        getFedoraManualTesting().map((data, index) => (
-          <Col key={index} sm="4" md="3" className="card-container">
-            <Card>
-              <CardHeader>{data.extra_data.milestone}</CardHeader>
-              <CardBody>
-                <FedoraManualTestingItem data={data} />
-              </CardBody>
+      {query.action === "manual_testing" &&
+        getData2().map((item) => (
+          <Col sm="6" className="card-container" key={item.toString()}>
+            <Card
+              onClick={() => {
+                handleChange(item)
+              }}
+              className="cards clickable text-center">
+              <CardHeader className="title">
+                {item} {getIcontestype(item)}{" "}
+              </CardHeader>
+              <CardBody>{getTesttype(item)}</CardBody>
             </Card>
           </Col>
         ))}
+      {query.action === "beginner_guide" && (
+        <Col sm="12">
+          <Manual query={query} />
+        </Col>
+      )}
     </Row>
   )
 }
diff --git a/src/wizard/step/Step5.js b/src/wizard/step/Step5.js
index 7755293..35b8333 100644
--- a/src/wizard/step/Step5.js
+++ b/src/wizard/step/Step5.js
@@ -2,6 +2,7 @@ import React from "react"
 import { Row, Col, Card, CardBody, CardHeader } from "reactstrap"
 import * as R from "ramda"
 import { shallowEqual, useSelector } from "react-redux"
+import { FedoraManualTestingItem } from "../FedoraManualTesting"
 
 const Step5 = (props) => {
   const { query } = props
@@ -10,6 +11,7 @@ const Step5 = (props) => {
 
   const actions = useSelector(selectAction, shallowEqual)
   const grouped = R.groupBy((action) => action.provider, actions["easyfix"])
+  const grouped2 = R.groupBy((action) => action.provider, actions["fedora_manual_testing"])
 
   const getIssues = () => {
     const actions = R.filter(
@@ -19,12 +21,23 @@ const Step5 = (props) => {
     return actions
   }
 
+  const getFedoraManualTesting = () => {
+    const actions = R.filter(
+      (a) =>
+        a.extra_data.testtype.includes(
+          query.issues.charAt(0).toUpperCase() + query.issues.slice(1)
+        ),
+      grouped2["fedora_manual_testing"]
+    )
+    return actions
+  }
+
   return (
     <Row>
       {query.issues &&
         getIssues().map((data) => (
           <Col sm="4" md="3" className="card-container" key={data.extra_data.ticket_url}>
-            <Card>
+            <Card className="cards">
               <CardHeader>{data.extra_data.repo_name}</CardHeader>
               <CardBody>
                 <a href={data.extra_data.ticket_url} target="_blank" rel="noopener noreferrer">
@@ -34,6 +47,17 @@ const Step5 = (props) => {
             </Card>
           </Col>
         ))}
+      {query.issues &&
+        getFedoraManualTesting().map((data, index) => (
+          <Col key={index} sm="4" md="3" className="card-container">
+            <Card className="cards">
+              <CardHeader>{data.extra_data.milestone}</CardHeader>
+              <CardBody>
+                <FedoraManualTestingItem data={data} />
+              </CardBody>
+            </Card>
+          </Col>
+        ))}
     </Row>
   )
 }
diff --git a/yarn.lock b/yarn.lock
index 8c2d60b..27a512e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1378,16 +1378,6 @@
   resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
   integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
 
-"@reduxjs/toolkit@^1.5.1":
-  version "1.5.1"
-  resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.5.1.tgz#05daa2f6eebc70dc18cd98a90421fab7fa565dc5"
-  integrity sha512-PngZKuwVZsd+mimnmhiOQzoD0FiMjqVks6ituO1//Ft5UEX5Ca9of13NEjo//pU22Jk7z/mdXVsmDfgsig1osA==
-  dependencies:
-    immer "^8.0.1"
-    redux "^4.0.0"
-    redux-thunk "^2.3.0"
-    reselect "^4.0.0"
-
 "@svgr/babel-plugin-add-jsx-attribute@^4.2.0":
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1"
@@ -2495,11 +2485,6 @@ boolbase@^1.0.0, boolbase@~1.0.0:
   resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
   integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
 
-bootstrap@^4.4.1:
-  version "4.6.0"
-  resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.6.0.tgz#97b9f29ac98f98dfa43bf7468262d84392552fd7"
-  integrity sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw==
-
 brace-expansion@^1.1.7:
   version "1.1.11"
   resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -2981,6 +2966,11 @@ clone-deep@^4.0.1:
     kind-of "^6.0.2"
     shallow-clone "^3.0.0"
 
+clsx@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
+  integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==
+
 co@^4.6.0:
   version "4.6.0"
   resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@@ -5300,11 +5290,6 @@ immer@1.10.0:
   resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d"
   integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg==
 
-immer@^8.0.1:
-  version "8.0.4"
-  resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.4.tgz#3a21605a4e2dded852fb2afd208ad50969737b7a"
-  integrity sha512-jMfL18P+/6P6epANRvRk6q8t+3gGhqsJ9EuJ25AXE+9bNTYtssvzeYbEd0mXRYWCmmXSIbnlpz6vd6iJlmGGGQ==
-
 import-cwd@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"
@@ -6653,6 +6638,11 @@ lodash.templatesettings@^4.0.0:
   dependencies:
     lodash._reinterpolate "^3.0.0"
 
+lodash.throttle@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
+  integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
+
 lodash.tonumber@^4.0.3:
   version "4.0.3"
   resolved "https://registry.yarnpkg.com/lodash.tonumber/-/lodash.tonumber-4.0.3.tgz#0b96b31b35672793eb7f5a63ee791f1b9e9025d9"
@@ -8501,7 +8491,7 @@ prompts@^2.0.1:
     kleur "^3.0.3"
     sisteransi "^1.0.5"
 
-prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
+prop-types@^15.5.8, prop-types@^15.5.9, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
   version "15.7.2"
   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
   integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -8670,6 +8660,14 @@ raw-body@2.4.0:
     iconv-lite "0.4.24"
     unpipe "1.0.0"
 
+react-animate-on-scroll@^2.1.5:
+  version "2.1.5"
+  resolved "https://registry.yarnpkg.com/react-animate-on-scroll/-/react-animate-on-scroll-2.1.5.tgz#c35ff5b19452b23270c7a42329b8dc391f273020"
+  integrity sha1-w1/1sZRSsjJwx6QjKbjcOR8nMCA=
+  dependencies:
+    lodash.throttle "^4.1.1"
+    prop-types "^15.5.9"
+
 react-app-polyfill@^1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-1.0.6.tgz#890f8d7f2842ce6073f030b117de9130a5f385f0"
@@ -8846,6 +8844,19 @@ react-scripts@^3.3.0:
   optionalDependencies:
     fsevents "2.1.2"
 
+react-scroll@^1.8.2:
+  version "1.8.2"
+  resolved "https://registry.yarnpkg.com/react-scroll/-/react-scroll-1.8.2.tgz#68e35b74ae296c88e7863393c9fd49f05afa29f5"
+  integrity sha512-f2ZEG5fsPbPTySI9ekcFpETCcNlqbmwbQj9hhzYK8tkgv+PA8APatSt66o/q0KSkDZxyT98ONTtXp9x0lyowEw==
+  dependencies:
+    lodash.throttle "^4.1.1"
+    prop-types "^15.7.2"
+
+react-step-wizard@^5.3.6:
+  version "5.3.6"
+  resolved "https://registry.yarnpkg.com/react-step-wizard/-/react-step-wizard-5.3.6.tgz#d109d741d258166fc2c08dabefd689764ec7a194"
+  integrity sha512-cJiJ+Pgku10scyL39HYKPgwoZQLgtOs4tVo9LC6IUoUqXdElrMrwRjSwOJrRgL6OmTAUaLIzAhq7mNSqaYtvMw==
+
 react-transition-group@^2.3.1:
   version "2.9.0"
   resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"
@@ -9156,11 +9167,6 @@ requires-port@^1.0.0:
   resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
   integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
 
-reselect@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7"
-  integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==
-
 resolve-cwd@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"

