text: /**
   * Copyright 2018 Google Inc. All rights reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  module.exports.addTests = function({testRunner, expect, FFOX}) {
    const {describe, xdescribe, fdescribe, describe_fails_ffox} = testRunner;
    const {it, fit, xit} = testRunner;
    const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
  
    describe('Accessibility', function() {
      it('should work', async function({page}) {
        await page.setContent(`
        <head>
          <title>Accessibility Test</title>
        </head>
        <body>
          <div>Hello World</div>
          <h1>Inputs</h1>
          <input placeholder="Empty input" autofocus />
          <input placeholder="readonly input" readonly />
          <input placeholder="disabled input" disabled />
          <input aria-label="Input with whitespace" value="  " />
          <input value="value only" />
          <input aria-placeholder="placeholder" value="and a value" />
          <div aria-hidden="true" id="desc">This is a description!</div>
          <input aria-placeholder="placeholder" value="and a value" aria-describedby="desc" />
          <select>
            <option>First Option</option>
            <option>Second Option</option>
          </select>
        </body>`);
  
        const golden = FFOX ? {
          role: 'document',
          name: 'Accessibility Test',
          children: [
            {role: 'text leaf', name: 'Hello World'},
            {role: 'heading', name: 'Inputs', level: 1},
            {role: 'entry', name: 'Empty input', focused: true},
            {role: 'entry', name: 'readonly input', readonly: true},
            {role: 'entry', name: 'disabled input', disabled: true},
            {role: 'entry', name: 'Input with whitespace', value: '  '},
            {role: 'entry', name: '', value: 'value only'},
            {role: 'entry', name: '', value: 'and a value'}, // firefox doesn't use aria-placeholder for the name
            {role: 'entry', name: '', value: 'and a value', description: 'This is a description!'}, // and here
            {role: 'combobox', name: '', value: 'First Option', haspopup: true, children: [
              {role: 'combobox option', name: 'First Option', selected: true},
              {role: 'combobox option', name: 'Second Option'}]
            }]
        } : {
          role: 'WebArea',
          name: 'Accessibility Test',
          children: [
            {role: 'text', name: 'Hello World'},
            {role: 'heading', name: 'Inputs', level: 1},
            {role: 'textbox', name: 'Empty input', focused: true},
            {role: 'textbox', name: 'readonly input', readonly: true},
            {role: 'textbox', name: 'disabled input', disabled: true},
            {role: 'textbox', name: 'Input with whitespace', value: '  '},
            {role: 'textbox', name: '', value: 'value only'},
            {role: 'textbox', name: 'placeholder', value: 'and a value'},
            {role: 'textbox', name: 'placeholder', value: 'and a value', description: 'This is a description!'},
            {role: 'combobox', name: '', value: 'First Option', children: [
              {role: 'menuitem', name: 'First Option', selected: true},
              {role: 'menuitem', name: 'Second Option'}]
            }]
        };
        expect(await page.accessibility.snapshot()).toEqual(golden);
      });
      it('should report uninteresting nodes', async function({page}) {
        await page.setContent(`<textarea autofocus>hi</textarea>`);
        const golden = FFOX ? {
          role: 'entry',
          name: '',
          value: 'hi',
          focused: true,
          multiline: true,
          children: [{
            role: 'text leaf',
            name: 'hi'
          }]
        } : {
          role: 'textbox',
          name: '',
          value: 'hi',
          focused: true,
          multiline: true,
          children: [{
            role: 'GenericContainer',
            name: '',
            children: [{
              role: 'text', name: 'hi'
            }]
          }]
        };
        expect(findFocusedNode(await page.accessibility.snapshot({interestingOnly: false}))).toEqual(golden);
      });
      it('roledescription', async({page}) => {
        await page.setContent('<div tabIndex=-1 aria-roledescription="foo">Hi</div>');
        const snapshot = await page.accessibility.snapshot();
        expect(snapshot.children[0].roledescription).toEqual('foo');
      });
      it('orientation', async({page}) => {
        await page.setContent('<a href="" role="slider" aria-orientation="vertical">11</a>');
        const snapshot = await page.accessibility.snapshot();
        expect(snapshot.children[0].orientation).toEqual('vertical');
      });
      it('autocomplete', async({page}) => {
        await page.setContent('<input type="number" aria-autocomplete="list" />');
        const snapshot = await page.accessibility.snapshot();
        expect(snapshot.children[0].autocomplete).toEqual('list');
      });
      it('multiselectable', async({page}) => {
        await page.setContent('<div role="grid" tabIndex=-1 aria-multiselectable=true>hey</div>');
        const snapshot = await page.accessibility.snapshot();
        expect(snapshot.children[0].multiselectable).toEqual(true);
      });
      it('keyshortcuts', async({page}) => {
        await page.setContent('<div role="grid" tabIndex=-1 aria-keyshortcuts="foo">hey</div>');
        const snapshot = await page.accessibility.snapshot();
        expect(snapshot.children[0].keyshortcuts).toEqual('foo');
      });
      describe('filtering children of leaf nodes', function() {
        it('should not report text nodes inside controls', async function({page}) {
          await page.setContent(`
          <div role="tablist">
            <div role="tab" aria-selected="true"><b>Tab1</b></div>
            <div role="tab">Tab2</div>
          </div>`);
          const golden = FFOX ? {
            role: 'document',
            name: '',
            children: [{
              role: 'pagetab',
              name: 'Tab1',
              selected: true
            }, {
              role: 'pagetab',
              name: 'Tab2'
            }]
          } : {
            role: 'WebArea',
            name: '',
            children: [{
              role: 'tab',
              name: 'Tab1',
              selected: true
            }, {
              role: 'tab',
              name: 'Tab2'
            }]
          };
          expect(await page.accessibility.snapshot()).toEqual(golden);
        });
        it('rich text editable fields should have children', async function({page}) {
          await page.setContent(`
          <div contenteditable="true">
            Edit this image: <img src="fakeimage.png" alt="my fake image">
          </div>`);
          const golden = FFOX ? {
            role: 'section',
            name: '',
            children: [{
              role: 'text leaf',
              name: 'Edit this image: '
            }, {
              role: 'text',
              name: 'my fake image'
            }]
          } : {
            role: 'GenericContainer',
            name: '',
            value: 'Edit this image: ',
            children: [{
              role: 'text',
              name: 'Edit this image:'
            }, {
              role: 'img',
              name: 'my fake image'
            }]
          };
          const snapshot = await page.accessibility.snapshot();
          expect(snapshot.children[0]).toEqual(golden);
        });
        it('rich text editable fields with role should have children', async function({page}) {
          await page.setContent(`
          <div contenteditable="true" role='textbox'>
            Edit this image: <img src="fakeimage.png" alt="my fake image">
          </div>`);
          const golden = FFOX ? {
            role: 'entry',
            name: '',
            value: 'Edit this image: my fake image',
            children: [{
              role: 'text',
              name: 'my fake image'
            }]
          } : {
            role: 'textbox',
            name: '',
            value: 'Edit this image: ',
            children: [{
              role: 'text',
              name: 'Edit this image:'
            }, {
              role: 'img',
              name: 'my fake image'
            }]
          };
          const snapshot = await page.accessibility.snapshot();
          expect(snapshot.children[0]).toEqual(golden);
        });
        // Firefox does not support contenteditable="plaintext-only".
        !FFOX && describe('plaintext contenteditable', function() {
          it('plain text field with role should not have children', async function({page}) {
            await page.setContent(`
            <div contenteditable="plaintext-only" role='textbox'>Edit this image:<img src="fakeimage.png" alt="my fake image"></div>`);
            const snapshot = await page.accessibility.snapshot();
            expect(snapshot.children[0]).toEqual({
              role: 'textbox',
              name: '',
              value: 'Edit this image:'
            });
          });
          it('plain text field without role should not have content', async function({page}) {
            await page.setContent(`
            <div contenteditable="plaintext-only">Edit this image:<img src="fakeimage.png" alt="my fake image"></div>`);
            const snapshot = await page.accessibility.snapshot();
            expect(snapshot.children[0]).toEqual({
              role: 'GenericContainer',
              name: ''
            });
          });
          it('plain text field with tabindex and without role should not have content', async function({page}) {
            await page.setContent(`
            <div contenteditable="plaintext-only" tabIndex=0>Edit this image:<img src="fakeimage.png" alt="my fake image"></div>`);
            const snapshot = await page.accessibility.snapshot();
            expect(snapshot.children[0]).toEqual({
              role: 'GenericContainer',
              name: ''
            });
          });
        });
        it('non editable textbox with role and tabIndex and label should not have children', async function({page}) {
          await page.setContent(`
          <div role="textbox" tabIndex=0 aria-checked="true" aria-label="my favorite textbox">
            this is the inner content
            <img alt="yo" src="fakeimg.png">
          </div>`);
          const golden = FFOX ? {
            role: 'entry',
            name: 'my favorite textbox',
            value: 'this is the inner content yo'
          } : {
            role: 'textbox',
            name: 'my favorite textbox',
            value: 'this is the inner content '
          };
          const snapshot = await page.accessibility.snapshot();
          expect(snapshot.children[0]).toEqual(golden);
        });
        it('checkbox with and tabIndex and label should not have children', async function({page}) {
          await page.setContent(`
          <div role="checkbox" tabIndex=0 aria-checked="true" aria-label="my favorite checkbox">
            this is the inner content
            <img alt="yo" src="fakeimg.png">
          </div>`);
          const golden = FFOX ? {
            role: 'checkbutton',
            name: 'my favorite checkbox',
            checked: true
          } : {
            role: 'checkbox',
            name: 'my favorite checkbox',
            checked: true
          };
          const snapshot = await page.accessibility.snapshot();
          expect(snapshot.children[0]).toEqual(golden);
        });
        it('checkbox without label should not have children', async function({page}) {
          await page.setContent(`
          <div role="checkbox" aria-checked="true">
            this is the inner content
            <img alt="yo" src="fakeimg.png">
          </div>`);
          const golden = FFOX ? {
            role: 'checkbutton',
            name: 'this is the inner content yo',
            checked: true
          } : {
            role: 'checkbox',
            name: 'this is the inner content yo',
            checked: true
          };
          const snapshot = await page.accessibility.snapshot();
          expect(snapshot.children[0]).toEqual(golden);
        });
      });
      function findFocusedNode(node) {
        if (node.focused)
          return node;
        for (const child of node.children || []) {
          const focusedChild = findFocusedNode(child);
          if (focusedChild)
            return focusedChild;
        }
        return null;
      }
    });
  };
  