<commit_before>var chai = require('chai'),
  should = chai.should(),
  validator = require('validator'),
  _ = require('underscore'),
  express = require('express'),
  app = express(),
  sinon = require("sinon"),
  sinonChai = require("sinon-chai"),
  request = require('supertest'),
  proxyquire = require('proxyquire'),
  eventStoreClient = {
    streams: {
      post: sinon.stub()
    },
    projection: {
      getState: sinon.stub()
    }
  },
  hypermediaResponseStub = {
    inboxes: {
      POST: sinon.stub(),
      uuid: {
        GET: sinon.stub(),
        POST: sinon.stub()
      }
    },

  },
  inboxAdded = {
    validate: sinon.stub(),
    create: sinon.stub()
  },
  sanitizer = {
    sanitize: sinon.stub()
  },
  translator = {
    translatePush: sinon.stub()
  },
  validator = {
    isUUID: sinon.stub()
  },
  controller = proxyquire('../../api/inboxesController', {
    './hypermediaResponse': hypermediaResponseStub,
    './sanitizer': sanitizer,
    './events/inboxAdded': inboxAdded,
    './helpers/eventStoreClient': eventStoreClient,
    './translators/githubTranslator': translator,
    'validator': validator
  });

chai.use(sinonChai);
chai.config.includeStack = true;

controller.init(app);

var getInbox = function(path, shouldBehaveThusly) {
  request(app)
    .get(path)
    .end(shouldBehaveThusly);
}

var postInboxCreate = function(payload, shouldBehaveThusly, contentType) {
  request(app)
    .post('/api/inboxes')
    .send(JSON.stringify(payload))
    .type(contentType || 'application/json')
    .end(shouldBehaveThusly);
};


var postInbox = function(payload, shouldBehaveThusly, contentType, inboxUuid, xGithubEventValue) {
  request(app)
    .post('/api/inboxes/' + inboxUuid || 'c347948f-e1d0-4cd7-9341-f0f6ef5289bf')
    .set('x-github-event', xGithubEventValue || 'push')
    .send(JSON.stringify(payload))
    .type(contentType || 'application/json')
    .end(shouldBehaveThusly);
};

