<commit_before>// Copyright 2017, University of Colorado Boulder

/**
 * Accessibility tests
 *
 * @author <NAME> (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var AccessibilityFuzzer = require( 'SCENERY/accessibility/AccessibilityFuzzer' );
  var AccessibilityUtil = require( 'SCENERY/accessibility/AccessibilityUtil' );
  var AccessiblePeer = require( 'SCENERY/accessibility/AccessiblePeer' );
  var Circle = require( 'SCENERY/nodes/Circle' );
  var Display = require( 'SCENERY/display/Display' );
  var Node = require( 'SCENERY/nodes/Node' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var scenery = require( 'SCENERY/scenery' );

  // constants
  var TEST_INNER_CONTENT = 'Test Inner Content Here please^&*. Thanks you so very mucho.';
  var TEST_LABEL = 'Test label';
  var TEST_LABEL_2 = 'Test label 2';
  var TEST_DESCRIPTION = 'Test description';
  var TEST_LABEL_HTML = '<strong>I ROCK as a LABEL</strong>';
  var TEST_LABEL_HTML_2 = '<strong>I ROCK as a LABEL 2</strong>';
  var TEST_DESCRIPTION_HTML = '<strong>I ROCK as a DESCRIPTION</strong>';
  var TEST_DESCRIPTION_HTML_2 = '<strong>I ROCK as a DESCRIPTION 2</strong>';

  // These should manually match the defaults in the Accessibility.js trait
  var DEFAULT_LABEL_TAG_NAME = AccessibilityUtil.DEFAULT_LABEL_TAG_NAME;
  var DEFAULT_DESCRIPTION_TAG_NAME = AccessibilityUtil.DEFAULT_DESCRIPTION_TAG_NAME;
  var DEFAULT_CONTAINER_TAG_NAME = AccessibilityUtil.DEFAULT_CONTAINER_TAG_NAME;

  // given the parent container element for a node, this value is the index of the label sibling in the
  // parent's array of children HTMLElements.
  // var DEFAULT_LABEL_SIBLING_INDEX = 0;
  // var DEFAULT_LABEL_SIBLING_INDEX = 0;

  // a focus highlight for testing, since dummy nodes tend to have no bounds
  var TEST_HIGHLIGHT = new Circle( 5 );

  QUnit.module( 'Accessibility', {
    before: function() {
      // add scenery logging for a11y in this unit test module, make sure it is turned off at the end of the file.
      if ( window.location.search.indexOf( 'a11yLog' ) >= 0 ) {
        scenery.enableLogging( [ 'a11y' ] );
      }

    },
    after: function() {
      // remove the logging that we added at the top
      if ( window.location.search.indexOf( 'a11yLog' ) >= 0 ) {
        scenery.disableIndividualLog( 'Accessibility' );
        scenery.disableIndividualLog( 'AccessibleInstance' );
        scenery.disableIndividualLog( 'AccessibilityTree' );
        scenery.disableIndividualLog( 'AccessibleDisplaysInfo' );
      }
    }
  } );

  /**
   * Get the id of a dom element representing a node in the DOM.  The accessible content must exist and be unique,
   * there should only be one accessible instance and one dom element for the node.
   *
   * NOTE: Be careful about getting references to dom Elements, the reference will be stale each time
   * Node.invalidateAccessibleContent is called, which is quite often when setting options.
   *
   * @param  {Node} node
   * @return {string}
   */
  function getPrimarySiblingElementByNode( node ) {
    if ( node.accessibleInstances.length === 0 ) {
      throw new Error( 'No accessibleInstances. Was your node added to the scene graph?' );
    }

    else if ( node.accessibleInstances.length > 1 ) {
      throw new Error( 'There should one and only one accessible instance for the node' );
    }
    else if ( !node.accessibleInstances[ 0 ].peer ) {
      throw new Error( 'accessibleInstance\'s peer should exist.' );
    }

    return document.getElementById( node.accessibleInstances[ 0 ].peer.primarySibling.id );
  }


  QUnit.test( 'tagName/innerContent options', function( assert ) {

    // test the behavior of swapVisibility function
    var rootNode = new Node( { tagName: 'div' } );
    var display = new Display( rootNode ); // eslint-disable-line
    document.body.appendChild( display.domElement );

    // create some nodes for testing
    var a = new Node( { tagName: 'button', innerContent: TEST_LABEL } );

    rootNode.addChild( a );

    var aElement = getPrimarySiblingElementByNode( a );
    assert.ok( a.accessibleInstances.length === 1, 'only 1 instance' );
    assert.ok( aElement.parentElement.childNodes.length === 1, 'parent contains one primary siblings' );
    assert.ok( aElement.tagName === 'BUTTON', 'default label tagName' );
    assert.ok( aElement.textContent === TEST_LABEL, 'no html should use textContent' );

    a.innerContent = TEST_LABEL_HTML;
    assert.ok( aElement.innerHTML === TEST_LABEL_HTML, 'html label should use innerHTML' );

    a.innerContent = TEST_LABEL_HTML_2;
    assert.ok( aElement.innerHTML === TEST_LABEL_HTML_2, 'html label should use innerHTML, overwrite from html' );

    a.tagName = null;
    assert.ok( a.accessibleInstances.length === 0, 'set to null should clear accessible instances' );

    // make sure that no errors when setting innerContent with tagName null.
    a.innerContent = 'hello';

    a.tagName = 'button';
    a.innerContent = TEST_LABEL_HTML_2;
    assert.ok( getPrimarySiblingElementByNode( a ).innerHTML === TEST_LABEL_HTML_2, 'innerContent not cleared when tagName set to null.' );

    // verify that setting inner content on an input is not allowed
    var b = new Node( { tagName: 'input' } );
    rootNode.addChild( b );
    window.assert && assert.throws( function() {
      b.innerContent = 'this should fail';
    }, /.*/, 'cannot set inner content on input' );

    // now that it is a div, innerContent is allowed
    b.tagName = 'div';
    assert.ok( b.tagName === 'div', 'expect tagName setter to work.' );
    b.innerContent = TEST_LABEL;
    assert.ok( b.innerContent === TEST_LABEL, 'inner content allowed' );

    // revert tag name to input, should throw an error
    window.assert && assert.throws( function() {
      b.tagName = 'input';
    }, /.*/, 'error thrown after setting tagName to input on Node with innerContent.' );
  } );


  QUnit.test( 'containerTagName option, container created if needed', function( assert ) {


    // test the behavior of swapVisibility function
    var rootNode = new Node( { tagName: 'div' } );
    var display = new Display( rootNode ); // eslint-disable-line
    document.body.appendChild( display.domElement );

    // create some nodes for testing
    var a = new Node( { tagName: 'button' } );

    rootNode.addChild( a );
    assert.ok( a.accessibleInstances.length === 1, 'only 1 instance' );
    assert.ok( a.accessibleInstances[ 0 ].peer.containerParent === null, 'no container parent for just button' );

    a.containerTagName = 'div';

    assert.ok( a.accessibleInstances[ 0 ].peer.containerParent.id.indexOf( 'container' ) >= 0, 'container parent is div if specified' );

    var b = new Node( { tagName: 'button', labelTagName: 'div', labelContent: TEST_LABEL } );

    rootNode.addChild( b );
    var buttonElement = b.accessibleInstances[ 0 ].peer.primarySibling;
    var parentElement = buttonElement.parentElement;

    assert.ok( b.containerTagName === DEFAULT_CONTAINER_TAG_NAME, 'container automatically created for label' );

    assert.ok( parentElement, 'parent element must be created with label option' );
    assert.ok( parentElement.childNodes.length === 2, 'only contain label and primary siblings' );

    assert.ok( parentElement.childNodes[ 1 ] === getPrimarySiblingElementByNode( b ), 'primary sibling after label sibling.' );


    var c = new Node( { tagName: 'button', descriptionTagName: 'div', descriptionContent: TEST_DESCRIPTION } );

    rootNode.addChild( c );
    buttonElement = c.accessibleInstances[ 0 ].peer.primarySibling;
    parentElement = buttonElement.parentElement;


    assert.ok( parentElement, 'parent element must be created with description option' );
    assert.ok( parentElement.childNodes.length === 2, 'only contain description and primary siblings' );

    c.containerTagName = 'SECTION';
    assert.ok( getPrimarySiblingElementByNode( c ).parentElement.tagName === 'SECTION', 'containerTagName should update default' );

    var d = new Node( { tagName: 'button', labelTagName: 'p', descriptionTagName: 'p' } );
    rootNode.addChild( d );
    assert.ok( getPrimarySiblingElementByNode( d ).parentElement.childNodes.length === 3, 'correct children' );

    var e = new Node( {
      tagName: 'div',
      labelContent: TEST_LABEL,
      containerTagName: 'SECTION'
    } );
    rootNode.addChild( e );
    assert.ok( getPrimarySiblingElementByNode( e ).parentElement.tagName === 'SECTION', 'containerTagName should update default in options block' );
  } );

  QUnit.test( 'labelTagName/labelContent option', function( assert ) {

    // test the behavior of swapVisibility function
    var rootNode = new Node( { tagName: 'div' } );
    var display = new Display( rootNode ); // eslint-disable-line<commit_msg>fix incorrect tests, https://github.com/phetsims/scenery/issues/715<commit_after>// Copyright 2017, University of Colorado Boulder

/**
 * Accessibility tests
 *
 * @author <NAME> (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var AccessibilityFuzzer = require( 'SCENERY/accessibility/AccessibilityFuzzer' );
  var AccessibilityUtil = require( 'SCENERY/accessibility/AccessibilityUtil' );
  var AccessiblePeer = require( 'SCENERY/accessibility/AccessiblePeer' );
  var Circle = require( 'SCENERY/nodes/Circle' );
  var Display = require( 'SCENERY/display/Display' );
  var Node = require( 'SCENERY/nodes/Node' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var scenery = require( 'SCENERY/scenery' );

  // constants
  var TEST_INNER_CONTENT = 'Test Inner Content Here please^&*. Thanks you so very mucho.';
  var TEST_LABEL = 'Test label';
  var TEST_LABEL_2 = 'Test label 2';
  var TEST_DESCRIPTION = 'Test description';
  var TEST_LABEL_HTML = '<strong>I ROCK as a LABEL</strong>';
  var TEST_LABEL_HTML_2 = '<strong>I ROCK as a LABEL 2</strong>';
  var TEST_DESCRIPTION_HTML = '<strong>I ROCK as a DESCRIPTION</strong>';
  var TEST_DESCRIPTION_HTML_2 = '<strong>I ROCK as a DESCRIPTION 2</strong>';

  // These should manually match the defaults in the Accessibility.js trait
  var DEFAULT_LABEL_TAG_NAME = AccessibilityUtil.DEFAULT_LABEL_TAG_NAME;
  var DEFAULT_DESCRIPTION_TAG_NAME = AccessibilityUtil.DEFAULT_DESCRIPTION_TAG_NAME;
  var DEFAULT_CONTAINER_TAG_NAME = AccessibilityUtil.DEFAULT_CONTAINER_TAG_NAME;

  // given the parent container element for a node, this value is the index of the label sibling in the
  // parent's array of children HTMLElements.
  // var DEFAULT_LABEL_SIBLING_INDEX = 0;
  // var DEFAULT_LABEL_SIBLING_INDEX = 0;

  // a focus highlight for testing, since dummy nodes tend to have no bounds
  var TEST_HIGHLIGHT = new Circle( 5 );

  QUnit.module( 'Accessibility', {
    before: function() {
      // add scenery logging for a11y in this unit test module, make sure it is turned off at the end of the file.
      if ( window.location.search.indexOf( 'a11yLog' ) >= 0 ) {
        scenery.enableLogging( [ 'a11y' ] );
      }

    },
    after: function() {
      // remove the logging that we added at the top
      if ( window.location.search.indexOf( 'a11yLog' ) >= 0 ) {
        scenery.disableIndividualLog( 'Accessibility' );
        scenery.disableIndividualLog( 'AccessibleInstance' );
        scenery.disableIndividualLog( 'AccessibilityTree' );
        scenery.disableIndividualLog( 'AccessibleDisplaysInfo' );
      }
    }
  } );

  /**
   * Get the id of a dom element representing a node in the DOM.  The accessible content must exist and be unique,
   * there should only be one accessible instance and one dom element for the node.
   *
   * NOTE: Be careful about getting references to dom Elements, the reference will be stale each time
   * Node.invalidateAccessibleContent is called, which is quite often when setting options.
   *
   * @param  {Node} node
   * @return {string}
   */
  function getPrimarySiblingElementByNode( node ) {
    if ( node.accessibleInstances.length === 0 ) {
      throw new Error( 'No accessibleInstances. Was your node added to the scene graph?' );
    }

    else if ( node.accessibleInstances.length > 1 ) {
      throw new Error( 'There should one and only one accessible instance for the node' );
    }
    else if ( !node.accessibleInstances[ 0 ].peer ) {
      throw new Error( 'accessibleInstance\'s peer should exist.' );
    }

    return document.getElementById( node.accessibleInstances[ 0 ].peer.primarySibling.id );
  }


  QUnit.test( 'tagName/innerContent options', function( assert ) {

    // test the behavior of swapVisibility function
    var rootNode = new Node( { tagName: 'div' } );
    var display = new Display( rootNode ); // eslint-disable-line
    document.body.appendChild( display.domElement );

    // create some nodes for testing
    var a = new Node( { tagName: 'button', innerContent: TEST_LABEL } );

    rootNode.addChild( a );

    var aElement = getPrimarySiblingElementByNode( a );
    assert.ok( a.accessibleInstances.length === 1, 'only 1 instance' );
    assert.ok( aElement.parentElement.childNodes.length === 1, 'parent contains one primary siblings' );
    assert.ok( aElement.tagName === 'BUTTON', 'default label tagName' );
    assert.ok( aElement.textContent === TEST_LABEL, 'no html should use textContent' );

    a.innerContent = TEST_LABEL_HTML;
    assert.ok( aElement.innerHTML === TEST_LABEL_HTML, 'html label should use innerHTML' );

    a.innerContent = TEST_LABEL_HTML_2;
    assert.ok( aElement.innerHTML === TEST_LABEL_HTML_2, 'html label should use innerHTML, overwrite from html' );

    a.tagName = null;
    assert.ok( a.accessibleInstances.length === 0, 'set to null should clear accessible instances' );

    // make sure that no errors when setting innerContent with tagName null.
    a.innerContent = 'hello';

    a.tagName = 'button';
    a.innerContent = TEST_LABEL_HTML_2;
    assert.ok( getPrimarySiblingElementByNode( a ).innerHTML === TEST_LABEL_HTML_2, 'innerContent not cleared when tagName set to null.' );

    // verify that setting inner content on an input is not allowed
    var b = new Node( { tagName: 'input' } );
    rootNode.addChild( b );
    window.assert && assert.throws( function() {
      b.innerContent = 'this should fail';
    }, /.*/, 'cannot set inner content on input' );

    // now that it is a div, innerContent is allowed
    b.tagName = 'div';
    assert.ok( b.tagName === 'div', 'expect tagName setter to work.' );
    b.innerContent = TEST_LABEL;
    assert.ok( b.innerContent === TEST_LABEL, 'inner content allowed' );

    // revert tag name to input, should throw an error
    window.assert && assert.throws( function() {
      b.tagName = 'input';
    }, /.*/, 'error thrown after setting tagName to input on Node with innerContent.' );
  } );


  QUnit.test( 'containerTagName option, container created if needed', function( assert ) {


    // test the behavior of swapVisibility function
    var rootNode = new Node( { tagName: 'div' } );
    var display = new Display( rootNode ); // eslint-disable-line
    document.body.appendChild( display.domElement );

    // create some nodes for testing
    var a = new Node( { tagName: 'button' } );

    rootNode.addChild( a );
    assert.ok( a.accessibleInstances.length === 1, 'only 1 instance' );
    assert.ok( a.accessibleInstances[ 0 ].peer.containerParent === null, 'no container parent for just button' );

    a.containerTagName = 'div';

    assert.ok( a.accessibleInstances[ 0 ].peer.containerParent.id.indexOf( 'container' ) >= 0, 'container parent is div if specified' );

    a.containerTagName = null;

    assert.ok( !a.accessibleInstances[ 0 ].peer.containerParent, 'container parent is cleared if specified' );

  } );

  QUnit.test( 'labelTagName/labelContent option', function( assert ) {

    // test the behavior of swapVisibility function
    var rootNode = new Node( { tagName: 'div' } );
    var display = new Display( rootNode ); // eslint-disable-line
{'fraction_non_alphanumeric': 0.11112498439255837, 'fraction_numerical': 0.005618678986140592, 'mean_word_length': 3.5547341484219506, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 29, 'https://': 1, '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': '5613926', 'n_tokens_mistral': 4850, 'n_tokens_neox': 4661, 'n_words': 1498}