diff options
| -rw-r--r-- | lib/PodcastView.js | 37 | ||||
| -rw-r--r-- | 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) { %><h1><%= episode.title %></h1><% }); %>', +    }); + +    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, '<h1>Episode 1</h1><h1>Episode 2</h1>'); + +    // 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: '<h1><%= episode.title %></h1>', +      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, '<h1>Episode 1</h1>'); + +    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, '<h1>Episode 2</h1>'); + +    // Verify the callback was called. +    assert(callback.calledOnce); +  }); + +  afterEach(function() {      mockery.deregisterAll(); +  }), + +  after(function() {      mockery.disable();    });  }); | 