describe('inboxesController', function() {

  describe('when creating an inbox (/api/inboxes)', function() {

    var digestId = 'e9be4a71-f6ca-4f02-b431-d74489dee5d0';
    var payload = {
      name: 'His name was <NAME>',
      digestId: digestId,
      family: 'GitHub'
    };

    describe('with an unsupported or missing Content-Type header', function() {
      var payload = {};
      it('should reject request and return a 415 status code.', function(done) {
        postInboxCreate(payload, function(err, res) {
          res.statusCode.should.equal(415);
          done();
        }, 'application/jackson');
      });

      it('it should reject the request and explain that only application/json is accepted when sending unsupported Content-Type.', function(done) {
        postInboxCreate(payload, function(err, res) {
          res.text.should.equal('When creating an inbox, you must send a Content-Type: application/json header.');
          done();
        }, 'application/jackson');
      });

      it('it should reject the request and explain that only application/json is accepted when not setting Content-Type', function(done) {
        var postInboxCreateNoContentType = function(payload, shouldBehaveThusly, contentType) {
          request(app)
            .post('/api/inboxes')
            .send(JSON.stringify(payload))
            .end(shouldBehaveThusly);
        };

        postInboxCreateNoContentType(payload, function(err, res) {
          res.text.should.equal('When creating an inbox, you must send a Content-Type: application/json header.');
          done();
        });
      })
    });

    describe('with a valid payload', function() {
      var inboxId = '53d8c6ac-37f4-453f-b252-cb2d93c18fa7';

      var protocol = 'http';
      var host = 'localhost';

      var hypermediaResponse = {
        "_links": {
          "self": {
            "href": protocol + "://" + host + "/api/inboxes/" + inboxId
          }
        }
      };

      var inboxAddedEvent = {
        eventType: 'InboxAdded',
        eventId: 'a4cfd6f3-3cb4-4504-ae52-cc8d9fcb8818',
        data: {
          digestId: digestId,
          inboxId: inboxId,
          family: 'GitHub',
          name: '<NAME>',
          url: 'http://www.someURL.com'
        }
      };

      before(function() {
        sanitizer.sanitize.returns([]);
        inboxAdded.validate.returns([]);
        inboxAdded.create.returns(inboxAddedEvent);
        hypermediaResponseStub.inboxes.POST.returns(hypermediaResponse);
      })

      beforeEach(function() {
        eventStoreClient.streams.post.callsArgWith(1, null, "unused response");
      });

      describe('but an unsupported Content-Type header', function() {
        it('it should reject the request and explain that only application/json is accepted.', function(done) {
          postInboxCreate(payload, function(err, res) {
            res.text.should.equal('When creating an inbox, you must send a Content-Type: application/json header.');
            done();
          }, 'application/jackson');
        });

        it('should reject request and return a 415 status code.', function(done) {
          postInboxCreate(payload, function(err, res) {
            res.statusCode.should.equal(415);
            done();
          }, 'application/jackson');
        });
      });

      describe('but with illegal content in the name field', function() {
        before(function() {
          sanitizer.sanitize.returns(['error']);
        })

        it('should call sanitizer.sanitize with correct parameters.', function(done) {
          postInboxCreate(payload, function() {
            sanitizer.sanitize.should.have.been.calledWith('inbox', payload, ['name']);
            done();
          });
        });
      })

      describe('but with a schema violation', function() {
        before(function() {
          sanitizer.sanitize.returns([]);
          inboxAdded.validate.returns(['error']);
        })

        it('should validate the payload against an inboxAdded schema', function(done) {
          postInboxCreate(payload, function() {
            inboxAdded.validate.should.have.been.calledWith(payload);
            done();
          });
        })
      })


      it('it should have a response Content-Type of hal+json', function(done) {
        postInboxCreate(payload, function(err, res) {
          res.get('Content-Type').should.equal('application/hal+json; charset=utf-8');
          done();
        });
      });

      it('it should use proper arguments when creating hypermedia.', function(done) {
        postInboxCreate(payload, function(err, res) {
          hypermediaResponseStub.inboxes.POST.should.have.been.calledWith(protocol, sinon.match.any, inboxAddedEvent.data.inboxId);
          done();
        });
      });

      it('it should have a response code of 201 created', function(done) {
        postInboxCreate(payload, function(err, res) {
          res.status.should.equal(201);
          done();
        });
      });

      it('it should set the Location response header to the newly created digest', function(done) {
        postInboxCreate(payload, function(err, res) {
          res.get('Location').should.equal(hypermediaResponse._links.self.href);
          done();
        });
      });
    });

    describe('for a non-existant digestId', function() {

      var nonExistantDigestId = 'dbb47eec-514c-441d-bb15-b7d6d3d2153c';

      before(function() {
        // eventStoreClient.projection.getState.callsArgWith(1, null, {
        //   body: JSON.stringify({
        //     digestId: digestId
        //   }),
        //   statusCode: 200
        // });
      })

      it('should reject request and return a 400 status code.', function(done) {
        postInboxCreate(payload, function(err, res) {
          res.statusCode.should.equal(400);
          done();
        }, 'application/jackson');
      });

      it('should call eventStore.projection.getState with the appropriate parameters', function(done) {
        postInboxCreate(payload, function(err, res) {
          eventStoreClient.projection.getState.should.have.been.calledWith({
            name: sinon.match.any,
            partition: 'digest-' + nonExistantDigestId
          }, sinon.match.any);<commit_msg>Move around some describes and mock out eventStoreClient.projection.getState such that the test takes the happy path.<commit_after>var chai = require('chai'),
  should = chai.should(),
  validator = require('validator'),
  _ = require('underscore'),
  express = require('express'),
  app = express(),
  sinon = require("sinon"),
  sinonChai = require("sinon-chai"),
  request = require('supertest'),
  proxyquire = require('proxyquire'),
  eventStoreClient = {
    streams: {
      post: sinon.stub()
    },
    projection: {
      getState: sinon.stub()
    }
  },
  hypermediaResponseStub = {
    inboxes: {
      POST: sinon.stub(),
      uuid: {
        GET: sinon.stub(),
        POST: sinon.stub()
      }
    },

  },
  inboxAdded = {
    validate: sinon.stub(),
    create: sinon.stub()
  },
  sanitizer = {
    sanitize: sinon.stub()
  },
  translator = {
    translatePush: sinon.stub()
  },
  validator = {
    isUUID: sinon.stub()
  },
  controller = proxyquire('../../api/inboxesController', {
    './hypermediaResponse': hypermediaResponseStub,
    './sanitizer': sanitizer,
    './events/inboxAdded': inboxAdded,
    './helpers/eventStoreClient': eventStoreClient,
    './translators/githubTranslator': translator,
    'validator': validator
  });

chai.use(sinonChai);
chai.config.includeStack = true;

controller.init(app);

var getInbox = function(path, shouldBehaveThusly) {
  request(app)
    .get(path)
    .end(shouldBehaveThusly);
}

var postInboxCreate = function(payload, shouldBehaveThusly, contentType) {
  request(app)
    .post('/api/inboxes')
    .send(JSON.stringify(payload))
    .type(contentType || 'application/json')
    .end(shouldBehaveThusly);
};


var postInbox = function(payload, shouldBehaveThusly, contentType, inboxUuid, xGithubEventValue) {
  request(app)
    .post('/api/inboxes/' + inboxUuid || 'c347948f-e1d0-4cd7-9341-f0f6ef5289bf')
    .set('x-github-event', xGithubEventValue || 'push')
    .send(JSON.stringify(payload))
    .type(contentType || 'application/json')
    .end(shouldBehaveThusly);
};

describe('inboxesController', function() {

  describe('when creating an inbox (/api/inboxes)', function() {

    var digestId = 'e9be4a71-f6ca-4f02-b431-d74489dee5d0';
    var payload = {
      name: 'His name was <NAME>',
      digestId: digestId,
      family: 'GitHub'
    };

    describe('with an unsupported or missing Content-Type header', function() {
      var payload = {};
      it('should reject request and return a 415 status code.', function(done) {
        postInboxCreate(payload, function(err, res) {
          res.statusCode.should.equal(415);
          done();
        }, 'application/jackson');
      });

      it('it should reject the request and explain that only application/json is accepted when sending unsupported Content-Type.', function(done) {
        postInboxCreate(payload, function(err, res) {
          res.text.should.equal('When creating an inbox, you must send a Content-Type: application/json header.');
          done();
        }, 'application/jackson');
      });

      it('it should reject the request and explain that only application/json is accepted when not setting Content-Type', function(done) {
        var postInboxCreateNoContentType = function(payload, shouldBehaveThusly, contentType) {
          request(app)
            .post('/api/inboxes')
            .send(JSON.stringify(payload))
            .end(shouldBehaveThusly);
        };

        postInboxCreateNoContentType(payload, function(err, res) {
          res.text.should.equal('When creating an inbox, you must send a Content-Type: application/json header.');
          done();
        });
      })
    });

    describe('with a valid payload', function() {
      var inboxId = '53d8c6ac-37f4-453f-b252-cb2d93c18fa7';

      var protocol = 'http';
      var host = 'localhost';

      var hypermediaResponse = {
        "_links": {
          "self": {
            "href": protocol + "://" + host + "/api/inboxes/" + inboxId
          }
        }
      };

      var inboxAddedEvent = {
        eventType: 'InboxAdded',
        eventId: 'a4cfd6f3-3cb4-4504-ae52-cc8d9fcb8818',
        data: {
          digestId: digestId,
          inboxId: inboxId,
          family: 'GitHub',
          name: '<NAME>',
          url: 'http://www.someURL.com'
        }
      };

      before(function() {
        sanitizer.sanitize.returns([]);
        inboxAdded.validate.returns([]);
        inboxAdded.create.returns(inboxAddedEvent);
        hypermediaResponseStub.inboxes.POST.returns(hypermediaResponse);
      })

      beforeEach(function() {
        eventStoreClient.streams.post.callsArgWith(1, null, "unused response");

        eventStoreClient.projection.getState.callsArgWith(1, null, {
          body: JSON.stringify({
            digestId: digestId
          }),
          statusCode: 200
        });
      });

      it('it should have a response Content-Type of hal+json', function(done) {
        postInboxCreate(payload, function(err, res) {
          res.get('Content-Type').should.equal('application/hal+json; charset=utf-8');
          done();
        });
      });

      it('it should use proper arguments when creating hypermedia.', function(done) {
        postInboxCreate(payload, function(err, res) {
          hypermediaResponseStub.inboxes.POST.should.have.been.calledWith(protocol, sinon.match.any, inboxAddedEvent.data.inboxId);
          done();
        });
      });

      it('it should have a response code of 201 created', function(done) {
        postInboxCreate(payload, function(err, res) {
          res.status.should.equal(201);
          done();
        });
      });

      it('it should set the Location response header to the newly created digest', function(done) {
        postInboxCreate(payload, function(err, res) {
          res.get('Location').should.equal(hypermediaResponse._links.self.href);
          done();
        });
      });

      describe('but an unsupported Content-Type header', function() {
        it('it should reject the request and explain that only application/json is accepted.', function(done) {
          postInboxCreate(payload, function(err, res) {
            res.text.should.equal('When creating an inbox, you must send a Content-Type: application/json header.');
            done();
          }, 'application/jackson');
        });

        it('should reject request and return a 415 status code.', function(done) {
          postInboxCreate(payload, function(err, res) {
            res.statusCode.should.equal(415);
            done();
          }, 'application/jackson');
        });
      });

      describe('but with illegal content in the name field', function() {
        before(function() {
          sanitizer.sanitize.returns(['error']);
        })

        it('should call sanitizer.sanitize with correct parameters.', function(done) {
          postInboxCreate(payload, function() {
            sanitizer.sanitize.should.have.been.calledWith('inbox', payload, ['name']);
            done();
          });
        });
      })

      describe('but with a schema violation', function() {
        before(function() {
          sanitizer.sanitize.returns([]);
          inboxAdded.validate.returns(['error']);
        })

        it('should validate the payload against an inboxAdded schema', function(done) {
          postInboxCreate(payload, function() {
            inboxAdded.validate.should.have.been.calledWith(payload);
            done();
          });
        })
      })
    });

    describe('for a non-existant digestId', function() {

      var nonExistantDigestId = 'dbb47eec-514c-441d-bb15-b7d6d3d2153c';

      before(function() {
        // eventStoreClient.projection.getState.callsArgWith(1, null, {
        //   body: JSON.stringify({
        //     digestId: digestId
        //   }),
        //   statusCode: 200
        // });
      })

      it('should reject request and return a 400 status code.', function(done) {
        postInboxCreate(payload, function(err, res) {
          res.statusCode.should.equal(400);
          done();
        }, 'application/jackson');
      });

      it('should call eventStore.projection.getState with the appropriate parameters', function(done) {
        postInboxCreate(payload, function(err, res) {
          eventStoreClient.projection.getState.should.have.been.calledWith({
            name: sinon.match.any,
            partition: 'digest-' + nonExistantDigestId
          }, sinon.match.any);
{'fraction_non_alphanumeric': 0.13638810791409942, 'fraction_numerical': 0.014715559011784412, 'mean_word_length': 2.503352891869237, 'pattern_counts': {'":': 8, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6071339', 'n_tokens_mistral': 5067, 'n_tokens_neox': 4872, 'n_words': 998}