<commit_before>'use strict';

var assert = require('assert');
var jsdom = require('mocha-jsdom');
var sinon = require('sinon');
require('../fixture/sandbox.js');

describe('Component', function() {

  jsdom();

  beforeEach(function() {
    Element.prototype.classList = {
      add: sinon.stub(),
      remove: sinon.stub()
    };
  });

  describe('Lifecycle', function() {
    it('should test component render lifecycle', function() {
      var CustomComponent = createCustomComponentClass();

      CustomComponent.SURFACES = {
        header: {},
        bottom: {}
      };

      var custom = new CustomComponent();
      custom.render();

      sinon.assert.callOrder(
        CustomComponent.prototype.created,
        CustomComponent.prototype.renderInternal,
        CustomComponent.prototype.getSurfaceContent,
        CustomComponent.prototype.attached
      );

      sinon.assert.callCount(CustomComponent.prototype.created, 1);
      sinon.assert.callCount(CustomComponent.prototype.renderInternal, 1);
      sinon.assert.callCount(CustomComponent.prototype.attached, 1);

      sinon.assert.callCount(CustomComponent.prototype.getSurfaceContent, 2);
      assert.strictEqual('header', CustomComponent.prototype.getSurfaceContent.args[0][0]);
      assert.strictEqual('bottom', CustomComponent.prototype.getSurfaceContent.args[1][0]);

      sinon.assert.notCalled(CustomComponent.prototype.decorateInternal);
      sinon.assert.notCalled(CustomComponent.prototype.detached);
    });

    it('should test component decorate lifecycle', function() {
      var CustomComponent = createCustomComponentClass();

      CustomComponent.SURFACES = {
        header: {},
        bottom: {}
      };

      var custom = new CustomComponent();
      custom.decorate();

      sinon.assert.callOrder(
        CustomComponent.prototype.created,
        CustomComponent.prototype.decorateInternal,
        CustomComponent.prototype.getSurfaceContent,
        CustomComponent.prototype.attached);

      sinon.assert.callCount(CustomComponent.prototype.created, 1);
      sinon.assert.callCount(CustomComponent.prototype.decorateInternal, 1);
      sinon.assert.callCount(CustomComponent.prototype.attached, 1);

      sinon.assert.callCount(CustomComponent.prototype.getSurfaceContent, 2);
      assert.strictEqual('header', CustomComponent.prototype.getSurfaceContent.args[0][0]);
      assert.strictEqual('bottom', CustomComponent.prototype.getSurfaceContent.args[1][0]);

      sinon.assert.notCalled(CustomComponent.prototype.renderInternal);
      sinon.assert.notCalled(CustomComponent.prototype.detached);
    });

    it('should be able to manually invoke detach/attach lifecycle', function() {
      var CustomComponent = createCustomComponentClass();
      var custom = new CustomComponent();
      custom.render();
      sinon.assert.callCount(CustomComponent.prototype.attached, 1);

      custom.detach();
      assert.strictEqual(null, document.getElementById(custom.id));
      assert.strictEqual(false, custom.inDocument);
      sinon.assert.callCount(CustomComponent.prototype.detached, 1);

      custom.attach();
      assert.notStrictEqual(null, document.getElementById(custom.id));
      assert.strictEqual(true, custom.inDocument);
      sinon.assert.callCount(CustomComponent.prototype.attached, 2);
    });

    it('should throw error when component renders and it was already rendered', function() {
      var CustomComponent = createCustomComponentClass();
      var custom = new CustomComponent();
      custom.render();
      assert.throws(function() {
        custom.render();
      }, Error);
      sinon.assert.callCount(CustomComponent.prototype.renderInternal, 1);
      sinon.assert.callCount(CustomComponent.prototype.attached, 1);
    });

    it('should throw error when component decorates and it was already decorated', function() {
      var CustomComponent = createCustomComponentClass();
      var custom = new CustomComponent();
      custom.decorate();
      assert.throws(function() {
        custom.decorate();
      }, Error);
      sinon.assert.callCount(CustomComponent.prototype.decorateInternal, 1);
      sinon.assert.callCount(CustomComponent.prototype.attached, 1);
    });

    it('should overwrite component element tagName', function() {
      var CustomComponent = createCustomComponentClass();
      CustomComponent.ELEMENT_TAG_NAME = 'span';

      var custom = new CustomComponent();
      custom.render();
      assert.strictEqual('span', custom.element.tagName.toLowerCase());
    });

    it('should dispose component', function() {
      var CustomComponent = createCustomComponentClass();
      var custom = new CustomComponent();
      custom.render();

      var customId = custom.id;
      assert.notStrictEqual(null, document.getElementById(customId));
      custom.dispose();
      assert.strictEqual(null, document.getElementById(customId));

      sinon.assert.callCount(CustomComponent.prototype.detached, 1);
    });
  });

  describe('Attributes', function() {
    it('should set component id attr', function() {
      var CustomComponent = createCustomComponentClass();

      var custom = new CustomComponent({
        id: 'customId'
      });
      custom.render();
      assert.strictEqual('customId', custom.id);
    });

    it('should set component element attr', function() {
      var CustomComponent = createCustomComponentClass();

      var element = document.createElement('div');
      element.id = 'elementId';
      document.body.appendChild(element);

      var custom = new CustomComponent({
        element: element
      });
      custom.render();
      assert.strictEqual('elementId', custom.id);
      assert.strictEqual(element, custom.element);
    });

    it('should set component element id from id attr', function() {
      var CustomComponent = createCustomComponentClass();

      var element = document.createElement('div');
      element.id = 'elementId';
      document.body.appendChild(element);

      var custom = new CustomComponent({
        element: element,
        id: 'customId'
      });
      custom.render();
      assert.strictEqual('customId', element.id);
      assert.strictEqual(element, custom.element);
    });

    it('should set component elementClasses attr', function() {
      var CustomComponent = createCustomComponentClass();

      var custom = new CustomComponent({
        elementClasses: ['foo', 'bar']
      });
      custom.render();
      assert.deepEqual(['component', 'foo', 'bar'], Element.prototype.classList.add.args[0]);
    });

    it('should overwrite default component elementClasses from static hint', function() {
      var CustomComponent = createCustomComponentClass();
      CustomComponent.ELEMENT_CLASSES = ['overwritten'];

      var custom = new CustomComponent();
      custom.render();
      assert.strictEqual('overwritten', Element.prototype.classList.add.args[0][0]);
    });

    it('should fire synchronize attr synchronously on render and asynchronously when attr value change', function() {
      var CustomComponent = createCustomComponentClass();
      CustomComponent.ATTRS = {
        foo: {
          value: 0<commit_msg>Adds test coverage for changing elementClass attr after component is rendered<commit_after>'use strict';

var assert = require('assert');
var jsdom = require('mocha-jsdom');
var sinon = require('sinon');
require('../fixture/sandbox.js');

describe('Component', function() {

  jsdom();

  beforeEach(function() {
    Element.prototype.classList = {
      add: sinon.stub(),
      remove: sinon.stub()
    };
  });

  describe('Lifecycle', function() {
    it('should test component render lifecycle', function() {
      var CustomComponent = createCustomComponentClass();

      CustomComponent.SURFACES = {
        header: {},
        bottom: {}
      };

      var custom = new CustomComponent();
      custom.render();

      sinon.assert.callOrder(
        CustomComponent.prototype.created,
        CustomComponent.prototype.renderInternal,
        CustomComponent.prototype.getSurfaceContent,
        CustomComponent.prototype.attached
      );

      sinon.assert.callCount(CustomComponent.prototype.created, 1);
      sinon.assert.callCount(CustomComponent.prototype.renderInternal, 1);
      sinon.assert.callCount(CustomComponent.prototype.attached, 1);

      sinon.assert.callCount(CustomComponent.prototype.getSurfaceContent, 2);
      assert.strictEqual('header', CustomComponent.prototype.getSurfaceContent.args[0][0]);
      assert.strictEqual('bottom', CustomComponent.prototype.getSurfaceContent.args[1][0]);

      sinon.assert.notCalled(CustomComponent.prototype.decorateInternal);
      sinon.assert.notCalled(CustomComponent.prototype.detached);
    });

    it('should test component decorate lifecycle', function() {
      var CustomComponent = createCustomComponentClass();

      CustomComponent.SURFACES = {
        header: {},
        bottom: {}
      };

      var custom = new CustomComponent();
      custom.decorate();

      sinon.assert.callOrder(
        CustomComponent.prototype.created,
        CustomComponent.prototype.decorateInternal,
        CustomComponent.prototype.getSurfaceContent,
        CustomComponent.prototype.attached);

      sinon.assert.callCount(CustomComponent.prototype.created, 1);
      sinon.assert.callCount(CustomComponent.prototype.decorateInternal, 1);
      sinon.assert.callCount(CustomComponent.prototype.attached, 1);

      sinon.assert.callCount(CustomComponent.prototype.getSurfaceContent, 2);
      assert.strictEqual('header', CustomComponent.prototype.getSurfaceContent.args[0][0]);
      assert.strictEqual('bottom', CustomComponent.prototype.getSurfaceContent.args[1][0]);

      sinon.assert.notCalled(CustomComponent.prototype.renderInternal);
      sinon.assert.notCalled(CustomComponent.prototype.detached);
    });

    it('should be able to manually invoke detach/attach lifecycle', function() {
      var CustomComponent = createCustomComponentClass();
      var custom = new CustomComponent();
      custom.render();
      sinon.assert.callCount(CustomComponent.prototype.attached, 1);

      custom.detach();
      assert.strictEqual(null, document.getElementById(custom.id));
      assert.strictEqual(false, custom.inDocument);
      sinon.assert.callCount(CustomComponent.prototype.detached, 1);

      custom.attach();
      assert.notStrictEqual(null, document.getElementById(custom.id));
      assert.strictEqual(true, custom.inDocument);
      sinon.assert.callCount(CustomComponent.prototype.attached, 2);
    });

    it('should throw error when component renders and it was already rendered', function() {
      var CustomComponent = createCustomComponentClass();
      var custom = new CustomComponent();
      custom.render();
      assert.throws(function() {
        custom.render();
      }, Error);
      sinon.assert.callCount(CustomComponent.prototype.renderInternal, 1);
      sinon.assert.callCount(CustomComponent.prototype.attached, 1);
    });

    it('should throw error when component decorates and it was already decorated', function() {
      var CustomComponent = createCustomComponentClass();
      var custom = new CustomComponent();
      custom.decorate();
      assert.throws(function() {
        custom.decorate();
      }, Error);
      sinon.assert.callCount(CustomComponent.prototype.decorateInternal, 1);
      sinon.assert.callCount(CustomComponent.prototype.attached, 1);
    });

    it('should overwrite component element tagName', function() {
      var CustomComponent = createCustomComponentClass();
      CustomComponent.ELEMENT_TAG_NAME = 'span';

      var custom = new CustomComponent();
      custom.render();
      assert.strictEqual('span', custom.element.tagName.toLowerCase());
    });

    it('should dispose component', function() {
      var CustomComponent = createCustomComponentClass();
      var custom = new CustomComponent();
      custom.render();

      var customId = custom.id;
      assert.notStrictEqual(null, document.getElementById(customId));
      custom.dispose();
      assert.strictEqual(null, document.getElementById(customId));

      sinon.assert.callCount(CustomComponent.prototype.detached, 1);
    });
  });

  describe('Attributes', function() {
    it('should set component id attr', function() {
      var CustomComponent = createCustomComponentClass();

      var custom = new CustomComponent({
        id: 'customId'
      });
      custom.render();
      assert.strictEqual('customId', custom.id);
    });

    it('should set component element attr', function() {
      var CustomComponent = createCustomComponentClass();

      var element = document.createElement('div');
      element.id = 'elementId';
      document.body.appendChild(element);

      var custom = new CustomComponent({
        element: element
      });
      custom.render();
      assert.strictEqual('elementId', custom.id);
      assert.strictEqual(element, custom.element);
    });

    it('should set component element id from id attr', function() {
      var CustomComponent = createCustomComponentClass();

      var element = document.createElement('div');
      element.id = 'elementId';
      document.body.appendChild(element);

      var custom = new CustomComponent({
        element: element,
        id: 'customId'
      });
      custom.render();
      assert.strictEqual('customId', element.id);
      assert.strictEqual(element, custom.element);
    });

    it('should set component elementClasses attr', function(done) {
      var CustomComponent = createCustomComponentClass();

      var custom = new CustomComponent({
        elementClasses: ['foo', 'bar']
      });
      custom.render();

      assert.deepEqual(['component', 'foo', 'bar'], Element.prototype.classList.add.args[0]);
      custom.elementClasses = ['other'];
      lfr.async.nextTick(function() {
        assert.deepEqual(['component', 'other'], Element.prototype.classList.add.args[1]);
        done();
      });
    });

    it('should overwrite default component elementClasses from static hint', function() {
      var CustomComponent = createCustomComponentClass();
      CustomComponent.ELEMENT_CLASSES = ['overwritten'];

      var custom = new CustomComponent();
      custom.render();
      assert.strictEqual('overwritten', Element.prototype.classList.add.args[0][0]);
    });

    it('should fire synchronize attr synchronously on render and asynchronously when attr value change', function() {
      var CustomComponent = createCustomComponentClass();
      CustomComponent.ATTRS = {
        foo: {
          value: 0
{'fraction_non_alphanumeric': 0.12199113535629048, 'fraction_numerical': 0.003886805318786226, 'mean_word_length': 3.463177115033475, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '1333379', 'n_tokens_mistral': 3830, 'n_tokens_neox': 3717, 'n_words': 740}