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

openwisp / openwisp-wifi-login-pages / 16529208119

25 Jul 2025 06:40PM UTC coverage: 95.101% (-0.3%) from 95.411%
16529208119

push

github

web-flow
[deps] Upgrade dependencies and react to v17 #854

- upgrade react to v17
- upgrade axios to v1.10.0
- upgrade express to v5.1.0
- upgrade jest to v29.7.0
- upgrade eslint to v8.57.0
- upgrade eslint-config-airbnb to v19.0.4
- upgrade @wojtekmaj/enzyme-adapter-react-17 to v0.8.0

Closes #898
Closes #854

Signed-off-by: Sankalp <sankalp.nex@gmail.com>

1065 of 1179 branches covered (90.33%)

Branch coverage included in aggregate %.

9 of 11 new or added lines in 7 files covered. (81.82%)

3 existing lines in 2 files now uncovered.

1614 of 1638 relevant lines covered (98.53%)

30.08 hits per line

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

97.55
/client/components/organization-wrapper/organization-wrapper.js
1
/* eslint-disable camelcase */
2
/* eslint jsx-a11y/label-has-associated-control: 0 */
3
/* eslint-disable react/no-unstable-nested-components */
4
import "./index.css";
5

6
import PropTypes from "prop-types";
7
import React, {Suspense} from "react";
8
import {Cookies} from "react-cookie";
9
import {Helmet} from "react-helmet";
10
import {Navigate, Route, Routes} from "react-router-dom";
11
import {t} from "ttag";
12

13
import getAssetPath from "../../utils/get-asset-path";
14
import Header from "../header";
15
import Footer from "../footer";
16
import LoadingContext from "../../utils/loading-context";
17
import Loader from "../../utils/loader";
18
import needsVerify from "../../utils/needs-verify";
19
import loadTranslation from "../../utils/load-translation";
20
import Login from "../login";
21
import {
22
  Registration,
23
  Status,
24
  PasswordChange,
25
  MobilePhoneChange,
26
  PasswordReset,
27
  PasswordConfirm,
28
  MobilePhoneVerification,
29
  PaymentStatus,
30
  PaymentProcess,
31
  ConnectedDoesNotExist,
32
  DoesNotExist,
33
} from "./lazy-import";
34
import Logout from "./lazy-logout";
35
import {localStorage} from "../../utils/storage";
36
import isOldBrowser from "../../utils/is-old-browser";
37

