@testing-library/dom#getByRole JavaScript Examples

The following examples show how to use @testing-library/dom#getByRole. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: constructor.test.js    From emoji-picker-element with Apache License 2.0 6 votes vote down vote up
describe('constructor', () => {
  beforeEach(basicBeforeEach)
  afterEach(basicAfterEach)

  async function testWithDefaults (...args) {
    const picker = new Picker(...args)
    document.body.appendChild(picker)
    const container = picker.shadowRoot.querySelector('.picker')
    await tick(20)

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())
    expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible()

    expect(fetch).toHaveBeenCalledTimes(1)
    expect(fetch).toHaveBeenLastCalledWith(DEFAULT_DATA_SOURCE, undefined)

    document.body.removeChild(picker)
    await tick(20)
  }

  test('contructor with undefined options works', async () => {
    await testWithDefaults()
  })

  test('contructor with empty options object works', async () => {
    await testWithDefaults({})
  })

  test('contructor with just dataSource option works', async () => {
    await testWithDefaults({ dataSource: DEFAULT_DATA_SOURCE })
  })

  test('contructor with just locale option works', async () => {
    await testWithDefaults({ locale: DEFAULT_LOCALE })
  })
})
Example #2
Source File: shared.js    From emoji-picker-element with Apache License 2.0 6 votes vote down vote up
export async function openSkintoneListbox (container) {
  await waitFor(() => expect(getByRole(container, 'button', { name: /Choose a skin tone/ }))
    .toBeVisible())
  expect(queryAllByRole(container, 'listbox', { name: 'Skin tones' })).toHaveLength(0)
  await fireEvent.click(getByRole(container, 'button', { name: /Choose a skin tone/ }))
  await waitFor(() => expect(getByRole(container, 'listbox', { name: 'Skin tones' })).toBeVisible())
  expect(getAllByRole(container, 'option')).toHaveLength(6)
  getByRole(container, 'option', { name: 'Default', selected: true }).focus()
  await waitFor(() => expect(getByRole(container, 'option', { name: 'Default', selected: true }))
    .toBeVisible())
  // JSDom doesn't fire transitionend events, so we do it manually here
  // https://github.com/jsdom/jsdom/issues/1781#issuecomment-467935000
  fireEvent(getByRole(container, 'listbox', { name: 'Skin tones' }), new Event('transitionend'))
}
Example #3
Source File: LibraryAccessForm.spec.jsx    From frontend-app-library-authoring with GNU Affero General Public License v3.0 6 votes vote down vote up
testSuite('<LibraryAccessForm />', () => {
  it('Renders an error for the email field', async () => {
    const library = libraryFactory();
    const props = { library, errorFields: { email: 'Too difficult to remember.' }, ...commonMocks() };
    const { container } = await ctxRender(<LibraryAccessFormContainer {...props} />);
    expect(getByText(container, /Too difficult/)).toBeTruthy();
  });
  it('Submits and adds a new user.', async () => {
    const library = libraryFactory();
    const props = { library, ...commonMocks() };
    const { addUser } = props;
    const user = userFactory();
    addUser.mockImplementation(() => immediate(user));
    const { container } = await ctxRender(<LibraryAccessFormContainer {...props} />);
    const emailField = getByLabelText(container, 'Email');
    fireEvent.change(emailField, { target: { value: '[email protected]' } });
    const submitButton = getByRole(container, 'button', { name: /Submit/ });
    fireEvent.click(submitButton);
    await waitFor(() => expect(addUser).toHaveBeenCalledWith({
      libraryId: library.id, data: { email: '[email protected]', access_level: LIBRARY_ACCESS.READ },
    }));
    expect(emailField.value).toBe('');
  });
  it('Closes out', async () => {
    const library = libraryFactory();
    const props = { library, ...commonMocks() };
    const { setShowAdd } = props;
    const { container } = await ctxRender(
      <LibraryAccessFormContainer
        {...props}
      />,
    );
    const button = getByRole(container, 'button', { name: /Cancel/ });
    fireEvent.click(button);
    expect(setShowAdd).toHaveBeenCalledWith(false);
  });
});
Example #4
Source File: dataSource.test.js    From emoji-picker-element with Apache License 2.0 5 votes vote down vote up
describe('dataSource test', () => {
  beforeEach(basicBeforeEach)
  afterEach(basicAfterEach)

  test('emoji with no shortcodes still work', async () => {
    mockDataSourceWithNoShortcodes()
    const dataSource = NO_SHORTCODES
    const picker = new Picker({ dataSource, locale: 'en-no-shortcodes' })
    document.body.appendChild(picker)
    const container = picker.shadowRoot.querySelector('.picker')
    await tick(20)

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())

    // no shortcodes, no title
    expect(getByRole(container, 'menuitem', { name: /?/ }).getAttribute('title')).toStrictEqual('')
    expect(getByRole(container, 'menuitem', { name: /?/ }).getAttribute('aria-label')).toStrictEqual('?')

    await picker.database.delete()
    await tick(20)
    document.body.removeChild(picker)
    await tick(20)
  })

  test('emoji with emojibase v5 data source still work', async () => {
    mockEmojibaseV5DataSource()
    const dataSource = EMOJIBASE_V5
    const picker = new Picker({ dataSource, locale: 'en-emojibase' })
    document.body.appendChild(picker)
    const container = picker.shadowRoot.querySelector('.picker')
    await tick(20)

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())

    // no shortcodes, no title
    expect(getByRole(container, 'menuitem', { name: /?/ }).getAttribute('title')).toStrictEqual('gleeful')
    expect(getByRole(container, 'menuitem', { name: /?/ }).getAttribute('aria-label')).toStrictEqual('?, gleeful')

    await picker.database.delete()
    await tick(20)
    document.body.removeChild(picker)
    await tick(20)
  })

  test('emoji with array skin tones work', async () => {
    mockDataSourceWithArraySkinTones()

    const dataSource = WITH_ARRAY_SKIN_TONES
    const picker = new Picker({ dataSource, locale: 'en-arrayskintones' })
    document.body.appendChild(picker)
    const container = picker.shadowRoot.querySelector('.picker')
    await tick(20)

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())
    await fireEvent.click(getByRole(container, 'tab', { name: /People and body/ }))
    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?‍?‍?/ })).toBeVisible())

    await openSkintoneListbox(container)

    await fireEvent.click(getByRole(container, 'option', { name: /Medium-Dark/ }))

    // both people in the emoji should have the same skin tone
    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /??‍?‍??/ })).toBeVisible())

    await picker.database.delete()
    await tick(20)
    document.body.removeChild(picker)
    await tick(20)
  })
})
Example #5
Source File: errors.test.js    From emoji-picker-element with Apache License 2.0 5 votes vote down vote up
describe('errors', () => {
  let errorSpy

  beforeEach(() => {
    basicBeforeEach()
    errorSpy = jest.spyOn(global.console, 'error').mockImplementation()
  })
  afterEach(async () => {
    await basicAfterEach()
    errorSpy.mockRestore()
  })

  // seems not possible to do
  test('throws error when setting the database', async () => {
    const picker = new Picker({ dataSource: ALL_EMOJI, locale: 'en' })
    document.body.appendChild(picker)
    await tick(20)
    expect(() => {
      picker.database = null
    }).toThrow(/database is read-only/)
    await tick(20)
    document.body.removeChild(picker)
    await tick(20)
  })

  // can't seem to get jest to ignore these expected errors
  test('offline shows an error', async () => {
    const dataSource = 'error.json'

    fetch.get(dataSource, { body: null, status: 500 })
    fetch.head(dataSource, { body: null, status: 500 })

    const picker = new Picker({ dataSource })
    const container = picker.shadowRoot
    document.body.appendChild(picker)

    await tick(20)

    await expect(picker.database.ready()).rejects.toThrow()

    await waitFor(() => expect(getByRole(container, 'alert').innerHTML).toContain('Could not load'))

    await new Database({ dataSource: ALL_EMOJI }).delete() // use different dataSource so it deletes properly
    document.body.removeChild(picker)
    await tick(20)
  })

  test('slow networks show "Loading"', async () => {
    const dataSource = 'slow.json'

    fetch.get(dataSource, () => new Response(JSON.stringify(truncatedEmoji), { headers: { ETag: 'W/slow' } }),
      { delay: 1500 })
    fetch.head(dataSource, () => new Response(null, { headers: { ETag: 'W/slow' } }),
      { delay: 1500 })

    const picker = new Picker({ dataSource })
    const container = picker.shadowRoot
    document.body.appendChild(picker)
    await tick(20)

    await waitFor(() => expect(getByRole(container, 'alert').innerHTML).toContain('Loading'), { timeout: 2000 })
    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible(), { timeout: 2000 })

    await new Database({ dataSource }).delete()
    document.body.removeChild(picker)
    await tick(20)
  }, 5000)
})
Example #6
Source File: lifecycle.test.js    From emoji-picker-element with Apache License 2.0 5 votes vote down vote up
describe('lifecycle', () => {
  beforeEach(basicBeforeEach)
  afterEach(basicAfterEach)

  test('can remove and re-append custom element', async () => {
    const picker = new Picker()
    const container = picker.shadowRoot

    document.body.appendChild(picker)

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())

    expect(fetch).toHaveBeenCalledTimes(1)
    expect(fetch).toHaveBeenLastCalledWith(DEFAULT_DATA_SOURCE, undefined)

    document.body.removeChild(picker)
    await tick(20)

    document.body.appendChild(picker)
    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())

    // fetch is called once again after re-insertion
    expect(fetch).toHaveBeenCalledTimes(2)
    expect(fetch).toHaveBeenLastCalledWith(DEFAULT_DATA_SOURCE, { method: 'HEAD' })

    document.body.removeChild(picker)
    await tick(20)
  })

  test('database.close() is called when disconnected', async () => {
    const picker = new Picker()
    document.body.appendChild(picker)
    const container = picker.shadowRoot

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())

    const spy = jest.spyOn(picker.database, 'close')

    document.body.removeChild(picker)
    await tick(20)

    expect(spy).toHaveBeenCalled()
    expect(spy).toHaveBeenCalledTimes(1)

    spy.mockRestore()
  })

  test('connect and immediately disconnect', async () => {
    const picker = new Picker()
    document.body.appendChild(picker)
    document.body.removeChild(picker)

    await tick(20)

    expect(fetch).toHaveBeenCalledTimes(1)
    expect(fetch).toHaveBeenLastCalledWith(DEFAULT_DATA_SOURCE, undefined)
  })

  test('connect, disconnect, and reconnect with a particular timing (#225)', async () => {
    const picker = new Picker()
    document.body.appendChild(picker)
    await tick(1)
    document.body.removeChild(picker)
    document.body.appendChild(picker)

    await expect(() => (
      expect(getByRole(picker.shadowRoot, 'option', { name: /?/ })).toBeVisible()
    ))

    await tick(20)
    document.body.removeChild(picker)
    await tick(20)
  })
})
Example #7
Source File: noResizeObserver.test.js    From emoji-picker-element with Apache License 2.0 5 votes vote down vote up
// TODO: we can remove these tests when/if we stop supporting browsers without ResizeObserver
// https://caniuse.com/resizeobserver

