From 686cdf055174044cbd037327418efbe91beb7131 Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Sun, 16 Aug 2015 15:27:15 -0700 Subject: Adding more tests for PodcastView. --- lib/PodcastView.js | 37 +++++++-- test/PodcastView.js | 214 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 231 insertions(+), 20 deletions(-) diff --git a/lib/PodcastView.js b/lib/PodcastView.js index 1236abd..a760371 100644 --- a/lib/PodcastView.js +++ b/lib/PodcastView.js @@ -91,22 +91,43 @@ function forEachView(feedId, callback, startKey) { } PodcastView.prototype.render = function(episodes, callback) { + var bucket = this.bucket; + var filenameTemplate = this.filenameTemplate; var template = this.template; var data = { view: this, episodes: episodes, - }; - var renderedView = _.template(template)(data); - - saveView(renderedView, callback); + }; + + if (this.renderEach) { + var remainingEpisodes = episodes.length; + var uploadCallback = function(error) { + remainingEpisodes--; + if (remainingEpisodes == 0 || error != null) { + callback(error); + } + }; + + episodes.forEach(function(episode) { + data['episode'] = episode; + + var filename = _.template(filenameTemplate)(data); + var renderedView = _.template(template)(data); + saveView(bucket, filename, renderedView, uploadCallback); + }); + } else { + var filename = _.template(filenameTemplate)(data); + var renderedView = _.template(template)(data); + saveView(bucket, filename, renderedView, callback); + } }; -function saveView(renderedView, callback) { +function saveView(bucket, filename, renderedView, callback) { var params = { - Bucket: this.bucket, - Key: this.key, - Body: renderedView + Bucket: bucket, + Key: filename, + Body: renderedView, }; s3.putObject(params, callback); diff --git a/test/PodcastView.js b/test/PodcastView.js index b1ef22a..24acef2 100644 --- a/test/PodcastView.js +++ b/test/PodcastView.js @@ -4,22 +4,49 @@ var sinon = require('sinon'); var PodcastView; // Subject of the test -var dynamoStub = { - getItem: sinon.stub() +var dynamoStub; +var s3Stub; + +var view456 = { + feedId: '123', + viewId: '456', + name: 'Test View', + template: 'Hello World' +}; + +var view789 = { + feedId: '123', + viewId: '789', + name: 'Test View 2', + template: 'Goodbye World' }; +var episodes = [ + { title: 'Episode 1' }, + { title: 'Episode 2' }, +]; + describe('PodcastView', function() { before(function() { - mockery.enable(); + mockery.enable({warnOnUnregistered: false}); }); beforeEach(function() { mockery.registerAllowable('underscore'); + mockery.registerMock('dynamodb-doc', { DynamoDB: function() { return dynamoStub } }); - mockery.registerAllowable('../lib/PodcastView', true); + dynamoStub = { + getItem: sinon.stub(), + query: sinon.stub(), + }; - PodcastView = require('../lib/PodcastView'); + mockery.registerMock('aws-sdk', { S3: function() { return s3Stub } }); + s3Stub = { + putObject: sinon.stub(), + }; + mockery.registerAllowable('../lib/PodcastView', true); + PodcastView = require('../lib/PodcastView'); }); it('calls the callback with a view when findById is called with a valid viewId', function() { @@ -31,12 +58,7 @@ describe('PodcastView', function() { Key: { feedId: '123', viewId: '456' } }) .callsArgWith(1, null, { - Item: { - feedId: '123', - viewId: '456', - name: 'Test View', - template: 'Hello World' - } + Item: view456 }); var callback = sinon.spy(); @@ -56,8 +78,176 @@ describe('PodcastView', function() { assert.equal(view.template, 'Hello World'); }); - after(function() { + it('calls the callback with each view when forEachView is called', function() { + // Setup stubs + dynamoStub + .query + .withArgs( + { + TableName: 'podcast-views', + KeyConditionExpression: "feedId = :feedId", + ExpressionAttributeValues: { + ':feedId': '123' + } + }) + .callsArgWith(1, null, { + Items: [view456, view789] + }); + + var callback = sinon.spy(); + + // Call findById + PodcastView.forEachView('123', callback); + + // Assertions + assert(callback.calledTwice); + + var error = callback.getCall(0).args[0]; + var view = callback.getCall(0).args[1]; + var last = callback.getCall(0).args[2]; + assert.equal(error, null); + assert.equal(view.feedId, '123'); + assert.equal(view.viewId, '456'); + assert.equal(view.name, 'Test View'); + assert.equal(view.template, 'Hello World'); + assert(!last); + + var error = callback.getCall(1).args[0]; + var view = callback.getCall(1).args[1]; + var last = callback.getCall(1).args[2]; + assert.equal(error, null); + assert.equal(view.feedId, '123'); + assert.equal(view.viewId, '789'); + assert.equal(view.name, 'Test View 2'); + assert.equal(view.template, 'Goodbye World'); + assert(last); + }); + + it("calls the callback with each view when forEachView's query is truncated", function() { + // Setup stubs + dynamoStub + .query + .withArgs( + { + TableName: 'podcast-views', + KeyConditionExpression: "feedId = :feedId", + ExpressionAttributeValues: { + ':feedId': '123' + } + }) + .callsArgWith(1, null, { + Items: [view456], + LastEvaluatedKey: { feedId: '123', viewId: '456' } + }); + dynamoStub + .query + .withArgs( + { + TableName: 'podcast-views', + KeyConditionExpression: "feedId = :feedId", + ExpressionAttributeValues: { + ':feedId': '123' + }, + ExclusiveStartKey: { feedId: '123', viewId: '456' }, + }) + .callsArgWith(1, null, { + Items: [view789], + }); + + var callback = sinon.spy(); + + // Call findById + PodcastView.forEachView('123', callback); + + // Assertions + assert(callback.calledTwice); + + var error = callback.getCall(0).args[0]; + var view = callback.getCall(0).args[1]; + var last = callback.getCall(0).args[2]; + assert.equal(error, null); + assert.equal(view.feedId, '123'); + assert.equal(view.viewId, '456'); + assert.equal(view.name, 'Test View'); + assert.equal(view.template, 'Hello World'); + assert(!last); + + var error = callback.getCall(1).args[0]; + var view = callback.getCall(1).args[1]; + var last = callback.getCall(1).args[2]; + assert.equal(error, null); + assert.equal(view.feedId, '123'); + assert.equal(view.viewId, '789'); + assert.equal(view.name, 'Test View 2'); + assert.equal(view.template, 'Goodbye World'); + assert(last); + }); + + it('uploads an artifact when render is called', function() { + // Setup the test. + s3Stub.putObject.onFirstCall().callsArgWith(1, null); + + var view = new PodcastView({ + bucket: 'test-bucket', + filenameTemplate: 'episodes.html', + template: '<% _.each(episodes, function(episode) { %>

<%= episode.title %>

<% }); %>', + }); + + var callback = sinon.stub(); + + // Render + view.render(episodes, callback); + + // Verify the correct artifact was rendered. + assert(s3Stub.putObject.calledOnce); + var params = s3Stub.putObject.getCall(0).args[0]; + assert.equal(params.Bucket, 'test-bucket'); + assert.equal(params.Key, 'episodes.html'); + assert.equal(params.Body, '

