Beispiel #1
0
test('handleKeydown space/enter key on a list item with a checkbox toggles the checkbox', () => {
  const {foundation, mockAdapter} = setupTest();
  const event = {key: 'Space', target: {tagName: 'li'}, preventDefault: td.func('preventDefault')};
  const checkbox = document.createElement('input');
  checkbox.type = 'checkbox';
  td.when(mockAdapter.elementContainsClass(event.target, listClasses.LIST_ITEM_CLASS)).thenReturn(false, true);
  td.when(mockAdapter.getParentElement(event.target)).thenReturn(event.target);
  td.when(mockAdapter.getElementIndex(event.target)).thenReturn(0);
  td.when(mockAdapter.getCheckboxAtIndex(0)).thenReturn(checkbox);

  foundation.handleKeydown(event);
  event.key = 'Enter';
  foundation.handleKeydown(event);

  td.verify(mockAdapter.toggleCheckbox(checkbox), {times: 2});
});
Beispiel #2
0
test('Click event inside of a selection group with another element selected', () => {
  const {foundation, mockAdapter} = setupTest();
  const clock = lolex.install();
  const event = {target: {tagName: 'li'}, preventDefault: td.func('preventDefault')};
  td.when(mockAdapter.elementContainsClass(event.target, listClasses.LIST_ITEM_CLASS)).thenReturn(true);
  td.when(mockAdapter.getElementIndex(event.target)).thenReturn(0);
  td.when(mockAdapter.getParentElement(event.target)).thenReturn(event.target);
  td.when(mockAdapter.elementContainsClass(event.target, cssClasses.MENU_SELECTION_GROUP)).thenReturn(true);
  td.when(mockAdapter.getSelectedElementIndex(event.target)).thenReturn(0);

  foundation.handleClick(event);
  clock.tick(numbers.TRANSITION_CLOSE_DURATION);

  td.verify(mockAdapter.removeClassFromElementAtIndex(0, cssClasses.MENU_SELECTED_LIST_ITEM), {times: 1});
  td.verify(mockAdapter.addClassToElementAtIndex(0, cssClasses.MENU_SELECTED_LIST_ITEM), {times: 1});
  clock.uninstall();
});
  test('(regression) activates ripple on keydown when the input element surface is active', () => {
    const raf = createMockRaf();
    const {root} = setupTest();
    const input = root.querySelector('input');
    raf.flush();

    const fakeMatches = td.func('.matches');
    td.when(fakeMatches(':active')).thenReturn(true);
    input[getMatchesProperty(HTMLElement.prototype)] = fakeMatches;

    assert.isTrue(root.classList.contains('mdc-ripple-upgraded'));
    domEvents.emit(input, 'keydown');
    raf.flush();

    assert.isTrue(root.classList.contains('mdc-ripple-upgraded--foreground-activation'));
    raf.restore();
  });
test('adapter#notifySelected fires an "MDLSimpleMenu:selected" custom event with the item and index', t => {
  const {root, component} = setupTest();
  const item = root.querySelectorAll('[role="menuitem"]')[0];
  const handler = td.func('notifySelected handler');
  let evtData = null;
  td.when(handler(td.matchers.isA(Object))).thenDo(evt => {
    evtData = evt.detail;
  });
  root.addEventListener('MDLSimpleMenu:selected', handler);
  component.getDefaultFoundation().adapter_.notifySelected({index: 0});
  t.true(evtData !== null);
  t.deepEqual(evtData, {
    item,
    index: 0
  });
  t.end();
});
Beispiel #5
0
 constructor(root) {
   this.root = root;
   this.destroy = td.func('.destroy');
   this.open = false;
   this.listen = td.function();
   this.unlisten = td.function();
   this.setAnchorCorner = td.func('.setAnchorCorner');
   this.setAnchorMargin = td.func('.setAnchorMargin');
   this.quickOpen = false;
   this.setFixedPosition = td.func('.setFixedPosition');
   this.setAbsolutePosition = td.func('.setAbsolutePosition');
   this.hoistMenuToBody = td.func('.hoistMenuToBody');
   this.setIsHoisted = td.func('.setIsHoisted');
   this.anchorElement = null;
 }
Beispiel #6
0
  'element updates first element tabindex', () => {
  const {foundation, mockAdapter} = setupTest();
  const preventDefault = td.func('preventDefault');
  const target = {classList: ['mdc-list-item']};
  const event = {key: 'Space', target, preventDefault};

  td.when(mockAdapter.getFocusedElementIndex()).thenReturn(1);
  td.when(mockAdapter.getListItemCount()).thenReturn(3);
  foundation.setSingleSelection(true);
  foundation.handleKeydown(event, true, 1);
  foundation.handleKeydown(event, true, 1);

  td.verify(preventDefault(), {times: 2});
  td.verify(mockAdapter.setAttributeForElementIndex(1, strings.ARIA_SELECTED, true), {times: 1});
  td.verify(mockAdapter.setAttributeForElementIndex(1, 'tabindex', 0), {times: 1});
  td.verify(mockAdapter.setAttributeForElementIndex(0, 'tabindex', -1), {times: 1});
});
test('#emit dispatches a custom event with the supplied data', () => {
  const root = document.createElement('div');
  const f = new FakeComponent(root);
  const handler = td.func('eventHandler');
  let evt = null;
  td.when(handler(td.matchers.isA(Object))).thenDo((evt_) => {
    evt = evt_;
  });
  const data = {evtData: true};
  const type = 'customeventtype';

  root.addEventListener(type, handler);
  f.emit(type, data);
  assert.isOk(evt !== null);
  assert.equal(evt.type, type);
  assert.deepEqual(evt.detail, data);
});
Beispiel #8
0
  test(`on body ${moveEvt} prevents default behavior`, () => {
    const {foundation, mockAdapter, raf, rootHandlers, bodyHandlers} = setupTest();
    const preventDefault = td.func('evt.preventDefault');

    td.when(mockAdapter.computeBoundingRect()).thenReturn({left: 0, width: 100});
    foundation.init();
    raf.flush();

    rootHandlers[downEvt](pageXObj(49));
    bodyHandlers[moveEvt](
      Object.assign({preventDefault}, pageXObj(50))
    );
    raf.flush();

    td.verify(preventDefault());

    raf.restore();
  });
