{"size": 4671, "ext": "js", "max_stars_repo_path": "test/topic.test.js", "max_stars_repo_name": "auth0/apns.js", "max_stars_repo_stars_event_min_datetime": "2016-11-19T19:50:41.000Z", "max_stars_repo_stars_event_max_datetime": "2021-03-26T06:23:49.000Z", "max_issues_repo_path": "test/topic.test.js", "max_issues_repo_name": "auth0/apns.js", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "test/topic.test.js", "max_forks_repo_name": "auth0/apns.js", "max_forks_repo_forks_event_min_datetime": "2018-12-21T21:44:06.000Z", "max_forks_repo_forks_event_max_datetime": "2018-12-21T21:44:06.000Z"}
{"max_stars_count": 3, "max_issues_count": null, "max_forks_count": 1, "avg_line_length": 32.8943661972, "max_line_length": 141, "alphanum_fraction": 0.6058659816}
`use strict`;

const chai = require('chai');
const chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
const expect = chai.expect;
const faker = require('faker');

const Topic = require('../topic');
const APNSError = require('../error');

describe('topic', function() {

  const token = faker.random.uuid();
  const device = faker.random.uuid();
  const notification = {aps:{alert:faker.random.word()}};

  describe('#constructor', function() {

    it('should create with topic for production', function() {
      const topic = new Topic('com.auth0.sample.APNS', 'production');
      expect(topic.name).to.be.equal('com.auth0.sample.APNS');
      expect(topic.host).to.be.equal('api.push.apple.com');
    });

    it('should create with topic for development', function() {
      const topic = new Topic('com.auth0.sample.APNS', 'development');
      expect(topic.name).to.be.equal('com.auth0.sample.APNS');
      expect(topic.host).to.be.equal('api.development.push.apple.com');
    });

    it('should create with topic only', function() {
      const topic = new Topic('com.auth0.sample.APNS');
      expect(topic.name).to.be.equal('com.auth0.sample.APNS');
      expect(topic.host).to.be.equal('api.push.apple.com');
    });

    it('should fail to build with no topic', function() {
      expect(() => new Topic()).to.throw(Error);
    });

  });

  describe('#send', function() {

    const name = 'com.auth0.sample.apns';
    var topic;

    beforeEach(function() {
      topic = new Topic(name);
      topic._request = () => { throw new Error('MOCKED!') };
    });

    describe('validations', function() {
      it('should fail with no parameters', function() {
        return expect(topic.send()).to.be.rejected;
      });

      it('should fail with only notification', function() {
        return expect(topic.send(notification)).to.be.rejected;
      });

      it('should fail without token', function() {
        return expect(topic.send(notification, device)).to.be.rejected;
      });

      it('should fail with null notification', function() {
        return expect(topic.send(null, device, token)).to.be.rejected;
      });

      it('should fail with null device', function() {
        return expect(topic.send(notification, null, token)).to.be.rejected;
      });

      it('should fail with null token', function() {
        return expect(topic.send(notification, device, null)).to.be.rejected;
      });
    });

    describe('request', function() {

      var options, body;
      const send = () => topic.send(notification, device, token);

      beforeEach(function() {
        options = {};
        body = null;
        topic._request = (opts, payload) => {
          options = opts;
          body = payload;
          return Promise.resolve({status: 200, headers: {'apns-id': faker.random.uuid()}});
        };
      });

      it('should use correct endpoint', function() {
        return send().then(() => expect(options.hostname).to.equal(topic.host));
      });

      it('should use correct port', function() {
        return send().then(() => expect(options.port).to.equal(443));
      });

      it('should use correct method', function() {
        return send().then(() => expect(options.method).to.equal('POST'));
      });

      it('should use correct path', function() {
        return send().then(() => expect(options.path).to.equal(`/3/device/${device}`));
      });

      it('should have authorization header with bearer token', function() {
        return send().then(() => expect(options.headers.authorization).to.equal(`Bearer ${token}`));
      });

      it('should have topic header', function() {
        return send().then(() => expect(options.headers['apns-topic']).to.equal(topic.name));
      });

      it('should have notification in the body', function() {
        return send().then(() => expect(body).to.equal(JSON.stringify(notification)));
      });
    });

    describe('response', function() {

      const send = () => topic.send(notification, device, token);

      it('should return apns-id on success', function() {
        const id = faker.random.uuid();
        topic._request = () => Promise.resolve({status: 200, headers: {'apns-id': id}});
        return expect(send()).to.eventually.have.property('id', id);
      });

      it('should return APNS error on failure', function() {
        topic._request = () => Promise.resolve({status: 400, data: JSON.stringify({reason: APNSError.Reasons.DeviceTokenNotForTopic.name})});
        return expect(send()).to.eventually.be.rejectedWith(APNSError, APNSError.Reasons.DeviceTokenNotForTopic.message);
      });

    });
  });
});
