• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / gui / 963124858

pending completion
963124858

Pull #3870

gitlab-ci

mzedel
chore: cleaned up left over onboarding tooltips & aligned with updated design

Signed-off-by: Manuel Zedel <manuel.zedel@northern.tech>
Pull Request #3870: MEN-5413

4368 of 6355 branches covered (68.73%)

91 of 118 new or added lines in 22 files covered. (77.12%)

1753 existing lines in 162 files now uncovered.

8246 of 10042 relevant lines covered (82.12%)

193.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

25.23
/src/js/utils/sockethook.js
1
// Copyright 2022 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14
import { useCallback, useEffect, useRef, useState } from 'react';
15

16
import msgpack5 from 'msgpack5';
17

18
import { apiUrl } from '../api/general-api';
19
import { TIMEOUTS } from '../constants/appConstants';
20
import { DEVICE_MESSAGE_PROTOCOLS as MessageProtocols, DEVICE_MESSAGE_TYPES as MessageTypes } from '../constants/deviceConstants';
21

22
const MessagePack = msgpack5();
16✔
23

24
export const byteArrayToString = body => String.fromCharCode(...body);
16✔
25

26
export const blobToString = blob =>
16✔
UNCOV
27
  new Promise(resolve => {
×
UNCOV
28
    let fr = new FileReader();
×
UNCOV
29
    fr.onload = () => {
×
UNCOV
30
      resolve(fr.result);
×
31
    };
UNCOV
32
    fr.readAsArrayBuffer(blob);
×
33
  });
34

35
export const useSession = ({ onClose, onHealthCheckFailed, onMessageReceived, onNotify, onOpen, onReady }) => {
16✔
36
  const [sessionId, setSessionId] = useState();
2✔
37
  const healthcheckTimeout = useRef();
2✔
38
  const socketRef = useRef();
2✔
39

40
  useEffect(() => {
2✔
41
    onReady(!!(socketRef.current?.readyState === WebSocket.OPEN && sessionId));
1✔
42
  }, [sessionId, onReady]);
43

44
  const sendMessage = useCallback(({ typ, body, props }) => {
2✔
UNCOV
45
    if (!socketRef.current) {
×
UNCOV
46
      return;
×
47
    }
UNCOV
48
    const proto_header = { proto: MessageProtocols.Shell, typ, sid: socketRef.current.sessionId, props };
×
UNCOV
49
    const encodedData = MessagePack.encode({ hdr: proto_header, body });
×
UNCOV
50
    socketRef.current.send(encodedData);
×
51
  }, []);
52

53
  const close = useCallback(() => {
2✔
54
    if (socketRef.current && socketRef.current.readyState === WebSocket.OPEN) {
1!
UNCOV
55
      sendMessage({ typ: MessageTypes.Stop, body: {}, props: {} });
×
UNCOV
56
      socketRef.current.close();
×
UNCOV
57
      setSessionId();
×
58
    }
59
  }, [sendMessage]);
60

61
  const healthcheckFailed = useCallback(() => {
2✔
UNCOV
62
    onHealthCheckFailed();
×
UNCOV
63
    close();
×
64
  }, [close, onHealthCheckFailed]);
65

66
  const onSocketMessage = useCallback(
2✔
67
    event => {
UNCOV
68
      blobToString(event.data).then(data => {
×
69
        const {
70
          hdr: { props = {}, proto, sid, typ },
×
71
          body
UNCOV
72
        } = MessagePack.decode(data);
×
UNCOV
73
        if (proto !== MessageProtocols.Shell) {
×
UNCOV
74
          return;
×
75
        }
UNCOV
76
        switch (typ) {
×
77
          case MessageTypes.New: {
UNCOV
78
            if (props.status == WebSocket.CLOSING) {
×
UNCOV
79
              onNotify(`Error: ${byteArrayToString(body)}`);
×
UNCOV
80
              setSessionId();
×
UNCOV
81
              return close();
×
82
            } else {
UNCOV
83
              clearTimeout(healthcheckTimeout.current);
×
UNCOV
84
              healthcheckTimeout.current = setTimeout(healthcheckFailed, 65 * TIMEOUTS.oneSecond);
×
UNCOV
85
              socketRef.current.sessionId = sid;
×
UNCOV
86
              return setSessionId(sid);
×
87
            }
88
          }
89
          case MessageTypes.Shell:
UNCOV
90
            return onMessageReceived(body);
×
91
          case MessageTypes.Stop:
UNCOV
92
            return close();
×
93
          case MessageTypes.Ping: {
UNCOV
94
            if (healthcheckTimeout.current) {
×
UNCOV
95
              clearTimeout(healthcheckTimeout.current);
×
96
            }
UNCOV
97
            sendMessage({ typ: MessageTypes.Pong });
×
98
            //
UNCOV
99
            const timeout = parseInt(props.timeout);
×
UNCOV
100
            if (timeout > 0) {
×
UNCOV
101
              healthcheckTimeout.current = setTimeout(healthcheckFailed, timeout * TIMEOUTS.oneSecond);
×
102
            }
UNCOV
103
            return;
×
104
          }
105
          default:
UNCOV
106
            break;
×
107
        }
108
      });
109
    },
110
    [close, healthcheckFailed, onMessageReceived, onNotify, sendMessage]
111
  );
112

113
  const onSocketError = useCallback(
2✔
114
    error => {
UNCOV
115
      onNotify(`WebSocket error: ${error.message}`);
×
UNCOV
116
      close();
×
UNCOV
117
      clearTimeout(healthcheckTimeout.current);
×
118
    },
119
    [close, onNotify]
120
  );
121

122
  const isOpen = socketRef.current?.readyState === WebSocket.OPEN;
2✔
123

124
  useEffect(() => {
2✔
125
    if (!socketRef.current || !isOpen || sessionId) {
1!
126
      return;
1✔
127
    }
UNCOV
128
    socketRef.current.addEventListener('close', onClose);
×
UNCOV
129
    socketRef.current.addEventListener('error', onSocketError);
×
UNCOV
130
    socketRef.current.addEventListener('message', onSocketMessage);
×
UNCOV
131
    socketRef.current.addEventListener('open', onOpen);
×
UNCOV
132
    return () => {
×
UNCOV
133
      if (!sessionId) {
×
UNCOV
134
        return;
×
135
      }
UNCOV
136
      socketRef.current.removeEventListener('close', onClose);
×
UNCOV
137
      socketRef.current.removeEventListener('error', onSocketError);
×
UNCOV
138
      socketRef.current.removeEventListener('message', onSocketMessage);
×
UNCOV
139
      socketRef.current.removeEventListener('open', onOpen);
×
140
    };
141
  }, [isOpen, sessionId, onClose, onSocketError, onSocketMessage, onOpen]);
142

143
  const connect = useCallback(deviceId => {
2✔
UNCOV
144
    const uri = `wss://${window.location.host}${apiUrl.v1}/deviceconnect/devices/${deviceId}/connect`;
×
UNCOV
145
    setSessionId();
×
UNCOV
146
    try {
×
UNCOV
147
      socketRef.current = new WebSocket(uri);
×
148
    } catch (error) {
UNCOV
149
      console.log(error);
×
150
    }
151
  }, []);
152

153
  return [connect, sendMessage, close, socketRef.current?.readyState, sessionId];
2✔
154
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc