From e37654816f70ab279dd12e268841838e9cf88db9 Mon Sep 17 00:00:00 2001 From: StrahilKazlachev Date: Sat, 2 Jun 2018 00:15:31 +0300 Subject: [PATCH 1/2] fix(attach-focus): restore behavior prior to #346 make it work as boolean attribute set the default binding mode to oneTime update tests --- src/attach-focus.ts | 12 ++--- test/unit/attach-focus.spec.ts | 91 +++++++++++++++++++++++----------- 2 files changed, 64 insertions(+), 39 deletions(-) diff --git a/src/attach-focus.ts b/src/attach-focus.ts index 37f5309..3d562c6 100644 --- a/src/attach-focus.ts +++ b/src/attach-focus.ts @@ -1,7 +1,8 @@ +import { bindingMode } from 'aurelia-binding'; import { customAttribute, ComponentAttached } from 'aurelia-templating'; import { DOM } from 'aurelia-pal'; -@customAttribute('attach-focus') +@customAttribute('attach-focus', bindingMode.oneTime) export class AttachFocus implements ComponentAttached { public value: boolean | string; @@ -15,14 +16,7 @@ export class AttachFocus implements ComponentAttached { } public attached(): void { - if (this.value && this.value !== 'false') { - this.element.focus(); - } - } - - public valueChanged(newValue: string) { - this.value = newValue; - if (this.value && this.value !== 'false') { + if (this.value === '' || (this.value && this.value !== 'false')) { this.element.focus(); } } diff --git a/test/unit/attach-focus.spec.ts b/test/unit/attach-focus.spec.ts index 50684a1..e82831a 100644 --- a/test/unit/attach-focus.spec.ts +++ b/test/unit/attach-focus.spec.ts @@ -1,13 +1,25 @@ -import { StageComponent } from 'aurelia-testing'; import { bootstrap } from 'aurelia-bootstrapper'; +import { Container } from 'aurelia-dependency-injection'; import { Aurelia } from 'aurelia-framework'; +import { TaskQueue } from 'aurelia-task-queue'; +import { StageComponent, ComponentTester } from 'aurelia-testing'; -describe('modal gets focused when attached', () => { - let component: any; - let viewModel: any; - +describe('attach-focus', () => { class ViewModel { public first: any; + public focusTargetElement: Element; + public hasFocus: boolean; + } + + let component: ComponentTester; + let viewModel: ViewModel; + + function setupView(component: ComponentTester, attachFocusFragment: string): void { + component.inView(` +
+ +
+ `); } beforeEach(() => { @@ -18,50 +30,69 @@ describe('modal gets focused when attached', () => { component.bootstrap((aurelia: Aurelia) => aurelia.use.basicConfiguration()); }); - describe('when using attribute without .bind', () => { - beforeEach(() => { - component.inView(` -
- -
- `); + describe('without binding command', () => { + describe('sets focus', () => { + it('without value', done => { + setupView(component, 'attach-focus'); + component.create(bootstrap).then(() => { + expect(document.activeElement).toBe(viewModel.focusTargetElement); + done(); + }, done.fail); + }); + + it('when the value is "true"', done => { + setupView(component, 'attach-focus="true"'); + component.create(bootstrap).then(() => { + expect(document.activeElement).toBe(viewModel.focusTargetElement); + done(); + }, done.fail); + }); }); - it('sets focus to no value element', done => { + it('does not set focus when the value is "false"', done => { + setupView(component, 'attach-focus="false"'); component.create(bootstrap).then(() => { - expect(document.activeElement).toBe(viewModel.noValueEl); + expect(document.activeElement).not.toBe(viewModel.focusTargetElement); done(); - }); + }, done.fail); }); }); - describe('when binding to vm property', () => { + describe('with binding command', () => { beforeEach(() => { - component.inView(` -
- - -
- `); + setupView(component, 'attach-focus.bind="hasFocus"'); }); - it('sets focus to first element when true', done => { - viewModel.first = true; + it('sets focus when the value is "true"', done => { + viewModel.hasFocus = true; component.create(bootstrap).then(() => { - expect(document.activeElement).toBe(viewModel.firstEl); + expect(document.activeElement).toBe(viewModel.focusTargetElement); done(); - }); + }, done.fail); }); - it('sets focus to second element when false', done => { - viewModel.first = false; + it('does not set focus when the value is "false"', done => { + viewModel.hasFocus = false; component.create(bootstrap).then(() => { - expect(document.activeElement).toBe(viewModel.secondEl); + expect(document.activeElement).not.toBe(viewModel.focusTargetElement); done(); - }); + }, done.fail); }); }); + it('sets focus only in ".attached"', done => { + setupView(component, 'attach-focus.to-view="hasFocus"'); + viewModel.hasFocus = false; + component.create(bootstrap).then(() => { + expect(document.activeElement).not.toBe(viewModel.focusTargetElement); + viewModel.hasFocus = true; + (Container.instance.get(TaskQueue) as TaskQueue).queueMicroTask(() => { + expect(document.activeElement).not.toBe(viewModel.focusTargetElement); + done(); + }); + }, done.fail); + }); + afterEach(() => { component.dispose(); }); From 702c62ba9dd37e671c83dc36c1ed5b0adf7b8d17 Mon Sep 17 00:00:00 2001 From: StrahilKazlachev Date: Sat, 2 Jun 2018 13:49:55 +0300 Subject: [PATCH 2/2] refactor(attach-focus.spec): use flushMicroTaskQueue --- test/unit/attach-focus.spec.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/unit/attach-focus.spec.ts b/test/unit/attach-focus.spec.ts index e82831a..5151847 100644 --- a/test/unit/attach-focus.spec.ts +++ b/test/unit/attach-focus.spec.ts @@ -86,10 +86,9 @@ describe('attach-focus', () => { component.create(bootstrap).then(() => { expect(document.activeElement).not.toBe(viewModel.focusTargetElement); viewModel.hasFocus = true; - (Container.instance.get(TaskQueue) as TaskQueue).queueMicroTask(() => { - expect(document.activeElement).not.toBe(viewModel.focusTargetElement); - done(); - }); + (Container.instance.get(TaskQueue) as TaskQueue).flushMicroTaskQueue(); + expect(document.activeElement).not.toBe(viewModel.focusTargetElement); + done(); }, done.fail); });