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

mendersoftware / gui / 951400782

pending completion
951400782

Pull #3900

gitlab-ci

web-flow
chore: bump @testing-library/jest-dom from 5.16.5 to 5.17.0

Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 5.16.5 to 5.17.0.
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v5.16.5...v5.17.0)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #3900: chore: bump @testing-library/jest-dom from 5.16.5 to 5.17.0

4446 of 6414 branches covered (69.32%)

8342 of 10084 relevant lines covered (82.73%)

186.0 hits per line

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

91.23
/src/js/components/devices/device-details/connection.js
1
// Copyright 2021 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 React, { useEffect, useState } from 'react';
15
import { Link } from 'react-router-dom';
16

17
import { ImportExport as ImportExportIcon, InfoOutlined as InfoIcon, Launch as LaunchIcon } from '@mui/icons-material';
18
import { Button, Typography } from '@mui/material';
19
import { useTheme } from '@mui/material/styles';
20

21
import { mdiConsole as ConsoleIcon } from '@mdi/js';
22

23
import { BEGINNING_OF_TIME } from '../../../constants/appConstants';
24
import { ALL_DEVICES, DEVICE_CONNECT_STATES } from '../../../constants/deviceConstants';
25
import { AUDIT_LOGS_TYPES } from '../../../constants/organizationConstants';
26
import { checkPermissionsObject, uiPermissionsById } from '../../../constants/userConstants';
27
import { formatAuditlogs } from '../../../utils/locationutils';
28
import DocsLink from '../../common/docslink';
29
import MaterialDesignIcon from '../../common/materialdesignicon';
30
import MenderTooltip from '../../common/mendertooltip';
31
import Time from '../../common/time';
32
import Troubleshootdialog from '../dialogs/troubleshootdialog';
33
import DeviceDataCollapse from './devicedatacollapse';
34

35
const buttonStyle = { textTransform: 'none', textAlign: 'left' };
11✔
36
export const PortForwardLink = () => (
11✔
37
  <MenderTooltip
3✔
38
    arrow
39
    title={
40
      <div style={{ whiteSpace: 'normal' }}>
41
        <h3>Port forwarding</h3>
42
        <p>Port forwarding allows you to troubleshoot or use services on or via the device, without opening any ports on the device itself.</p>
43
        <p>
44
          To enable port forwarding you will need to install and configure the necessary software on the device and your workstation. Follow the link to learn
45
          more.
46
        </p>
47
      </div>
48
    }
49
  >
50
    <DocsLink className="flexbox centered margin-left" path="add-ons/port-forward">
51
      Enable port forwarding
52
      <LaunchIcon className="margin-left-small" fontSize="small" />
53
    </DocsLink>
54
  </MenderTooltip>
55
);
56

57
export const DeviceConnectionNote = ({ children, style = buttonStyle }) => {
11✔
58
  const theme = useTheme();
7✔
59
  return (
7✔
60
    <div className="flexbox muted">
61
      <InfoIcon fontSize="small" style={{ marginRight: theme.spacing() }} />
62
      <Typography variant="body1" style={style}>
63
        {children}
64
      </Typography>
65
    </div>
66
  );
67
};
68

69
export const DeviceConnectionMissingNote = () => (
11✔
70
  <DeviceConnectionNote>
3✔
71
    The troubleshoot add-on does not seem to be enabled on this device.
72
    <br />
73
    Please <DocsLink path="add-ons/remote-terminal" title="see the documentation" /> for a description on how it works and how to enable it.
74
  </DeviceConnectionNote>
75
);
76

77
export const DeviceDisconnectedNote = ({ lastConnectionTs }) => (
11✔
78
  <DeviceConnectionNote>
3✔
79
    The troubleshoot add-on is not currently connected on this device, it was last connected on <Time value={lastConnectionTs} />.
80
    <br />
81
    Please <DocsLink path="add-ons/remote-terminal" title="see the documentation" /> for more information.
82
  </DeviceConnectionNote>
83
);
84

85
export const TroubleshootButton = ({ disabled, item, onClick }) => {
11✔
86
  const theme = useTheme();
4✔
87
  return (
4✔
88
    <Button onClick={() => onClick(item.key)} disabled={disabled} startIcon={item.icon} style={{ marginRight: theme.spacing(2) }}>
×
89
      <Typography variant="subtitle2" style={buttonStyle}>
90
        {item.title}
91
      </Typography>
92
    </Button>
93
  );
94
};
95

