+`;
+
+exports[` when there was an error in the response renders and matches the snapshot 1`] = `
+RenderContext {
+ "0": VNode {
+ "attributes": undefined,
+ "children": Array [],
+ "key": undefined,
+ "nodeName": [Function],
+ },
+ "length": 1,
+}
+`;
diff --git a/app/javascript/githubRepos/__tests__/__snapshots__/singleRepo.test.jsx.snap b/app/javascript/githubRepos/__tests__/__snapshots__/singleRepo.test.jsx.snap
new file mode 100644
index 000000000..31e6ca280
--- /dev/null
+++ b/app/javascript/githubRepos/__tests__/__snapshots__/singleRepo.test.jsx.snap
@@ -0,0 +1,66 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` when it is a fork should render and match the snapshot 1`] = `
+
+
+
+ dev.to
+
+ fork
+
+
+
+`;
+
+exports[` when it is not already selected should render and match the snapshot 1`] = `
+
+
+
+ dev.to
+
+
+`;
+
+exports[` when it is selected should render and match the snapshot 1`] = `
+
+
+
+ dev.to
+
+
+`;
diff --git a/app/javascript/githubRepos/__tests__/githubRepos.test.jsx b/app/javascript/githubRepos/__tests__/githubRepos.test.jsx
new file mode 100644
index 000000000..6ad93ad0d
--- /dev/null
+++ b/app/javascript/githubRepos/__tests__/githubRepos.test.jsx
@@ -0,0 +1,34 @@
+import { h } from 'preact';
+import { shallow } from 'preact-render-spy';
+import render from 'preact-render-to-json';
+import fetch from 'jest-fetch-mock';
+import { GithubRepos } from '../githubRepos';
+
+global.fetch = fetch;
+
+describe('', () => {
+ describe('when there are no repos loaded yet', () => {
+ it('should render and match the snapshot', () => {
+ const tree = render();
+ expect(tree).toMatchSnapshot();
+ });
+
+ it('should have the loading div', () => {
+ const context = shallow();
+ expect(context.find('.loading-repos')[0].attributes.className).toEqual(
+ 'github-repos loading-repos',
+ );
+ });
+ });
+
+ describe('when there was an error in the response', () => {
+ it('renders and matches the snapshot', () => {
+ fetch.mockReject('some error');
+ const context = shallow();
+ context.setState({ erroredOut: true });
+ context.rerender();
+ const tree = render(context);
+ expect(tree).toMatchSnapshot();
+ });
+ });
+});
diff --git a/app/javascript/githubRepos/__tests__/singleRepo.test.jsx b/app/javascript/githubRepos/__tests__/singleRepo.test.jsx
new file mode 100644
index 000000000..c8445ccfb
--- /dev/null
+++ b/app/javascript/githubRepos/__tests__/singleRepo.test.jsx
@@ -0,0 +1,56 @@
+import { h } from 'preact';
+import { shallow } from 'preact-render-spy';
+import render from 'preact-render-to-json';
+import fetch from 'jest-fetch-mock';
+import { SingleRepo } from '../singleRepo';
+
+global.fetch = fetch;
+
+describe('', () => {
+ describe('when it is not already selected', () => {
+ const subject = (
+
+ );
+
+ it('should render and match the snapshot', () => {
+ const tree = render(subject);
+ expect(tree).toMatchSnapshot();
+ });
+
+ it('should have a state of { selected: false }', () => {
+ const context = shallow(subject);
+ expect(context.state()).toEqual({ selected: false });
+ });
+ });
+
+ describe('when it is selected', () => {
+ const subject = (
+
+ );
+ it('should render and match the snapshot', () => {
+ const tree = render(subject);
+ expect(tree).toMatchSnapshot();
+ });
+
+ it('should have a state of { selected: true }', () => {
+ const context = shallow(subject);
+ expect(context.state()).toEqual({ selected: true });
+ });
+ });
+
+ describe('when it is a fork', () => {
+ const subject = (
+
+ );
+
+ it('should render and match the snapshot', () => {
+ const tree = render(subject);
+ expect(tree).toMatchSnapshot();
+ });
+ });
+});
diff --git a/app/javascript/githubRepos/githubRepos.jsx b/app/javascript/githubRepos/githubRepos.jsx
new file mode 100644
index 000000000..7238f63a5
--- /dev/null
+++ b/app/javascript/githubRepos/githubRepos.jsx
@@ -0,0 +1,59 @@
+import { h, Component } from 'preact';
+import { SingleRepo } from './singleRepo';
+
+export class GithubRepos extends Component {
+ state = {
+ repos: [],
+ erroredOut: false,
+ };
+
+ componentDidMount() {
+ this.getGithubRepos();
+ }
+
+ getGithubRepos = () => {
+ fetch(`/api/github_repos`, {
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ credentials: 'same-origin',
+ })
+ .then(response => response.json())
+ .then(json => {
+ this.setState({ repos: json });
+ })
+ .catch(error => {
+ console.log(error);
+ this.setState({ erroredOut: true });
+ });
+ };
+
+ render() {
+ const { repos, erroredOut } = this.state;
+ const allRepos = repos.map(repo => (
+
+ ));
+
+ if (erroredOut) {
+ return (
+
+ An error occurred. Please check your browser console and email
+ yo@dev.to
+ for more help.
+
+ <%= javascript_pack_tag "githubRepos", defer: true %>
+
<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index 0d25ac310..f02c16b34 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -77,6 +77,11 @@ Rails.application.routes.draw do
end
end
resources :follows, only: [:create]
+ resources :github_repos, only: [:index] do
+ collection do
+ post "/update_or_create", to: "github_repos#update_or_create"
+ end
+ end
end
end