export { ServerFailureError } from '../errors.js'
export class WebSocketClient {
+ public get connected (): boolean {
+ return this.ws?.readyState === WebSocketReadyState.OPEN
+ }
+
public get url (): string {
const scheme = this.config.secure === true ? 'wss' : 'ws'
return `${scheme}://${this.config.host}:${this.config.port.toString()}`
})
}
+ public isConnected (): boolean {
+ return this.client.connected
+ }
+
public async listChargingStations (): Promise<ResponsePayload> {
return this.sendRequest(ProcedureName.LIST_CHARGING_STATIONS, {})
}
unsubscribeRefresh = $uiClient.onRefresh(() => {
getChargingStations()
})
+ if ($uiClient.isConnected()) {
+ getData()
+ }
})
onUnmounted(() => {
authorize: ReturnType<typeof vi.fn>
closeConnection: ReturnType<typeof vi.fn>
deleteChargingStation: ReturnType<typeof vi.fn>
+ isConnected: ReturnType<typeof vi.fn>
listChargingStations: ReturnType<typeof vi.fn>
listTemplates: ReturnType<typeof vi.fn>
lockConnector: ReturnType<typeof vi.fn>
authorize: vi.fn().mockResolvedValue(successResponse),
closeConnection: vi.fn().mockResolvedValue(successResponse),
deleteChargingStation: vi.fn().mockResolvedValue(successResponse),
+ isConnected: vi.fn().mockReturnValue(false),
listChargingStations: vi.fn().mockResolvedValue({ ...successResponse, chargingStations: [] }),
listTemplates: vi.fn().mockResolvedValue({ ...successResponse, templates: [] }),
lockConnector: vi.fn().mockResolvedValue(successResponse),
vi.clearAllMocks()
})
- it('should call simulatorState, listTemplates, and listChargingStations on getData', () => {
+ it('should call simulatorState, listTemplates, and listChargingStations on getData', async () => {
const [result] = mountComposable()
+ // Wait for the initial getData() triggered by onMounted to complete so that
+ // the useFetchData guard (fetching === false) is reset before we call again.
+ await flushPromises()
mockClient.simulatorState.mockClear()
mockClient.listTemplates.mockClear()
mockClient.listChargingStations.mockClear()
expect(unsubscribe).toHaveBeenCalledTimes(1)
})
+ it('should call getData immediately on mount when WS is already connected', async () => {
+ mockClient.isConnected.mockReturnValue(true)
+ mountComposable()
+ await flushPromises()
+ expect(mockClient.simulatorState).toHaveBeenCalledTimes(1)
+ expect(mockClient.listTemplates).toHaveBeenCalledTimes(1)
+ expect(mockClient.listChargingStations).toHaveBeenCalledTimes(1)
+ })
+
+ it('should not call getData on mount when WS is not yet connected', () => {
+ mockClient.isConnected.mockReturnValue(false)
+ mountComposable()
+ expect(mockClient.simulatorState).not.toHaveBeenCalled()
+ expect(mockClient.listTemplates).not.toHaveBeenCalled()
+ expect(mockClient.listChargingStations).not.toHaveBeenCalled()
+ })
+
describe('error handling', () => {
it('should set loading to false when getSimulatorState rejects', async () => {
mockClient.simulatorState.mockRejectedValueOnce(new Error('network'))
})
it('should render a StationCard per charging station', async () => {
- const wrapper = mountView({
- chargingStations: [
- createChargingStationData({
- stationInfo: {
- baseName: 'CS-1',
- chargePointModel: 'm',
- chargePointVendor: 'v',
- chargingStationId: 'CS-1',
- hashId: 'h1',
- templateIndex: 0,
- templateName: 't',
- },
- }),
- createChargingStationData({
- stationInfo: {
- baseName: 'CS-2',
- chargePointModel: 'm',
- chargePointVendor: 'v',
- chargingStationId: 'CS-2',
- hashId: 'h2',
- templateIndex: 0,
- templateName: 't',
- },
- }),
- ],
- })
+ const stations = [
+ createChargingStationData({
+ stationInfo: {
+ baseName: 'CS-1',
+ chargePointModel: 'm',
+ chargePointVendor: 'v',
+ chargingStationId: 'CS-1',
+ hashId: 'h1',
+ templateIndex: 0,
+ templateName: 't',
+ },
+ }),
+ createChargingStationData({
+ stationInfo: {
+ baseName: 'CS-2',
+ chargePointModel: 'm',
+ chargePointVendor: 'v',
+ chargingStationId: 'CS-2',
+ hashId: 'h2',
+ templateIndex: 0,
+ templateName: 't',
+ },
+ }),
+ ]
+ mockClient.listChargingStations = vi
+ .fn()
+ .mockResolvedValue({ chargingStations: stations, status: 'success' })
+ const wrapper = mountView({ chargingStations: stations })
await flushPromises()
expect(wrapper.findAll('.stub-station-card')).toHaveLength(2)
})
templateName: 't',
},
})
+ mockClient.listChargingStations = vi
+ .fn()
+ .mockResolvedValue({ chargingStations: [station], status: 'success' })
const wrapper = mount(ModernLayout, {
global: {
provide: {