Repository: open-sauced/open-sauced (js)

Issue:
Feature: Remove url dependency for issue number
### Type of feature

🍕 Feature

### Current behavior

When visiting a repository it is required to have the goal issue number in the url. I would like to remove that so anyone can view any repo. 

### Suggested solution

Remove :id here https://github.com/open-sauced/open-sauced/blob/main/src/containers/Dashboard.jsx#L11

Also watch for tests to not fail. 

### Additional context

_No response_

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct

### Contributing Docs

- [X] I agree to follow this project's Contribution Docs

Pull request:
feat: no issue id in url
<!--
  For Work In Progress Pull Requests, please use the Draft PR feature,
  see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for further details.
  
  For a timely review/response, please avoid force-pushing additional
  commits if your PR already received reviews or comments.
  
  Before submitting a Pull Request, please ensure you've done the following:
  - 📖 Read the Open Sauced Contributing Guide: https://github.com/open-sauced/open-sauced/blob/HEAD/CONTRIBUTING.md#create-a-pull-request.
  - 📖 Read the Open Sauced Code of Conduct: https://github.com/open-sauced/open-sauced/blob/HEAD/CODE_OF_CONDUCT.md.
  - 👷‍♀️ Create small PRs. In most cases, this will be possible.
  - ✅ Provide tests for your changes.
  - 📝 Use descriptive commit messages.
  - 📗 Update any related documentation and include any relevant screenshots.
-->

## What type of PR is this? (check all applicable)

- [x] 🍕 Feature
- [ ] 🐛 Bug Fix
- [ ] 📝 Documentation Update
- [ ] 🎨 Style
- [x] 🧑‍💻 Code Refactor
- [ ] 🔥 Performance Improvements
- [x] ✅ Test
- [ ] 🤖 Build
- [ ] 🔁 CI
- [ ] 📦 Chore (Release)
- [ ] ⏩ Revert

## Description

<!-- Please do not leave this blank -->

In response to issue #1424, this PR makes the following changes:

- pulls issue ID references and dependent components out of Repository.jsx
- updates state for whether to show any kind of fork button ("Fork" or "View Fork")
- updates Route in App.jsx not to look at issue number, and to allow viewing repos
 without being logged in, but still passing user through
- updates Route in Dashboard.jsx not to look at issue number
- updates ListGoals component not use goal number
- updates tests for ListGoals component, including having links without goal number

## Related Tickets & Documents
<!-- 
Please use this format link issue numbers: Fixes #123
https://docs.github.com/en/free-pro-team@latest/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword 
-->

Resolves #1424 

## Mobile & Desktop Screenshots/Recordings

<!-- Visual changes require screenshots -->
Repository, URL does not contain issue number, user logged out:
![Screen Shot 2022-05-06 at 10 43 20 PM](https://user-images.githubusercontent.com/3792749/167234955-21a417ab-a6ce-4522-b67e-66841cc18a73.png)

Repository, URL does not contain issue number, user logged in:
![Screen Shot 2022-05-06 at 10 43 40 PM](https://user-images.githubusercontent.com/3792749/167234957-a14918eb-5d9b-4217-8719-43d8917d5606.png)

ListGoals, link does not contain issue number.
![Screen Shot 2022-05-06 at 10 44 00 PM](https://user-images.githubusercontent.com/3792749/167234959-3a13347d-56f9-41cd-af8b-ca36c7a7b474.png)


## Added tests?

- [x] 👍 yes
- [ ] 🙅 no, because they aren't needed
- [ ] 🙋 no, because I need help

## Added to documentation?

- [ ] 📜 README.md
- [ ] 📓 docs.opensauced.pizza
- [ ] 🍕 dev.to/opensauced
- [ ] 📕 storybook
- [x] 🙅 no documentation needed

## [optional] Are there any post-deployment tasks we need to perform?
N/A

## [optional] What gif best describes this PR or how it makes you feel?
![been a while](https://media.giphy.com/media/ehV4b6NlcCmdWbsatE/giphy.gif)



<!-- note: PRs with deletes sections will be marked invalid -->



Patch:
diff --git a/src/components/ListGoals.jsx b/src/components/ListGoals.jsx
index 14026b6..72034e4 100644
--- a/src/components/ListGoals.jsx
+++ b/src/components/ListGoals.jsx
@@ -89,12 +89,10 @@ function ListGoals({goals, data}) {
         <List>
           {goalsWithData &&
             filteredSearch.map(goal => (
-              <li key={goal.full_name + goal.number}>
+              <li key={goal.full_name}>
                 <Link
                   to={{
-                    pathname: `/repos/${goal.full_name.replace(/\s+/g, "")}/${
-                      goal.number
-                    }/`,
+                    pathname: `/repos/${goal.full_name.replace(/\s+/g, "")}/`,
                   }}
                 >
                   <RepoListItem goal={goal} stars={goal.stargazers_count} />
diff --git a/src/components/Repository.jsx b/src/components/Repository.jsx
index bc37a85..d6d9670 100644
--- a/src/components/Repository.jsx
+++ b/src/components/Repository.jsx
@@ -1,5 +1,4 @@
 import React, {useState, useEffect} from "react";
-import DangerZone from "../components/DangerZone";
 import Card from "../components/Card";
 import Issues from "../components/Issues";
 import DetailInfo from "../components/DetailInfo";
@@ -20,14 +19,13 @@ import {fontSize} from "../styles/variables";
 
 function Repository({user, match}) {
   const {
-    params: {repoName, repoOwner, id: issueNumber},
+    params: {repoName, repoOwner},
   } = match;
   const [repository, setRepository] = useState(null);
   const [error, setError] = useState(null);
-  const [note, setNote] = useState(null);
-  const [issueId, setIssueId] = useState();
   const [isForkLoading, setIsForkLoading] = useState(true);
   const [isForked, setIsForked] = useState(false);
+  const [showFork, setShowFork] = useState(false);
   const languagesShown = 3;
   const contributorsShown = 5;
 
@@ -53,17 +51,6 @@ function Repository({user, match}) {
         console.log(e);
       });
 
-    api
-      .fetchGoalQuery(parseInt(issueNumber))
-      .then(res => {
-        const {issue} = res.data.gitHub.viewer.repository;
-        setNote(issue.body);
-        setIssueId(issue.id);
-      })
-      .catch(e => {
-        console.log(e);
-      });
-
     api
       .persistedForkFetch({repoName, repoOwner}, "FetchUserForkCount")
       .then(({data, errors}) => {
@@ -76,7 +63,7 @@ function Repository({user, match}) {
       })
       .catch(e => console.log(e))
       .finally(() => setIsForkLoading(false));
-  }, [issueNumber, repoName, repoOwner]);
+  }, [repoName, repoOwner]);
 
   const forkRepository = () => {
     setIsForkLoading(true);
@@ -96,8 +83,9 @@ function Repository({user, match}) {
       .catch(e => console.log(e))
       .finally(() => setIsForkLoading(false));
   };
-
-  const showFork = repository && user && repoOwner !== user && user.login ? true : isForkLoading;
+  useEffect(()=>{
+    setShowFork(repository && user && repoOwner !== user && user.login ? true : isForkLoading);
+  },[user, repository, repoOwner, isForkLoading])
 
   const {
     url,
@@ -174,7 +162,7 @@ function Repository({user, match}) {
               <a rel="noreferrer" target="_blank" href={`https://codetriage.com/${nameWithOwner}`}>
                 <Button primary>Set up CodeTriage</Button>
               </a>
-              {showFork && isForked ? (
+              {showFork && (isForked ? (
                 <a rel="noreferrer" target="_blank" href={`https://github.com/${user.login}/${repoName}`}>
                   <Button disabled={isForkLoading} data-test="go-to-fork-button">
                     View fork
@@ -184,7 +172,7 @@ function Repository({user, match}) {
                 <Button disabled={isForkLoading} onClick={forkRepository}>
                   <RepoForkedIcon verticalAlign="middle" /> Fork
                 </Button>
-              )}
+              ))}
               <h3 style={{fontSize: fontSize.default}}>Contributors</h3>
               <div className="contributors">
                 {contributors.slice(0, contributorsShown).map((user, key) => (
@@ -244,7 +232,6 @@ function Repository({user, match}) {
               <DetailInfo text={`${humanizeNumber(stargazers.totalCount)} stars`} icon="StarIcon" />
               {licenseInfo && <DetailInfo text={`${licenseInfo.name}`} icon="LawIcon" />}
             </Card>
-            {owner && <DangerZone note={note} goalId={issueId} repoName={nameWithOwner} />}
           </FormColumn>
         ) : (
           !error && <Spinner />
diff --git a/src/containers/App.jsx b/src/containers/App.jsx
index ac9bf8f..568f8d7 100644
--- a/src/containers/App.jsx
+++ b/src/containers/App.jsx
@@ -85,15 +85,19 @@ function App({handleLogIn, handleLogOut, user, isAdmin, isLoggedIn}) {
 
           <Switch>
             <Route exact path="/" component={guard(Dashboard)} />
-            <Route path="/repos/:repoOwner/:repoName/:id" component={guard(Repository)} />
+            <Route path="/repos/:repoOwner/:repoName" render={({match})=>{
+              return <Repository user={user} match={match} />
+            }}></Route>
             <Route path="/callback" component={guard(Dashboard)} />
-            <Route exact path="/logout" render={() => (
-              isLoggedIn ? (
-                handleLogOut()
-              ) : (
-                <Redirect to="/" />
-              )
-            )}/>
+            <Route exact path="/logout" render={() => {
+              return (
+                isLoggedIn ? (
+                  handleLogOut()
+                ) : (
+                  <Redirect to="/" />
+                )
+              );
+            }}/>
             <Route component={NoMatch} />
           </Switch>
           <Footer />
diff --git a/src/containers/Dashboard.jsx b/src/containers/Dashboard.jsx
index d918f9a..e98819d 100644
--- a/src/containers/Dashboard.jsx
+++ b/src/containers/Dashboard.jsx
@@ -8,7 +8,7 @@ function Repositories({user, match}) {
   return (
     <Suspense fallback={<Spinner />}>
       <Route exact path={match.url} render={(props) => <RepositoryGoals user={user} {...props} />} />
-      <Route path={"/repos/:repoOwner/:repoName/:id"} render={(props) => <Repository user={user} {...props} />} />
+      <Route path={"/repos/:repoOwner/:repoName"} render={(props) => <Repository user={user} {...props} />} />
     </Suspense>
   );
 }


Test patch:
diff --git a/src/tests/ListGoals.test.js b/src/tests/ListGoals.test.js
index d37a1b7..af24634 100644
--- a/src/tests/ListGoals.test.js
+++ b/src/tests/ListGoals.test.js
@@ -1,6 +1,6 @@
 import React from "react";
 import "@testing-library/jest-dom/extend-expect";
-import {render, cleanup} from "@testing-library/react";
+import {render, screen, cleanup} from "@testing-library/react";
 import ListGoals from "../components/ListGoals";
 import {BrowserRouter} from "react-router-dom";
 import {data} from "./mocks";
@@ -8,15 +8,38 @@ import {axe, toHaveNoViolations} from "jest-axe";
 expect.extend(toHaveNoViolations);
 
 const {goals} = data;
-
-test("container component should have no violations", async() => {
-  const {container} = render(
-    <BrowserRouter>
-      <ListGoals goals={goals} data={[]} />
-    </BrowserRouter>,
-  );
-  const results = await axe(container);
-  expect(results).toHaveNoViolations();
-
-  cleanup();
-});
+describe("<ListGoals />", ()=>{
+  const setupRender = async () => {
+    return render(
+      <BrowserRouter>
+        <ListGoals goals={goals} data={[]} />
+      </BrowserRouter>
+    ); 
+  };
+  afterEach(()=>{
+    cleanup();
+  });
+  it("should have no violations", async () => {
+    const {container} = await setupRender();
+    const results = await axe(container);
+    expect(results).toHaveNoViolations();
+  });
+  it("should have a search field", async () => {
+    await setupRender();
+    expect(screen.getByLabelText("search")).toHaveAttribute("type","search");
+  });
+  it("should have a sort selection field", async () => {
+    await setupRender();
+    expect(screen.getByRole("combobox").tagName).toEqual("SELECT");
+  });
+  it("should include links for each goal", async () => {
+    await setupRender();
+    const links = screen.getAllByRole("link");
+    goals.nodes.forEach((goal)=>{
+      const linkFound = links.some(link => {
+        return link.getAttribute("href") === `/repos/${goal.full_name}/`;
+      });
+      expect(linkFound).toBeTruthy();
+    });  
+  });
+});
\ No newline at end of file