test('#supportsCssVariables returns true when feature-detecting its way around Safari < 10', () => {
  const windowObj = {
    CSS: {
      supports: td.func('.supports'),
    },
  };
  td.when(windowObj.CSS.supports('--css-vars', td.matchers.anything())).thenReturn(false);
  td.when(windowObj.CSS.supports(td.matchers.contains('(--css-vars:'))).thenReturn(true);
  td.when(windowObj.CSS.supports('color', '#00000000')).thenReturn(true);
  assert.isOk(util.supportsCssVariables(windowObj), 'true iff both CSS Vars and #rgba are supported');

  td.when(windowObj.CSS.supports(td.matchers.contains('(--css-vars:'))).thenReturn(false);
  assert.isNotOk(util.supportsCssVariables(windowObj), 'false if CSS Vars are supported but not #rgba');
  td.when(windowObj.CSS.supports(td.matchers.contains('(--css-vars:'))).thenReturn(true);

  td.when(windowObj.CSS.supports('color', '#00000000')).thenReturn(false);
  assert.isNotOk(util.supportsCssVariables(windowObj), 'false if #rgba is supported but not CSS Vars');
});
test('on click does not trigger event target has aria-disabled set to true', () => {
  const {foundation, mockAdapter} = setupTest();
  const handlers = captureHandlers(mockAdapter, 'registerInteractionHandler');

  td.when(mockAdapter.getAttributeForEventTarget(td.matchers.anything(), strings.ARIA_DISABLED_ATTR))
    .thenReturn('true');
  const clock = lolex.install();
  const mockEvt = {
    target: {},
    stopPropagation: td.func('stopPropagation'),
  };

  foundation.init();
  handlers.click(mockEvt);
  clock.tick(numbers.SELECTED_TRIGGER_DELAY);
  td.verify(mockAdapter.notifySelected(td.matchers.anything()), {times: 0});

  clock.uninstall();
});
test('on spacebar keydown prevents default on the event', () => {
  const {foundation, mockAdapter} = setupTest();
  const handlers = captureHandlers(mockAdapter, 'registerInteractionHandler');
  const clock = lolex.install();
  const raf = createMockRaf();
  const target = {};
  const preventDefault = td.func('event.preventDefault');
  td.when(mockAdapter.getNumberOfItems()).thenReturn(3);
  td.when(mockAdapter.getFocusedItemIndex()).thenReturn(2);

  foundation.init();
  handlers.keydown({target, key: 'Space', preventDefault});
  clock.tick(numbers.SELECTED_TRIGGER_DELAY);
  raf.flush();
  td.verify(preventDefault());

  raf.restore();
  clock.uninstall();
});
Beispiel #12
0
  'with additional markup does not cause loop', () => {
  // This test will timeout of there is an endless loop in the selection group logic.
  const {foundation, mockAdapter} = setupTest();
  const clock = lolex.install();
  const parentElement = {};
  const event = {key: 'Space', target: {tagName: 'li'}, preventDefault: td.func('preventDefault')};
  td.when(mockAdapter.elementContainsClass(event.target, listClasses.LIST_ITEM_CLASS)).thenReturn(true);
  td.when(mockAdapter.elementContainsClass(td.matchers.anything(), listClasses.ROOT)).thenReturn(false, true);
  td.when(mockAdapter.getElementIndex(event.target)).thenReturn(0);
  td.when(mockAdapter.getParentElement(td.matchers.anything())).thenReturn(parentElement, null);
  td.when(mockAdapter.elementContainsClass(td.matchers.anything(), cssClasses.MENU_SELECTION_GROUP)).thenReturn(false);

  foundation.handleKeydown(event);
  event.key = 'Enter';
  foundation.handleKeydown(event);
  clock.tick(numbers.TRANSITION_CLOSE_DURATION);

  td.verify(mockAdapter.closeSurface(), {times: 2});
  clock.uninstall();
});
Beispiel #13
0
  'element selected', () => {
  const {foundation, mockAdapter} = setupTest();
  const clock = lolex.install();
  const event = {key: 'Space', target: {tagName: 'li'}, preventDefault: td.func('preventDefault')};
  td.when(mockAdapter.elementContainsClass(event.target, listClasses.LIST_ITEM_CLASS)).thenReturn(true);
  td.when(mockAdapter.getElementIndex(event.target)).thenReturn(0);
  td.when(mockAdapter.getParentElement(event.target)).thenReturn(event.target);
  td.when(mockAdapter.elementContainsClass(event.target, cssClasses.MENU_SELECTION_GROUP)).thenReturn(false, true);
  td.when(mockAdapter.getSelectedElementIndex(event.target)).thenReturn(-1);

  foundation.handleKeydown(event);
  event.key = 'Enter';
  foundation.handleKeydown(event);
  clock.tick(numbers.TRANSITION_CLOSE_DURATION);

  td.verify(mockAdapter.removeClassFromElementAtIndex(td.matchers.isA(Number), cssClasses.MENU_SELECTED_LIST_ITEM),
    {times: 0});
  td.verify(mockAdapter.addClassToElementAtIndex(0, cssClasses.MENU_SELECTED_LIST_ITEM), {times: 2});
  clock.uninstall();
});
testFoundation('#open removes the animation class at the end of the animation', t => {
  const {foundation, mockAdapter, mockRaf} = t.data;
  const {now} = window.performance;
  const mockNow = td.func('window.performance.now');
  window.performance.now = mockNow;

  td.when(mockNow()).thenReturn(0);
  td.when(mockAdapter.hasClass('mdl-simple-menu--open-from-top-right')).thenReturn(true);

  foundation.open();
  mockRaf.flush();
  mockRaf.flush();
  t.doesNotThrow(() => td.verify(mockAdapter.addClass('mdl-simple-menu--animating')), 'sanity check');

  td.when(mockNow()).thenReturn(500);
  mockRaf.flush();
  t.doesNotThrow(() => td.verify(mockAdapter.removeClass('mdl-simple-menu--animating')));

  window.performance.now = now;
  t.end();
});
test('#componentDidMount should call props.handleValueChange', () => {
  const handleValueChange = td.func();
  shallow(<Input handleValueChange={handleValueChange} value='woof'/>);
  td.verify(handleValueChange('woof'), {times: 1});
});
test('#event.onBlur calls foundation.deactivateFocus()', () => {
  const foundation = {deactivateFocus: td.func()};
  const wrapper = shallow(<Input foundation={foundation} />);
  wrapper.simulate('blur');
  td.verify(foundation.deactivateFocus(), {times: 1});
});
test('#event.onBlur calls props.handleFocusChange(false)', () => {
  const handleFocusChange = td.func();
  const wrapper = shallow(<Input handleFocusChange={handleFocusChange} />);
  wrapper.simulate('blur');
  td.verify(handleFocusChange(false), {times: 1});
});
test('#componentWillReceiveProps calls setInputId if id updates', () => {
  const setInputId = td.func();
  const wrapper = shallow(<Input setInputId={setInputId} id='best-id'/>);
  wrapper.setProps({id: 'better-id'});
  td.verify(setInputId('better-id'), {times: 1});
});
 constructor() {
   this.destroy = td.func('.destroy');
 }
 constructor() {
   this.float = td.func('label.float');
 }
  '#foundation.setRippleCenter', () => {
  const wrapper = shallow(<LineRipple />);
  wrapper.instance().foundation_.setRippleCenter = td.func();
  wrapper.setProps({rippleCenter: 10});
  td.verify(wrapper.instance().foundation_.setRippleCenter(10), {times: 1});
});
 constructor(el) {
   this.id = el.id;
   this.destroy = td.func('.destroy');
   this.selected = false;
 }
