• 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

73.08
/src/js/components/settings/organization/organization.js
1
// Copyright 2017 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, { useCallback, useEffect, useState } from 'react';
15
import CopyToClipboard from 'react-copy-to-clipboard';
16
import { useDispatch, useSelector } from 'react-redux';
17

18
// material ui
19
import { FileCopy as CopyPasteIcon, Info as InfoIcon } from '@mui/icons-material';
20
import { Button, Checkbox, Collapse, FormControlLabel, List } from '@mui/material';
21
import { makeStyles } from 'tss-react/mui';
22

23
import copy from 'copy-to-clipboard';
24
import moment from 'moment';
25

26
import { setSnackbar } from '../../../actions/appActions';
27
import {
28
  changeSamlConfig,
29
  deleteSamlConfig,
30
  downloadLicenseReport,
31
  getSamlConfigs,
32
  getUserOrganization,
33
  storeSamlConfig
34
} from '../../../actions/organizationActions';
35
import { TIMEOUTS } from '../../../constants/appConstants';
36
import { createFileDownload, toggle } from '../../../helpers';
37
import { getFeatures, getIsEnterprise, getIsPreview, getOrganization, getUserRoles } from '../../../selectors';
38
import ExpandableAttribute from '../../common/expandable-attribute';
39
import { MenderTooltipClickable } from '../../common/mendertooltip';
40
import Billing from './billing';
41
import OrganizationSettingsItem, { maxWidth } from './organizationsettingsitem';
42
import { SAMLConfig } from './samlconfig';
43

44
const useStyles = makeStyles()(theme => ({
13✔
45
  copyNotification: { height: 30, padding: 15 },
46
  deviceLimitBar: { backgroundColor: theme.palette.grey[500], margin: '15px 0' },
47
  ssoToggle: { width: `calc(${maxWidth}px + ${theme.spacing(4)})` },
48
  tenantInfo: { marginTop: 11, paddingBottom: 3, 'span': { marginLeft: theme.spacing(0.5), color: theme.palette.text.disabled } },
49
  tenantToken: { width: `calc(${maxWidth}px - ${theme.spacing(4)})` },
50
  tokenTitle: { paddingRight: 10 },
51
  tokenExplanation: { margin: '1em 0' }
52
}));
53

54
export const OrgHeader = () => {
6✔
55
  const { classes } = useStyles();
15✔
56
  return (
15✔
57
    <div className="flexbox center-aligned">
58
      <div className={classes.tokenTitle}>Organization token</div>
59
      <MenderTooltipClickable
60
        disableHoverListener={false}
61
        placement="top"
62
        title={
63
          <>
64
            <h3>Organization token</h3>
65
            <p className={classes.tokenExplanation}>
66
              This token is unique for your organization and ensures that only devices that you own are able to connect to your account.
67
            </p>
68
          </>
69
        }
70
      >
71
        <InfoIcon />
72
      </MenderTooltipClickable>
73
    </div>
74
  );
75
};
76

77
export const CopyTextToClipboard = ({ token }) => {
6✔
78
  const [copied, setCopied] = useState(false);
24✔
79
  const { classes } = useStyles();
24✔
80

81
  const onCopied = () => {
24✔
82
    setCopied(true);
×
83
    setTimeout(() => setCopied(false), TIMEOUTS.fiveSeconds);
×
84
  };
85

86
  return (
24✔
87
    <div>
88
      <CopyToClipboard text={token} onCopy={onCopied}>
89
        <Button startIcon={<CopyPasteIcon />}>Copy to clipboard</Button>
90
      </CopyToClipboard>
91
      <div className={classes.copyNotification}>{copied && <span className="green fadeIn">Copied to clipboard.</span>}</div>
24!
92
    </div>
93
  );
94
};
95

96
export const Organization = () => {
6✔
97
  const [hasSingleSignOn, setHasSingleSignOn] = useState(false);
17✔
98
  const [isResettingSSO, setIsResettingSSO] = useState(false);
16✔
99
  const [isConfiguringSSO, setIsConfiguringSSO] = useState(false);
16✔
100
  const isEnterprise = useSelector(getIsEnterprise);
16✔
101
  const { isAdmin } = useSelector(getUserRoles);
16✔
102
  const canPreview = useSelector(getIsPreview);
16✔
103
  const { isHosted } = useSelector(getFeatures);
16✔
104
  const org = useSelector(getOrganization);
16✔
105
  const samlConfigs = useSelector(state => state.organization.samlConfigs);
30✔
106
  const dispatch = useDispatch();
16✔
107

108
  const { classes } = useStyles();
16✔
109

110
  useEffect(() => {
16✔
111
    dispatch(getUserOrganization());
3✔
112
  }, []);
113

114
  useEffect(() => {
16✔
115
    if (isEnterprise) {
3!
116
      dispatch(getSamlConfigs());
3✔
117
    }
118
  }, [isEnterprise]);
119

120
  useEffect(() => {
16✔
121
    setHasSingleSignOn(!!samlConfigs.length);
6✔
122
    setIsConfiguringSSO(!!samlConfigs.length);
6✔
123
  }, [samlConfigs.length]);
124

125
  const onSSOClick = () => {
16✔
126
    if (hasSingleSignOn) {
4!
127
      setIsConfiguringSSO(false);
4✔
128
      return setIsResettingSSO(true);
4✔
129
    }
130
    setIsConfiguringSSO(toggle);
×
131
  };
132

133
  const onCancelSSOSettings = () => {
16✔
134
    setIsResettingSSO(false);
×
135
    setIsConfiguringSSO(hasSingleSignOn);
×
136
  };
137

138
  const onSaveSSOSettings = useCallback(
16✔
139
    (id, fileContent) => {
140
      if (isResettingSSO) {
4!
141
        return dispatch(deleteSamlConfig(samlConfigs[0])).then(() => setIsResettingSSO(false));
4✔
142
      }
143
      if (id) {
×
144
        return dispatch(changeSamlConfig({ id, config: fileContent }));
×
145
      }
146
      return dispatch(storeSamlConfig(fileContent));
×
147
    },
148
    [isResettingSSO, changeSamlConfig, deleteSamlConfig, storeSamlConfig]
149
  );
150

151
  const onDownloadReportClick = () =>
16✔
152
    dispatch(downloadLicenseReport()).then(report => createFileDownload(report, `Mender-license-report-${moment().format(moment.HTML5_FMT.DATE)}`));
×
153

154
  const onTenantInfoClick = () => {
16✔
155
    copy(`Organization: ${org.name}, Tenant ID: ${org.id}`);
×
156
    setSnackbar('Copied to clipboard');
×
157
  };
158

159
  return (
16✔
160
    <div className="margin-top-small">
161
      <h2 className="margin-top-small">Organization and billing</h2>
162
      <List>
163
        <OrganizationSettingsItem
164
          title="Organization name"
165
          content={{
166
            action: { action: onTenantInfoClick, internal: true },
167
            description: (
168
              <div className={`clickable ${classes.tenantInfo}`} onClick={onTenantInfoClick}>
169
                {org.name}
170
                <span>({org.id})</span>
171
              </div>
172
            )
173
          }}
174
        />
175
        <OrganizationSettingsItem
176
          title={<OrgHeader />}
177
          content={{}}
178
          secondary={
179
            <ExpandableAttribute
180
              className={classes.tenantToken}
181
              component="div"
182
              disableGutters
183
              dividerDisabled
184
              key="org_token"
185
              secondary={org.tenant_token}
186
              textClasses={{ secondary: 'inventory-text tenant-token-text' }}
187
            />
188
          }
189
          sideBarContent={<CopyTextToClipboard token={org.tenant_token} />}
190
        />
191
      </List>
192
      {isEnterprise && isAdmin && (
48✔
193
        <div className="flexbox center-aligned">
194
          <FormControlLabel
195
            className={`margin-bottom-small ${classes.ssoToggle}`}
196
            control={<Checkbox checked={!isResettingSSO && (hasSingleSignOn || isConfiguringSSO)} onChange={onSSOClick} />}
36✔
197
            label="Enable SAML single sign-on"
198
          />
199
          {isResettingSSO && !isConfiguringSSO && (
24✔
200
            <>
201
              <Button onClick={onCancelSSOSettings}>Cancel</Button>
202
              <Button onClick={onSaveSSOSettings} disabled={!hasSingleSignOn} variant="contained">
203
                Save
204
              </Button>
205
            </>
206
          )}
207
        </div>
208
      )}
209
      <Collapse className="margin-left-large" in={isConfiguringSSO}>
210
        <SAMLConfig configs={samlConfigs} onSave={onSaveSSOSettings} onCancel={onCancelSSOSettings} setSnackbar={message => dispatch(setSnackbar(message))} />
×
211
      </Collapse>
212
      {isHosted && <Billing />}
32✔
213
      {(canPreview || !isHosted) && isEnterprise && isAdmin && (
32!
214
        <Button className="margin-top" onClick={onDownloadReportClick} variant="contained">
215
          Download license report
216
        </Button>
217
      )}
218
    </div>
219
  );
220
};
221

222
export default Organization;
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