Merge pull request #67 from maxevilmind/feat/steps-getter-method
[steps] Allow extensions to introduce new non-default slots
This commit is contained in:
commit
f4bbc713fb
4 changed files with 169 additions and 139 deletions
|
|
@ -97,9 +97,8 @@ export class LionStep extends LionLitElement {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
firstUpdated() {
|
||||||
// eslint-disable-next-line wc/guard-super-call
|
super.firstUpdated();
|
||||||
super.connectedCallback();
|
|
||||||
this.controller = this.parentNode;
|
this.controller = this.parentNode;
|
||||||
if (this.initialStep === true) {
|
if (this.initialStep === true) {
|
||||||
this.enter(true);
|
this.enter(true);
|
||||||
|
|
@ -107,9 +106,9 @@ export class LionStep extends LionLitElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
getControllerIndex() {
|
getControllerIndex() {
|
||||||
const controllerChildren = this.controller.children;
|
const { steps } = this.controller;
|
||||||
for (let i = 0; i < controllerChildren.length; i += 1) {
|
for (let i = 0; i < steps.length; i += 1) {
|
||||||
if (controllerChildren[i] === this) {
|
if (steps[i] === this) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ export class LionSteps extends ObserverMixin(LionLitElement) {
|
||||||
|
|
||||||
firstUpdated() {
|
firstUpdated() {
|
||||||
super.firstUpdated();
|
super.firstUpdated();
|
||||||
this._max = this.children.length - 1;
|
this._max = this.steps.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
next() {
|
next() {
|
||||||
|
|
@ -74,12 +74,17 @@ export class LionSteps extends ObserverMixin(LionLitElement) {
|
||||||
this._goTo(this.current - 1, this.current);
|
this._goTo(this.current - 1, this.current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get steps() {
|
||||||
|
const defaultSlot = this.shadowRoot.querySelector('slot:not([name])');
|
||||||
|
return defaultSlot.assignedNodes().filter(node => node.nodeType === Node.ELEMENT_NODE);
|
||||||
|
}
|
||||||
|
|
||||||
_goTo(newCurrent, oldCurrent) {
|
_goTo(newCurrent, oldCurrent) {
|
||||||
if (newCurrent < 0 || newCurrent > this._max) {
|
if (newCurrent < 0 || newCurrent > this._max) {
|
||||||
throw new Error(`There is no step at index ${newCurrent}.`);
|
throw new Error(`There is no step at index ${newCurrent}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextStep = this.children[newCurrent];
|
const nextStep = this.steps[newCurrent];
|
||||||
const back = newCurrent < oldCurrent;
|
const back = newCurrent < oldCurrent;
|
||||||
|
|
||||||
if (nextStep.passesCondition(this.data)) {
|
if (nextStep.passesCondition(this.data)) {
|
||||||
|
|
@ -99,8 +104,8 @@ export class LionSteps extends ObserverMixin(LionLitElement) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_changeStep(newCurrent, oldCurrent) {
|
_changeStep(newCurrent, oldCurrent) {
|
||||||
const oldStepElement = this.children[oldCurrent];
|
const oldStepElement = this.steps[oldCurrent];
|
||||||
const newStepElement = this.children[newCurrent];
|
const newStepElement = this.steps[newCurrent];
|
||||||
const fromStep = { number: oldCurrent, element: oldStepElement };
|
const fromStep = { number: oldCurrent, element: oldStepElement };
|
||||||
const toStep = { number: newCurrent, element: newStepElement };
|
const toStep = { number: newCurrent, element: newStepElement };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,90 +1,114 @@
|
||||||
import { expect, fixture, oneEvent } from '@open-wc/testing';
|
import { expect, fixture, fixtureSync, html, oneEvent } from '@open-wc/testing';
|
||||||
|
|
||||||
import '../lion-steps.js';
|
|
||||||
import '../lion-step.js';
|
import '../lion-step.js';
|
||||||
|
|
||||||
describe('lion-step', () => {
|
describe('lion-step', () => {
|
||||||
it('has a condition which allows it to become active (condition is true by default)', async () => {
|
it('has a condition which allows it to become active (condition is true by default)', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<fake-lion-steps><lion-step>Step 1</lion-step></fake-lion-steps>
|
<fake-lion-steps>
|
||||||
|
<lion-step>Step 1</lion-step>
|
||||||
|
</fake-lion-steps>
|
||||||
`);
|
`);
|
||||||
expect(steps.children[0].condition()).to.equal(true);
|
expect(el.children[0].condition()).to.equal(true);
|
||||||
expect(steps.children[0].passesCondition()).to.equal(true);
|
expect(el.children[0].passesCondition()).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not invert condition by default', async () => {
|
it('does not invert condition by default', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<fake-lion-steps><lion-step>Step 1</lion-step></fake-lion-steps>
|
<fake-lion-steps>
|
||||||
|
<lion-step>Step 1</lion-step>
|
||||||
|
</fake-lion-steps>
|
||||||
`);
|
`);
|
||||||
expect(steps.children[0].invertCondition).to.equal(false);
|
expect(el.children[0].invertCondition).to.equal(false);
|
||||||
expect(steps.children[0].passesCondition()).to.equal(true);
|
expect(el.children[0].passesCondition()).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can invert its condition', async () => {
|
it('can invert its condition', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<fake-lion-steps><lion-step>Step 1</lion-step></fake-lion-steps>
|
<fake-lion-steps>
|
||||||
|
<lion-step>Step 1</lion-step>
|
||||||
|
</fake-lion-steps>
|
||||||
`);
|
`);
|
||||||
steps.children[0].condition = () => true;
|
el.children[0].condition = () => true;
|
||||||
steps.children[0].invertCondition = true;
|
el.children[0].invertCondition = true;
|
||||||
expect(steps.children[0].condition()).to.equal(true);
|
expect(el.children[0].condition()).to.equal(true);
|
||||||
expect(steps.children[0].passesCondition()).to.equal(false);
|
expect(el.children[0].passesCondition()).to.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows to define it as the initial-step', async () => {
|
it('allows to define it as the initial-step', async () => {
|
||||||
const withInitial = await fixture(`
|
const el = fixtureSync(html`
|
||||||
<fake-lion-steps><lion-step initial-step>Step 1</lion-step></fake-lion-steps>
|
<fake-lion-steps>
|
||||||
|
<lion-step initial-step>Step 1</lion-step>
|
||||||
|
</fake-lion-steps>
|
||||||
`);
|
`);
|
||||||
expect(withInitial.current).to.equal(0);
|
el.steps = [el.children[0]];
|
||||||
expect(withInitial.children[0].status).to.equal('entered');
|
await el.updateComplete;
|
||||||
|
expect(el.current).to.equal(0);
|
||||||
|
expect(el.children[0].status).to.equal('entered');
|
||||||
|
|
||||||
const withSecondInitial = await fixture(`<fake-lion-steps
|
const el2 = fixtureSync(html`
|
||||||
><lion-step>Step 1</lion-step><lion-step initial-step>Step 2</lion-step></fake-lion-steps>
|
<fake-lion-steps>
|
||||||
`);
|
<lion-step>Step 1</lion-step>
|
||||||
expect(withSecondInitial.current).to.equal(1);
|
<lion-step initial-step>Step 2</lion-step>
|
||||||
expect(withSecondInitial.children[0].status).to.equal('untouched');
|
</fake-lion-steps>
|
||||||
expect(withSecondInitial.children[1].status).to.equal('entered');
|
`);
|
||||||
|
el2.steps = [el2.children[0], el2.children[1]];
|
||||||
|
await el2.updateComplete;
|
||||||
|
expect(el2.current).to.equal(1);
|
||||||
|
expect(el2.children[0].status).to.equal('untouched');
|
||||||
|
expect(el2.children[1].status).to.equal('entered');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('has "untouched" status by default', async () => {
|
it('has "untouched" status by default', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<fake-lion-steps><lion-step>Step 1</lion-step></fake-lion-steps>
|
<fake-lion-steps>
|
||||||
|
<lion-step>Step 1</lion-step>
|
||||||
|
</fake-lion-steps>
|
||||||
`);
|
`);
|
||||||
expect(steps.children[0].status).to.equal('untouched');
|
expect(el.children[0].status).to.equal('untouched');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('communicates with a parent steps controller to handles actions', async () => {
|
it('communicates with a parent steps controller to handles actions', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<fake-lion-steps><lion-step>Step 1</lion-step></fake-lion-steps>
|
<fake-lion-steps>
|
||||||
|
<lion-step>Step 1</lion-step>
|
||||||
|
</fake-lion-steps>
|
||||||
`);
|
`);
|
||||||
expect(steps.children[0].controller).to.equal(steps);
|
expect(el.children[0].controller).to.equal(el);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('navigation', () => {
|
describe('navigation', () => {
|
||||||
it('can be entered', async () => {
|
it('can be entered', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<fake-lion-steps><lion-step>Step 1</lion-step></fake-lion-steps>
|
<fake-lion-steps>
|
||||||
|
<lion-step>Step 1</lion-step>
|
||||||
|
</fake-lion-steps>
|
||||||
`);
|
`);
|
||||||
setTimeout(() => steps.children[0].enter(), 0);
|
setTimeout(() => el.children[0].enter(), 0);
|
||||||
await oneEvent(steps.children[0], 'enter');
|
await oneEvent(el.children[0], 'enter');
|
||||||
expect(steps.children[0].status).to.equal('entered');
|
expect(el.children[0].status).to.equal('entered');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can be left', async () => {
|
it('can be left', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<fake-lion-steps><lion-step>Step 1</lion-step></fake-lion-steps>
|
<fake-lion-steps>
|
||||||
|
<lion-step>Step 1</lion-step>
|
||||||
|
</fake-lion-steps>
|
||||||
`);
|
`);
|
||||||
setTimeout(() => steps.children[0].leave(), 0);
|
setTimeout(() => el.children[0].leave(), 0);
|
||||||
await oneEvent(steps.children[0], 'leave');
|
await oneEvent(el.children[0], 'leave');
|
||||||
expect(steps.children[0].status).to.equal('left');
|
expect(el.children[0].status).to.equal('left');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can be skipped', async () => {
|
it('can be skipped', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<fake-lion-steps><lion-step>Step 1</lion-step></fake-lion-steps>
|
<fake-lion-steps>
|
||||||
|
<lion-step>Step 1</lion-step>
|
||||||
|
</fake-lion-steps>
|
||||||
`);
|
`);
|
||||||
setTimeout(() => steps.children[0].skip(), 0);
|
setTimeout(() => el.children[0].skip(), 0);
|
||||||
await oneEvent(steps.children[0], 'skip');
|
await oneEvent(el.children[0], 'skip');
|
||||||
expect(steps.children[0].status).to.equal('skipped');
|
expect(el.children[0].status).to.equal('skipped');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -27,91 +27,101 @@ async function checkWorkflow(steps, expected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('lion-steps', () => {
|
describe('lion-steps', () => {
|
||||||
|
it('has "steps" getter that returns default slot elements', async () => {
|
||||||
|
const el = await fixture(html`
|
||||||
|
<lion-steps>
|
||||||
|
<lion-step>Step 1</lion-step>
|
||||||
|
<lion-step initial-step>Step 2</lion-step>
|
||||||
|
<other-step-element>Step 3</other-step-element>
|
||||||
|
<steps-extension-element slot="new-slot">e.g. steps indicator</steps-extension-element>
|
||||||
|
</lion-steps>
|
||||||
|
`);
|
||||||
|
expect(el.steps.length).to.equal(3);
|
||||||
|
expect(el.steps[0].tagName).to.equal('LION-STEP');
|
||||||
|
expect(el.steps[1].tagName).to.equal('LION-STEP');
|
||||||
|
expect(el.steps[2].tagName).to.equal('OTHER-STEP-ELEMENT');
|
||||||
|
});
|
||||||
|
|
||||||
describe('initialization', () => {
|
describe('initialization', () => {
|
||||||
it('activates step with an "initial-step" attribute', async () => {
|
it('activates step with an "initial-step" attribute', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<lion-steps>
|
<lion-steps>
|
||||||
<lion-step initial-step>Step 0</lion-step>
|
<lion-step initial-step>Step 0</lion-step>
|
||||||
<lion-step>Step 1</lion-step>
|
<lion-step>Step 1</lion-step>
|
||||||
</lion-steps>
|
</lion-steps>
|
||||||
`);
|
`);
|
||||||
const firstStep = steps.children[0];
|
expect(el.current).to.equal(0);
|
||||||
expect(steps.current).to.equal(0);
|
expect(el.children[0].status).to.equal('entered');
|
||||||
expect(firstStep.status).to.equal('entered');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('navigation', () => {
|
describe('navigation', () => {
|
||||||
it('can navigate to the next step', async () => {
|
it('can navigate to the next step', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<lion-steps>
|
<lion-steps>
|
||||||
<lion-step initial-step>Step 0</lion-step>
|
<lion-step initial-step>Step 0</lion-step>
|
||||||
<lion-step>Step 1</lion-step>
|
<lion-step>Step 1</lion-step>
|
||||||
</lion-steps>
|
</lion-steps>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => el.next());
|
||||||
steps.next();
|
|
||||||
});
|
|
||||||
|
|
||||||
const { detail } = await oneEvent(steps, 'transition');
|
const { detail } = await oneEvent(el, 'transition');
|
||||||
expect(detail.fromStep.number).to.equal(0);
|
expect(detail.fromStep.number).to.equal(0);
|
||||||
expect(detail.fromStep.element.innerHTML).to.equal('Step 0');
|
expect(detail.fromStep.element.innerHTML).to.equal('Step 0');
|
||||||
expect(detail.toStep.number).to.equal(1);
|
expect(detail.toStep.number).to.equal(1);
|
||||||
expect(detail.toStep.element.innerHTML).to.equal('Step 1');
|
expect(detail.toStep.element.innerHTML).to.equal('Step 1');
|
||||||
expect(steps.current).to.equal(1);
|
expect(el.current).to.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can navigate to the previous step', async () => {
|
it('can navigate to the previous step', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<lion-steps>
|
<lion-steps>
|
||||||
<lion-step>Step 0</lion-step>
|
<lion-step>Step 0</lion-step>
|
||||||
<lion-step initial-step>Step 1</lion-step>
|
<lion-step initial-step>Step 1</lion-step>
|
||||||
</lion-steps>
|
</lion-steps>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => el.previous());
|
||||||
steps.previous();
|
|
||||||
});
|
|
||||||
|
|
||||||
const { detail } = await oneEvent(steps, 'transition');
|
const { detail } = await oneEvent(el, 'transition');
|
||||||
expect(detail.fromStep.number).to.equal(1);
|
expect(detail.fromStep.number).to.equal(1);
|
||||||
expect(detail.fromStep.element.innerHTML).to.equal('Step 1');
|
expect(detail.fromStep.element.innerHTML).to.equal('Step 1');
|
||||||
expect(detail.toStep.number).to.equal(0);
|
expect(detail.toStep.number).to.equal(0);
|
||||||
expect(detail.toStep.element.innerHTML).to.equal('Step 0');
|
expect(detail.toStep.element.innerHTML).to.equal('Step 0');
|
||||||
expect(steps.current).to.equal(0);
|
expect(el.current).to.equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('prevents navigating to the next step if user is on the last step', async () => {
|
it('prevents navigating to the next step if user is on the last step', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<lion-steps>
|
<lion-steps>
|
||||||
<lion-step>Step 0</lion-step>
|
<lion-step>Step 0</lion-step>
|
||||||
<lion-step initial-step>Step 1</lion-step>
|
<lion-step initial-step>Step 1</lion-step>
|
||||||
</lion-steps>
|
</lion-steps>
|
||||||
`);
|
`);
|
||||||
const cb = sinon.spy();
|
const cb = sinon.spy();
|
||||||
steps.addEventListener('transition', cb);
|
el.addEventListener('transition', cb);
|
||||||
expect(() => steps.next()).to.throw();
|
expect(() => el.next()).to.throw();
|
||||||
expect(cb.callCount).to.equal(0);
|
expect(cb.callCount).to.equal(0);
|
||||||
expect(steps.current).to.equal(1);
|
expect(el.current).to.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('prevents navigating to the previous step if user is on the first step', async () => {
|
it('prevents navigating to the previous step if user is on the first step', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<lion-steps>
|
<lion-steps>
|
||||||
<lion-step initial-step>Step 0</lion-step>
|
<lion-step initial-step>Step 0</lion-step>
|
||||||
<lion-step>Step 1</lion-step>
|
<lion-step>Step 1</lion-step>
|
||||||
</lion-steps>
|
</lion-steps>
|
||||||
`);
|
`);
|
||||||
const cb = sinon.spy();
|
const cb = sinon.spy();
|
||||||
steps.addEventListener('transition', cb);
|
el.addEventListener('transition', cb);
|
||||||
expect(() => steps.previous()).to.throw();
|
expect(() => el.previous()).to.throw();
|
||||||
expect(cb.callCount).to.equal(0);
|
expect(cb.callCount).to.equal(0);
|
||||||
expect(steps.current).to.equal(0);
|
expect(el.current).to.equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can navigate to an arbitrary step skipping intermediate conditions', async () => {
|
it('can navigate to an arbitrary step skipping intermediate conditions', async () => {
|
||||||
const steps = await fixture(html`
|
const el = await fixture(html`
|
||||||
<lion-steps .data=${{ age: 25 }}>
|
<lion-steps .data=${{ age: 25 }}>
|
||||||
<lion-step initial-step>Step 0</lion-step>
|
<lion-step initial-step>Step 0</lion-step>
|
||||||
<lion-step .condition=${data => data.age < 18}>Step 1</lion-step>
|
<lion-step .condition=${data => data.age < 18}>Step 1</lion-step>
|
||||||
|
|
@ -121,21 +131,21 @@ describe('lion-steps', () => {
|
||||||
</lion-steps>
|
</lion-steps>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
steps.current = 2;
|
el.current = 2;
|
||||||
await checkWorkflow(steps, {
|
await checkWorkflow(el, {
|
||||||
transitions: '0 => 2',
|
transitions: '0 => 2',
|
||||||
statuses: 'left untouched entered untouched untouched',
|
statuses: 'left untouched entered untouched untouched',
|
||||||
});
|
});
|
||||||
|
|
||||||
steps.current = 3; // can't enter because of condition move to next available one
|
el.current = 3; // can't enter because of condition move to next available one
|
||||||
await checkWorkflow(steps, {
|
await checkWorkflow(el, {
|
||||||
transitions: '2 => 4',
|
transitions: '2 => 4',
|
||||||
statuses: 'left untouched left skipped entered',
|
statuses: 'left untouched left skipped entered',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws an error if current step is set out of bounds', async () => {
|
it('throws an error if current step is set out of bounds', async () => {
|
||||||
const el = await fixture(`
|
const el = await fixture(html`
|
||||||
<lion-steps>
|
<lion-steps>
|
||||||
<lion-step>Step 0</lion-step>
|
<lion-step>Step 0</lion-step>
|
||||||
<lion-step>Step 1</lion-step>
|
<lion-step>Step 1</lion-step>
|
||||||
|
|
@ -150,7 +160,7 @@ describe('lion-steps', () => {
|
||||||
|
|
||||||
describe('workflow with data and conditions', () => {
|
describe('workflow with data and conditions', () => {
|
||||||
it('navigates to the next step which passes the condition', async () => {
|
it('navigates to the next step which passes the condition', async () => {
|
||||||
const steps = await fixture(html`
|
const el = await fixture(html`
|
||||||
<lion-steps .data=${{ age: 25 }}>
|
<lion-steps .data=${{ age: 25 }}>
|
||||||
<lion-step initial-step>Step 0</lion-step>
|
<lion-step initial-step>Step 0</lion-step>
|
||||||
<lion-step .condition=${data => data.age < 18}>Step 1</lion-step>
|
<lion-step .condition=${data => data.age < 18}>Step 1</lion-step>
|
||||||
|
|
@ -160,18 +170,16 @@ describe('lion-steps', () => {
|
||||||
</lion-steps>
|
</lion-steps>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => el.next());
|
||||||
steps.next();
|
|
||||||
});
|
|
||||||
|
|
||||||
await checkWorkflow(steps, {
|
await checkWorkflow(el, {
|
||||||
transitions: '0 => 3',
|
transitions: '0 => 3',
|
||||||
statuses: 'left skipped skipped entered untouched',
|
statuses: 'left skipped skipped entered untouched',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('skips steps with failing condition when navigating to the next step', async () => {
|
it('skips steps with failing condition when navigating to the next step', async () => {
|
||||||
const steps = await fixture(html`
|
const el = await fixture(html`
|
||||||
<lion-steps .data=${{ age: 19 }}>
|
<lion-steps .data=${{ age: 19 }}>
|
||||||
<lion-step initial-step>Step 0</lion-step>
|
<lion-step initial-step>Step 0</lion-step>
|
||||||
<lion-step .condition=${data => data.age < 18}>Step 1</lion-step>
|
<lion-step .condition=${data => data.age < 18}>Step 1</lion-step>
|
||||||
|
|
@ -181,20 +189,18 @@ describe('lion-steps', () => {
|
||||||
</lion-steps>
|
</lion-steps>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
steps.next();
|
el.next();
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => el.next());
|
||||||
steps.next();
|
|
||||||
});
|
|
||||||
|
|
||||||
await checkWorkflow(steps, {
|
await checkWorkflow(el, {
|
||||||
transitions: '2 => 4',
|
transitions: '2 => 4',
|
||||||
statuses: 'left skipped left skipped entered',
|
statuses: 'left skipped left skipped entered',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('skips steps with failing condition when navigating to the previous step', async () => {
|
it('skips steps with failing condition when navigating to the previous step', async () => {
|
||||||
const steps = await fixture(html`
|
const el = await fixture(html`
|
||||||
<lion-steps .data=${{ age: 15 }}>
|
<lion-steps .data=${{ age: 15 }}>
|
||||||
<lion-step initial-step>Step 0</lion-step>
|
<lion-step initial-step>Step 0</lion-step>
|
||||||
<lion-step .condition=${data => data.age < 18}>Step 1</lion-step>
|
<lion-step .condition=${data => data.age < 18}>Step 1</lion-step>
|
||||||
|
|
@ -204,14 +210,12 @@ describe('lion-steps', () => {
|
||||||
</lion-steps>
|
</lion-steps>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
steps.next();
|
el.next();
|
||||||
steps.next();
|
el.next();
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => el.previous());
|
||||||
steps.previous();
|
|
||||||
});
|
|
||||||
|
|
||||||
await checkWorkflow(steps, {
|
await checkWorkflow(el, {
|
||||||
transitions: '4 => 1',
|
transitions: '4 => 1',
|
||||||
statuses: 'left entered skipped skipped left',
|
statuses: 'left entered skipped skipped left',
|
||||||
});
|
});
|
||||||
|
|
@ -220,7 +224,7 @@ describe('lion-steps', () => {
|
||||||
|
|
||||||
describe('workflow with inverted condition', () => {
|
describe('workflow with inverted condition', () => {
|
||||||
it('behaves like "if not" when inverted condition is present', async () => {
|
it('behaves like "if not" when inverted condition is present', async () => {
|
||||||
const steps = await fixture(html`
|
const el = await fixture(html`
|
||||||
<lion-steps .data=${{}}>
|
<lion-steps .data=${{}}>
|
||||||
<lion-step initial-step>Step 0</lion-step>
|
<lion-step initial-step>Step 0</lion-step>
|
||||||
<lion-step .condition=${data => data.age < 18} invert-condition>Step 1</lion-step>
|
<lion-step .condition=${data => data.age < 18} invert-condition>Step 1</lion-step>
|
||||||
|
|
@ -229,17 +233,17 @@ describe('lion-steps', () => {
|
||||||
`);
|
`);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
steps.data.age = 15;
|
el.data.age = 15;
|
||||||
steps.next();
|
el.next();
|
||||||
steps.previous();
|
el.previous();
|
||||||
steps.data.age = 20;
|
el.data.age = 20;
|
||||||
steps.next();
|
el.next();
|
||||||
steps.next();
|
el.next();
|
||||||
steps.previous();
|
el.previous();
|
||||||
steps.previous();
|
el.previous();
|
||||||
});
|
});
|
||||||
|
|
||||||
await checkWorkflow(steps, {
|
await checkWorkflow(el, {
|
||||||
transitions: '0 => 2 => 0 => 1 => 2 => 1 => 0',
|
transitions: '0 => 2 => 0 => 1 => 2 => 1 => 0',
|
||||||
statuses: 'entered left left',
|
statuses: 'entered left left',
|
||||||
});
|
});
|
||||||
|
|
@ -247,7 +251,7 @@ describe('lion-steps', () => {
|
||||||
|
|
||||||
it('behaves like "if/else" in case both condition and inverted condition are present', async () => {
|
it('behaves like "if/else" in case both condition and inverted condition are present', async () => {
|
||||||
const condition = data => data.age < 18;
|
const condition = data => data.age < 18;
|
||||||
const steps = await fixture(html`
|
const el = await fixture(html`
|
||||||
<lion-steps .data=${{}}>
|
<lion-steps .data=${{}}>
|
||||||
<lion-step initial-step>Step 0</lion-step>
|
<lion-step initial-step>Step 0</lion-step>
|
||||||
<lion-step .condition=${condition}>Step 1</lion-step>
|
<lion-step .condition=${condition}>Step 1</lion-step>
|
||||||
|
|
@ -256,15 +260,15 @@ describe('lion-steps', () => {
|
||||||
`);
|
`);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
steps.data.age = 15;
|
el.data.age = 15;
|
||||||
steps.next();
|
el.next();
|
||||||
steps.previous();
|
el.previous();
|
||||||
steps.data.age = 20;
|
el.data.age = 20;
|
||||||
steps.next();
|
el.next();
|
||||||
steps.previous();
|
el.previous();
|
||||||
});
|
});
|
||||||
|
|
||||||
await checkWorkflow(steps, {
|
await checkWorkflow(el, {
|
||||||
transitions: '0 => 1 => 0 => 2 => 0',
|
transitions: '0 => 1 => 0 => 2 => 0',
|
||||||
statuses: 'entered skipped left',
|
statuses: 'entered skipped left',
|
||||||
});
|
});
|
||||||
|
|
@ -273,7 +277,7 @@ describe('lion-steps', () => {
|
||||||
|
|
||||||
describe('workflow with forward-only', () => {
|
describe('workflow with forward-only', () => {
|
||||||
it('activates step when going forward', async () => {
|
it('activates step when going forward', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<lion-steps>
|
<lion-steps>
|
||||||
<lion-step initial-step>Step 0</lion-step>
|
<lion-step initial-step>Step 0</lion-step>
|
||||||
<lion-step forward-only>Step 1</lion-step>
|
<lion-step forward-only>Step 1</lion-step>
|
||||||
|
|
@ -282,18 +286,18 @@ describe('lion-steps', () => {
|
||||||
`);
|
`);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
steps.next();
|
el.next();
|
||||||
steps.next();
|
el.next();
|
||||||
});
|
});
|
||||||
|
|
||||||
await checkWorkflow(steps, {
|
await checkWorkflow(el, {
|
||||||
transitions: '0 => 1 => 2',
|
transitions: '0 => 1 => 2',
|
||||||
statuses: 'left left entered',
|
statuses: 'left left entered',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('skips step when going back to prevent reevaluation of "service" steps', async () => {
|
it('skips step when going back to prevent reevaluation of "service" steps', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<lion-steps>
|
<lion-steps>
|
||||||
<lion-step initial-step>Step 0</lion-step>
|
<lion-step initial-step>Step 0</lion-step>
|
||||||
<lion-step forward-only>Step 1</lion-step>
|
<lion-step forward-only>Step 1</lion-step>
|
||||||
|
|
@ -301,21 +305,19 @@ describe('lion-steps', () => {
|
||||||
</lion-steps>
|
</lion-steps>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
steps.next();
|
el.next();
|
||||||
steps.next();
|
el.next();
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => el.previous());
|
||||||
steps.previous();
|
|
||||||
});
|
|
||||||
|
|
||||||
await checkWorkflow(steps, {
|
await checkWorkflow(el, {
|
||||||
transitions: '2 => 0',
|
transitions: '2 => 0',
|
||||||
statuses: 'entered left left',
|
statuses: 'entered left left',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not set "skipped" status when going back', async () => {
|
it('does not set "skipped" status when going back', async () => {
|
||||||
const steps = await fixture(`
|
const el = await fixture(html`
|
||||||
<lion-steps>
|
<lion-steps>
|
||||||
<lion-step initial-step>Step 0</lion-step>
|
<lion-step initial-step>Step 0</lion-step>
|
||||||
<lion-step forward-only>Step 1</lion-step>
|
<lion-step forward-only>Step 1</lion-step>
|
||||||
|
|
@ -323,11 +325,11 @@ describe('lion-steps', () => {
|
||||||
</lion-steps>
|
</lion-steps>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
steps.next();
|
el.next();
|
||||||
steps.next();
|
el.next();
|
||||||
steps.previous();
|
el.previous();
|
||||||
|
|
||||||
expect(steps.children[1].status).to.equal('left');
|
expect(el.children[1].status).to.equal('left');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue