From c7a9cc6fc245bee8c6f2714b7af6f5c7a2c74634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Hau?= Date: Mon, 22 Jun 2026 18:01:44 +0200 Subject: [PATCH] fix: not call destroy on destroyed step --- shepherd.js/src/step.ts | 5 +++-- shepherd.js/src/utils/type-check.ts | 8 ++++++++ shepherd.js/test/unit/step.spec.js | 13 +++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/shepherd.js/src/step.ts b/shepherd.js/src/step.ts index 9e1587a0f..2d60dfbaf 100644 --- a/shepherd.js/src/step.ts +++ b/shepherd.js/src/step.ts @@ -5,7 +5,8 @@ import { isElement, isHTMLElement, isFunction, - isUndefined + isUndefined, + isNull } from './utils/type-check.ts'; import { bindAdvance } from './utils/bind.ts'; import { @@ -699,7 +700,7 @@ export class Step extends Evented { * @private */ _setupElements() { - if (!isUndefined(this.el)) { + if (!isUndefined(this.el) && !isNull(this.el)) { this.destroy(); } diff --git a/shepherd.js/src/utils/type-check.ts b/shepherd.js/src/utils/type-check.ts index adf211f15..35654b3af 100644 --- a/shepherd.js/src/utils/type-check.ts +++ b/shepherd.js/src/utils/type-check.ts @@ -37,3 +37,11 @@ export function isString(value: T | string): value is string { export function isUndefined(value: T | undefined): value is undefined { return value === undefined; } + +/** + * Checks if `value` is null. + * @param value The param to check if it is null + */ +export function isNull(value: T | undefined | null): value is null { + return value === null; +} diff --git a/shepherd.js/test/unit/step.spec.js b/shepherd.js/test/unit/step.spec.js index 3a7ec9d9f..75bee3794 100644 --- a/shepherd.js/test/unit/step.spec.js +++ b/shepherd.js/test/unit/step.spec.js @@ -441,6 +441,19 @@ describe('Tour | Step', () => { ).toBeTruthy(); }); + it('not calls destroy on the step if the step was destroyed', () => { + const step = new Step(tour, {}); + let destroyCalled = false; + step.el = document.createElement('a'); + step.destroy(); + step.destroy = () => (destroyCalled = true); + step._setupElements(); + expect( + destroyCalled, + '_setupElements method not called destroy if the step was destroyed' + ).toBeFalsy(); + }); + it('calls destroy on the tooltip if it already exists', () => { const step = new Step(tour, {}); let destroyCalled = false;