From 652b3291bb5570d459f33023d251aa875d30c0c2 Mon Sep 17 00:00:00 2001 From: Sarah Richards <62299569+sarah-storm@users.noreply.github.com> Date: Fri, 20 Sep 2024 11:36:39 +0100 Subject: [PATCH] Bug/tabs bad markup (#262) * Make tabs more defensive against bad / missing markup * Checks for complete panel markup before initialising tabset * Update warning message --- packages/tabs/__tests__/integrations.js | 23 ++++++++++++++++++++++- packages/tabs/src/index.js | 15 +++++++++++---- packages/tabs/src/lib/dom.js | 2 +- packages/tabs/src/lib/factory.js | 3 +++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/packages/tabs/__tests__/integrations.js b/packages/tabs/__tests__/integrations.js index 80d3e1d4..17a49fdd 100644 --- a/packages/tabs/__tests__/integrations.js +++ b/packages/tabs/__tests__/integrations.js @@ -49,8 +49,9 @@ const init = (mode) => { describe(`Tabs > Initialisation`, () => { beforeAll(() => {init()}); + console.log(TabSet) - it('should return array of length 1', async () => { + it('should return array of length 2', async () => { expect(TabSet.length).toEqual(2); }); @@ -66,6 +67,26 @@ describe(`Tabs > Initialisation`, () => { }); }); + +describe(`Tabs > Initialisation no panel markup`, () => { + + beforeAll(() => { + document.body.innerHTML = ` +
+ +
`; + + TabSet = tabs('[role=tablist]'); + }); + + it('should return array of length 0', async () => { + expect(TabSet.length).toEqual(0); + }); +}); + + describe(`Tabs > Accessibility > ARIA`, () => { diff --git a/packages/tabs/src/index.js b/packages/tabs/src/index.js index 005f346f..05c1032b 100644 --- a/packages/tabs/src/index.js +++ b/packages/tabs/src/index.js @@ -19,8 +19,15 @@ export default (selector, options) => { //return array of Objects, one for each DOM node found //each Object has a prototype consisting of the node (HTMLElement), //and a settings property composed from defaults, data-attributes on the node, and options passed to init - return nodes.map(node => Object.create(factory({ - settings: { ...defaults, ...node.dataset, ...options }, - node - }))); + return nodes.map(node => { + const instance = factory({ + settings: { ...defaults, ...node.dataset, ...options }, + node + }); + if(instance) { + return Object.create(instance); + } else { + console.warn("Tabset not initialised, required markup not found"); + } + }).filter((instance) => typeof instance !== "undefined"); }; \ No newline at end of file diff --git a/packages/tabs/src/lib/dom.js b/packages/tabs/src/lib/dom.js index a0261b4d..f6c9aeba 100644 --- a/packages/tabs/src/lib/dom.js +++ b/packages/tabs/src/lib/dom.js @@ -13,7 +13,7 @@ import { KEYCODES, MODES } from './constants'; */ export const findTabsAndPanels = (node, settings) => { const tabs = [].slice.call(node.querySelectorAll(settings.tabSelector)); - const panels = tabs.map(tab => document.getElementById(tab.getAttribute('href').substr(1)) || console.warn(`Tab panel for ${tab}`)); + const panels = tabs.map(tab => document.getElementById(tab.getAttribute('href').substr(1)) || console.warn(`Tab panel not found for ${tab}`)); return { tabs, panels }; }; diff --git a/packages/tabs/src/lib/factory.js b/packages/tabs/src/lib/factory.js index 69485e79..7988f373 100644 --- a/packages/tabs/src/lib/factory.js +++ b/packages/tabs/src/lib/factory.js @@ -11,6 +11,9 @@ import { getActiveIndexOnLoad } from './utils'; export default ({ node, settings }) => { const Store = createStore(); const { tabs, panels } = findTabsAndPanels(node, settings); + + if(!tabs.length || !panels.length || panels.includes(undefined)) return false; + const activeIndex = getActiveIndexOnLoad(panels, node); Store.dispatch({ settings,