-
Notifications
You must be signed in to change notification settings - Fork 277
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
Chitter frontend #126
base: master
Are you sure you want to change the base?
Chitter frontend #126
Changes from all commits
d683edf
ef22e13
2310fd1
87e8745
acd54cd
3df038b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
bundle.js |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
class ChitterApi { | ||
fetchPeeps(callback) { | ||
fetch("https://chitter-backend-api-v2.herokuapp.com/peeps") | ||
.then((response) => response.json()) | ||
.then(callback); | ||
} | ||
|
||
createUser(newUsername, newPassword, callback) { | ||
fetch("https://chitter-backend-api-v2.herokuapp.com/users", { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
user: { handle: newUsername, password: newPassword }, | ||
}), | ||
}) | ||
.then((response) => response.json()) | ||
.then(callback); | ||
} | ||
|
||
loginUser(username, password, callback) { | ||
fetch("https://chitter-backend-api-v2.herokuapp.com/sessions", { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
session: { handle: username, password: password }, | ||
}), | ||
}) | ||
.then((response) => response.json()) | ||
.then(callback); | ||
} | ||
|
||
postPeep(sessionKey, userId, peepBody, callback) { | ||
fetch("https://chitter-backend-api-v2.herokuapp.com/peeps", { | ||
method: "POST", | ||
headers: { | ||
Authorization: `Token token=${sessionKey}`, | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
peep: { | ||
user_id: userId, | ||
body: peepBody, | ||
}, | ||
}), | ||
}) | ||
.then((response) => response.json()) | ||
.then(callback); | ||
} | ||
|
||
deletePeep(peepId, sessionKey, callback) { | ||
fetch(`https://chitter-backend-api-v2.herokuapp.com/peeps/${peepId}`, { | ||
method: "DELETE", | ||
headers: { Authorization: `Token token=${sessionKey}` }, | ||
}).then(callback); | ||
} | ||
} | ||
|
||
module.exports = ChitterApi; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
const ChitterApi = require("./chitterApi"); | ||
|
||
require("jest-fetch-mock").enableMocks(); | ||
|
||
let api, | ||
testPeepsArray, | ||
testUserSessionResponse, | ||
testPostPeepResponse, | ||
testDeletePeepResponse; | ||
|
||
describe("ChitterApi class", () => { | ||
beforeEach(() => { | ||
api = new ChitterApi(); | ||
testPeepsArray = require("./testPeepsArray"); | ||
testUserSessionResponse = require("./testUserSessionResponse"); | ||
testPostPeepResponse = require("./testPostPeepResponse"); | ||
testDeletePeepResponse = require("./testDeletePeepResponse"); | ||
fetch.resetMocks(); | ||
Comment on lines
+14
to
+18
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. Overall the tests are logical and beautifully written. Main question is: Would the tests have achieved the same objectives with 'simple' data rather than the 'real' examples you've used in each of the files? You could have all of your test data in one json file (test-data.json for example?) I like that you've used the example data - but if the tests have the same integrity with simplified data then it would be best to simplify. |
||
}); | ||
|
||
it("gets peeps from chitter", () => { | ||
expect.assertions(4); | ||
fetch.mockResponseOnce(JSON.stringify(testPeepsArray)); | ||
api.fetchPeeps((data) => { | ||
expect(data.length).toBe(2); | ||
expect(data[0].id).toBe(1494); | ||
expect(data[1].id).toBe(1461); | ||
expect(fetch.mock.calls[0][0]).toEqual( | ||
"https://chitter-backend-api-v2.herokuapp.com/peeps" | ||
); | ||
}); | ||
}); | ||
|
||
it("creates a new user", () => { | ||
expect.assertions(3); | ||
|
||
fetch.mockResponseOnce(JSON.stringify(testUserSessionResponse)); | ||
api.createUser("kay", "mypassword", (data) => { | ||
expect(data.handle).toBe("kay"); | ||
expect(fetch.mock.calls[0][0]).toEqual( | ||
"https://chitter-backend-api-v2.herokuapp.com/users" | ||
); | ||
expect(fetch.mock.calls[0][1].method).toBe("POST"); | ||
}); | ||
}); | ||
|
||
it("logs in a user", () => { | ||
expect.assertions(4); | ||
fetch.mockResponseOnce( | ||
JSON.stringify({ | ||
user_id: 1, | ||
session_key: "a_valid_session_key", | ||
}) | ||
); | ||
api.loginUser("kay", "mypassword", (data) => { | ||
expect(data.user_id).toBe(1); | ||
expect(data.session_key).toBe("a_valid_session_key"); | ||
expect(fetch.mock.calls[0][0]).toEqual( | ||
"https://chitter-backend-api-v2.herokuapp.com/sessions" | ||
); | ||
expect(fetch.mock.calls[0][1].method).toBe("POST"); | ||
}); | ||
}); | ||
|
||
it("posts a Peep", () => { | ||
expect.assertions(3); | ||
fetch.mockResponseOnce(JSON.stringify(testPostPeepResponse)); | ||
api.postPeep("sessionKey", 1, "my first peep :)", (data) => { | ||
expect(data).toEqual(testPostPeepResponse); | ||
expect(fetch.mock.calls[0][0]).toEqual( | ||
"https://chitter-backend-api-v2.herokuapp.com/peeps" | ||
); | ||
expect(fetch.mock.calls[0][1].method).toBe("POST"); | ||
}); | ||
}); | ||
|
||
it("deletes a Peep", () => { | ||
expect.assertions(3); | ||
fetch.mockResponseOnce({}, { status: 204 }); | ||
api.deletePeep(1494, "session key", (response) => { | ||
expect(fetch.mock.calls[0][0]).toEqual( | ||
"https://chitter-backend-api-v2.herokuapp.com/peeps/1494" | ||
); | ||
expect(fetch.mock.calls[0][1].method).toBe("DELETE"); | ||
expect(response.status).toBe(204); | ||
}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
class ChitterModel { | ||
constructor() { | ||
this.peepsArray = []; | ||
this.userId = null; | ||
this.sessionKey = null; | ||
} | ||
|
||
setPeeps(peepsArray) { | ||
this.peepsArray = peepsArray; | ||
} | ||
|
||
loadPeeps() { | ||
return this.peepsArray; | ||
} | ||
|
||
setUserId(userId) { | ||
this.userId = userId; | ||
} | ||
|
||
loadUserId() { | ||
return this.userId; | ||
} | ||
|
||
resetUserId() { | ||
this.userId = null; | ||
} | ||
Comment on lines
+24
to
+26
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. This method has not been tested in chitterModel.test.js |
||
|
||
setSessionKey(sessionKey) { | ||
this.sessionKey = sessionKey; | ||
} | ||
|
||
loadSessionKey() { | ||
return this.sessionKey; | ||
} | ||
|
||
resetSessionKey() { | ||
this.sessionKey = null; | ||
} | ||
Comment on lines
+36
to
+38
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. This method has not been tested in chitterModel.test.js |
||
} | ||
|
||
module.exports = ChitterModel; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
const ChitterModel = require("./chitterModel"); | ||
|
||
let model, peepsArray; | ||
|
||
describe("ChitterModel class", () => { | ||
beforeEach(() => { | ||
model = new ChitterModel(); | ||
testPeepsArray = require("./testPeepsArray"); | ||
}); | ||
|
||
it("sets and loads Peeps", () => { | ||
model.setPeeps(peepsArray); | ||
expect(model.loadPeeps()).toBe(peepsArray); | ||
}); | ||
|
||
it("sets the user ID", () => { | ||
model.setUserId(1); | ||
expect(model.loadUserId()).toBe(1); | ||
}); | ||
|
||
it("sets the session key", () => { | ||
model.setSessionKey("session key"); | ||
expect(model.loadSessionKey()).toBe("session key"); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
class ChitterView { | ||
constructor(model, api, displaySinglePeep) { | ||
this.model = model; | ||
this.api = api; | ||
this.displaySinglePeep = displaySinglePeep; | ||
|
||
this.newUsernameInputEl = document.querySelector("input#create-username"); | ||
this.newPasswordInputEl = document.querySelector("input#create-password"); | ||
|
||
// create user button listener | ||
document | ||
.querySelector("#create-user-button") | ||
.addEventListener("click", () => { | ||
this.removeUserCreatedMessages(); | ||
this.api.createUser( | ||
this.newUsernameInputEl.value, | ||
this.newPasswordInputEl.value, | ||
(data) => { | ||
this.handleTakenLogic(data); | ||
this.newUsernameInputEl.value = ""; | ||
this.newPasswordInputEl.value = ""; | ||
} | ||
); | ||
}); | ||
|
||
this.loginUsernameEl = document.querySelector("#login-username"); | ||
this.loginPasswordEl = document.querySelector("#login-password"); | ||
|
||
// login button listener | ||
document.querySelector("#login-button").addEventListener("click", () => { | ||
this.api.loginUser( | ||
this.loginUsernameEl.value, | ||
this.loginPasswordEl.value, | ||
(data) => { | ||
this.model.setUserId(data.user_id); | ||
this.model.setSessionKey(data.session_key); | ||
this.loginUsernameEl.value = ""; | ||
this.loginPasswordEl.value = ""; | ||
setTimeout(this.displayPeepsFromApi(), 500); | ||
} | ||
); | ||
}); | ||
|
||
// logout button listener | ||
document.querySelector("#logout-button").addEventListener("click", () => { | ||
this.model.resetSessionKey(); | ||
this.model.resetUserId(); | ||
setTimeout(this.displayPeepsFromApi(), 500); | ||
}); | ||
|
||
this.postPeepBodyEl = document.querySelector("#post-peep-body"); | ||
|
||
// post peep button listener | ||
document | ||
.querySelector("#post-peep-button") | ||
.addEventListener("click", () => { | ||
this.api.postPeep( | ||
this.model.loadSessionKey(), | ||
this.model.loadUserId(), | ||
this.postPeepBodyEl.value, | ||
() => { | ||
this.createPeepSuccessMesage(); | ||
this.postPeepBodyEl.value = ""; | ||
setTimeout(this.displayPeepsFromApi(), 500); | ||
} | ||
); | ||
}); | ||
} | ||
|
||
addDeleteButtonListeners() { | ||
document.querySelectorAll(".delete-peep-button").forEach((element) => { | ||
const peepId = element.id.split("-")[3]; | ||
element.addEventListener("click", () => { | ||
this.api.deletePeep(peepId, this.model.loadSessionKey(), (data) => { | ||
setTimeout(this.displayPeepsFromApi(), 500); | ||
}); | ||
}); | ||
}); | ||
} | ||
|
||
createPeepSuccessMesage() { | ||
const postPeepSuccessMessageEl = document.createElement("p"); | ||
postPeepSuccessMessageEl.id = "post-peep-success-message"; | ||
postPeepSuccessMessageEl.textContent = "Peep posted successfully!"; | ||
document | ||
.querySelector("div#post-peep-container") | ||
.append(postPeepSuccessMessageEl); | ||
} | ||
|
||
removeUserCreatedMessages() { | ||
if (document.querySelector("#handle-taken-message") !== null) | ||
document.querySelector("#handle-taken-message").remove(); | ||
if (document.querySelector("#new-user-created-message") !== null) | ||
document.querySelector("#new-user-created-message").remove(); | ||
} | ||
|
||
handleTakenLogic(data) { | ||
if (data.handle[0] === "has already been taken") { | ||
this.handleTaken(); | ||
} else { | ||
this.userCreated(); | ||
} | ||
} | ||
|
||
handleTaken() { | ||
const handleTakenMessageEl = document.createElement("p"); | ||
handleTakenMessageEl.id = "handle-taken-message"; | ||
handleTakenMessageEl.textContent = "This handle has been taken"; | ||
this.createUserContainerEl.append(handleTakenMessageEl); | ||
} | ||
|
||
userCreated() { | ||
const newUserCreatedMessageEl = document.createElement("p"); | ||
newUserCreatedMessageEl.textContent = "You have created a new account!"; | ||
newUserCreatedMessageEl.id = "new-user-created-message"; | ||
this.createUserContainerEl.append(newUserCreatedMessageEl); | ||
} | ||
|
||
displayPeeps() { | ||
if (document.querySelectorAll("div.peep").length > 0) { | ||
document | ||
.querySelectorAll("div.peep") | ||
.forEach((element) => element.remove()); | ||
} | ||
this.model | ||
.loadPeeps() | ||
.forEach((peep) => | ||
this.displaySinglePeep.display(peep, this.model.loadUserId()) | ||
); | ||
this.addDeleteButtonListeners(); | ||
} | ||
|
||
displayPeepsFromApi() { | ||
this.api.fetchPeeps((peeps) => { | ||
this.model.setPeeps(peeps); | ||
this.displayPeeps(); | ||
}); | ||
} | ||
} | ||
|
||
module.exports = ChitterView; |
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.
Interesting difference here.
Will also work as 'Token token=' + sessionKey
I don't know which is best.