]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
refactor(webui): order station action buttons by CSO lifecycle (#2084)
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Fri, 14 Aug 2026 22:08:21 +0000 (00:08 +0200)
committerGitHub <noreply@github.com>
Fri, 14 Aug 2026 22:08:21 +0000 (00:08 +0200)
* refactor(webui): order station action buttons by CSO lifecycle

Reorder the station-card action buttons in both skins to follow the
Charging Station Operator lifecycle (bring-up, provisioning, exploitation,
observability):

- modern StationCard: Start/Stop, Connect/Disconnect, Configuration,
  Authorize, Details
- classic CSData: Start/Stop, Connection, Set Supervision Url,
  Change Configuration, Show Details

This fixes Authorize (runtime) preceding Configuration (provisioning) and
Details being wedged between active commands. Action sets, labels, handlers,
routes, styling and the isolated Delete button are unchanged.

Make the classic CSData show-details toggle assertions look the button up by
id instead of a fixed index, so they stay robust to ordering.

* test(webui): cover classic change-configuration toggle navigation

Add id-based navigation tests for the change-configuration toggle in
classic CSData, mirroring the show-details coverage: assert on() pushes
the change-configuration route with hashId/chargingStationId params and
off() pushes back to charging-stations. Closes the coverage gap for the
toggle reordered in this change.

* test(webui): select set-supervision-url toggle by id for consistency

Align the set-supervision-url toggle navigation tests with the
change-configuration and show-details ones by looking the toggle up via
its id instead of a fixed index, so the whole toggle-navigation suite is
order-independent and uses a single selection convention.

ui/web/src/skins/classic/components/charging-stations/CSData.vue
ui/web/src/skins/modern/components/StationCard.vue
ui/web/tests/unit/skins/classic/CSData.test.ts

index 13377f46bcd5f659bea042d5f5cdeccccedd2181..a8e8c2604f09c04d64fe4cc757e99ee87be976d6 100644 (file)
@@ -71,7 +71,7 @@
         Set Supervision Url
       </ToggleButton>
       <ToggleButton
-        :id="`${chargingStation.stationInfo.hashId}-show-details`"
+        :id="`${chargingStation.stationInfo.hashId}-change-configuration`"
         :off="
           () => {
             $router.push({ name: ROUTE_NAMES.CHARGING_STATIONS }).catch(() => undefined)
@@ -81,7 +81,7 @@
           () => {
             $router
               .push({
-                name: ROUTE_NAMES.SHOW_DETAILS,
+                name: ROUTE_NAMES.CHANGE_CONFIGURATION,
                 params: {
                   hashId: chargingStation.stationInfo.hashId,
                   chargingStationId: chargingStation.stationInfo.chargingStationId,
         :shared="true"
         @clicked="$emit('need-refresh')"
       >
-        Show Details
+        Change Configuration
       </ToggleButton>
       <ToggleButton
-        :id="`${chargingStation.stationInfo.hashId}-change-configuration`"
+        :id="`${chargingStation.stationInfo.hashId}-show-details`"
         :off="
           () => {
             $router.push({ name: ROUTE_NAMES.CHARGING_STATIONS }).catch(() => undefined)
           () => {
             $router
               .push({
-                name: ROUTE_NAMES.CHANGE_CONFIGURATION,
+                name: ROUTE_NAMES.SHOW_DETAILS,
                 params: {
                   hashId: chargingStation.stationInfo.hashId,
                   chargingStationId: chargingStation.stationInfo.chargingStationId,
         :shared="true"
         @clicked="$emit('need-refresh')"
       >
-        Change Configuration
+        Show Details
       </ToggleButton>
       <Button @click="deleteChargingStation()">
         Delete Charging Station
index 9882ccebf5a2c38d99c38321ab7c368b20ab7d27..92b4866763feca2d00f565b86596adfb5e53831f 100644 (file)
         </ActionButton>
         <ActionButton
           variant="ghost"
-          @click="emitOpenAuthorize"
+          @click="emitOpenChangeConfig"
         >
-          Authorize
+          Configuration
         </ActionButton>
         <ActionButton
           variant="ghost"
-          @click="emitOpenDetails"
+          @click="emitOpenAuthorize"
         >
-          Details
+          Authorize
         </ActionButton>
         <ActionButton
           variant="ghost"
-          @click="emitOpenChangeConfig"
+          @click="emitOpenDetails"
         >
-          Configuration
+          Details
         </ActionButton>
       </div>
       <ActionButton
index 512d469c7f6394b1723a33f79507af5d4c25cea3..16387fd3296a622be6525eb9bd7bd63b9f2e05f2 100644 (file)
@@ -290,14 +290,21 @@ describe('CSData', () => {
     it('should render set-supervision-url toggle button', () => {
       const wrapper = mountCSData()
       const toggleButtons = wrapper.findAllComponents(ToggleButtonStub)
-      expect(toggleButtons.length).toBeGreaterThanOrEqual(1)
-      expect(toggleButtons[0].props('shared')).toBe(true)
+      const setSupervisionUrlToggle = toggleButtons.find(
+        toggleButton => toggleButton.props('id') === `${TEST_HASH_ID}-set-supervision-url`
+      )
+      expect(setSupervisionUrlToggle).toBeDefined()
+      expect(setSupervisionUrlToggle?.props('shared')).toBe(true)
     })
 
     it('should trigger router push to set-supervision-url on toggle on', () => {
       const wrapper = mountCSData()
       const toggleButtons = wrapper.findAllComponents(ToggleButtonStub)
-      const toggleProps = toggleButtons[0].props() as unknown as StubProps
+      const setSupervisionUrlToggle = toggleButtons.find(
+        toggleButton => toggleButton.props('id') === `${TEST_HASH_ID}-set-supervision-url`
+      )
+      expect(setSupervisionUrlToggle).toBeDefined()
+      const toggleProps = setSupervisionUrlToggle?.props() as unknown as StubProps
       toggleProps.on?.()
       expect(mockPush).toHaveBeenCalledOnce()
       const callArg = mockPush.mock.calls[0][0] as { name: string; params: Record<string, string> }
@@ -309,7 +316,39 @@ describe('CSData', () => {
     it('should trigger router push to charging-stations on toggle off', () => {
       const wrapper = mountCSData()
       const toggleButtons = wrapper.findAllComponents(ToggleButtonStub)
-      const toggleProps = toggleButtons[0].props() as unknown as StubProps
+      const setSupervisionUrlToggle = toggleButtons.find(
+        toggleButton => toggleButton.props('id') === `${TEST_HASH_ID}-set-supervision-url`
+      )
+      expect(setSupervisionUrlToggle).toBeDefined()
+      const toggleProps = setSupervisionUrlToggle?.props() as unknown as StubProps
+      toggleProps.off?.()
+      expect(mockPush).toHaveBeenCalledWith({ name: 'charging-stations' })
+    })
+
+    it('should trigger router push to change-configuration on toggle on', () => {
+      const wrapper = mountCSData()
+      const toggleButtons = wrapper.findAllComponents(ToggleButtonStub)
+      const changeConfigurationToggle = toggleButtons.find(
+        toggleButton => toggleButton.props('id') === `${TEST_HASH_ID}-change-configuration`
+      )
+      expect(changeConfigurationToggle).toBeDefined()
+      const toggleProps = changeConfigurationToggle?.props() as unknown as StubProps
+      toggleProps.on?.()
+      expect(mockPush).toHaveBeenCalledOnce()
+      const callArg = mockPush.mock.calls[0][0] as { name: string; params: Record<string, string> }
+      expect(callArg.name).toBe('change-configuration')
+      expect(callArg.params.hashId).toBe(TEST_HASH_ID)
+      expect(callArg.params.chargingStationId).toBe(TEST_STATION_ID)
+    })
+
+    it('should trigger router push to charging-stations on change-configuration toggle off', () => {
+      const wrapper = mountCSData()
+      const toggleButtons = wrapper.findAllComponents(ToggleButtonStub)
+      const changeConfigurationToggle = toggleButtons.find(
+        toggleButton => toggleButton.props('id') === `${TEST_HASH_ID}-change-configuration`
+      )
+      expect(changeConfigurationToggle).toBeDefined()
+      const toggleProps = changeConfigurationToggle?.props() as unknown as StubProps
       toggleProps.off?.()
       expect(mockPush).toHaveBeenCalledWith({ name: 'charging-stations' })
     })
@@ -317,8 +356,11 @@ describe('CSData', () => {
     it('should trigger router push to show-details on toggle on', () => {
       const wrapper = mountCSData()
       const toggleButtons = wrapper.findAllComponents(ToggleButtonStub)
-      expect(toggleButtons[1].props('id')).toBe(`${TEST_HASH_ID}-show-details`)
-      const toggleProps = toggleButtons[1].props() as unknown as StubProps
+      const showDetailsToggle = toggleButtons.find(
+        toggleButton => toggleButton.props('id') === `${TEST_HASH_ID}-show-details`
+      )
+      expect(showDetailsToggle).toBeDefined()
+      const toggleProps = showDetailsToggle?.props() as unknown as StubProps
       toggleProps.on?.()
       expect(mockPush).toHaveBeenCalledOnce()
       const callArg = mockPush.mock.calls[0][0] as { name: string; params: Record<string, string> }
@@ -330,8 +372,11 @@ describe('CSData', () => {
     it('should trigger router push to charging-stations on show-details toggle off', () => {
       const wrapper = mountCSData()
       const toggleButtons = wrapper.findAllComponents(ToggleButtonStub)
-      expect(toggleButtons[1].props('id')).toBe(`${TEST_HASH_ID}-show-details`)
-      const toggleProps = toggleButtons[1].props() as unknown as StubProps
+      const showDetailsToggle = toggleButtons.find(
+        toggleButton => toggleButton.props('id') === `${TEST_HASH_ID}-show-details`
+      )
+      expect(showDetailsToggle).toBeDefined()
+      const toggleProps = showDetailsToggle?.props() as unknown as StubProps
       toggleProps.off?.()
       expect(mockPush).toHaveBeenCalledWith({ name: 'charging-stations' })
     })