38
export default class OrganizationWrapper extends React.Component {
39
  constructor(props) {
40
    super(props);
21✔
41
    this.state = {
21✔
42
      loading: false,
43
      translationLoaded: true,
44
      configLoaded: false,
45
    };
46
    this.loadLanguage = this.loadLanguage.bind(this);
21✔
47
  }
48

49
  async componentDidMount() {
50
    const {params, setOrganization, cookies} = this.props;
20✔
51
    const organizationSlug = params.organization;
20✔
52
    if (organizationSlug) await setOrganization(organizationSlug, cookies);
20!
53
    this.setState({translationLoaded: false, configLoaded: true});
20✔
54
  }
55

56
  async componentDidUpdate(prevProps) {
57
    const {setOrganization, params, cookies, language} = this.props;
82✔
58
    const {translationLoaded, configLoaded} = this.state;
82✔
59
    if (prevProps.params.organization !== params.organization) {
82✔
60
      if (params.organization) setOrganization(params.organization, cookies);
2✔
61
    }
62
    if (translationLoaded !== true && configLoaded === true) {
82✔
63
      const userLangChoice = localStorage.getItem(
22✔
64
        `${params.organization}-userLangChoice`,
65
      );
66
      if (userLangChoice) {
22✔
67
        await this.loadLanguage(userLangChoice, params.organization, false);
3✔
68
      } else await this.loadLanguage(language, params.organization, true);
19✔
69
    } else if (prevProps.language !== language && prevProps.language !== "") {
60✔
70
      this.setLoading(true);
1✔
71
      localStorage.setItem(`${params.organization}-userLangChoice`, language);
1✔
72
      await this.loadLanguage(language, params.organization, false);
1✔
73
      this.setLoading(false);
1✔
74
    }
75
  }
76

77
  setLoading = (value) => {
21✔
78
    this.setState({loading: value});
3✔
79
  };
80

81
  loadLanguage = async (language, orgSlug, useBrowserLang = false) => {
21!
82
    const {languages, defaultLanguage, setLanguage} = this.props;
23✔
83
    await loadTranslation(
23✔
84
      language,
85
      orgSlug,
86
      defaultLanguage,
87
      setLanguage,
88
      useBrowserLang,
89
      languages,
90
    );
91
    this.setState(
23✔
92
      {
93
        translationLoaded: true,
94
        configLoaded: false,
95
      },
96
      () => this.setState({configLoaded: true}), // to force re-render in child components
23✔
97
    );
98
  };
99

100
  render() {
101
    const {organization, params, cookies, location, navigate} = this.props;
101✔
102
    const {loading, translationLoaded, configLoaded} = this.state;
101✔
103
    const {
104
      favicon,
105
      isAuthenticated,
106
      userData,
107
      settings,
108
      pageTitle,
109
      slug: orgSlug,
110
      name: orgName,
111
      css_path: cssPath,
112
      js,
113
    } = organization.configuration;
101✔
114
    const {is_active} = userData;
101✔
115
    let {css} = organization.configuration;
101✔
116
    if (!css) css = [];
101✔
117
    if (cssPath) css.push(cssPath);
101✔
118
    const userAutoLogin = localStorage.getItem("userAutoLogin") === "true";
101✔
119
    const needsVerifyPhone = needsVerify("mobile_phone", userData, settings);
101✔
120
    if (organization.exists === true) {
101✔
121
      const {setLoading} = this;
99✔
122
      let extraClasses = "";
99✔
123
      if (loading) extraClasses += " no-scroll";
99✔
124
      if (isOldBrowser()) extraClasses += " oldbrowser";
99!
125
      return (
99✔
126
        <>
127
          {translationLoaded && configLoaded ? (
276✔
128
            <LoadingContext.Provider
129
              // eslint-disable-next-line react/jsx-no-constructed-context-values
UNCOV
130
              value={{setLoading, getLoading: () => loading}}
×
131
            >
132
              <div className={`app-container ${extraClasses}`}>
133
                <Routes>
134
                  <Route
135
                    path="*"
136
                    element={<Header location={location} params={params} />}
137
                  />
138
                </Routes>
139
                <Routes>
140
                  <Route
141
                    path=""
142
                    exact
143
                    element={<Navigate to={`/${orgSlug}/login`} />}
144
                  />
145
                  <Route
146
                    path="*"
147
                    element={
148
                      <Suspense fallback={<Loader />}>
149
                        <ConnectedDoesNotExist />
150
                      </Suspense>
151
                    }
152
                  />
153
                  <Route
154
                    path="registration/*"
155
                    element={(() => {
156
                      if (isAuthenticated && !needsVerifyPhone) {
32✔
157
                        return <Navigate to={`/${orgSlug}/status`} />;
27✔
158
                      }
159
                      if (isAuthenticated && needsVerifyPhone) {
5✔
160
                        return (
1✔
161
                          <Navigate
162
                            to={`/${orgSlug}/mobile-phone-verification`}
163
                          />
164
                        );
165
                      }
166
                      return (
4✔
167
                        <Suspense fallback={<Loader />}>
168
                          <Registration loading={loading} navigate={navigate} />
169
                        </Suspense>
170
                      );
171
                    })()}
172
                  />
173
                  <Route
174
                    path="mobile-phone-verification"
175
                    element={(() => {
176
                      if (
32✔
177
                        isAuthenticated &&
79✔
178
                        needsVerifyPhone === false &&
179
                        is_active
180
                      ) {
181
                        return <Navigate to={`/${orgSlug}/status`} />;
19✔
182
                      }
183
                      if (!isAuthenticated) {
13✔
184
                        return <Navigate to={`/${orgSlug}/login`} />;
4✔
185
                      }
186
                      return (
9✔
187
                        <Suspense fallback={<Loader />}>
188
                          <MobilePhoneVerification cookies={cookies} />
189
                        </Suspense>
190
                      );
191
                    })()}
192
                  />
193
                  <Route
194
                    path="password/reset/confirm/:uid/:token"
195
                    element={
196
                      isAuthenticated ? (
32✔
197
                        <Navigate to={`/${orgSlug}/status`} />
198
                      ) : (
199
                        <Suspense fallback={<Loader />}>
200
                          <PasswordConfirm />
201
                        </Suspense>
202
                      )
203
                    }
204
                  />
205
                  <Route
206
                    path="password/reset"
207
                    exact
208
                    element={
209
                      isAuthenticated ? (
32✔
210
                        <Navigate to={`/${orgSlug}/status`} />
211
                      ) : (
212
                        <Suspense fallback={<Loader />}>
213
                          <PasswordReset />
214
                        </Suspense>
215
                      )
216
                    }
217
                  />
218
                  <Route
219
                    path="login/*"
220
                    element={
221
                      isAuthenticated && is_active ? (
92✔
222
                        <Navigate to={`/${orgSlug}/status`} />
223
                      ) : (
224
                        <Login navigate={navigate} />
225
                      )
226
                    }
227
                  />
228
                  <Route
229
                    path="status"
230
                    element={(() => {
231
                      if (isAuthenticated && needsVerifyPhone)
32✔
232
                        return (
1✔
233
                          <Navigate
234
                            to={`/${orgSlug}/mobile-phone-verification`}
235
                          />
236
                        );
237
                      if (isAuthenticated) {
31✔
238
                        return (
27✔
239
                          <Suspense fallback={<Loader />}>
240
                            <Status
241
                              cookies={cookies}
242
                              location={location}
243
                              navigate={navigate}
244
                            />
245
                          </Suspense>
246
                        );
247
                      }
248
                      if (userAutoLogin)
4✔
249
                        return <Navigate to={`/${orgSlug}/logout`} />;
1✔
250
                      return <Navigate to={`/${orgSlug}/login`} />;
3✔
251
                    })()}
252
                  />
253
                  <Route
254
                    path="logout"
255
                    element={(() => {
256
                      if (isAuthenticated)
32✔
257
                        return <Navigate to={`/${orgSlug}/status`} />;
28✔
258
                      if (userAutoLogin)
4✔
259
                        return (
1✔
260
                          <Suspense fallback={<Loader />}>
261
                            <Logout />
262
                          </Suspense>
263
                        );
264
                      return <Navigate to={`/${orgSlug}/login`} />;
3✔
265
                    })()}
266
                  />
267
                  <Route
268
                    path="change-password"
269
                    element={
270
                      isAuthenticated ? (
32✔
271
                        <Suspense fallback={<Loader />}>
272
                          <PasswordChange
273
                            cookies={cookies}
274
                            navigate={navigate}
275
                          />
276
                        </Suspense>
277
                      ) : (
278
                        <Navigate to={`/${orgSlug}/login`} />
279
                      )
280
                    }
281
                  />
282
                  <Route
283
                    path="change-phone-number"
284
                    element={
285
                      isAuthenticated ? (
32✔
286
                        <Suspense fallback={<Loader />}>
287
                          <MobilePhoneChange
288
                            cookies={cookies}
289
                            navigate={navigate}
290
                          />
291
                        </Suspense>
292
                      ) : (
293
                        <Navigate to={`/${orgSlug}/login`} />
294
                      )
295
                    }
296
                  />
297
                  <Route
298
                    path="payment/process/"
299
                    element={
300
                      <Suspense fallback={<Loader />}>
301
                        <PaymentProcess cookies={cookies} navigate={navigate} />
302
                      </Suspense>
303
                    }
304
                  />
305
                  <Route
306
                    path="payment/:status"
307
                    element={
308
                      <Suspense fallback={<Loader />}>
309
                        <PaymentStatus cookies={cookies} />
310
                      </Suspense>
311
                    }
312
                  />
313
                </Routes>
314
                <Routes>
315
                  <Route path="*" element={<Footer />} />
316
                </Routes>
317
              </div>
318
              <Helmet>
319
                <title>
320
                  {pageTitle === undefined
32✔
321
                    ? t`DEFAULT_TITL${orgName}`
322
                    : pageTitle}
323
                </title>
324
              </Helmet>
325
              {loading && <Loader />}
35✔
326
            </LoadingContext.Provider>
327
          ) : null}
328
          {css && css.length !== 0 && orgSlug ? (
300✔
329
            <Helmet>
330
              {css.map((cssLocation) => (
331
                <link
4✔
332
                  rel="stylesheet"
333
                  href={getAssetPath(orgSlug, cssLocation)}
334
                  key={cssLocation}
335
                />
336
              ))}
337
            </Helmet>
338
          ) : null}
339
          {favicon && orgSlug ? (
200✔
340
            <Helmet>
341
              <link
342
                rel="shortcut icon"
343
                type="image/x-icon"
344
                href={getAssetPath(orgSlug, favicon)}
345
              />
346
            </Helmet>
347
          ) : null}
348
          {js && js.length !== 0 && orgSlug ? (
200✔
349
            <Helmet>
350
              {js.map((jsPath) => (
351
                <script src={getAssetPath(orgSlug, jsPath)} key={jsPath} />
2✔
352
              ))}
353
            </Helmet>
354
          ) : null}
355
        </>
356
      );
357
    }
358
    if (organization.exists === false) {
2✔
359
      return (
1✔
360
        <div className="org-wrapper-not-found">
361
          <Suspense fallback={<Loader />}>
362
            <DoesNotExist />
363
          </Suspense>
364
        </div>
365
      );
366
    }
367
    return <Loader />;
1✔
368
  }
369
}
370
OrganizationWrapper.defaultProps = {
1✔
371
  defaultLanguage: "",
372
  languages: [],
373
};
374
OrganizationWrapper.propTypes = {
1✔
375
  params: PropTypes.shape({
376
    organization: PropTypes.string.isRequired,
377
  }).isRequired,
378
  location: PropTypes.object.isRequired,
379
  navigate: PropTypes.func.isRequired,
380
  setOrganization: PropTypes.func.isRequired,
381
  setLanguage: PropTypes.func.isRequired,
382
  organization: PropTypes.shape({
383
    configuration: PropTypes.shape({
384
      title: PropTypes.string,
385
      pageTitle: PropTypes.string,
386
      css_path: PropTypes.string,
387
      css: PropTypes.array,
388
      slug: PropTypes.string,
389
      name: PropTypes.string,
390
      favicon: PropTypes.string,
391
      isAuthenticated: PropTypes.bool,
392
      needsVerifyPhone: PropTypes.bool,
393
      userData: PropTypes.object,
394
      settings: PropTypes.shape({
395
        mobile_phone_verification: PropTypes.bool,
396
      }),
397
      js: PropTypes.array,
398
    }),
399
    exists: PropTypes.bool,
400
  }).isRequired,
401
  cookies: PropTypes.instanceOf(Cookies).isRequired,
402
  language: PropTypes.string.isRequired,
403
  defaultLanguage: PropTypes.string,
404
  languages: PropTypes.arrayOf(
405
    PropTypes.shape({
406
      slug: PropTypes.string,
407
      text: PropTypes.string,
408
    }),
409
  ),
410
};
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

© 2026 Coveralls, Inc