96
const troubleshootingTools = [
11✔
97
  {
98
    key: 'terminal',
99
    title: 'Launch a new Remote Terminal session',
100
    icon: <MaterialDesignIcon path={ConsoleIcon} />,
101
    needsWriteAccess: true,
102
    needsTroubleshoot: true
103
  },
104
  { key: 'transfer', title: 'Launch File Transfer', icon: <ImportExportIcon />, needsWriteAccess: false, needsTroubleshoot: false },
105
  { key: 'portForward', component: PortForwardLink, needsWriteAccess: false, needsTroubleshoot: true }
106
];
107

108
const deviceAuditlogType = AUDIT_LOGS_TYPES.find(type => type.value === 'device');
33✔
109

110
export const DeviceConnection = ({ className = '', device, hasAuditlogs, socketClosed, startTroubleshoot, userCapabilities }) => {
11✔
111
  const [availableTabs, setAvailableTabs] = useState(troubleshootingTools);
6✔
112

113
  const { canAuditlog, canTroubleshoot, canWriteDevices: hasWriteAccess, groupsPermissions } = userCapabilities;
6✔
114

115
  useEffect(() => {
6✔
116
    const allowedTabs = troubleshootingTools.reduce((accu, tab) => {
3✔
117
      if (
9!
118
        (tab.needsWriteAccess && (!hasWriteAccess || !checkPermissionsObject(groupsPermissions, uiPermissionsById.connect.value, device.group, ALL_DEVICES))) ||
30✔
119
        (tab.needsTroubleshoot && !canTroubleshoot)
120
      ) {
121
        return accu;
×
122
      }
123
      accu.push(tab);
9✔
124
      return accu;
9✔
125
    }, []);
126
    setAvailableTabs(allowedTabs);
3✔
127
  }, [hasWriteAccess, canTroubleshoot]);
128

129
  const { connect_status = DEVICE_CONNECT_STATES.unknown, connect_updated_ts } = device;
6✔
130
  return (
6✔
131
    <DeviceDataCollapse
132
      header={
133
        <div className={`flexbox ${className}`}>
134
          {connect_status === DEVICE_CONNECT_STATES.unknown && <DeviceConnectionMissingNote />}
8✔
135
          {connect_status === DEVICE_CONNECT_STATES.disconnected && <DeviceDisconnectedNote lastConnectionTs={connect_updated_ts} />}
8✔
136
          {connect_status === DEVICE_CONNECT_STATES.connected &&
8✔
137
            availableTabs.map(item => {
138
              let Component = TroubleshootButton;
6✔
139
              if (item.component) {
6✔
140
                Component = item.component;
2✔
141
              }
142
              return <Component key={item.key} onClick={startTroubleshoot} disabled={!socketClosed} item={item} />;
6✔
143
            })}
144
          {canAuditlog && hasAuditlogs && connect_status !== DEVICE_CONNECT_STATES.unknown && (
16✔
145
            <Link
146
              className="flexbox center-aligned margin-left"
147
              to={`/auditlog?${formatAuditlogs({ pageState: { type: deviceAuditlogType, detail: device.id, startDate: BEGINNING_OF_TIME } }, {})}`}
148
            >
149
              List all log entries for this device
150
            </Link>
151
          )}
152
        </div>
153
      }
154
      isAddOn
155
      title="Troubleshoot"
156
    ></DeviceDataCollapse>
157
  );
158
};
159

160
export default DeviceConnection;
161

162
export const TroubleshootTab = ({
11✔
163
  classes,
164
  device,
165
  tenantCapabilities: { hasAuditlogs },
166
  socketClosed,
167
  launchTroubleshoot,
168
  userCapabilities,
169
  troubleshootType,
170
  setTroubleshootType,
171
  setSocketClosed
172
}) => (
173
  <>
×
174
    <DeviceConnection
175
      className={classes.deviceConnection}
176
      device={device}
177
      hasAuditlogs={hasAuditlogs}
178
      socketClosed={socketClosed}
179
      startTroubleshoot={launchTroubleshoot}
180
      userCapabilities={userCapabilities}
181
    />
182
    <Troubleshootdialog
183
      device={device}
184
      open={Boolean(troubleshootType)}
185
      onCancel={() => setTroubleshootType()}
×
186
      setSocketClosed={setSocketClosed}
187
      type={troubleshootType}
188
    />
189
  </>
190
);
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