-
Notifications
You must be signed in to change notification settings - Fork 274
Jimmy Lyons Frontend Chitter Challenge #120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jimmy-lyons
wants to merge
18
commits into
makersacademy:master
Choose a base branch
from
jimmy-lyons:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
09c0ef7
added gitignore
jimmy-lyons 07bcf7e
repo initialised with npm and jest and initial files made
jimmy-lyons bde62a8
add feature to fetch peeps (TD)
jimmy-lyons e0c8610
increased scope on happy path test
jimmy-lyons 860d506
fetch peep catches error (TD)
jimmy-lyons 6b11511
chitterModel created with empty notes array
jimmy-lyons a6c8727
changed name from notes to peeps in model
jimmy-lyons fd33eb8
Test added to return loaded peeps
jimmy-lyons ce26701
can load peeps into model (TD)
jimmy-lyons 0f9fc95
Created view with initial test for loading
jimmy-lyons 1a25436
View loads peeps from server
jimmy-lyons 85268b5
Enabled login and session creation - no test
jimmy-lyons 6e26c75
unsuccessfully added session test, com'd out
jimmy-lyons 7c52b4b
added API test for authorisation
jimmy-lyons 65795f0
added AIP test to catch failures
jimmy-lyons a9fb36c
Can post a new peep to server
jimmy-lyons 9915248
Added README_JL
jimmy-lyons bc6a702
Updated README
jimmy-lyons File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| .DS_Store | ||
| node_modules | ||
| bundle.js | ||
| notes.txt |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,37 +1,50 @@ | ||
| # Chitter API Frontend Challenge | ||
|
|
||
| * Feel free to use Google, your notes, books, etc. but work on your own | ||
| * If you refer to the solution of another coach or student, please put a link to that in your README | ||
| * If you have a partial solution, **still check in a partial solution** | ||
| * You must submit a pull request to this repo with your code by 9am Monday morning | ||
| ## Motivation | ||
|
|
||
| Challenge: | ||
| ------- | ||
| The purpose of this challenge is to write a Single Page Application that makes calls to back end server for 'Chitter'. The following API interactions were provided by the server: | ||
|
|
||
| As usual please start by forking this repo. | ||
|
|
||
| We are going to write a small Twitter clone that will allow the users to post messages to a public stream. | ||
| * Creating Users | ||
| * Logging in | ||
| * Posting Peeps | ||
| * Viewing all Peeps *(I suggest you start here)* | ||
| * Viewing individual Peeps | ||
| * Deleting Peeps | ||
| * Liking Peeps | ||
| * Unliking Peeps | ||
|
|
||
| The scenario is similar to the [Chitter Challenge](https://github.com/makersacademy/chitter-challenge), except someone has already built a backend API for you and hosted it on Heroku. | ||
| ## Functions Implemented | ||
|
|
||
| Your task is to build a front-end single-page-app to interface with this API. You can do this in any framework you like, or in pure Javascript. [The API documentation is here.](https://github.com/makersacademy/chitter_api_backend) | ||
| * Logging In - This requires users to already be signed up. With further time I would have implemented a signing up feature. | ||
| * Viewing Peeps - The page automatically renders the most recent 50 peeps. | ||
| * Posting Peeps - You can post a peep, which is then saved on the server. | ||
|
|
||
| Here are some interactions the API supports. Implement as many as you see fit. | ||
| ## Functions to be Implemented | ||
|
|
||
| * Creating Users | ||
| * Logging in | ||
| * Posting Peeps | ||
| * Viewing all Peeps *(I suggest you start here)* | ||
| * Viewing individual Peeps | ||
| * Deleting Peeps | ||
| * Liking Peeps | ||
| * Unliking Peeps | ||
|
|
||
| We are looking for well tested, easy to read, easy to change code. This is more important than the number of interactions you implement. | ||
| ## Structure | ||
|
|
||
| The Application is split into three classes, each with distinct responsibilities: | ||
|
|
||
| * ChitterApi - handles outgoing and incoming fetch requests with asynchronus fucntions. | ||
| * ChitterModel - manages and manipulates data (peeps) which come from the server. | ||
| * ChitterView - this is responsible for the functions of the user interface. It displays peeps and extracts data input by the user for requests sent by the API. | ||
|
|
||
| The application is rendered through an HTML file, which runs a bundled script of the classes above, plus an 'index' script, which executes the classes and functions on the web page. | ||
| With more time I would have stylised the page using CSS. | ||
|
|
||
| The backend server was already created by Makers. The API documentation are found through the following link: | ||
|
|
||
| Note that others may be doing the same task at the same time, so the data may change as you are using it. | ||
| [Chitter Backend](https://github.com/makersacademy/chitter-challenge) | ||
|
|
||
| ## Utilities you might find useful | ||
| ## How to Use | ||
|
|
||
| * [The Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) for making requests. | ||
| * [Postman](https://www.getpostman.com/) or [Insomnia](https://insomnia.rest/) for exploring the API. | ||
| - Fork and clone repository. | ||
| - Install jest, node and npm. | ||
| - To run tests, run 'jest' from the terminal. | ||
| - To open the page run 'open index.html' from the terminal. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| class ChitterApi { | ||
|
|
||
| fetchPeeps = (callback) => { | ||
| try { | ||
| fetch("https://chitter-backend-api-v2.herokuapp.com/peeps") | ||
| .then(response => response.json()) | ||
| .then(data => callback(data)); | ||
| } catch(err) { | ||
| return null; | ||
| }; | ||
| }; | ||
|
|
||
| userAuthorisation(handle, password, callback) { | ||
| try { | ||
| fetch('https://chitter-backend-api-v2.herokuapp.com/sessions', { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/json' | ||
| }, | ||
| body: JSON.stringify({ | ||
| "session": { | ||
| "handle":handle, | ||
| "password":password | ||
| } | ||
| }) | ||
| }) | ||
| .then(response => response.json()) | ||
| .then(data => callback(data)); | ||
| // catch doesn't seem to be working as I want it to. | ||
| // doesn't log the error in the format I want. | ||
| } catch (error) { | ||
| console.error('There was an error!', error); | ||
| } | ||
| } | ||
|
|
||
| postPeep(sessionKey, userID, peepContent, callback) { | ||
| try { | ||
| fetch('https://chitter-backend-api-v2.herokuapp.com/peeps', { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| "Authorization": `Token token=${sessionKey}` | ||
| }, | ||
| body: JSON.stringify({ | ||
| "peep": { | ||
| "user_id": userID, | ||
| "body": peepContent | ||
| }}) | ||
| }) | ||
| .then(response => response.json()) | ||
| .then(data => callback(data)); | ||
| } catch (error) { | ||
| console.error('There was an error!', error); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| module.exports = ChitterApi; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| const ChitterApi = require('./chitterApi'); | ||
|
|
||
| require('jest-fetch-mock').enableMocks(); | ||
|
|
||
| describe('ChitterApi class', () => { | ||
|
|
||
| beforeEach(() => { | ||
| fetch.resetMocks(); | ||
| }) | ||
|
|
||
| it('fetches peeps using fetchPeeps', () => { | ||
| fetch.mockResponseOnce(JSON.stringify([{"id":1234, "body":"Testing testing 1,2"}])); | ||
|
|
||
| const api = new ChitterApi; | ||
| api.fetchPeeps((peepsObject) => { | ||
| let peeps = peepsObject; | ||
| expect(peeps[0].body).toEqual("Testing testing 1,2"); | ||
| expect(fetch).toHaveBeenCalledTimes(1); | ||
| expect(fetch).toHaveBeenCalledWith( | ||
| "https://chitter-backend-api-v2.herokuapp.com/peeps" | ||
| ); | ||
| }); | ||
| }) | ||
|
|
||
| it('catches errors', () => { | ||
| fetch.mockReject(() => 'API Failure'); | ||
|
|
||
| const api = new ChitterApi; | ||
| api.fetchPeeps((peepsObject) => { | ||
| expect(peepsObject).toEqual(null); | ||
| }) | ||
| }) | ||
|
|
||
| it('sends authorisation requests and returns session keys', () => { | ||
| fetch.mockResponseOnce(JSON.stringify({ | ||
| "user_id":12345, | ||
| "session_key":"_3b_65_WEjfcW0unkmN9uVtIMa24f" | ||
| })); | ||
|
|
||
| const api = new ChitterApi; | ||
| api.userAuthorisation('testName', 'password123', (result) => { | ||
| expect(result.user_id).toEqual(12345); | ||
| expect(result.session_key).toEqual("_3b_65_WEjfcW0unkmN9uVtIMa24f"); | ||
| }) | ||
| }) | ||
|
|
||
| it('raises an error when wrong credentials are provided', () => { | ||
| // I'd like to write this test so that I'm checkng for an error instead of a string | ||
| // but I can't figure out the syntax. | ||
| fetch.mockResponseOnce(JSON.stringify({ | ||
| "errors":{ | ||
| "password":"Invalid username or password" | ||
| } | ||
| })); | ||
|
|
||
| const api = new ChitterApi; | ||
| api.userAuthorisation('testName', 'password123', (result) => { | ||
| expect(result.errors.password).toEqual("Invalid username or password"); | ||
| }) | ||
| }) | ||
|
|
||
| it('sends a peep to server and recieves confirmation', () => { | ||
| fetch.mockResponseOnce(JSON.stringify({ | ||
| "id": 3, | ||
| "body": "my first peep :)", | ||
| "created_at": "2018-06-23T13:21:23.317Z", | ||
| "updated_at": "2018-06-23T13:21:23.317Z", | ||
| "user": { | ||
| "id": 1, | ||
| "handle": "kay" | ||
| }, | ||
| "likes": [{ | ||
| "user": { | ||
| "id": 1, | ||
| "handle": "kay" | ||
| } | ||
| }] | ||
| })); | ||
|
|
||
| const api = new ChitterApi; | ||
| let sessionKey = "_3b_65_WEjfcW0unkmN9uVtIMa24f"; | ||
| let userID = 1; | ||
| let peepContent = "my first peep :)"; | ||
| api.postPeep(sessionKey, userID, peepContent, (result) => { | ||
| expect(result.body).toEqual(peepContent); | ||
| }) | ||
| }) | ||
| }) | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| class ChitterModel { | ||
|
|
||
| constructor(peeps = []) { | ||
| this.loadedPeeps = peeps; | ||
| } | ||
|
|
||
| loadPeeps(peeps) { | ||
| peeps.forEach((peep) => { | ||
| this.loadedPeeps.push(peep); | ||
| }) | ||
| console.log('Loaded peeps are as follows:') | ||
| console.log(this.loadedPeeps); | ||
| } | ||
|
|
||
| returnLoadedPeeps() { | ||
| return this.loadedPeeps; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| module.exports = ChitterModel |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| const ChitterModel = require('./chittermodel'); | ||
|
|
||
| describe("ChitterModel class", () => { | ||
|
|
||
| it('returns empty array of notes when none have been added', () => { | ||
| const model = new ChitterModel; | ||
| expect(model.returnLoadedPeeps()).toEqual([]); | ||
| }); | ||
|
|
||
| it('returns peeps loaded into model', () => { | ||
| const testPeep = [{ | ||
| "id":12345, | ||
| "body":"this is a test", | ||
| "created_at":"2022-06-03T17:43:02.492Z", | ||
| "updated_at":"2022-06-03T17:43:02.492Z", | ||
| "user":{ | ||
| "id":678, | ||
| "handle":"testUser" | ||
| }, | ||
| "likes":[] | ||
| }]; | ||
|
|
||
| const model = new ChitterModel(testPeep); | ||
| expect(model.returnLoadedPeeps()).toEqual(testPeep); | ||
| }) | ||
|
|
||
| it('loads peeps into the model', () => { | ||
| const testPeep = [{ | ||
| "id":12345, | ||
| "body":"this is a test", | ||
| "created_at":"2022-06-03T17:43:02.492Z", | ||
| "updated_at":"2022-06-03T17:43:02.492Z", | ||
| "user":{ | ||
| "id":678, | ||
| "handle":"testUser" | ||
| }, | ||
| "likes":[] | ||
| }]; | ||
|
|
||
| const model = new ChitterModel | ||
| model.loadPeeps(testPeep); | ||
| expect(model.returnLoadedPeeps()).toEqual(testPeep); | ||
| }) | ||
|
|
||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| class ChitterView { | ||
|
|
||
| constructor(model, api) { | ||
| this.model = model; | ||
| this.api = api; | ||
|
|
||
| this.userID = null; | ||
| this.sessionKey = null; | ||
|
|
||
| this.peepContainerEl = document.querySelector('#peep-container'); | ||
| this.loginButtonEl = document.querySelector('#login-button'); | ||
| this.loginButtonEl.addEventListener('click', () => { | ||
| this.checkAuthorisation(); | ||
| }); | ||
| this.newPeepButtonEl = document.querySelector('#peep-button'); | ||
| this.newPeepButtonEl.addEventListener('click', () => { | ||
| this.newPeepToApi(); | ||
| }); | ||
| } | ||
|
|
||
| importPeepsFromServer() { | ||
| this.api.fetchPeeps(peeps => { | ||
| console.log('Peeps retrieved from server:'); | ||
| console.log(peeps); | ||
| this.model.loadPeeps(peeps); | ||
| this.displayPeeps(); | ||
| }) | ||
| } | ||
|
|
||
| displayPeeps() { | ||
| let peeps = this.model.returnLoadedPeeps(); | ||
| peeps.forEach((peep) => { | ||
| const peepEl = document.createElement('div'); | ||
| peepEl.innerText = peep.body; | ||
| peepEl.className = 'peep'; | ||
| this.peepContainerEl.append(peepEl); | ||
| }); | ||
| }; | ||
|
|
||
| checkAuthorisation() { | ||
| let userHandle = document.querySelector('#handle').value; | ||
| let userPassword = document.querySelector('#password').value; | ||
| this.api.userAuthorisation(userHandle, userPassword, response => { | ||
| this.userID = response.user_id; | ||
| this.sessionKey = response.session_key; | ||
| console.log(this.userID, this.sessionKey); | ||
| }); | ||
| } | ||
|
|
||
| newPeepToApi() { | ||
| if (this.sessionKey === null) { | ||
| throw new Error('Not Logged In'); | ||
| }; | ||
| let peepContent = document.querySelector('#new-peep').value; | ||
| this.api.postPeep(this.sessionKey, this.userID, peepContent, (result) => { | ||
| console.log(result); | ||
| }) | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does the page display the newly added peep automatically? |
||
| }; | ||
|
|
||
| module.exports = ChitterView; | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor comment, new ChitterApi could be moved to the before stattement