test('change to minLength calls handleValidationAttributeChange', () => {
  const handleValidationAttributeChange = td.func();
  const wrapper = shallow(<Input foundation={{handleValidationAttributeChange}} />);
  wrapper.setProps({minLength: 20});
  td.verify(handleValidationAttributeChange(['minlength']), {times: 1});
});
Beispiel #24
0
 beforeEach(() => {
   props = { value: 'a', onChange: td.func('onChange') };
 });
Beispiel #25
0
 beforeEach(() => {
   props = { value: '', onBlur: td.func('onBlur') };
   instance = shallow(<FormFieldTick {...props} />).instance();
   instance.handleBlur();
 });
test('#componentDidMount should call props.setInputId if props.id exists', () => {
  const setInputId = td.func();
  shallow(<Input setInputId={setInputId} id='best-id'/>);
  td.verify(setInputId('best-id'), {times: 1});
});
test('#componentDidMount should call props.disabled if props.disabled is true', () => {
  const setDisabled = td.func();
  shallow(<Input setDisabled={setDisabled} disabled />);
  td.verify(setDisabled(true), {times: 1});
});
 constructor() {
   this.activate = td.func('bottomLine.activate');
   this.deactivate = td.func('bottomLine.deactivate');
 }
  'a whitelisted attr updates', () => {
  const handleValidationAttributeChange = td.func();
  const wrapper = shallow(<Input foundation={{handleValidationAttributeChange}} />);
  wrapper.setProps({required: true});
  td.verify(handleValidationAttributeChange(['required']), {times: 1});
});
Beispiel #30
0
 beforeEach(() => {
   props = { options: [], onFocus: td.func('onFocus') };
   instance = shallow(<FormFieldSelectGroup {...props} />).instance();
   instance.handleFocus();
 });