Skip to content

Commit

Permalink
fix: fixing selection logic for radio group
Browse files Browse the repository at this point in the history
  • Loading branch information
jarrodek committed Aug 7, 2019
1 parent abcb788 commit 950edcc
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 17 deletions.
29 changes: 15 additions & 14 deletions anypoint-radio-group.js
Expand Up @@ -56,7 +56,7 @@ class AnypointRadioGroup extends HTMLElement {
connectedCallback() {
this.style.display = 'inline-block';
this.style.verticalAlign = 'middle';

this.setAttribute('role', 'radiogroup');
const config = {
attributes: true,
childList: true,
Expand All @@ -75,20 +75,21 @@ class AnypointRadioGroup extends HTMLElement {
/**
* Processes mutations to the light DOM of this element.
* Processes added and removed nodes and changes to attributes.
* @param {Array<MutationRecord>} changes List of changes discovered by
* @param {Array<MutationRecord>} mutationsList List of changes discovered by
* `MutationObserver`
*/
_nodesChanged(changes) {
const record = changes[0];
switch (record.type) {
case 'attributes':
this._processNodeAttributeChange(record);
break;
case 'childList':
this._processAddedNodes(record.addedNodes);
this._processRemovedNodes(record.removedNodes);
this._manageNodesSelection(record.addedNodes);
break;
_nodesChanged(mutationsList) {
for (const mutation of mutationsList) {
switch (mutation.type) {
case 'attributes':
this._processNodeAttributeChange(mutation);
break;
case 'childList':
this._processAddedNodes(mutation.addedNodes);
this._processRemovedNodes(mutation.removedNodes);
this._manageNodesSelection(mutation.addedNodes);
break;
}
}
}
/**
Expand Down Expand Up @@ -257,7 +258,7 @@ class AnypointRadioGroup extends HTMLElement {
const nodes = this.elements;
for (let i = 0, len = nodes.length; i < len; i++) {
const node = nodes[i];
if (node.name === name && node !== target && node.checked) {
if (node.name !== name && node !== target && node.checked) {
node.checked = false;
}
}
Expand Down
4 changes: 1 addition & 3 deletions test/anypoint-radio-button.test.js
@@ -1,9 +1,7 @@
import { fixture, assert, aTimeout } from '@open-wc/testing';
import sinon from 'sinon/pkg/sinon-esm.js';
import '../anypoint-radio-button.js';
import '@polymer/iron-test-helpers/mock-interactions.js';

/* global MockInteractions */
import * as MockInteractions from '@polymer/iron-test-helpers/mock-interactions.js';

describe('<anypoint-radio-button>', function() {
async function basicFixture() {
Expand Down
174 changes: 174 additions & 0 deletions test/anypoint-radio-group.test.js
@@ -0,0 +1,174 @@
import { fixture, assert, nextFrame } from '@open-wc/testing';
import '../anypoint-radio-button.js';
import '../anypoint-radio-group.js';
import * as MockInteractions from '@polymer/iron-test-helpers/mock-interactions.js';

describe('<anypoint-radio-group>', function() {
async function basicFixture() {
return (await fixture(`<anypoint-radio-group selectable="anypoint-radio-button">
<anypoint-radio-button name="a">Apple</anypoint-radio-button>
<anypoint-radio-button name="b">Banana</anypoint-radio-button>
<anypoint-radio-button name="c">Orange</anypoint-radio-button>
</anypoint-radio-group>`));
}

async function selectedFixture() {
return (await fixture(`<anypoint-radio-group selectable="anypoint-radio-button">
<anypoint-radio-button checked name="a">Apple</anypoint-radio-button>
<anypoint-radio-button name="b">Banana</anypoint-radio-button>
<anypoint-radio-button name="c">Orange</anypoint-radio-button>
</anypoint-radio-group>`));
}

async function ignoredFixture() {
return (await fixture(`<anypoint-radio-group selectable="anypoint-radio-button">
<anypoint-radio-button checked name="a">Apple</anypoint-radio-button>
<anypoint-radio-button name="b">Banana</anypoint-radio-button>
<anypoint-radio-button name="c">Orange</anypoint-radio-button>
<div name="d">Strawberry</div>
</anypoint-radio-group>`));
}

async function mixedFixture() {
return (await fixture(`<anypoint-radio-group selectable="anypoint-radio-button">
<anypoint-radio-button checked name="a">Apple</anypoint-radio-button>
<anypoint-radio-button name="b">Banana</anypoint-radio-button>
<anypoint-radio-button name="c">Orange</anypoint-radio-button>
<label><input type="radio" name="d"/>Strawberry</label>
</anypoint-radio-group>`));
}

describe('Selection states', () => {
it('sets selected property when selection changes', async () => {
const element = await basicFixture();
const node = element.querySelector('anypoint-radio-button');
MockInteractions.tap(node);
assert.equal(element.selected, node);
});

it('deselects old node', async () => {
const element = await selectedFixture();
const oldSelected = element.querySelector('anypoint-radio-button[name="a"]');
const node = element.querySelector('anypoint-radio-button[name="c"]');
MockInteractions.tap(node);
assert.isFalse(oldSelected.checked);
});

it('selects new node', async () => {
const element = await selectedFixture();
const node = element.querySelector('anypoint-radio-button[name="c"]');
MockInteractions.tap(node);
assert.isTrue(node.checked);
});

it('selected property changes after selection change', async () => {
const element = await selectedFixture();
const node = element.querySelector('anypoint-radio-button[name="c"]');
MockInteractions.tap(node);
assert.equal(element.selected, node);
});

it('accespts dynamic node', async () => {
const element = await selectedFixture();
const node = document.createElement('anypoint-radio-button');
node.name = 'd';
node.innerText = 'Dino';
element.appendChild(node);
await nextFrame();
MockInteractions.tap(node);
assert.equal(element.selected, node);
});

it('ignores nodes that are not role radio', async () => {
const element = await ignoredFixture();
const node = element.querySelector('div[name="d"]');
MockInteractions.tap(node);
assert.isUndefined(element.selected);
});

it('ignores removed nodes', async () => {
const element = await basicFixture();
const node = element.querySelector('anypoint-radio-button[name="a"]');
element.removeChild(node);
await nextFrame();
MockInteractions.tap(node);
assert.isUndefined(element.selected);
});

it('ignores nodes with changed role', async () => {
const element = await basicFixture();
const node = element.querySelector('anypoint-radio-button[name="a"]');
node.setAttribute('role', 'input');
await nextFrame();
MockInteractions.tap(node);
assert.isUndefined(element.selected);
});

it('removes selection when removing selected node', async () => {
const element = await selectedFixture();
const node = element.querySelector('anypoint-radio-button[name="a"]');
element.removeChild(node);
await nextFrame();
assert.isUndefined(element.selected);
});

it('accepts input radio', async () => {
const element = await mixedFixture();
const node = element.querySelector('input[name="d"]');
MockInteractions.tap(node);
assert.equal(element.selected, node);
});
});

describe('_isRadioButton()', () => {
let element;
beforeEach(async () => {
element = await basicFixture();
});

it('return true when has radio role', () => {
const node = document.createElement('span');
node.setAttribute('role', 'radio');
const result = element._isRadioButton(node);
assert.isTrue(result);
});

it('return true for radio input', () => {
const node = document.createElement('input');
node.type = 'radio';
const result = element._isRadioButton(node);
assert.isTrue(result);
});

it('resturns false for other roles', () => {
const node = document.createElement('span');
node.setAttribute('role', 'display');
const result = element._isRadioButton(node);
assert.isFalse(result);
});

it('resturns false for other inputs', () => {
const node = document.createElement('input');
node.type = 'checkbox';
const result = element._isRadioButton(node);
assert.isFalse(result);
});
});

describe('a11y', () => {
it('has role', async () => {
const element = await basicFixture();
assert.equal(element.getAttribute('role'), 'radiogroup');
});

it('is accessible when no selection', async () => {
const element = await basicFixture();
await assert.isAccessible(element);
});

it('is accessible when selected', async () => {
const element = await selectedFixture();
await assert.isAccessible(element);
});
});
});

0 comments on commit 950edcc

Please sign in to comment.