Skip to content

Commit 8242405

Browse files
authored
Added an enableBackLinks directive, which enables a user to leave an entered completion step (#13)
- added tests for the enableBackkLinks directive
1 parent aa50940 commit 8242405

File tree

6 files changed

+227
-6
lines changed

6 files changed

+227
-6
lines changed

src/components/components/wizard-completion-step.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ export class WizardCompletionStepComponent extends WizardStep {
145145
* @inheritDoc
146146
*/
147147
exit(direction: MovingDirection): void {
148-
// do nothing
148+
this.wizard.completed = false;
149+
this.stepExit.emit(direction);
149150
}
150151
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/**
2+
* Created by marc on 30.06.17.
3+
*/
4+
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
5+
import {ViewChild, Component} from '@angular/core';
6+
import {WizardComponent} from '../components/wizard.component';
7+
import {MovingDirection} from '../util/moving-direction.enum';
8+
import {By} from '@angular/platform-browser';
9+
import {WizardModule} from '../wizard.module';
10+
11+
@Component({
12+
selector: 'test-wizard',
13+
template: `
14+
<wizard>
15+
<wizard-step title='Steptitle 1' (stepEnter)="enterInto($event, 1)" (stepExit)="exitFrom($event, 1)">
16+
Step 1
17+
</wizard-step>
18+
<wizard-step title='Steptitle 2' [canExit]="isValid"
19+
optionalStep (stepEnter)="enterInto($event, 2)" (stepExit)="exitFrom($event, 2)">
20+
Step 2
21+
</wizard-step>
22+
<wizard-completion-step enableBackLinks title='Completion steptitle 3' (stepEnter)="enterInto($event, 3)"
23+
(stepExit)="completionStepExit($event, 3)">
24+
Step 3
25+
</wizard-completion-step>
26+
</wizard>
27+
`
28+
})
29+
class WizardTestComponent {
30+
@ViewChild(WizardComponent)
31+
public wizard: WizardComponent;
32+
33+
public isValid: any = true;
34+
35+
public eventLog: Array<string> = new Array<string>();
36+
37+
public completionStepExit: (direction: MovingDirection, source: number) => void = this.exitFrom;
38+
39+
enterInto(direction: MovingDirection, destination: number): void {
40+
this.eventLog.push(`enter ${MovingDirection[direction]} ${destination}`);
41+
}
42+
43+
exitFrom(direction: MovingDirection, source: number): void {
44+
this.eventLog.push(`exit ${MovingDirection[direction]} ${source}`);
45+
}
46+
}
47+
48+
describe('EnableBackLinksDirective', () => {
49+
let wizardTest: WizardTestComponent;
50+
let wizardTestFixture: ComponentFixture<WizardTestComponent>;
51+
52+
beforeEach(async(() => {
53+
TestBed.configureTestingModule({
54+
declarations: [WizardTestComponent],
55+
imports: [WizardModule]
56+
}).compileComponents();
57+
}));
58+
59+
beforeEach(() => {
60+
wizardTestFixture = TestBed.createComponent(WizardTestComponent);
61+
wizardTest = wizardTestFixture.componentInstance;
62+
wizardTestFixture.detectChanges();
63+
});
64+
65+
it('should create', () => {
66+
expect(wizardTest).toBeTruthy();
67+
expect(wizardTestFixture.debugElement.queryAll(By.css('wizard-step')).length).toBe(2);
68+
expect(wizardTestFixture.debugElement.queryAll(By.css('wizard-completion-step')).length).toBe(1);
69+
});
70+
71+
it('should have correct step title', () => {
72+
expect(wizardTest).toBeTruthy();
73+
expect(wizardTest.wizard.getStepAtIndex(0).title).toBe('Steptitle 1');
74+
expect(wizardTest.wizard.getStepAtIndex(1).title).toBe('Steptitle 2');
75+
expect(wizardTest.wizard.getStepAtIndex(2).title).toBe('Completion steptitle 3');
76+
});
77+
78+
it('should enter first step after initialisation', () => {
79+
expect(wizardTest.eventLog).toEqual(['enter Forwards 1']);
80+
});
81+
82+
it('should enter completion step after first step', () => {
83+
expect(wizardTest.wizard.currentStepIndex).toBe(0);
84+
85+
wizardTest.wizard.goToNextStep();
86+
wizardTestFixture.detectChanges();
87+
88+
expect(wizardTest.wizard.currentStepIndex).toBe(1);
89+
expect(wizardTest.eventLog).toEqual(['enter Forwards 1', 'exit Forwards 1', 'enter Forwards 2']);
90+
91+
wizardTest.wizard.goToNextStep();
92+
wizardTestFixture.detectChanges();
93+
94+
expect(wizardTest.wizard.currentStepIndex).toBe(2);
95+
expect(wizardTest.eventLog).toEqual(['enter Forwards 1', 'exit Forwards 1', 'enter Forwards 2',
96+
'exit Forwards 2', 'enter Forwards 3']);
97+
});
98+
99+
it('should enter completion step after jumping over second optional step', () => {
100+
wizardTest.wizard.goToStep(2);
101+
wizardTestFixture.detectChanges();
102+
103+
expect(wizardTest.wizard.completed).toBe(true);
104+
expect(wizardTest.eventLog).toEqual(['enter Forwards 1', 'exit Forwards 1', 'enter Forwards 3']);
105+
});
106+
107+
it('should be able to leave the completion step', () => {
108+
wizardTest.wizard.goToStep(2);
109+
wizardTestFixture.detectChanges();
110+
111+
expect(wizardTest.wizard.canGoToStep(0)).toBe(true);
112+
expect(wizardTest.wizard.canGoToStep(1)).toBe(true);
113+
});
114+
115+
116+
it('should be able to leave the completion step in any direction', () => {
117+
wizardTest.isValid = false;
118+
119+
wizardTest.wizard.goToStep(2);
120+
wizardTestFixture.detectChanges();
121+
122+
expect(wizardTest.wizard.currentStepIndex).toBe(2);
123+
expect(wizardTest.wizard.currentStep.canExit).toBe(true);
124+
});
125+
126+
it('should leave the completion step', () => {
127+
wizardTest.isValid = false;
128+
129+
wizardTest.wizard.goToStep(2);
130+
wizardTestFixture.detectChanges();
131+
132+
expect(wizardTest.wizard.currentStepIndex).toBe(2);
133+
134+
wizardTest.wizard.goToPreviousStep();
135+
wizardTestFixture.detectChanges();
136+
137+
expect(wizardTest.wizard.currentStepIndex).toBe(1);
138+
expect(wizardTest.eventLog)
139+
.toEqual(['enter Forwards 1', 'exit Forwards 1', 'enter Forwards 3', 'exit Backwards 3', 'enter Backwards 2']);
140+
});
141+
142+
it('should work with changed stepExit value', () => {
143+
wizardTest.isValid = false;
144+
wizardTest.completionStepExit = (direction: MovingDirection, source: number) => {
145+
wizardTest.eventLog.push(`changed exit ${MovingDirection[direction]} ${source}`);
146+
};
147+
148+
expect(wizardTest.wizard.completed).toBe(false);
149+
150+
wizardTest.wizard.goToStep(2);
151+
wizardTestFixture.detectChanges();
152+
153+
expect(wizardTest.wizard.currentStepIndex).toBe(2);
154+
expect(wizardTest.wizard.completed).toBe(true);
155+
156+
wizardTest.wizard.goToPreviousStep();
157+
wizardTestFixture.detectChanges();
158+
159+
expect(wizardTest.wizard.currentStepIndex).toBe(1);
160+
expect(wizardTest.eventLog)
161+
.toEqual(['enter Forwards 1', 'exit Forwards 1', 'enter Forwards 3', 'changed exit Backwards 3', 'enter Backwards 2']);
162+
expect(wizardTest.wizard.completed).toBe(false);
163+
});
164+
});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import {Directive, EventEmitter, Host, OnInit, Output} from '@angular/core';
2+
import {WizardCompletionStepComponent} from '../components/wizard-completion-step.component';
3+
import {MovingDirection} from '../util/moving-direction.enum';
4+
5+
/**
6+
* The `enableBackLinks` directive can be used to allow the user to leave a [[WizardCompletionStepComponent]] after is has been entered.
7+
*
8+
* ### Syntax
9+
*
10+
* ```html
11+
* <wizard-completion-step enableBackLinks (stepExit)="exit function">
12+
* ...
13+
* </wizard-completion-step>
14+
* ```
15+
*
16+
* ### Example
17+
*
18+
* ```html
19+
* <wizard-completion-step title="Final step" enableBackLinks>
20+
* ...
21+
* </wizard-completion-step>
22+
* ```
23+
*
24+
* @author Marc Arndt
25+
*/
26+
@Directive({
27+
selector: 'wizard-completion-step[enableBackLinks]'
28+
})
29+
export class EnableBackLinksDirective implements OnInit {
30+
/**
31+
* This EventEmitter is called when the step is exited.
32+
* The bound method can be used to do cleanup work.
33+
*
34+
* @type {EventEmitter<MovingDirection>}
35+
*/
36+
@Output()
37+
public stepExit = new EventEmitter<MovingDirection>();
38+
39+
/**
40+
* Constructor
41+
*
42+
* @param completionStep The wizard completion step, which should be exitable
43+
*/
44+
constructor(@Host() private completionStep: WizardCompletionStepComponent) { }
45+
46+
/**
47+
* Initialization work
48+
*/
49+
ngOnInit(): void {
50+
this.completionStep.canExit = true;
51+
this.completionStep.stepExit = this.stepExit;
52+
}
53+
}

src/components/directives/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ export {NextStepDirective} from './next-step.directive';
77
export {PreviousStepDirective} from './previous-step.directive';
88
export {OptionalStepDirective} from './optional-step.directive';
99
export {WizardStepTitleDirective} from './wizard-step-title.directive';
10+
export {EnableBackLinksDirective} from './enable-back-links.directive';
1011

src/components/directives/optional-step.directive.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ import {WizardStep} from '../util/wizard-step.interface';
33

44
/**
55
* The `optionalStep` directive can be used to define an optional `wizard-step`.
6-
* An optional `wizard-step` is a [[WizardStepComponent]] that doesn't need to be completed to transition to later wizard steps.
7-
* It's important to note, that this directive can only be used on a [[WizardStepComponent]] and not a [[WizardCompletionStepComponent]]
6+
* An optional `wizard-step` is a [[WizardStep]] that doesn't need to be completed to transition to later wizard steps.
87
*
98
* ### Syntax
109
*
@@ -31,7 +30,7 @@ export class OptionalStepDirective implements OnInit {
3130
/**
3231
* Constructor
3332
*
34-
* @param wizardStep The wizard, which contains this [[OptionalStepDirective]]
33+
* @param wizardStep The wizard step, which contains this [[OptionalStepDirective]]
3534
*/
3635
constructor(@Host() private wizardStep: WizardStep) { }
3736

src/components/wizard.module.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {PreviousStepDirective} from './directives/previous-step.directive';
1111
import {OptionalStepDirective} from './directives/optional-step.directive';
1212
import {GoToStepDirective} from './directives/go-to-step.directive';
1313
import {WizardStepTitleDirective} from './directives/wizard-step-title.directive';
14+
import {EnableBackLinksDirective} from './directives/enable-back-links.directive';
1415

1516
/**
1617
* The module defining all the content inside `ng2-archwizard`
@@ -27,7 +28,8 @@ import {WizardStepTitleDirective} from './directives/wizard-step-title.directive
2728
NextStepDirective,
2829
PreviousStepDirective,
2930
OptionalStepDirective,
30-
WizardStepTitleDirective
31+
WizardStepTitleDirective,
32+
EnableBackLinksDirective
3133
],
3234
imports: [
3335
CommonModule
@@ -41,7 +43,8 @@ import {WizardStepTitleDirective} from './directives/wizard-step-title.directive
4143
NextStepDirective,
4244
PreviousStepDirective,
4345
OptionalStepDirective,
44-
WizardStepTitleDirective
46+
WizardStepTitleDirective,
47+
EnableBackLinksDirective
4548
]
4649
})
4750
export class WizardModule {

0 commit comments

Comments
 (0)