From 094fc039e9f29f5df893dab3f053a3cce46aac8a Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 7 Mar 2023 10:01:35 +1100 Subject: [PATCH] Update tabs_and_panels to display tab and panel based on the url anchor For Vouchers, this means the voucher tab and panel are displayed when you come back to entreprise edit screen from the new vourcher page --- .../controllers/tabs_and_panels_controller.js | 35 +++++- .../tabs_and_panels_controller_test.js | 102 ++++++++++++++---- 2 files changed, 116 insertions(+), 21 deletions(-) diff --git a/app/webpacker/controllers/tabs_and_panels_controller.js b/app/webpacker/controllers/tabs_and_panels_controller.js index 0a1762cedb..b6a119c3e8 100644 --- a/app/webpacker/controllers/tabs_and_panels_controller.js +++ b/app/webpacker/controllers/tabs_and_panels_controller.js @@ -12,13 +12,34 @@ export default class extends Controller { // only display the default panel this.defaultTarget.style.display = "block"; + + // Display panel specified in url anchor + const anchors = window.location.toString().split("#"); + const anchor = anchors.length > 1 ? anchors.pop() : ""; + + if (anchor != "") { + this.updateActivePanel(anchor); + + // tab + const tab_id = anchor.split("_panel").shift(); + this.updateActiveTab(tab_id); + } } changeActivePanel(event) { + this.updateActivePanel(`${event.currentTarget.id}_panel`); + } + + updateActivePanel(panel_id) { const newActivePanel = this.panelTargets.find( - (panel) => panel.id == `${event.currentTarget.id}_panel` + (panel) => panel.id == panel_id ); + if (newActivePanel === undefined) { + // No panel found + return; + } + this.currentActivePanel.style.display = "none"; newActivePanel.style.display = "block"; } @@ -28,6 +49,18 @@ export default class extends Controller { event.currentTarget.classList.add(`${this.classNameValue}`); } + updateActiveTab(tab_id) { + const newActiveTab = this.tabTargets.find((tab) => tab.id == tab_id); + + if (newActiveTab === undefined) { + // No tab found + return; + } + + this.currentActiveTab.classList.remove(`${this.classNameValue}`); + newActiveTab.classList.add(`${this.classNameValue}`); + } + get currentActiveTab() { return this.tabTargets.find((tab) => tab.classList.contains("selected")); } diff --git a/spec/javascripts/stimulus/tabs_and_panels_controller_test.js b/spec/javascripts/stimulus/tabs_and_panels_controller_test.js index 8fdfedd117..c87c08f6d0 100644 --- a/spec/javascripts/stimulus/tabs_and_panels_controller_test.js +++ b/spec/javascripts/stimulus/tabs_and_panels_controller_test.js @@ -2,16 +2,26 @@ * @jest-environment jsdom */ -import { Application } from "stimulus"; -import tabs_and_panels_controller from "../../../app/webpacker/controllers/tabs_and_panels_controller"; +import { Application } from 'stimulus'; +import tabs_and_panels_controller from '../../../app/webpacker/controllers/tabs_and_panels_controller'; -describe("EnterprisePanelController", () => { +describe('EnterprisePanelController', () => { beforeAll(() => { const application = Application.start(); - application.register("tabs-and-panels", tabs_and_panels_controller); + application.register('tabs-and-panels', tabs_and_panels_controller); }); - describe("#tabs-and-panels", () => { + describe('#tabs-and-panels', () => { + const checkDefaultPanel = () => { + const peekPanel = document.getElementById('peek_panel'); + const kaPanel = document.getElementById('ka_panel'); + const booPanel = document.getElementById('boo_panel'); + + expect(peekPanel.style.display).toBe('block'); + expect(kaPanel.style.display).toBe('none'); + expect(booPanel.style.display).toBe('none'); + } + beforeEach(() => { document.body.innerHTML = `
@@ -26,23 +36,75 @@ describe("EnterprisePanelController", () => {
`; }); - it("displays only the default panel", () => { - const peekPanel = document.getElementById("peek_panel"); - const kaPanel = document.getElementById("ka_panel"); - const booPanel = document.getElementById("boo_panel"); - - expect(peekPanel.style.display).toBe("block"); - expect(kaPanel.style.display).toBe("none"); - expect(booPanel.style.display).toBe("none"); + it('displays only the default panel', () => { + checkDefaultPanel() }); - it("displays appropriate panel when associated tab is clicked", () => { - const kaPanel = document.getElementById("ka_panel"); - const ka = document.getElementById("ka"); + describe('when tab is clicked', () => { + let ka; - expect(kaPanel.style.display).toBe("none"); - ka.click(); - expect(kaPanel.style.display).toBe("block"); - }); + beforeEach(() => { + ka = document.getElementById('ka'); + }) + + it('displays appropriate panel', () => { + const kaPanel = document.getElementById('ka_panel'); + + expect(kaPanel.style.display).toBe('none'); + ka.click(); + expect(kaPanel.style.display).toBe('block'); + }); + + it('selects the clicked tab', () => { + ka.click(); + expect(ka.classList.contains('selected')).toBe(true); + }); + }) + + describe('when anchor is specified in the url', () => { + const { location } = window; + const mockLocationToString = (panel) => { + // Mocking window.location.toString() + const url = `http://localhost:3000/admin/enterprises/great-shop/edit#!#${panel}` + const mockedToString = jest.fn() + mockedToString.mockImplementation(() => (url)) + + delete window.location + window.location = { + toString: mockedToString + } + } + + beforeAll(() => { + mockLocationToString('ka_panel') + }) + + afterAll(() => { + // cleaning up + window.location = location + }) + + it('displays the panel associated with the anchor', () => { + const kaPanel = document.getElementById('ka_panel'); + + expect(kaPanel.style.display).toBe('block'); + }) + + it('selects the tab entry associated with the anchor', () => { + const ka = document.getElementById('ka'); + + expect(ka.classList.contains('selected')).toBe(true); + }) + + describe("when anchor doesn't macht any panel", () => { + beforeAll(() => { + mockLocationToString('random_panel') + }) + + it('displays the default panel', () => { + checkDefaultPanel() + }) + }) + }) }); });