describe('ResizeObserver unsupported', () => {
  let picker
  let container
  let oldResizeObserver

  beforeEach(async () => {
    basicBeforeEach()

    oldResizeObserver = global.ResizeObserver
    delete global.ResizeObserver
    resetResizeObserverSupported()

    picker = new Picker({ dataSource: ALL_EMOJI })
    document.body.appendChild(picker)
    container = picker.shadowRoot.querySelector('.picker')
    await tick(40)
  })

  afterEach(async () => {
    await tick(40)
    document.body.removeChild(picker)
    await tick(40)
    await new Database({ dataSource: ALL_EMOJI }).delete()
    await tick(40)
    await basicAfterEach()

    global.ResizeObserver = oldResizeObserver
    resetResizeObserverSupported()
  })

  test('basic picker test', async () => {
    const numInGroup1 = truncatedEmoji.filter(_ => _.group === 0).length
    const numInGroup2 = truncatedEmoji.filter(_ => _.group === 1).length

    await waitFor(() => expect(getByRole(container, 'button', { name: 'Choose a skin tone (currently Default)' })).toBeVisible())
    expect(getAllByRole(container, 'tab')).toHaveLength(groups.length)

    expect(getByRole(container, 'tab', { name: 'Smileys and emoticons', selected: true })).toBeVisible()
    await waitFor(() => expect(
      testingLibrary.getAllByRole(getByRole(container, 'tabpanel'), 'menuitem')).toHaveLength(numInGroup1)
    )

    expect(getByRole(container, 'tab', { name: 'People and body' })).toBeVisible()
    fireEvent.click(getByRole(container, 'tab', { name: 'People and body' }))

    await waitFor(() => expect(
      testingLibrary.getAllByRole(getByRole(container, 'tabpanel'), 'menuitem')).toHaveLength(numInGroup2))

    expect(getByRole(container, 'tab', { name: 'People and body', selected: true })).toBeVisible()
  })
})
Example #8
Source File: upgrade.test.js    From emoji-picker-element with Apache License 2.0 5 votes vote down vote up
describe('upgrade tests', () => {
  beforeEach(async () => {
    basicBeforeEach()
    mockFrenchDataSource()
  })
  afterEach(async () => {
    await basicAfterEach()
  })

  test('setting props and attributes before upgrade', async () => {
    const div = document.createElement('div')
    document.body.appendChild(div)
    div.innerHTML = '<emoji-picker locale="fr"></emoji-picker>'

    const picker = div.querySelector('emoji-picker')
    picker.dataSource = FR_EMOJI
    picker.skinToneEmoji = '?'

    expect(picker.shadowRoot).toBeNull()

    await tick(20)

    expect(fetch).not.toHaveBeenCalled()

    await import('../../../src/picker/PickerElement')

    await waitFor(() => expect(getByRole(picker.shadowRoot, 'menuitem', { name: /?/ })).toBeVisible())

    const container = picker.shadowRoot

    expect(fetch).toHaveBeenCalledTimes(1)
    expect(fetch).toHaveBeenLastCalledWith(FR_EMOJI, undefined)

    expect(getByRole(container, 'button', { name: /Choose a skin tone/ }).innerHTML).toContain('?')

    expect(picker.locale).toEqual('fr')
    expect(picker.dataSource).toEqual(FR_EMOJI)

    // The setter should now work as expected
    picker.skinToneEmoji = '✌'

    await waitFor(() => expect(getByRole(container, 'button', { name: /Choose a skin tone/ }).innerHTML).toContain('✌'))

    document.body.removeChild(div)
    await tick(20)
  })
})
Example #9
Source File: attributes.test.js    From emoji-picker-element with Apache License 2.0 4 votes vote down vote up
describe('attributes tests', () => {
  beforeEach(async () => {
    basicBeforeEach()
    mockFrenchDataSource()
  })

  afterEach(basicAfterEach)

  test('setting initial locale/dataSource issues only one GET', async () => {
    const picker = new Picker()
    picker.setAttribute('locale', 'fr')
    picker.setAttribute('data-source', FR_EMOJI)
    document.body.appendChild(picker)
    await tick(20)

    expect(fetch).toHaveBeenCalledTimes(1)
    expect(fetch).toHaveBeenLastCalledWith(FR_EMOJI, undefined)

    expect(picker.locale).toEqual('fr')
    expect(picker.dataSource).toEqual(FR_EMOJI)
    expect(picker.getAttribute('locale')).toEqual('fr')
    expect(picker.getAttribute('data-source')).toEqual(FR_EMOJI)

    document.body.removeChild(picker)
    await tick(20)
  })

  test('can set skintone emoji using an attribute', async () => {
    const picker = new Picker()
    picker.setAttribute('data-source', ALL_EMOJI)
    picker.setAttribute('skin-tone-emoji', '✌')
    document.body.appendChild(picker)
    await tick(20)
    expect(getByRole(picker.shadowRoot, 'button', { name: /Choose a skin tone/ }).innerHTML)
      .toContain('✌')
    expect(picker.skinToneEmoji).toEqual('✌')
    expect(picker.getAttribute('skin-tone-emoji')).toEqual('✌')
    expect(picker.locale).toEqual('en')

    picker.setAttribute('skin-tone-emoji', '?')
    await tick(20)
    expect(getByRole(picker.shadowRoot, 'button', { name: /Choose a skin tone/ }).innerHTML)
      .toContain('?')
    expect(picker.skinToneEmoji).toEqual('?')

    document.body.removeChild(picker)
    await tick(20)
  })

  test('change property while disconnected from DOM', async () => {
    const picker = new Picker()
    picker.setAttribute('data-source', ALL_EMOJI)
    document.body.appendChild(picker)
    await tick(20)
    document.body.removeChild(picker)
    await tick(20)
    picker.skinToneEmoji = '✌'
    expect(picker.skinToneEmoji).toEqual('✌')
    document.body.appendChild(picker)
    await tick(20)

    expect(getByRole(picker.shadowRoot, 'button', { name: /Choose a skin tone/ }).innerHTML)
      .toContain('✌')
    expect(picker.skinToneEmoji).toEqual('✌')

    document.body.removeChild(picker)
    await tick(20)
  })

  test('change property while disconnected from DOM', async () => {
    const picker = new Picker()
    picker.setAttribute('data-source', ALL_EMOJI)
    document.body.appendChild(picker)
    await tick(20)
    document.body.removeChild(picker)
    await tick(20)
    picker.setAttribute('skin-tone-emoji', '✌')
    expect(picker.skinToneEmoji).toEqual('✌')
    document.body.appendChild(picker)
    await tick(20)

    expect(getByRole(picker.shadowRoot, 'button', { name: /Choose a skin tone/ }).innerHTML)
      .toContain('✌')
    expect(picker.skinToneEmoji).toEqual('✌')
    expect(picker.getAttribute('skin-tone-emoji')).toEqual('✌')

    document.body.removeChild(picker)
    await tick(20)
  })

  function testDefaultProps (picker) {
    expect(picker.customCategorySorting).toEqual(DEFAULT_CATEGORY_SORTING)
    expect(picker.customEmoji).toEqual(null)
    expect(picker.dataSource).toEqual(DEFAULT_DATA_SOURCE)
    expect(picker.i18n).toEqual(enI18n)
    expect(picker.locale).toEqual(DEFAULT_LOCALE)
    expect(picker.skinToneEmoji).toEqual(DEFAULT_SKIN_TONE_EMOJI)
  }

  function expectTruthyDatabase (picker) {
    expect(typeof picker.database).toEqual('object')
    expect(picker.database).toBeTruthy()
  }

  test('default properties - connected', async () => {
    const picker = new Picker()
    document.body.appendChild(picker)
    await tick(20)

    testDefaultProps(picker)
    expectTruthyDatabase(picker)

    document.body.removeChild(picker)
    await tick(20)
  })

  test('default properties - disconnected', async () => {
    const picker = new Picker()
    document.body.appendChild(picker)
    await tick(20)

    document.body.removeChild(picker)
    await tick(20)

    testDefaultProps(picker)
    expectTruthyDatabase(picker)
  })

  test('default properties - never connected', async () => {
    const picker = new Picker()

    testDefaultProps(picker)
    expectTruthyDatabase(picker)

    document.body.appendChild(picker)
    await tick(20)

    document.body.removeChild(picker)
    await tick(20)
  })

  test('attributes present on element at creation time', async () => {
    const div = document.createElement('div')
    document.body.appendChild(div)
    div.innerHTML = `<emoji-picker locale="fr" data-source="${ALL_EMOJI}" skin-tone-emoji="✌"></emoji-picker>`
    const picker = div.querySelector('emoji-picker')
    await tick(20)
    expect(picker.locale).toEqual('fr')
    expect(picker.dataSource).toEqual(ALL_EMOJI)
    expect(picker.skinToneEmoji).toEqual('✌')
    expect(getByRole(picker.shadowRoot, 'button', { name: /Choose a skin tone/ }).innerHTML)
      .toContain('✌')

    expect(fetch).toHaveBeenCalledTimes(1)
    expect(fetch).toHaveBeenLastCalledWith(ALL_EMOJI, undefined)

    document.body.removeChild(div)
    await tick(20)
  })
})
Example #10
Source File: custom.test.js    From emoji-picker-element with Apache License 2.0 4 votes vote down vote up
describe('Custom emojis tests', () => {
  beforeEach(basicBeforeEach)
  afterEach(basicAfterEach)

  test('Setting custom emoji shows the proper first page', async () => {
    const picker = new Picker({
      locale: 'en',
      dataSource: ALL_EMOJI
    })
    picker.customEmoji = [
      {
        name: 'monkey',
        shortcodes: ['monkey'],
        url: 'monkey.png'
      }
    ]
    document.body.appendChild(picker)

    const container = picker.shadowRoot.querySelector('.picker')

    await waitFor(() => expect(getAllByRole(container, 'tab')).toHaveLength(groups.length + 1))

    // We actually have to sleep here, because we want to test for a race condition where the
    // custom emoji show first, but then are replaced by the non-custom emoji
    // https://github.com/nolanlawson/emoji-picker-element/issues/84
    await tick(50)

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: 'monkey' })).toBeVisible())

    await waitFor(async () => (
      expect(
        await Promise.all(getAllByRole(container, 'menu').map(node => getAccessibleName(container, node)))
      ).toStrictEqual([
        'Custom',
        'Favorites'
      ])
    ))

    // Visibility test, has nothing to do with accessibility. We don't visually show the label if there's
    // just one category and it's the default "Custom" one.
    expect(container.querySelector('.category').textContent).toEqual('Custom')
    expect(container.querySelector('.category')).toHaveClass('gone')

    document.body.removeChild(picker)
    await tick(20)
  })

  test('Setting custom emoji, selecting flags, unsetting custom emoji', async () => {
    const picker = new Picker({
      locale: 'en',
      dataSource: ALL_EMOJI
    })
    picker.customEmoji = [
      {
        name: 'themonkey',
        shortcodes: ['themonkey'],
        url: 'themonkey.png'
      }
    ]
    document.body.appendChild(picker)

    const container = picker.shadowRoot.querySelector('.picker')

    await waitFor(() => expect(getAllByRole(container, 'tab')).toHaveLength(groups.length + 1))

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: 'themonkey' })).toBeVisible())

    getByRole(container, 'tab', { name: 'Flags' }).click()

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())

    picker.customEmoji = undefined

    await waitFor(() => expect(getAllByRole(container, 'tab')).toHaveLength(groups.length))

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())

    expect(getByRole(container, 'tab', { name: 'Flags' }).getAttribute('aria-selected')).toEqual('true')

    document.body.removeChild(picker)
    await tick(20)
  })

  test('Setting custom emoji, unsetting custom emoji', async () => {
    const picker = new Picker({
      locale: 'en',
      dataSource: ALL_EMOJI
    })
    picker.customEmoji = [
      {
        name: 'themonkey',
        shortcodes: ['themonkey'],
        url: 'themonkey.png'
      }
    ]
    document.body.appendChild(picker)

    const container = picker.shadowRoot.querySelector('.picker')

    await waitFor(() => expect(getAllByRole(container, 'tab')).toHaveLength(groups.length + 1))

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: 'themonkey' })).toBeVisible())

    picker.customEmoji = undefined

    await waitFor(() => expect(getAllByRole(container, 'tab')).toHaveLength(groups.length))

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())

    expect(getByRole(container, 'tab', { name: 'Smileys and emoticons' }).getAttribute('aria-selected')).toEqual('true')

    document.body.removeChild(picker)
    await tick(20)
  })
})
Example #11
Source File: element.test.js    From emoji-picker-element with Apache License 2.0 4 votes vote down vote up
describe('element tests', () => {
  describe('UI tests', () => {
    let picker
    let container

    beforeEach(async () => {
      basicBeforeEach()
      mockFrenchDataSource()
      picker = new Picker({ dataSource: ALL_EMOJI, locale: 'en' })
      container = picker.shadowRoot
      document.body.appendChild(picker)
      await tick(20)
    })
    afterEach(async () => {
      document.body.removeChild(picker)
      await tick(20)
      await new Database({ dataSource: FR_EMOJI, locale: 'fr' }).delete()
      await new Database({ dataSource: ALL_EMOJI, locale: 'en' }).delete()
      await tick(20)
      await basicAfterEach()
    })

    test('changing locale/dataSource prop causes only one network request', async () => {
      expect(fetch).toHaveBeenCalledTimes(1)
      expect(fetch).toHaveBeenLastCalledWith(ALL_EMOJI, undefined)
      await type(getByRole(container, 'combobox'), 'monkey face')
      await waitFor(() => expect(getAllByRole(container, 'option')).toHaveLength(1), {
        timeout: 2000
      })
      expect(getByRole(container, 'option', { name: /?/ })).toBeVisible()
      picker.locale = 'fr'
      picker.dataSource = FR_EMOJI
      await tick(20)
      expect(fetch).toHaveBeenCalledTimes(2)
      expect(fetch).toHaveBeenLastCalledWith(FR_EMOJI, undefined)
      await clear(getByRole(container, 'combobox'))
      await type(getByRole(container, 'combobox'), 'singe tête')
      await waitFor(() => expect(getAllByRole(container, 'option')).toHaveLength(1))
      expect(getByRole(container, 'option', { name: /?/ })).toBeVisible()
    })

    test('changing locale/dataSource attr causes only one network request', async () => {
      expect(fetch).toHaveBeenCalledTimes(1)
      expect(fetch).toHaveBeenLastCalledWith(ALL_EMOJI, undefined)
      await type(getByRole(container, 'combobox'), 'monkey face')
      await waitFor(() => expect(getAllByRole(container, 'option')).toHaveLength(1), {
        timeout: 2000
      })
      expect(getByRole(container, 'option', { name: /?/ })).toBeVisible()
      picker.setAttribute('locale', 'fr')
      picker.setAttribute('data-source', FR_EMOJI)
      await tick(20)
      expect(fetch).toHaveBeenCalledTimes(2)
      expect(fetch).toHaveBeenLastCalledWith(FR_EMOJI, undefined)
      await clear(getByRole(container, 'combobox'))
      await type(getByRole(container, 'combobox'), 'singe tête')
      await waitFor(() => expect(getAllByRole(container, 'option')).toHaveLength(1))
      expect(getByRole(container, 'option', { name: /?/ })).toBeVisible()
    })

    test('can dynamically change i18n', async () => {
      picker.i18n = frI18n
      await tick(10)
      expect(getByRole(container, 'combobox', { name: 'Recherche' })).toBeVisible()
      expect(getByRole(container, 'tab', { name: 'Sourires et emoticons' })).toBeVisible()
      expect(getByRole(container, 'button', { name: 'Choose a skin tone (currently Défaut)' })).toBeVisible()
    })

    test('can change default skin tone emoji', async () => {
      expect(picker.skinToneEmoji).toBe(DEFAULT_SKIN_TONE_EMOJI)
      expect(getByRole(container, 'button', { name: /Choose a skin tone/ }).innerHTML)
        .toContain(DEFAULT_SKIN_TONE_EMOJI)
      picker.skinToneEmoji = '?'
      await waitFor(() => expect(getByRole(container, 'button', { name: /Choose a skin tone/ }).innerHTML).toContain('?'))
      picker.skinToneEmoji = '?'
      await waitFor(() => expect(getByRole(container, 'button', { name: /Choose a skin tone/ }).innerHTML).toContain('?'))
    })

    test('can get the locale/dataSource', () => {
      expect(picker.locale).toBe('en')
      expect(picker.dataSource).toBe(ALL_EMOJI)
    })
  })

  describe('defaults test', () => {
    beforeEach(() => {
      fetch.get(DEFAULT_DATA_SOURCE, () => new Response(JSON.stringify(truncatedEmoji), { headers: { ETag: 'W/aaa' } }))
      fetch.head(DEFAULT_DATA_SOURCE, () => new Response(null, { headers: { ETag: 'W/aaa' } }))
    })

    afterEach(basicAfterEach)

    test('has a default locale/dataSource', async () => {
      const picker = new Picker()
      document.body.appendChild(picker)
      const container = picker.shadowRoot
      await tick(20)

      await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())

      await new Database().delete()
      await tick(20)
      await document.body.removeChild(picker)
      await tick(20)
    })
  })
})
Example #12
Source File: favorites.test.js    From emoji-picker-element with Apache License 2.0 4 votes vote down vote up
describe('Favorites UI', () => {
  let picker
  let container

  beforeEach(async () => {
    basicBeforeEach()

    const dataWithFavorites = uniqBy([
      ...truncatedEmoji,
      ...allData.filter(_ => MOST_COMMONLY_USED_EMOJI.includes(_.emoji))
    ], _ => _.emoji)

    fetch.get(dataSource, () => new Response(JSON.stringify(dataWithFavorites), { headers: { ETag: 'W/favs' } }))
    fetch.head(dataSource, () => new Response(null, { headers: { ETag: 'W/favs' } }))

    picker = new Picker({ dataSource, locale: 'en' })
    document.body.appendChild(picker)
    container = picker.shadowRoot.querySelector('.picker')

    await tick(40)
  })
  afterEach(async () => {
    await tick(40)
    document.body.removeChild(picker)
    await tick(40)
    await basicAfterEach()
  })

  async function remount () {
    await tick(40)
    document.body.removeChild(picker)
    await tick(40)
    document.body.appendChild(picker)
    container = picker.shadowRoot
    await tick(40)
  }

  test('Favorites UI basic test', async () => {
    let favoritesBar = getByRole(container, 'menu', { name: 'Favorites' })
    expect(favoritesBar).toBeVisible()
    await waitFor(() => expect(getAllByRole(favoritesBar, 'menuitem')).toHaveLength(8))
    expect(getAllByRole(favoritesBar, 'menuitem').map(_ => _.getAttribute('id').substring(4))).toStrictEqual(
      MOST_COMMONLY_USED_EMOJI.slice(0, 8)
    )
    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())
    fireEvent.click(getByRole(container, 'menuitem', { name: /?/ }))

    // have to unmount/remount to force a favorites refresh
    await remount()

    favoritesBar = getByRole(container, 'menu', { name: 'Favorites' })
    await waitFor(() => expect(getAllByRole(favoritesBar, 'menuitem')
      .map(_ => _.getAttribute('id').substring(4))).toStrictEqual([
      '?',
      ...MOST_COMMONLY_USED_EMOJI.slice(0, 7)
    ]
    ))
  })

  test('Favorites with custom emoji', async () => {
    const transparent = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
    const black = 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='

    const customEmoji = [
      {
        name: 'transparent',
        shortcodes: ['transparent'],
        url: transparent
      },
      {
        name: 'black',
        shortcodes: ['black'],
        url: black
      }
    ]

    await waitFor(() => expect(getAllByRole(container, 'tab')).toHaveLength(groups.length))

    // when setting custom emoji, they can appear in the favorites
    await tick(40)
    picker.customEmoji = customEmoji
    await tick(40)

    await waitFor(() => expect(getAllByRole(container, 'tab')).toHaveLength(groups.length + 1))

    expect(getByRole(container, 'tab', { name: 'Custom', selected: true })).toBeVisible()
    await tick(40)
    await waitFor(() => expect(queryAllByRole(container, 'menuitem', { name: /transparent/i })).toHaveLength(1), {
      timeout: 5000
    })
    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /transparent/i })).toBeVisible(), {
      timeout: 3000
    })

    fireEvent.click(getByRole(container, 'menuitem', { name: /transparent/i }))
    fireEvent.click(getByRole(container, 'menuitem', { name: /black/i }))

    // have to unmount/remount to force a favorites refresh
    await remount()

    await waitFor(
      () => expect(getByRole(getByRole(container, 'menu', { name: 'Favorites' }), 'menuitem', { name: /transparent/i })).toBeVisible
    )

    await waitFor(
      () => expect(getByRole(getByRole(container, 'menu', { name: 'Favorites' }), 'menuitem', { name: /black/i })).toBeVisible
    )

    // when setting custom emoji back to [], the favorites bar removes the custom emoji
    picker.customEmoji = []

    await waitFor(() => expect(getAllByRole(container, 'tab')).toHaveLength(groups.length))

    await waitFor(
      () => expect(queryAllByRole(getByRole(container, 'menu', { name: 'Favorites' }), 'menuitem', { name: /transparent/i })).toHaveLength(0)
    )
    await waitFor(
      () => expect(queryAllByRole(getByRole(container, 'menu', { name: 'Favorites' }), 'menuitem', { name: /black/i })).toHaveLength(0)
    )
  })
})
Example #13
Source File: scrolling.test.js    From emoji-picker-element with Apache License 2.0 4 votes vote down vote up
describe('scrolling', () => {
  beforeEach(basicBeforeEach)
  afterEach(basicAfterEach)

  test('can scroll', async () => {
    const picker = new Picker()
    const container = picker.shadowRoot

    document.body.appendChild(picker)

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())

    const tabPanel = getByRole(container, 'tabpanel')

    await tick(20)
    expect(tabPanel.scrollTop).toEqual(0)

    tabPanel.scrollTop = 1

    await tick(20)
    expect(tabPanel.scrollTop).toEqual(1)

    document.body.removeChild(picker)
    await tick(20)
  })

  test('scrollTop resets to 0 on changing tabs', async () => {
    const picker = new Picker()
    const container = picker.shadowRoot

    document.body.appendChild(picker)

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())

    await tick(100)
    const tabPanel = getByRole(container, 'tabpanel')
    tabPanel.scrollTop = 1

    await tick(100)
    expect(tabPanel.scrollTop).toEqual(1)

    await userEvent.click(getByRole(container, 'tab', { name: 'People and body' }))

    await tick(20)
    expect(tabPanel.scrollTop).toEqual(0)

    await userEvent.click(getByRole(container, 'tab', { name: 'Smileys and emoticons' }))

    await tick(20)
    expect(tabPanel.scrollTop).toEqual(0)

    document.body.removeChild(picker)
    await tick(20)
  })

  test('scrollTop resets to 0 on changing search input', async () => {
    const picker = new Picker()
    const container = picker.shadowRoot

    document.body.appendChild(picker)

    await waitFor(() => expect(getByRole(container, 'menuitem', { name: /?/ })).toBeVisible())
    const tabPanel = getByRole(container, 'tabpanel')

    await userEvent.type(getByRole(container, 'combobox'), 'monkey')

    await waitFor(() => expect(getAllByRole(container, 'option')).toHaveLength(2))
    expect(getByRole(container, 'option', { name: /?/ })).toBeVisible()

    await tick(100)
    tabPanel.scrollTop = 1

    await tick(100)
    expect(tabPanel.scrollTop).toEqual(1)

    await userEvent.type(getByRole(container, 'combobox'), ' face')

    await waitFor(() => expect(getAllByRole(container, 'option')).toHaveLength(1))
    expect(getByRole(container, 'option', { name: /?/ })).toBeVisible()

    await tick(40)
    expect(tabPanel.scrollTop).toEqual(0)

    document.body.removeChild(picker)
    await tick(20)
  })
})
Example #14
Source File: UserAccessContainer.spec.jsx    From frontend-app-library-authoring with GNU Affero General Public License v3.0 4 votes vote down vote up
testSuite('<UserAccessWidgetContainer />', () => {
  [
    [LIBRARY_ACCESS.READ, 'Read Only'],
    [LIBRARY_ACCESS.ADMIN, 'Admin'],
    [LIBRARY_ACCESS.AUTHOR, 'Author'],
  ].forEach(([accessLevel, text]) => {
    it(`Should render a badge labeled ${text} when the target user's access level is ${accessLevel}.`, async () => {
      const [library] = libraryFactoryLine();
      // userId doesn't exist on users pulled from the team listings, but it does exist on authenticated users.
      const [user, currentUser] = userFactoryLine([{ access_level: accessLevel }, { userId: 3 }]);
      const props = {
        library, user, multipleAdmins: false, ...commonMocks(),
      };
      await ctxRender(
        <UserAccessWidgetContainer
          {...props}
        />,
        { context: { authenticatedUser: currentUser } },
      );
      const badge = screen.getByText(text);
      expect(badge).toBeTruthy();
    });
  });

  [
    [true, LIBRARY_ACCESS.ADMIN, false, false],
    [true, LIBRARY_ACCESS.ADMIN, true, true],
    [true, LIBRARY_ACCESS.AUTHOR, true, false],
    [true, LIBRARY_ACCESS.AUTHOR, false, false],
    [true, LIBRARY_ACCESS.READ, true, false],
    [true, LIBRARY_ACCESS.READ, false, false],
    [false, LIBRARY_ACCESS.ADMIN, true, false],
    [false, LIBRARY_ACCESS.ADMIN, false, false],
  ].forEach(async ([isAdmin, accessLevel, multipleAdmins, buttonsShown]) => {
    let testName = 'The admin privilege management buttons are ';
    if (!buttonsShown) {
      testName += 'not ';
    }
    testName += 'shown when the viewer is ';
    if (!isAdmin) {
      testName += 'not ';
    }
    testName += `an admin and the subject's access level is ${accessLevel} and there are `;
    if (!multipleAdmins) {
      testName += 'multiple admins.';
    }

    it(testName, async () => {
      const [library] = libraryFactoryLine();
      const [currentUser, targetUser] = userFactoryLine([{}, { access_level: accessLevel }]);
      const props = {
        library, user: targetUser, multipleAdmins, isAdmin, ...commonMocks(),
      };
      const { container } = await ctxRender(
        <UserAccessWidgetContainer
          {...props}
        />,
        { context: { authenticatedUser: currentUser } },
      );
      if (buttonsShown) {
        const removeButton = getByRole(container, 'button', { name: /Remove Admin/ });
        expect(removeButton).toBeTruthy();
      } else {
        const buttonList = queryAllByRole(container, 'button', { name: /Remove Admin/ });
        expect(buttonList.length).toBe(0);
        if (isAdmin && targetUser.access_level === LIBRARY_ACCESS.ADMIN) {
          expect(getByText(container, /Promote another member/)).toBeTruthy();
        } else {
          expect(queryAllByText(container, /Promote another member/).length).toBe(0);
        }
      }
    });
  });

  [
    [true, LIBRARY_ACCESS.ADMIN, false],
    [true, LIBRARY_ACCESS.AUTHOR, true],
    [true, LIBRARY_ACCESS.READ, false],
    [false, LIBRARY_ACCESS.AUTHOR, false],
  ].forEach(async ([isAdmin, accessLevel, buttonsShown]) => {
    let testName = 'The staff management buttons are ';
    if (!buttonsShown) {
      testName += 'not ';
    }
    testName += 'visible when the viewer is ';
    if (!isAdmin) {
      testName += 'not ';
    }
    testName += `an admin and the subject's current access_level is ${accessLevel}.`;

    it(testName, async () => {
      const [library] = libraryFactoryLine();
      const [currentUser, targetUser] = userFactoryLine([{}, { access_level: accessLevel }]);
      const props = {
        library, user: targetUser, multipleAdmins: false, isAdmin, ...commonMocks(),
      };
      const { container } = await ctxRender(
        <UserAccessWidgetContainer
          {...props}
        />,
        { context: { authenticatedUser: currentUser } },
      );
      if (buttonsShown) {
        const removeButton = getByRole(container, 'button', { name: /Remove Author/ });
        expect(removeButton).toBeTruthy();
        const addButton = getByRole(container, 'button', { name: /Add Admin/ });
        expect(addButton).toBeTruthy();
      } else {
        const buttonList = queryAllByRole(container, 'button', { name: /(Remove Author|Add Admin)/ });
        expect(buttonList.length).toBe(0);
      }
    });
  });

  [
    [true, LIBRARY_ACCESS.ADMIN, false],
    [true, LIBRARY_ACCESS.AUTHOR, false],
    [true, LIBRARY_ACCESS.READ, true],
    [false, LIBRARY_ACCESS.READ, false],
  ].forEach(async ([isAdmin, accessLevel, buttonShown]) => {
    let testName = 'The add author privileges button is ';
    if (!buttonShown) {
      testName += 'not ';
    }
    testName += 'visible if the viewer is ';
    if (!isAdmin) {
      testName += 'not ';
    }
    testName += `an admin and the subject's access level is ${accessLevel}.`;

    it(testName, async () => {
      const [library] = libraryFactoryLine();
      const [currentUser, targetUser] = userFactoryLine([{}, { access_level: accessLevel }]);
      const props = {
        library, user: targetUser, multipleAdmins: false, isAdmin, ...commonMocks(),
      };
      const { container } = await ctxRender(
        <UserAccessWidgetContainer
          {...props}
        />,
        { context: { authenticatedUser: currentUser } },
      );
      const buttonList = queryAllByRole(container, 'button', { name: /Add Author/ });
      if (buttonShown) {
        expect(buttonList.length).toBe(1);
      } else {
        expect(buttonList.length).toBe(0);
      }
    });
  });

  [
    [true, LIBRARY_ACCESS.ADMIN, false, false],
    [true, LIBRARY_ACCESS.ADMIN, true, true],
    [true, LIBRARY_ACCESS.AUTHOR, true, true],
    [true, LIBRARY_ACCESS.AUTHOR, false, true],
    [true, LIBRARY_ACCESS.READ, true, true],
    [true, LIBRARY_ACCESS.READ, false, true],
    [false, LIBRARY_ACCESS.ADMIN, true, false],
    [false, LIBRARY_ACCESS.ADMIN, false, false],
    [false, LIBRARY_ACCESS.AUTHOR, true, false],
    [false, LIBRARY_ACCESS.AUTHOR, false, false],
    [false, LIBRARY_ACCESS.READ, true, false],
    [false, LIBRARY_ACCESS.READ, false, false],
  ].forEach(([isAdmin, accessLevel, multipleAdmins, buttonShown]) => {
    let testName = 'The button for removing a user is ';
    if (buttonShown) {
      testName += 'present';
    } else {
      testName += 'not present';
    }
    testName += ' when the viewer is ';
    if (!isAdmin) {
      testName += 'not ';
    }
    testName += 'an admin and there are ';
    if (!multipleAdmins) {
      testName += ' not ';
    }
    testName += 'multiple admins in a library.';

    it(testName, async () => {
      const [library] = libraryFactoryLine();
      const [currentUser, targetUser] = userFactoryLine([{}, { access_level: accessLevel }]);
      const props = {
        library, user: targetUser, multipleAdmins, isAdmin, ...commonMocks(),
      };
      const { container } = await ctxRender(
        <UserAccessWidgetContainer
          {...props}
        />,
        { context: { authenticatedUser: currentUser } },
      );
      const buttonList = queryAllByRole(container, 'button', { name: /Remove user/ });
      if (buttonShown) {
        expect(buttonList.length).toBe(1);
      } else {
        expect(buttonList.length).toBe(0);
      }
    });
  });
});