'use strict';

var _fs;

function _load_fs() {
  return _fs = _interopRequireDefault(require('fs'));
}

var _path;

function _load_path() {
  return _path = _interopRequireDefault(require('path'));
}

var _chai;

function _load_chai() {
  return _chai = require('chai');
}

var _jsdoc;

function _load_jsdoc() {
  return _jsdoc = require('../../src/jsdoc');
}

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var fixtures = (_path || _load_path()).default.join(__dirname, '../..', 'fixtures', 'jsdoc');

describe('JSDoc Parser', function () {
  describe('parse()', function () {
    describe('Function Declaration', function () {
      var doclet = void 0;
      before(function () {
        var functionDeclarationFile = (_path || _load_path()).default.join(fixtures, 'functionDeclaration.js');
        var functionDeclaration = (_fs || _load_fs()).default.readFileSync(functionDeclarationFile).toString();
        var doclets = (0, (_jsdoc || _load_jsdoc()).parser)(functionDeclaration);
        (0, (_chai || _load_chai()).expect)(doclets).to.be.a('array');
        (0, (_chai || _load_chai()).expect)(doclets).to.have.lengthOf(1);
        doclet = doclets[0];
      });
      it('should have all the proper keys', function () {
        (0, (_chai || _load_chai()).expect)(doclet).to.include.keys('name', 'description', 'returns', 'args', 'access', 'examples', 'static');
      });
      it('should extract the correct name', function () {
        (0, (_chai || _load_chai()).expect)(doclet.name).to.equal('add');
      });
      it('should extract the correct description', function () {
        (0, (_chai || _load_chai()).expect)(doclet.description).to.equal('Adds two numbers.');
      });
      it('should extract the correct args', function () {
        var args = doclet.args;
        (0, (_chai || _load_chai()).expect)(args).to.be.a('array');
        (0, (_chai || _load_chai()).expect)(args).to.have.lengthOf(2);
        var _iteratorNormalCompletion = true;
        var _didIteratorError = false;
        var _iteratorError = undefined;

        try {
          for (var _iterator = args[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
            var arg = _step.value;

            (0, (_chai || _load_chai()).expect)(arg).to.include.keys('name', 'type', 'description');
          }
        } catch (err) {
          _didIteratorError = true;
          _iteratorError = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion && _iterator.return) {
              _iterator.return();
            }
          } finally {
            if (_didIteratorError) {
              throw _iteratorError;
            }
          }
        }

        (0, (_chai || _load_chai()).expect)(args[0].name).to.equal('a');
        (0, (_chai || _load_chai()).expect)(args[1].name).to.equal('b');
        (0, (_chai || _load_chai()).expect)(args[0].description).to.equal('The first number in an addition.');
        (0, (_chai || _load_chai()).expect)(args[1].description).to.equal('The second number in an addition.');
        (0, (_chai || _load_chai()).expect)(args[0].type).to.equal('number');
        (0, (_chai || _load_chai()).expect)(args[1].type).to.equal('number');
      });
      it('should extract the correct returns', function () {
        (0, (_chai || _load_chai()).expect)(doclet.returns).to.include.keys('type', 'description');
        (0, (_chai || _load_chai()).expect)(doclet.returns.description).to.equal('Returns the total.');
        (0, (_chai || _load_chai()).expect)(doclet.returns.type).to.equal('number');
      });
      it('should extract the correct access from the @public annotation', function () {
        (0, (_chai || _load_chai()).expect)(doclet.access).to.equal('public');
      });
      it('should extract the static attribute from the @static annotation', function () {
        (0, (_chai || _load_chai()).expect)(doclet.static).to.be.true;
      });
    });

    describe('Invalid code', function () {
      it('should returns an empty array', function () {
        var doclets = (0, (_jsdoc || _load_jsdoc()).parser)('this is an invalid code');
        (0, (_chai || _load_chai()).expect)(doclets).to.be.a('array');
        (0, (_chai || _load_chai()).expect)(doclets).to.have.lengthOf(0);
      });
    });

    describe('Method Declaration and Class Declaration', function () {
      var doclets = void 0;
      before(function () {
        var methodDeclarationFile = (_path || _load_path()).default.join(fixtures, 'methodDeclaration.js');
        var methodDeclaration = (_fs || _load_fs()).default.readFileSync(methodDeclarationFile).toString();
        doclets = (0, (_jsdoc || _load_jsdoc()).parser)(methodDeclaration);
      });
      it('should be a populated array', function () {
        (0, (_chai || _load_chai()).expect)(doclets).to.be.an('array');
        (0, (_chai || _load_chai()).expect)(doclets).to.have.length.of.at.least(2);
      });
      xit('should recognize the Class Declaration first', function () {
        var doclet = doclets[0];
        (0, (_chai || _load_chai()).expect)(doclet).to.have.all.keys('name', 'description');
        (0, (_chai || _load_chai()).expect)(doclet.name).to.equal('Point');
        (0, (_chai || _load_chai()).expect)(doclet.description).to.equal('Class representing a point.');
      });
      it('should recognize the constructor', function () {
        var doclet = doclets[0];
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('name').that.equals('constructor');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('description').that.equals('Create a point.');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('access').that.equals('public');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('static').that.is.false;
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('returns').that.is.an('object').that.is.empty;
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('examples').that.is.an('array').that.is.empty;
      });
      it("should extract the constructor's args correctly", function () {
        var doclet = doclets[0];
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('args').that.is.an('array').with.lengthOf(2);
        var args = doclet.args;
        var _iteratorNormalCompletion2 = true;
        var _didIteratorError2 = false;
        var _iteratorError2 = undefined;

        try {
          for (var _iterator2 = args[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
            var arg = _step2.value;

            (0, (_chai || _load_chai()).expect)(arg).to.include.keys('name', 'type', 'description');
            (0, (_chai || _load_chai()).expect)(arg.type).to.equal('number');
          }
        } catch (err) {
          _didIteratorError2 = true;
          _iteratorError2 = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion2 && _iterator2.return) {
              _iterator2.return();
            }
          } finally {
            if (_didIteratorError2) {
              throw _iteratorError2;
            }
          }
        }

        (0, (_chai || _load_chai()).expect)(args[0].name).to.equal('x');
        (0, (_chai || _load_chai()).expect)(args[1].name).to.equal('y');
        (0, (_chai || _load_chai()).expect)(args[0].description).to.equal('The x value.');
        (0, (_chai || _load_chai()).expect)(args[1].description).to.equal('The y value.');
      });
      it('should recognize the getX method', function () {
        var doclet = doclets[1];
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('name').that.equals('getX');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('description').that.equals('Get the x value.');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('access').that.equals('public');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('static').that.is.false;
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('returns').that.is.an('object').that.is.not.empty;
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('examples').that.is.an('array').that.is.empty;
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('args').that.is.an('array').that.is.empty;
      });
      it('should recognize the getY method', function () {
        var doclet = doclets[2];
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('name').that.equals('getY');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('description').that.equals('Get the y value.');
      });
      it('should recognize the fromString method as the last doclet', function () {
        var doclet = doclets[doclets.length - 1];
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('name').that.equals('fromString');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('description').that.equals('Convert a string containing two comma-separated numbers into a point.');
      });
    });

    describe('Variable Declaration', function () {
      var doclets = void 0;
      before(function () {
        var variableDeclarationFile = (_path || _load_path()).default.join(fixtures, 'variableDeclaration.js');
        var variableDeclaration = (_fs || _load_fs()).default.readFileSync(variableDeclarationFile).toString();
        doclets = (0, (_jsdoc || _load_jsdoc()).parser)(variableDeclaration);
      });
      it('should be an array of one Doclet', function () {
        (0, (_chai || _load_chai()).expect)(doclets).to.be.an('array').and.to.have.lengthOf(1);
      });
      it('should parse the doc correctly', function () {
        var doclet = doclets[0];
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('name').that.equals('add');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('description').that.equals('Adds two numbers.');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('access').that.equals('public');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('static').that.is.false;
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('returns').that.is.an('object').that.is.not.empty;
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('examples').that.is.an('array').that.is.not.empty;
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('args').that.is.an('array').that.have.lengthOf(2);
      });
    });

    describe('Various Param Types', function () {
      var args = void 0;
      before(function () {
        var file = (_path || _load_path()).default.join(fixtures, 'variousParamTypes.js');
        var doclets = (0, (_jsdoc || _load_jsdoc()).parser)((_fs || _load_fs()).default.readFileSync(file).toString());
        (0, (_chai || _load_chai()).expect)(doclets).to.be.an('array').and.to.have.lengthOf(1);
        var doclet = doclets[0];
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('args').that.is.an('array').that.is.not.empty;
        args = doclet.args;
      });
      it('should recognize "*" as "*"', function () {
        var anyArg = args.find(function (arg) {
          return arg.name === 'anyType';
        });
        (0, (_chai || _load_chai()).expect)(anyArg.type).to.equal('*');
      });
      it('should recognize "[]" as "[]"', function () {
        var anyArg = args.find(function (arg) {
          return arg.name === 'arrayType';
        });
        (0, (_chai || _load_chai()).expect)(anyArg.type).to.equal('[]');
      });
      it('should recognize Union type correctly', function () {
        var anyArg = args.find(function (arg) {
          return arg.name === 'unionType';
        });
        (0, (_chai || _load_chai()).expect)(anyArg.type).to.equal('(number | [])');
      });
      it('should recognize custom type correctly', function () {
        var anyArg = args.find(function (arg) {
          return arg.name === 'myCustomType';
        });
        (0, (_chai || _load_chai()).expect)(anyArg.type).to.equal('CustomType');
      });
      it('should recognize Object type', function () {
        var anyArg = args.find(function (arg) {
          return arg.name === 'objectType';
        });
        (0, (_chai || _load_chai()).expect)(anyArg.type).to.equal('Object');
      });
      it('should recognize Function type', function () {
        var anyArg = args.find(function (arg) {
          return arg.name === 'functionType';
        });
        (0, (_chai || _load_chai()).expect)(anyArg.type).to.equal('Function');
      });
      it('should recognize Array of one type', function () {
        var anyArg = args.find(function (arg) {
          return arg.name === 'arrayOfType';
        });
        (0, (_chai || _load_chai()).expect)(anyArg.type).to.equal('Array<string>');
      });
      it('should recognize Array of union', function () {
        var anyArg = args.find(function (arg) {
          return arg.name === 'arrayOfUnion';
        });
        (0, (_chai || _load_chai()).expect)(anyArg.type).to.equal('Array<(number | Object)>');
      });
    });

    describe('Flow Type File', function () {
      it('should parse the file with no errors', function () {
        var file = (_path || _load_path()).default.join(fixtures, 'flowTypeFile.js');
        var doclets = (0, (_jsdoc || _load_jsdoc()).parser)((_fs || _load_fs()).default.readFileSync(file).toString());
        (0, (_chai || _load_chai()).expect)(doclets).to.be.an('array').and.to.have.lengthOf(1);
        var doclet = doclets[0];

        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('name').that.equals('first');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('description').that.equals('returns the first element of an array reference.');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('access').that.equals('public');
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('static').that.is.false;
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('returns').that.is.an('object').that.is.not.empty;
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('examples').that.is.an('array').that.is.not.empty;
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('args').that.is.an('array').that.is.not.empty;
      });
    });

    describe('Description Tag', function () {
      var doclets = void 0;
      before(function () {
        var file = (_path || _load_path()).default.join(fixtures, 'descriptionTag.js');
        doclets = (0, (_jsdoc || _load_jsdoc()).parser)((_fs || _load_fs()).default.readFileSync(file).toString());
        (0, (_chai || _load_chai()).expect)(doclets).to.be.an('array').and.to.have.lengthOf(3);
      });
      it('should ignore an invalid description', function () {
        var doclet = doclets[0];
        (0, (_chai || _load_chai()).expect)(doclet.name).to.equal('invalidDescription');
        (0, (_chai || _load_chai()).expect)(doclet.description).to.equal('');
      });

      it('should recognize the description tag', function () {
        var doclet = doclets[1];
        (0, (_chai || _load_chai()).expect)(doclet.name).to.equal('descriptionTag');
        (0, (_chai || _load_chai()).expect)(doclet.description).to.equal('Adds two numbers.');
      });

      it('should recognize the synonym "desc"', function () {
        var doclet = doclets[2];
        (0, (_chai || _load_chai()).expect)(doclet.name).to.equal('descTag');
        (0, (_chai || _load_chai()).expect)(doclet.description).to.equal('Adds two numbers.');
      });
    });

    describe('Access property', function () {
      var doclets = void 0;
      before(function () {
        var file = (_path || _load_path()).default.join(fixtures, 'misc.js');
        doclets = (0, (_jsdoc || _load_jsdoc()).parser)((_fs || _load_fs()).default.readFileSync(file).toString());
        (0, (_chai || _load_chai()).expect)(doclets).to.be.an('array');
      });
      it('should find only public functions', function () {
        (0, (_chai || _load_chai()).expect)(doclets.find(function (doclet) {
          return doclet.name === 'publicFunc';
        })).not.to.be.undefined;
        (0, (_chai || _load_chai()).expect)(doclets.find(function (doclet) {
          return doclet.name === 'privateFunc';
        })).to.be.undefined;
      });
    });

    describe('Properties property', function () {
      var doclets = void 0;
      before(function () {
        var file = (_path || _load_path()).default.join(fixtures, 'properties.js');
        doclets = (0, (_jsdoc || _load_jsdoc()).parser)((_fs || _load_fs()).default.readFileSync(file).toString());
        (0, (_chai || _load_chai()).expect)(doclets).to.be.an('array');
      });
      it('should parse the property tag correctly', function () {
        var doclet = doclets[0];
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('properties').that.is.an('array').that.have.lengthOf(5);
        (0, (_chai || _load_chai()).expect)(doclet.properties[0].name).to.equal('defaults');
        (0, (_chai || _load_chai()).expect)(doclet.properties[0].type).to.equal('object');
        (0, (_chai || _load_chai()).expect)(doclet.properties[0].description).to.equal('The default values for parties.');
      });
    });

    describe('Doc ending with more than one star', function () {
      var doclets = void 0;
      before(function () {
        var file = (_path || _load_path()).default.join(fixtures, 'endWithTwoStars.js');
        doclets = (0, (_jsdoc || _load_jsdoc()).parser)((_fs || _load_fs()).default.readFileSync(file).toString());
        (0, (_chai || _load_chai()).expect)(doclets).to.be.an('array');
      });
      it('should parse the doc and not hang due to catastrophic backtracking', function () {
        var doclet = doclets[0];
        (0, (_chai || _load_chai()).expect)(doclet).to.have.property('description').that.is.equal('Basic accordion component');
      });
    });
  });
});