text: const expect = require('chai').expect;
  const {graphql} = require('graphql');
  
  const schema = require('../../../../graph/schema');
  const Context = require('../../../../graph/context');
  
  const UserModel = require('../../../../models/user');
  const AssetModel = require('../../../../models/asset');
  const ActionModel = require('../../../../models/action');
  
  const SettingsService = require('../../../../services/settings');
  const CommentsService = require('../../../../services/comments');
  
  describe('graph.mutations.createComment', () => {
    beforeEach(() => SettingsService.init());
  
    const query = `
      mutation CreateComment($comment: CreateCommentInput = {asset_id: 123, body: "Here's my comment!"}) {
        createComment(comment: $comment) {
          comment {
            id
            status
            tags {
              tag {
                name
              }
            }
          }
          errors {
            translation_key
          }
        }
      }
    `;
  
    describe('context with different user properties', () => {
  
      beforeEach(() => AssetModel.create({id: '123'}));
  
      [
        {user: null, error: 'NOT_AUTHORIZED'},
        {user: new UserModel({}), error: null}
      ].forEach(({user, error}) => {
        describe(user != null ? 'with user' : 'without user', () => {
  
          it(error ? 'does not create the comment' : 'creates the comment', () => {
            const context = new Context({user});
  
            return graphql(schema, query, {}, context)
              .then(({data, errors}) => {
                expect(errors).to.be.undefined;
                if (error) {
                  expect(data.createComment).to.have.property('comment').null;
                  expect(data.createComment).to.have.property('errors').not.null;
                  expect(data.createComment.errors[0]).to.have.property('translation_key', error);
                } else {
                  expect(data.createComment).to.have.property('comment').not.null;
                  expect(data.createComment).to.have.property('errors').null;
                }
              });
          });
  
        });
      });
  
    });
  
    describe('users with different statuses', () => {
  
      beforeEach(() => AssetModel.create({id: '123'}));
  
      [
        {user: new UserModel({status: 'ACTIVE'}), error: null},
        {user: new UserModel({status: 'BANNED'}), error: 'NOT_AUTHORIZED'},
        {user: new UserModel({status: 'PENDING'}), error: null},
        {user: new UserModel({status: 'APPROVED'}), error: null}
      ].forEach(({user, error}) => {
        describe(`user.status=${user.status}`, () => {
          it(error ? 'does not create the comment' : 'creates the comment', () => {
            const context = new Context({user});
  
            return graphql(schema, query, {}, context)
              .then(({data, errors}) => {
                expect(errors).to.be.undefined;
                if (error) {
                  expect(data.createComment).to.have.property('comment').null;
                  expect(data.createComment).to.have.property('errors').not.null;
                  expect(data.createComment.errors[0]).to.have.property('translation_key', error);
                } else {
                  expect(data.createComment).to.have.property('comment').not.null;
                  expect(data.createComment).to.have.property('errors').null;
                }
              });
          });
        });
      });
  
    });
  
    describe('assets with different statuses', () => {
  
      [
        {asset: new AssetModel({id: '123', closedAt: new Date((new Date()).getTime() + (10 * 86400000))}), error: null},
        {asset: new AssetModel({id: '123', closedAt: new Date((new Date()).getTime() - (10 * 86400000))}), error: 'COMMENTING_CLOSED'}
      ].forEach(({asset, error}) => {
        describe(`asset.isClosed=${asset.isClosed}`, () => {
  
          beforeEach(() => asset.save());
  
          it(error ? 'does not create the comment' : 'creates the comment', () => {
            const context = new Context({user: new UserModel({status: 'ACTIVE'})});
  
            return graphql(schema, query, {}, context)
              .then(({data, errors}) => {
                expect(errors).to.be.undefined;
                if (error) {
                  expect(data.createComment).to.have.property('comment').null;
                  expect(data.createComment).to.have.property('errors').not.null;
                  expect(data.createComment.errors[0]).to.have.property('translation_key', error);
                } else {
                  expect(data.createComment).to.have.property('comment').not.null;
                  expect(data.createComment).to.have.property('errors').null;
                }
              });
          });
  
        });
  
      });
  
    });
  
    describe('comments made with different asset moderation settings', () => {
  
      [
        {moderation: 'PRE', status: 'PREMOD'},
        {moderation: 'POST', status: 'NONE'}
      ].forEach(({moderation, status}) => {
        describe(`moderation=${moderation}`, () => {
  
          beforeEach(() => AssetModel.create({id: '123', settings: {moderation}}));
  
          it(`creates comment with status=${status}`, () => {
            const context = new Context({user: new UserModel({status: 'ACTIVE'})});
  
            return graphql(schema, query, {}, context)
              .then(({data, errors}) => {
                expect(errors).to.be.undefined;
                expect(data.createComment).to.have.property('comment').not.null;
                expect(data.createComment).to.have.property('errors').null;
                expect(data.createComment.comment).to.have.property('status', status);
              });
          });
  
        });
      });
  
    });
  
    describe('comments with/without banned words', () => {
  
      beforeEach(() => Promise.all([
        AssetModel.create({id: '123'}),
        SettingsService.update({wordlist: {banned: ['WORST'], suspect: ['EH']}})
      ]));
  
      [
        {message: 'comment does not contain banned/suspect words', body: 'This is such a nice comment!', status: 'NONE', flagged: false},
        {message: 'comment contains banned words', body: 'This is the WORST comment!', status: 'REJECTED', flagged: false},
        {message: 'comment contains suspect words', body: 'This is the EH comment!', status: 'NONE', flagged: true}
      ].forEach(({message, body, status, flagged}) => {
        describe(message, () => {
  
          it(`should create a comment with status=${status} and it ${flagged ? 'should' : 'should not'} be flagged`, () => {
            const context = new Context({user: new UserModel({status: 'ACTIVE'})});
  
            return graphql(schema, query, {}, context, {
              comment: {
                asset_id: '123',
                body
              }
            })
            .then(({data, errors}) => {
              expect(errors).to.be.undefined;
              expect(data.createComment).to.have.property('comment').not.null;
              expect(data.createComment.comment).to.have.property('status', status);
              expect(data.createComment).to.have.property('errors').null;
  
              return ActionModel.find({
                item_id: data.createComment.comment.id,
                action_type: 'FLAG'
              });
            })
            .then((actions) => {
              if (flagged) {
                expect(actions).to.have.length(1);
              } else {
                expect(actions).to.have.length(0);
              }
            });
          });
  
        });
      });
    });
  
    describe('users with different roles', () => {
  
      beforeEach(() => AssetModel.create({id: '123'}));
  
      [
        {roles: [], tag: null},
        {roles: ['ADMIN'], tag: 'STAFF'},
        {roles: ['MODERATOR'], tag: 'STAFF'},
        {roles: ['ADMIN', 'MODERATOR'], tag: 'STAFF'}
      ].forEach(({roles, tag}) => {
        describe(`user.roles=${JSON.stringify(roles)}`, () => {
  
          it(`creates comment ${tag ? `with tag=${tag}` : 'without tags'}`, () => {
            const context = new Context({user: new UserModel({roles})});
  
            return graphql(schema, query, {}, context)
              .then(({data, errors}) => {
                expect(errors).to.be.undefined;
                expect(data.createComment).to.have.property('comment').not.null;
                expect(data.createComment).to.have.property('errors').null;
  
                return CommentsService.findById(data.createComment.comment.id);
              })
              .then(({tags}) => {
                if (tag) {
                  expect(tags).to.have.length(1);
                  expect(tags[0].tag.name).to.have.equal(tag);
                } else {
                  expect(tags).length(0);
                }
              });
          });
  
        });
      });
  
    });
  });
  