Skip to content

Chitter challenge #138

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
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f042775
Project setup
mirandaweston Mar 4, 2023
8d22b15
Printed confirmation Chitter app is running
mirandaweston Mar 4, 2023
ea58ff8
Adding PeepModel class and test suite: passes 'getPeeps()' and 'addPe…
mirandaweston Mar 4, 2023
ed128d0
Adding PeepsView class and test suite: passes 'displayPeeps' method
mirandaweston Mar 4, 2023
575bdf3
Updating PeepsModel class and test suite: adding 'reset' method
mirandaweston Mar 4, 2023
36a0a69
Adding peep input with submit button
mirandaweston Mar 4, 2023
0e443c2
Minor reformatting of html
mirandaweston Mar 5, 2023
7cba84e
Updating main file to show peeps displaying
mirandaweston Mar 5, 2023
a2b0a49
Updating PeepsView class and test suite: passes 'displayPeeps' and 'a…
mirandaweston Mar 5, 2023
0710662
Updating PeepsView class and test suite: clears previous notes
mirandaweston Mar 5, 2023
faf4825
Amending esbuild
mirandaweston Mar 5, 2023
04be237
Adding Chitter API backend
mirandaweston Mar 5, 2023
2661c49
Adding jest-fetch-mock
mirandaweston Mar 5, 2023
29ee904
Installing express and cors
mirandaweston Mar 5, 2023
35805e6
Backend server up and running for /peeps
mirandaweston Mar 5, 2023
92a12d0
Adding PeepsClient class and test suite: mocked fetch to TD 'loadPeeps'
mirandaweston Mar 5, 2023
cc7a1e4
Updated PeepsView class and test suite: loads peeps from Chitter API
mirandaweston Mar 5, 2023
25b8df4
Updating main file and PeepsView to return a Promise to load peeps fr…
mirandaweston Mar 5, 2023
e56bcea
Updating PeepsClient class and test suite: sends POST request to crea…
mirandaweston Mar 5, 2023
24f0c47
Little CSS break: Changing title colour and font
mirandaweston Mar 5, 2023
237ef0a
Removing duplicate file
mirandaweston Mar 5, 2023
044931a
Updating PeepsClient class and test suite: displays peeps in reverse …
mirandaweston Mar 5, 2023
189ef66
Updating PeepsClient test suite: tests error when fetch fails
mirandaweston Mar 5, 2023
8080df1
Displaying peeps in reverse chronological order
mirandaweston Mar 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
bundle.js
15 changes: 15 additions & 0 deletions __tests__/peepModel.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const fs = require('fs')
const PeepsModel = require('../src/peepModel');

describe('PeepsModel', () => {
it('initialises with an empty array for Peep objects', () => {
const model = new PeepsModel();
expect(model.getPeeps()).toEqual([]);
})

it('adds a new Peep to the array of Peep objects', () => {
const model = new PeepsModel();
model.addPeep('first peep');
expect(model.getPeeps()).toEqual(['first peep']);
});
})
64 changes: 64 additions & 0 deletions __tests__/peepsClient.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
const PeepsClient = require('../src/peepsClient');

require('jest-fetch-mock').enableMocks();

describe('peepsClient', () => {
describe('loadPeeps', () => {
beforeEach(() => {
fetch.resetMocks();
});

it('should return peeps with correct properties', async () => {
const responseData = [ { id: 1, body: 'Hello, world!', created_at: '2022-03-05T12:00:00.000Z', updated_at: '2022-03-05T12:00:00.000Z', user: { id: 1, handle: 'user1' }, likes: []
}
];

fetch.mockResponseOnce(JSON.stringify(responseData));

const peepsClient = new PeepsClient();
const peeps = await peepsClient.loadPeeps();

// check they have the right properties
const peep = peeps[0];
expect(peep.id).toBeDefined();
expect(peep.body).toBeDefined();
expect(peep.created_at).toBeDefined();
expect(peep.updated_at).toBeDefined();
expect(peep.user.id).toBeDefined();
expect(peep.user.handle).toBeDefined();
expect(Array.isArray(peep.likes)).toBe(true);
if (peep.likes.length > 0) {
const like = peep.likes[0];
expect(like.user.id).toBeDefined();
expect(like.user.handle).toBeDefined();
}
});

it('throws an error when fetch fails', async () => {
const fetchError = new Error('Fetch error');
fetch.mockReject(fetchError);
const client = new PeepsClient();

await expect(client.loadPeeps()).rejects.toThrow(fetchError);
});
});

describe('createPeep', () => {
beforeEach(() => {
fetch.resetMocks();
});

it('sends a POST request to the peeps backend to create new peep', async () => {
const client = new PeepsClient();

fetch.mockResponseOnce(JSON.stringify({
name: 'another peep',
id: 456
}));

const returnedDataFromApi = await client.createPeep('another peep');
expect(returnedDataFromApi.name).toEqual('another peep');
expect(returnedDataFromApi.id).toEqual(456);
});
});
});
23 changes: 23 additions & 0 deletions __tests__/peepsModel.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const fs = require('fs')
const PeepsModel = require('../src/peepsModel');

describe('PeepsModel', () => {
it('initialises with an empty array for Peep objects', () => {
const model = new PeepsModel();
expect(model.getPeeps()).toEqual([]);
})

it('adds a new Peep to the array of Peep objects', () => {
const model = new PeepsModel();
model.addPeep('first peep');
expect(model.getPeeps()).toEqual(['first peep']);
});

it('resets the list of peeps', () => {
const peeps = new PeepsModel();
peeps.addPeep('next peep');
peeps.reset();

expect(peeps.getPeeps()).toEqual([]);
})
})
92 changes: 92 additions & 0 deletions __tests__/peepsView.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
require('jest-fetch-mock').enableMocks();

const { JSDOM } = require('jsdom');
const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>');
global.document = dom.window.document;

const fs = require('fs');

const PeepsView = require('../src/peepsView');
const PeepsModel = require('../src/peepsModel');
const PeepsClient = require('../src/peepsClient');

jest.mock('../src/peepsClient');

describe('Peeps view', () => {
it('displays two peeps', () => {
document.body.innerHTML = fs.readFileSync('./index.html');

const model = new PeepsModel;
const view = new PeepsView(model);
model.addPeep('my first peep');
model.addPeep('my second peep');

view.displayPeeps();

expect(document.querySelectorAll('div.peep').length).toEqual(2);
});

it('allows the user to add a new peep', () => {
document.body.innerHTML = fs.readFileSync('./index.html');

const model = new PeepsModel;
const view = new PeepsView(model);

const input = document.querySelector('#add-peep-input');
input.value = 'another peep';

const button = document.querySelector('#add-peep-btn');
button.click();

expect(document.querySelectorAll('div.peep').length).toEqual(1);
expect(document.querySelectorAll('div.peep')[0].textContent).toEqual('another peep');
})

it('clears previous peeps before displaying', () => {
document.body.innerHTML = fs.readFileSync('./index.html');

const model = new PeepsModel;
const view = new PeepsView(model);

model.addPeep('and another peep');
model.addPeep('peeping once more');

view.displayPeeps();
view.displayPeeps();

expect(document.querySelectorAll('div.peep').length).toEqual(2);
})

it('displays peep data from Chitter API', (done) => {
document.body.innerHTML = fs.readFileSync('./index.html');
PeepsClient.mockClear();

const fakeClient = {loadPeeps: () => Promise.resolve(['mock peep'])};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good use of promise resolution!

const client = new PeepsClient();
const model = new PeepsModel();
const view = new PeepsView(model, fakeClient);

view.displayPeepsFromApi().then(() => {
const peepE1s = document.querySelectorAll('.peep');
expect(peepE1s.length).toEqual(1);
expect(peepE1s[0].textContent).toEqual('mock peep');
done();
});
});

it('sends a POST request to create a new peep', () => {
document.body.innerHTML = fs.readFileSync('./index.html');
PeepsClient.mockClear();

const fakeClient = {loadPeeps: () => Promise.resolve(['mock peep'])};
const client = new PeepsClient();
const model = new PeepsModel();
const view = new PeepsView(model, fakeClient);

view.addNewPeep('mock note')

const peepE1 = document.querySelectorAll('.peep');
expect(peepE1.length).toEqual(1);
expect(peepE1[0].textContent).toEqual('mock note');
})
})
26 changes: 26 additions & 0 deletions chitter_api_backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'

# Ignore bundler config.
/.bundle

# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal

# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep

# Ignore uploaded files in development
/storage/*

.byebug_history

# Ignore master key for decrypting credentials and more.
/config/master.key
1 change: 1 addition & 0 deletions chitter_api_backend/.rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--require spec_helper
1 change: 1 addition & 0 deletions chitter_api_backend/.ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.4.0
48 changes: 48 additions & 0 deletions chitter_api_backend/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.4.0'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.0'
# Use PostgreSQL as the database for Active Record
gem 'pg'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
# gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false

gem 'bcrypt'

# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
gem 'rack-cors'

group :development, :test do
gem 'rspec-rails'
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
gem 'listen', '>= 3.0.5', '< 3.2'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
end


# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
Loading