Episode 1

Episode 2

'); + + // Verify the callback was called. + assert(callback.calledOnce); + }); + + it('uploads multiple artifacts when render is called and renderEach is true', function() { + // Setup the test. + s3Stub.putObject.onFirstCall().callsArgWith(1, null); + s3Stub.putObject.onSecondCall().callsArgWith(1, null); + + var view = new PodcastView({ + bucket: 'test-bucket', + filenameTemplate: '<%= episode.title.toLowerCase().replace(/[^\w ]+/g,'').replace(/ +/g,'-') %>.html', + template: '

<%= episode.title %>

', + renderEach: true, + }); + + var callback = sinon.stub(); + + // Render + view.render(episodes, callback); + + // Verify the correct artifact was rendered. + assert.equal(s3Stub.putObject.callCount, 2); + + var params = s3Stub.putObject.getCall(0).args[0]; + assert.equal(params.Bucket, 'test-bucket'); + assert.equal(params.Key, 'episode-1.html'); + assert.equal(params.Body, '

Episode 1

'); + + var params = s3Stub.putObject.getCall(1).args[0]; + assert.equal(params.Bucket, 'test-bucket'); + assert.equal(params.Key, 'episode-2.html'); + assert.equal(params.Body, '

Episode 2

'); + + // Verify the callback was called. + assert(callback.calledOnce); + }); + + afterEach(function() { mockery.deregisterAll(); + }), + + after(function() { mockery.disable(); }); }); -- cgit v1.2.3