Skip to content

Commit

Permalink
Properly invalidate if required attribute/property changes
Browse files Browse the repository at this point in the history
  • Loading branch information
KaneFreeman committed Sep 30, 2019
1 parent 99ac08c commit 15b22a7
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 10 deletions.
5 changes: 3 additions & 2 deletions src/core/meta/InputValidity.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import Base from './Base';

export class InputValidity extends Base {
get(key: string | number, value: string) {
get(key: string | number, value: string, required: boolean) {
const node = this.getNode(key) as HTMLFormElement | undefined;

if (!node) {
return { valid: undefined, message: '' };
}

if (value !== node.value) {
const nodeRequired = node.attributes.getNamedItem('required');
if (value !== node.value && required !== Boolean(nodeRequired && nodeRequired.value)) {
// if the vdom is out of sync with the real dom our
// validation check will be one render behind.
// Call invalidate on the next loop.
Expand Down
5 changes: 3 additions & 2 deletions src/core/middleware/validity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ const factory = create({ node, invalidator });

const validity = factory(function({ middleware: { node, invalidator } }) {
return {
get(key: string | number, value: string) {
get(key: string | number, value: string, required: boolean) {
const domNode = node.get(key) as HTMLFormElement | undefined;

if (!domNode) {
return { valid: undefined, message: '' };
}

if (value !== domNode.value) {
const nodeRequired = domNode.attributes.getNamedItem('required');
if (value !== domNode.value && required !== Boolean(nodeRequired && nodeRequired.value)) {
setTimeout(() => invalidator());
}

Expand Down
42 changes: 39 additions & 3 deletions tests/core/unit/meta/InputValidity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,17 @@ registerSuite('meta - InputValidity', {
bind: bindInstance
});

const { message, valid } = validity.get('test', 'testValue');
const { message, valid } = validity.get('test', 'testValue', true);
assert.strictEqual(message, '');
assert.isUndefined(valid);
},

'returns the validity and message for the element'() {
sandbox.stub(nodeHandler, 'get').returns({
validity: { valid: false },
attributes: {
getNamedItem: () => true
},
value: 'testValue',
validationMessage: 'test validation message'
});
Expand All @@ -51,7 +54,7 @@ registerSuite('meta - InputValidity', {
bind: bindInstance
});

const { message, valid } = validity.get('test', 'testValue');
const { message, valid } = validity.get('test', 'testValue', true);
assert.strictEqual(message, 'test validation message');
assert.isFalse(valid);
},
Expand All @@ -63,6 +66,9 @@ registerSuite('meta - InputValidity', {
.withArgs('input')
.returns({
validity: { valid: true },
attributes: {
getNamedItem: () => true
},
value: 'test1',
validationMessage: ''
});
Expand All @@ -73,7 +79,37 @@ registerSuite('meta - InputValidity', {
bind: bindInstance
});

validity.get('input', 'test2');
validity.get('input', 'test2', true);
return new Promise((resolve) => {
setTimeout(() => {
assert.isTrue(invalidateStub.calledOnce);
nodeStub.reset();
resolve();
}, 10);
});
},

async 'calls invalidate if the required value and node required attribute do not match'() {
const nodeHandler = new NodeHandler();
const nodeStub = sandbox
.stub(nodeHandler, 'get')
.withArgs('input')
.returns({
validity: { valid: true },
attributes: {
getNamedItem: () => false
},
value: 'test1',
validationMessage: ''
});

const validity = new InputValidity({
invalidate: invalidateStub,
nodeHandler,
bind: bindInstance
});

validity.get('input', 'test2', true);
return new Promise((resolve) => {
setTimeout(() => {
assert.isTrue(invalidateStub.calledOnce);
Expand Down
42 changes: 39 additions & 3 deletions tests/core/unit/middleware/validity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('validity middleware', () => {
properties: () => ({}),
children: () => []
});
const result = validity.get('root', 'testValue');
const result = validity.get('root', 'testValue', true);
assert.deepEqual(result, { valid: undefined, message: '' });
});

Expand All @@ -43,11 +43,14 @@ describe('validity middleware', () => {
});
const domNode = {
validity: { valid: false },
attributes: {
getNamedItem: () => true
},
value: 'testValue',
validationMessage: 'test validation message'
};
nodeStub.get.withArgs('root').returns(domNode);
const result = validity.get('root', 'testValue');
const result = validity.get('root', 'testValue', true);
assert.deepEqual(result, { valid: false, message: 'test validation message' });
assert.isTrue(invalidatorStub.notCalled);
});
Expand All @@ -65,11 +68,44 @@ describe('validity middleware', () => {
});
const domNode = {
validity: { valid: false },
attributes: {
getNamedItem: () => true
},
value: 'otherValue',
validationMessage: 'test validation message'
};
nodeStub.get.withArgs('root').returns(domNode);
const result = validity.get('root', 'testValue', true);
assert.deepEqual(result, { valid: false, message: 'test validation message' });
return new Promise((resolve) => {
setTimeout(() => {
assert.isTrue(invalidatorStub.calledOnce);
resolve();
}, 10);
});
});

it('should invalidate if the required value and domNode required attribute do not match', () => {
const { callback } = validityMiddleware();
const validity = callback({
id: 'test',
middleware: {
node: nodeStub,
invalidator: invalidatorStub
},
properties: () => ({}),
children: () => []
});
const domNode = {
validity: { valid: false },
attributes: {
getNamedItem: () => false
},
value: 'otherValue',
validationMessage: 'test validation message'
};
nodeStub.get.withArgs('root').returns(domNode);
const result = validity.get('root', 'testValue');
const result = validity.get('root', 'testValue', true);
assert.deepEqual(result, { valid: false, message: 'test validation message' });
return new Promise((resolve) => {
setTimeout(() => {
Expand Down

0 comments on commit 15b22a7

Please sign in to comment.