Skip to content

Commit fe0eee8

Browse files
authored
fix(wizard): wizard remains in "not ready" state if a custom init() was provided #6339
## Problem The wizard remained in a "not ready" state if a custom `init()` was provided, requiring manual toggles in the test code. ## Solution - Wrap the user’s init() with a small decorator that sets _ready = true. - Remove the manual toggles in wizardTestUtils.ts, letting the wizard handle readiness on its own.
1 parent 39473b7 commit fe0eee8

File tree

2 files changed

+11
-6
lines changed

2 files changed

+11
-6
lines changed

packages/core/src/shared/wizards/wizard.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export class Wizard<TState extends Partial<Record<keyof TState, unknown>>> {
9494
private assertReady() {
9595
// Check for `false` explicity so that the base-class constructor can access `this._form`.
9696
// We want to guard against confusion when implementing a subclass, not this base-class.
97-
if (this._ready === false && this.init) {
97+
if (this._ready === false) {
9898
throw Error('run() (or init()) must be called immediately after creating the Wizard')
9999
}
100100
}
@@ -113,7 +113,7 @@ export class Wizard<TState extends Partial<Record<keyof TState, unknown>>> {
113113
return this._stepOffset[1] + this.stateController.totalSteps
114114
}
115115

116-
public get _form() {
116+
protected get _form() {
117117
this.assertReady()
118118
return this.__form
119119
}
@@ -136,14 +136,22 @@ export class Wizard<TState extends Partial<Record<keyof TState, unknown>>> {
136136
this._estimator = estimator
137137
}
138138

139-
public constructor(private readonly options: WizardOptions<TState> = {}) {
139+
public constructor(protected readonly options: WizardOptions<TState> = {}) {
140140
this.stateController = new StateMachineController(options.initState as TState)
141141
this.__form = options.initForm ?? new WizardForm()
142142
this._exitStep =
143143
options.exitPrompterProvider !== undefined ? this.createExitStep(options.exitPrompterProvider) : undefined
144144

145145
// Subclass constructor logic should live in `init()`, if it exists.
146146
this._ready = !this.init
147+
148+
if (typeof this.init === 'function') {
149+
const _init = this.init.bind(this)
150+
this.init = () => {
151+
this._ready = true
152+
return _init()
153+
}
154+
}
147155
}
148156

149157
/**
@@ -166,7 +174,6 @@ export class Wizard<TState extends Partial<Record<keyof TState, unknown>>> {
166174
if (!this._ready && this.init) {
167175
this._ready = true // Let init() use `this._form`.
168176
await this.init()
169-
delete this.init
170177
}
171178

172179
this.assignSteps()

packages/core/src/test/shared/wizards/wizardTestUtils.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,7 @@ function failIf(cond: boolean, message?: string): void {
6565
export async function createWizardTester<T extends Partial<T>>(wizard: Wizard<T> | WizardForm<T>): Promise<Tester<T>> {
6666
if (wizard instanceof Wizard && wizard.init) {
6767
// Ensure that init() was called. Needed because createWizardTester() does not call run().
68-
;(wizard as any)._ready = true
6968
await wizard.init()
70-
delete wizard.init
7169
}
7270

7371
const form = wizard instanceof Wizard ? wizard.boundForm : wizard

0 commit comments

Comments
 (0)