diff --git a/formatDate.js b/formatDate.js index da8c1c3..0ee95b4 100644 --- a/formatDate.js +++ b/formatDate.js @@ -1,5 +1,41 @@ -function formatDate(date) { - // Напишите код форматирования даты в этом месте +const moths = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'] + +function formatDate(dateIn) { + if (arguments.length !== 1){ + throw new Error('На вход подаётся только 1 аргумент.'); + } + + date = new Date(dateIn); + if (isNaN(date.getTime())) { + throw new Error('На вход должна подаваться валидная дата.'); + } + + var twMinutes = timeToStr(date.getUTCMinutes()); + var twHours = timeToStr(date.getUTCHours()); + var twDate = date.getUTCDate(); + var twMonth = date.getUTCMonth(); + var twYear = date.getFullYear(); + + var today = new Date(); + var curDd = today.getUTCDate(); + var curYear = today.getFullYear(); + + if (twDate === curDd){ + return twHours + ':' + twMinutes; + } + if (twDate === curDd-1){ + return 'вчера в '+ twHours + ':' + twMinutes; + } + if (twYear < curYear) + return twDate + ' ' + moths[twMonth] + ' ' + twYear + ' года в ' + twHours + ':'+ twMinutes; + return twDate + ' ' + moths[twMonth] + ' в ' + twHours + ':'+ twMinutes; + +} + +function timeToStr(time){ + if (time < 10) + return('0' + time); + return time; } module.exports = formatDate; diff --git a/package.json b/package.json index 8966adc..e33fe45 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "showTweets.js", "scripts": { "test": "mocha tests", - "cover": "istanbul cover ./node_modules/.bin/_mocha tests --report text-summary" + "cover": "istanbul cover ./node_modules/mocha/bin/_mocha tests --report text-summary" }, "author": "Sergey Zhigalov ", "license": "MIT", diff --git a/showTweets.js b/showTweets.js index 7257166..8b2ccf1 100644 --- a/showTweets.js +++ b/showTweets.js @@ -1,8 +1,33 @@ const formatDate = require('./formatDate'); +const request = require('request'); + + +function showTweets(cb) { + + const urladdr = 'https://api.twitter.com/1.1/search/tweets.json?q=%23urfu-testing-2016'; + request(urladdr, function (error, response, body) { + if (error){ + console.error(error.message); + return cb(); + } + else if (response.statusCode != 200) { + console.log('statusCode: ' + response.statusCode); + return cb(); + } + else { + try{ + const data = JSON.parse(body); + data.forEach(tweet => { + console.log(formatDate(tweet.createdAt) + '\n' + tweet.text); + }); + } + catch (parseError){ // следует-ли сюда добавлять проверку на выброс Error из formatDate? + console.error(parseError.message); + } + return cb(); + } + }); -function showTweets() { - // Здесь будет код, который получает твиты и - // выводит их на консоль } module.exports = showTweets; diff --git a/tests/formatDate-test.js b/tests/formatDate-test.js new file mode 100644 index 0000000..1ac7dde --- /dev/null +++ b/tests/formatDate-test.js @@ -0,0 +1,52 @@ +const assert = require('assert'); +const formatDate = require('../formatDate'); + +describe('formatDate', () => { + it('should return `00:00` for `2017-05-18T00:00:00.000Z`', () => { // валится каждый день + const actual = formatDate("2017-05-18T00:00:00.000Z"); + + assert.equal(actual, "00:00"); + }); + + + it('should return `вчера в 23:59` for `2017-05-17T23:59:59.999Z`', () => { // валится каждый день + const actual = formatDate("2017-05-17T23:59:59.999Z"); + + assert.equal(actual, "вчера в 23:59"); + }); + + + it('should return `30 апреля в 02:31` for `2017-04-30T02:31:59.999Z`', () => { + const actual = formatDate("2017-04-30T02:31:59.999Z"); + + assert.equal(actual, "30 апреля в 02:31"); + }); + + it('should return `31 января 2000 года в 11:59` for `2000-01-31T11:59:59.000Z`', () => { + const actual = formatDate("2000-01-31T11:59:59.999Z"); + + assert.equal(actual, "31 января 2000 года в 11:59"); + }); + + + + + it('should throw an error when arguments in are more than 1', () => { + const actual = () => formatDate("1999-12-31T10:59:59.999Z", "2007-08-15T10:22:59.999Z"); + + assert.throws(actual, /На вход подаётся только 1 аргумент./); + }); + + it ('should throw error when arguments number is 0', () =>{ + const actual = () => formatDate(); + + assert.throws(actual, /На вход подаётся только 1 аргумент./); + }); + it ('should throw error when arguments number is not data', () =>{ + const actual = () => formatDate("эээээ"); + + assert.throws(actual, /На вход должна подаваться валидная дата./); + }); + + +}); diff --git a/tests/showTweets-test.js b/tests/showTweets-test.js new file mode 100644 index 0000000..c8b82e1 --- /dev/null +++ b/tests/showTweets-test.js @@ -0,0 +1,135 @@ +const assert = require('assert'); +const proxyquire = require('proxyquire'); +const sinon = require('sinon'); +const nock = require('nock'); + + +const url = 'https://api.twitter.com/1.1/search/tweets.json?q=%23urfu-testing-2016'; + + +describe('showTweets tests', () =>{ + + afterEach(() => { + console.log.restore(); + console.error.restore(); + nock.cleanAll(); + }); + + + + it('should print tweets', done =>{ + + var tweets = [ + { + "createdAt":"2017-05-03T10:09:00.333Z", + "text": "Hello, world!" + }, + { + "createdAt": "1999-01-11T03:02:01.000Z", + "text": "Hellow, me!" + } + ]; + + var expDates = ['10:09', '11 января 1999 года в 03:02'] + + nock('https://api.twitter.com') + .get('/1.1/search/tweets.json?q=%23urfu-testing-2016') + .reply(200, tweets) + + + const log = sinon.spy(console, 'log'); + const error = sinon.spy(console, 'error'); + + const formatDate = sinon.stub(); + + formatDate.withArgs(tweets[0].createdAt).returns(expDates[0]); + formatDate.withArgs(tweets[1].createdAt).returns(expDates[1]); + + + const showTweets = proxyquire('../showTweets', { + './formatDate' : formatDate + }); + + showTweets(() => { + assert(log.calledTwice); + assert(log.calledWith(expDates[0] + '\n' + tweets[0].text)); + assert(log.calledWith(expDates[1] + '\n' + tweets[1].text)); + assert(!error.called); + done(); + }); + + + }); + + + + it('should print error message from request', done => { + const log = sinon.spy(console, 'log'); + const error = sinon.spy(console, 'error'); + + nock('https://api.twitter.com') + .get('/1.1/search/tweets.json?q=%23urfu-testing-2016') + .replyWithError({code: 303, message: 'Having fun now! Do not disturb!!!'}); + + var formatDateShadow = sinon.stub(); + + const showTweets = proxyquire('../showTweets', { + './formatDate' : { formatDate : formatDateShadow} + }); + + showTweets(() => { + + assert(!log.called); + assert(error.called); + assert(error.calledWith('Having fun now! Do not disturb!!!')); + done(); + }); + }); + + + it('should print status code different from 200', done => { + const log = sinon.spy(console, 'log'); + const error = sinon.spy(console, 'error'); + + nock('https://api.twitter.com') + .get('/1.1/search/tweets.json?q=%23urfu-testing-2016') + .reply(309, 0) + + var formatDateShadow = sinon.stub(); + + const showTweets = proxyquire('../showTweets', { + './formatDate' : formatDateShadow + }); + + showTweets(() => { + assert(log.calledOnce); + assert(log.calledWithMatch('statusCode: 309')); + assert(!error.called); + done(); + }); + }); + + + it('should throw error on parsing', done => { + const log = sinon.spy(console, 'log'); + const error = sinon.spy(console, 'error'); + + nock('https://api.twitter.com') + .get('/1.1/search/tweets.json?q=%23urfu-testing-2016') + .reply(200, '1mku.,liu234') + + var formatDateShadow = sinon.stub(); + + const showTweets = proxyquire('../showTweets', { + './formatDate' : formatDateShadow + }); + + showTweets(() => { + assert(!log.called); + assert(error.calledWith('Unexpected token m in JSON at position 1')); + assert(error.calledOnce); + done(); + }); + }); + +}); \ No newline at end of file