matlab-proxy 0.10.1__tar.gz → 0.12.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of matlab-proxy might be problematic. Click here for more details.

Files changed (131) hide show
  1. {matlab-proxy-0.10.1/matlab_proxy.egg-info → matlab-proxy-0.12.0}/PKG-INFO +3 -2
  2. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/README.md +2 -1
  3. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/package.json +1 -1
  4. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/actionCreators/actionCreators.spec.js +20 -61
  5. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/actionCreators/index.js +77 -5
  6. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/actions/index.js +7 -1
  7. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/App.spec.js +32 -56
  8. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/index.js +58 -9
  9. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Confirmation/Confirmation.spec.js +8 -25
  10. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Confirmation/index.js +6 -5
  11. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Controls/Controls.spec.js +14 -28
  12. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/EntitlementSelector/EntitlementSelector.spec.js +4 -33
  13. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Help/Help.spec.js +19 -29
  14. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Help/index.js +2 -4
  15. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Information/Information.css +11 -9
  16. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Information/Information.spec.js +22 -37
  17. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Information/index.js +32 -6
  18. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/LicensingGatherer/LicenseGatherer.spec.js +20 -26
  19. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/LicensingGatherer/MHLM.js +63 -11
  20. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/OverlayTrigger/OverlayTrigger.spec.js +3 -23
  21. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/reducers/index.js +116 -17
  22. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/reducers/reducers.spec.js +14 -22
  23. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/selectors/index.js +35 -10
  24. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/selectors/selectors.spec.js +60 -66
  25. matlab-proxy-0.12.0/gui/src/test/utils/state.js +55 -0
  26. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/app.py +75 -22
  27. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/app_state.py +74 -53
  28. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/constants.py +15 -2
  29. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/matlab/startup.m +2 -2
  30. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/settings.py +17 -8
  31. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0/matlab_proxy.egg-info}/PKG-INFO +3 -2
  32. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy.egg-info/SOURCES.txt +1 -0
  33. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/setup.py +1 -1
  34. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/LICENSE.md +0 -0
  35. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/MANIFEST.in +0 -0
  36. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/.gitignore +0 -0
  37. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/README.md +0 -0
  38. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/package-lock.json +0 -0
  39. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/public/favicon.ico +0 -0
  40. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/public/index.html +0 -0
  41. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/public/manifest.json +0 -0
  42. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/public/robots.txt +0 -0
  43. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/css/bootstrap.min.css +0 -0
  44. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/css/site7.min.css +0 -0
  45. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/glyphicons-halflings-regular.eot +0 -0
  46. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/glyphicons-halflings-regular.svg +0 -0
  47. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/glyphicons-halflings-regular.ttf +0 -0
  48. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/glyphicons-halflings-regular.woff +0 -0
  49. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/glyphicons-halflings-regular.woff2 +0 -0
  50. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/mathworks-eps.svg +0 -0
  51. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/mathworks-eps.ttf +0 -0
  52. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/mathworks-eps.woff +0 -0
  53. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/mathworks-pictograms.svg +0 -0
  54. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/mathworks-pictograms.ttf +0 -0
  55. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/mathworks-pictograms.woff +0 -0
  56. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/mathworks.svg +0 -0
  57. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/mathworks.ttf +0 -0
  58. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/fonts/mathworks.woff +0 -0
  59. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/images/bug_reports/workaround.gif +0 -0
  60. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/images/responsive/global/ico-header-account-hover.svg +0 -0
  61. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/images/responsive/global/ico-header-account.svg +0 -0
  62. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/images/responsive/global/ico-header-contact-hover.svg +0 -0
  63. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/images/responsive/global/ico-header-contact.svg +0 -0
  64. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/3p/images/responsive/global/ico-sprite.png +0 -0
  65. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/App.css +0 -0
  66. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/App/MATLAB-env-blur.png +0 -0
  67. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Controls/Controls.css +0 -0
  68. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Controls/feedback.svg +0 -0
  69. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Controls/help.svg +0 -0
  70. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Controls/index.js +0 -0
  71. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Controls/restart.svg +0 -0
  72. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Controls/sign-out.svg +0 -0
  73. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Controls/start.svg +0 -0
  74. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Controls/stop.svg +0 -0
  75. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Controls/terminate.svg +0 -0
  76. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/EntitlementSelector/index.js +0 -0
  77. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Error/Error.css +0 -0
  78. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Error/Error.spec.js +0 -0
  79. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Error/index.js +0 -0
  80. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Help/Help.css +0 -0
  81. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/LicensingGatherer/ExistingLicense.css +0 -0
  82. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/LicensingGatherer/ExistingLicense.js +0 -0
  83. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/LicensingGatherer/LicensingGatherer.css +0 -0
  84. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/LicensingGatherer/NLM.js +0 -0
  85. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/LicensingGatherer/index.js +0 -0
  86. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/MatlabJsd/MatlabJsd.css +0 -0
  87. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/MatlabJsd/MatlabJsd.spec.js +0 -0
  88. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/MatlabJsd/index.js +0 -0
  89. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Overlay/Overlay.css +0 -0
  90. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Overlay/Overlay.spec.js +0 -0
  91. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/Overlay/index.js +0 -0
  92. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/OverlayTrigger/OverlayTrigger.css +0 -0
  93. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/OverlayTrigger/ResizeOverlayTrigger.spec.js +0 -0
  94. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/OverlayTrigger/arrow.svg +0 -0
  95. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/OverlayTrigger/gripper.svg +0 -0
  96. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/OverlayTrigger/index.js +0 -0
  97. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/OverlayTrigger/trigger-error.svg +0 -0
  98. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/components/OverlayTrigger/trigger-ok.svg +0 -0
  99. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/index.css +0 -0
  100. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/index.js +0 -0
  101. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/jest.config.json +0 -0
  102. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/logo.svg +0 -0
  103. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/serviceWorker.js +0 -0
  104. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/setupTests.js +0 -0
  105. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/gui/src/test/utils/react-test.js +0 -0
  106. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/__init__.py +0 -0
  107. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/default_configuration.py +0 -0
  108. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/devel.py +0 -0
  109. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/icons/matlab.svg +0 -0
  110. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/__init__.py +0 -0
  111. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/event_loop.py +0 -0
  112. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/list_servers.py +0 -0
  113. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/mw.py +0 -0
  114. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/mwi/__init__.py +0 -0
  115. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/mwi/custom_http_headers.py +0 -0
  116. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/mwi/embedded_connector/__init__.py +0 -0
  117. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/mwi/embedded_connector/helpers.py +0 -0
  118. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/mwi/embedded_connector/request.py +0 -0
  119. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/mwi/environment_variables.py +0 -0
  120. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/mwi/exceptions.py +0 -0
  121. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/mwi/logger.py +0 -0
  122. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/mwi/token_auth.py +0 -0
  123. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/mwi/validators.py +0 -0
  124. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/system.py +0 -0
  125. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy/util/windows.py +0 -0
  126. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy.egg-info/dependency_links.txt +0 -0
  127. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy.egg-info/entry_points.txt +0 -0
  128. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy.egg-info/not-zip-safe +0 -0
  129. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy.egg-info/requires.txt +0 -0
  130. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/matlab_proxy.egg-info/top_level.txt +0 -0
  131. {matlab-proxy-0.10.1 → matlab-proxy-0.12.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: matlab-proxy
3
- Version: 0.10.1
3
+ Version: 0.12.0
4
4
  Summary: Python® package enables you to launch MATLAB® and access it from a web browser.
5
5
  Home-page: https://github.com/mathworks/matlab-proxy/
6
6
  Author: The MathWorks, Inc.
@@ -55,9 +55,10 @@ Description: # MATLAB Proxy
55
55
 
56
56
  $ sudo yum install xorg-x11-server-Xvfb
57
57
  ```
58
+
59
+ *Note: The installation of Xvfb is **optional** (w.e.f. v0.11.0 of matlab-proxy). However, we highly recommend installing it.*
58
60
  * Python versions: **3.8** | **3.9** | **3.10** | **3.11**
59
61
  * [Browser Requirements](https://www.mathworks.com/support/requirements/browser-requirements.html)
60
-
61
62
  * Supported Operating Systems:
62
63
  * Linux®
63
64
  * Windows® Operating System ( starting v0.4.0 of matlab-proxy )
@@ -47,9 +47,10 @@ The MATLAB Proxy is under active development. For support or to report issues, s
47
47
 
48
48
  $ sudo yum install xorg-x11-server-Xvfb
49
49
  ```
50
+
51
+ *Note: The installation of Xvfb is **optional** (w.e.f. v0.11.0 of matlab-proxy). However, we highly recommend installing it.*
50
52
  * Python versions: **3.8** | **3.9** | **3.10** | **3.11**
51
53
  * [Browser Requirements](https://www.mathworks.com/support/requirements/browser-requirements.html)
52
-
53
54
  * Supported Operating Systems:
54
55
  * Linux®
55
56
  * Windows® Operating System ( starting v0.4.0 of matlab-proxy )
@@ -40,7 +40,7 @@
40
40
  "last 1 safari version"
41
41
  ]
42
42
  },
43
- "proxy": "http://127.0.0.1:8000",
43
+ "proxy": "http://127.0.0.1:8888",
44
44
  "homepage": "./",
45
45
  "devDependencies": {
46
46
  "@babel/preset-env": "^7.11.0",
@@ -1,10 +1,13 @@
1
- // Copyright 2020-2023 The MathWorks, Inc.
1
+ // Copyright 2020-2024 The MathWorks, Inc.
2
2
 
3
3
  import configureMockStore from 'redux-mock-store';
4
4
  import thunk from 'redux-thunk';
5
5
  import fetchMock from 'fetch-mock';
6
6
  import * as actions from '../actions';
7
7
  import * as actionCreators from './index';
8
+ import state from '../test/utils/state';
9
+
10
+ const _ = require("lodash");
8
11
 
9
12
  const middlewares = [thunk];
10
13
  const mockStore = configureMockStore(middlewares);
@@ -60,25 +63,7 @@ describe.each([
60
63
 
61
64
  describe('Test Sync actionCreators', () => {
62
65
  it('should dispatch action of type RECEIVE_SERVER_STATUS ', () => {
63
- const store = mockStore({
64
- overlayVisibility: false,
65
- error: null,
66
- serverStatus: {
67
- matlabStatus: 'starting',
68
- isFetching: true,
69
- hasFetched: false,
70
- fetchFailCount: 0,
71
- licensingInfo: {
72
- type: 'NLM',
73
- connectionString: 'abc@nlm',
74
- }
75
- },
76
- authInfo: {
77
- authEnabled: false,
78
- authStatus: false,
79
- authToken: null,
80
- }
81
- });
66
+ const store = mockStore(state);
82
67
 
83
68
  const status = {
84
69
  matlab: {
@@ -101,19 +86,7 @@ describe('Test Sync actionCreators', () => {
101
86
  describe('Test fetchWithTimeout method', () => {
102
87
  let store;
103
88
  beforeEach(() => {
104
- store = mockStore({
105
- error: null,
106
- serverStatus: {
107
- licensingInfo: {
108
- type: 'NLM',
109
- connectionString: 'abc@nlm',
110
- },
111
- isFetching: false,
112
- isSubmitting: false,
113
- hasFetched: false,
114
- fetchFailCount: 0,
115
- },
116
- });
89
+ store = mockStore(state);
117
90
  });
118
91
 
119
92
  afterEach(() => {
@@ -121,7 +94,7 @@ describe('Test fetchWithTimeout method', () => {
121
94
  });
122
95
 
123
96
  it('should fetch requested data without raising an exception or dispatching any action', async () => {
124
- fetchMock.getOnce('/get_status', {
97
+ fetchMock.getOnce('/get_status?IS_DESKTOP=TRUE', {
125
98
  body: {
126
99
  matlab: {
127
100
  status: 'down',
@@ -131,7 +104,7 @@ describe('Test fetchWithTimeout method', () => {
131
104
  headers: { 'content-type': 'application/json' },
132
105
  });
133
106
 
134
- const response = await actionCreators.fetchWithTimeout(store.dispatch, '/get_status', {}, 10000);
107
+ const response = await actionCreators.fetchWithTimeout(store.dispatch, '/get_status?IS_DESKTOP=TRUE', {}, 10000);
135
108
  const body = await response.json()
136
109
 
137
110
  expect(body).not.toBeNull();
@@ -143,7 +116,7 @@ describe('Test fetchWithTimeout method', () => {
143
116
  ];
144
117
 
145
118
  try {
146
- const response = await actionCreators.fetchWithTimeout(store.dispatch, '/get_status', {}, 100);
119
+ const response = await actionCreators.fetchWithTimeout(store.dispatch, '/get_status?IS_DESKTOP=TRUE', {}, 100);
147
120
  } catch (error) {
148
121
  expect(error).toBeInstanceOf(TypeError)
149
122
  const received = store.getActions();
@@ -157,14 +130,14 @@ describe('Test fetchWithTimeout method', () => {
157
130
 
158
131
  // Send a delayed response, well after the timeout for the request has expired.
159
132
  // This should trigger the abort() method of the AbortController()
160
- fetchMock.getOnce('/get_status', new Promise(resolve => setTimeout(() => resolve({ body: 'ok' }), 1000 + timeout)));
133
+ fetchMock.getOnce('/get_status?IS_DESKTOP=TRUE', new Promise(resolve => setTimeout(() => resolve({ body: 'ok' }), 1000 + timeout)));
161
134
 
162
135
  const abortSpy = jest.spyOn(global.AbortController.prototype, 'abort');
163
136
  const expectedActions = [
164
137
  actions.RECEIVE_ERROR,
165
138
  ];
166
139
 
167
- await actionCreators.fetchWithTimeout(store.dispatch, '/get_status', {}, timeout);
140
+ await actionCreators.fetchWithTimeout(store.dispatch, '/get_status?IS_DESKTOP=TRUE', {}, timeout);
168
141
 
169
142
  expect(abortSpy).toBeCalledTimes(1);
170
143
  const received = store.getActions();
@@ -174,26 +147,10 @@ describe('Test fetchWithTimeout method', () => {
174
147
  });
175
148
 
176
149
  describe('Test Async actionCreators', () => {
177
- let store;
150
+ let store, initialState;
178
151
  beforeEach(() => {
179
- store = mockStore({
180
- error: null,
181
- serverStatus: {
182
- licensingInfo: {
183
- type: 'NLM',
184
- connectionString: 'abc@nlm',
185
- },
186
- isFetching: false,
187
- isSubmitting: false,
188
- hasFetched: false,
189
- fetchFailCount: 0,
190
- },
191
- authInfo: {
192
- authEnabled: false,
193
- authStatus: false,
194
- authToken: null,
195
- },
196
- });
152
+ initialState = _.cloneDeep(state)
153
+ store = mockStore(initialState);
197
154
  });
198
155
 
199
156
  afterEach(() => {
@@ -236,15 +193,17 @@ describe('Test Async actionCreators', () => {
236
193
  });
237
194
  });
238
195
 
239
-
240
-
241
196
  it('dispatches REQUEST_SERVER_STATUS, RECEIVE_SERVER_STATUS when fetching status', () => {
242
- fetchMock.getOnce('/get_status', {
197
+ fetchMock.getOnce('/get_status?IS_DESKTOP=TRUE', {
243
198
  body: {
244
199
  matlab: {
245
200
  status: 'down',
201
+ version: 'R2023a'
246
202
  },
247
- licensing: {},
203
+ licensing: null,
204
+ loadUrl: null,
205
+ error: null,
206
+ wsEnv: "",
248
207
  },
249
208
  headers: { 'content-type': 'application/json' },
250
209
  });
@@ -1,4 +1,4 @@
1
- // Copyright 2020-2023 The MathWorks, Inc.
1
+ // Copyright 2020-2024 The MathWorks, Inc.
2
2
 
3
3
  import {
4
4
  SET_TRIGGER_POSITION,
@@ -19,10 +19,19 @@ import {
19
19
  RECEIVE_START_MATLAB,
20
20
  RECEIVE_ERROR,
21
21
  RECEIVE_ENV_CONFIG,
22
+ RECEIVE_CONCURRENCY_CHECK,
22
23
  SET_AUTH_STATUS,
23
- SET_AUTH_TOKEN
24
+ SET_AUTH_TOKEN,
25
+ RECEIVE_SESSION_STATUS,
26
+ WAS_EVER_ACTIVE,
27
+ REQUEST_SESSION_STATUS,
28
+ SET_CLIENT_ID,
24
29
  } from '../actions';
25
- import { selectMatlabPending } from '../selectors';
30
+ import {
31
+ selectMatlabPending,
32
+ selectIsConcurrencyEnabled,
33
+ selectClientId,
34
+ } from '../selectors';
26
35
  import sha256 from 'crypto-js/sha256';
27
36
 
28
37
  export function setAuthStatus(authInfo) {
@@ -61,12 +70,25 @@ export function setOverlayVisibility(visibility) {
61
70
  };
62
71
  }
63
72
 
73
+ export function setClientId(client_id) {
74
+ return {
75
+ type: SET_CLIENT_ID,
76
+ client_id
77
+ };
78
+ }
79
+
64
80
  export function requestServerStatus() {
65
81
  return {
66
82
  type: REQUEST_SERVER_STATUS,
67
83
  };
68
84
  }
69
85
 
86
+ export function wasEverActive() {
87
+ return {
88
+ type: WAS_EVER_ACTIVE,
89
+ }
90
+ }
91
+
70
92
  export function receiveServerStatus(status) {
71
93
  return function (dispatch, getState) {
72
94
  return dispatch({
@@ -76,6 +98,20 @@ export function receiveServerStatus(status) {
76
98
  });
77
99
  }
78
100
  }
101
+ export function requestSessionStatus() {
102
+ return {
103
+ type: REQUEST_SESSION_STATUS,
104
+ };
105
+ }
106
+
107
+ export function receiveSessionStatus(status) {
108
+ return function (dispatch, getState) {
109
+ return dispatch({
110
+ type: RECEIVE_SESSION_STATUS,
111
+ status,
112
+ })
113
+ }
114
+ }
79
115
 
80
116
  export function requestEnvConfig() {
81
117
  return {
@@ -90,6 +126,13 @@ export function receiveEnvConfig(config) {
90
126
  };
91
127
  }
92
128
 
129
+ export function receiveConcurrencyCheck(config) {
130
+ return {
131
+ type: RECEIVE_CONCURRENCY_CHECK,
132
+ config,
133
+ }
134
+ }
135
+
93
136
  export function requestSetLicensing() {
94
137
  return {
95
138
  type: REQUEST_SET_LICENSING,
@@ -193,14 +236,43 @@ export async function fetchWithTimeout(dispatch, resource, options = {}, timeout
193
236
  }
194
237
  }
195
238
 
196
- export function fetchServerStatus() {
239
+ export function fetchServerStatus(requestTransferSession = false) {
197
240
  return async function (dispatch, getState) {
241
+ const isConcurrencyEnabled = selectIsConcurrencyEnabled(getState());
242
+ const clientIdInState = selectClientId(getState());
243
+ const clientId = clientIdInState ? clientIdInState : sessionStorage.getItem("MWI_CLIENT_ID");
198
244
 
199
245
  dispatch(requestServerStatus());
200
- const response = await fetchWithTimeout(dispatch, './get_status', {}, 10000);
246
+
247
+ let url = './get_status?IS_DESKTOP=TRUE'
248
+
249
+ if (isConcurrencyEnabled && clientId) {
250
+ let params = new URLSearchParams();
251
+ params.append("MWI_CLIENT_ID",encodeURIComponent(clientId))
252
+
253
+ if (requestTransferSession){
254
+ params.append("TRANSFER_SESSION",encodeURIComponent(requestTransferSession))
255
+ }
256
+
257
+ url = url + '&' + params.toString();
258
+
259
+ }
260
+
261
+ const response = await fetchWithTimeout(dispatch, url, {}, 10000);
262
+
201
263
  const data = await response.json();
202
264
  dispatch(receiveServerStatus(data));
203
265
 
266
+ if (clientId == null && data["clientId"]) {
267
+ sessionStorage.setItem("MWI_CLIENT_ID", data["clientId"]);
268
+ dispatch(setClientId(data["clientId"]));
269
+ }
270
+ if ("isActiveClient" in data) {
271
+ dispatch(receiveSessionStatus(data))
272
+ if (data["isActiveClient"] === true) {
273
+ dispatch(wasEverActive())
274
+ }
275
+ }
204
276
  }
205
277
  }
206
278
 
@@ -1,8 +1,9 @@
1
- // Copyright (c) 2020-2023 The MathWorks, Inc.
1
+ // Copyright 2020-2024 The MathWorks, Inc.
2
2
 
3
3
  export const SET_TRIGGER_POSITION = 'SET_TRIGGER_POSITION';
4
4
  export const SET_TUTORIAL_HIDDEN = 'SET_TUTORIAL_HIDDEN';
5
5
  export const SET_OVERLAY_VISIBILITY = 'SET_OVERLAY_VISIBILITY';
6
+ export const SET_CLIENT_ID = 'SET_CLIENT_ID';
6
7
  export const REQUEST_SERVER_STATUS = 'REQUEST_SERVER_STATUS';
7
8
  export const RECEIVE_SERVER_STATUS = 'RECEIVE_SERVER_STATUS';
8
9
  export const REQUEST_SET_LICENSING = 'REQUEST_SET_LICENSING';
@@ -18,5 +19,10 @@ export const RECEIVE_START_MATLAB = 'RECEIVE_START_MATLAB';
18
19
  export const RECEIVE_ERROR = 'RECEIVE_ERROR';
19
20
  export const REQUEST_ENV_CONFIG = 'REQUEST_ENV_CONFIG';
20
21
  export const RECEIVE_ENV_CONFIG = 'RECEIVE_ENV_CONFIG';
22
+ export const RECEIVE_CONCURRENCY_CHECK = 'RECEIVE_CONCURRENCY_CHECK';
21
23
  export const SET_AUTH_STATUS = 'SET_AUTH_STATUS';
22
24
  export const SET_AUTH_TOKEN = 'SET_AUTH_TOKEN';
25
+ export const REQUEST_SERVER_INITIALIZATION = 'REQUEST_SERVER_INITIALIZATION';
26
+ export const RECEIVE_SESSION_STATUS = 'RECEIVE_SESSION_STATUS';
27
+ export const WAS_EVER_ACTIVE = 'WAS_EVER_ACTIVE';
28
+ export const REQUEST_SESSION_STATUS = 'REQUEST_SESSION_STATUS';
@@ -4,31 +4,28 @@ import React from 'react';
4
4
  import { render, fireEvent } from '../../test/utils/react-test';
5
5
  import App from './index';
6
6
  import * as actionCreators from '../../actionCreators';
7
+ import state from '../../test/utils/state';
8
+
9
+ const _ = require("lodash");
7
10
 
8
11
  describe('App Component', () => {
9
12
  let initialState;
10
13
  beforeEach(() => {
11
- initialState = {
12
- triggerPosition: { x: 539, y: 0 },
13
- tutorialHidden: false,
14
- overlayVisibility: false,
15
- serverStatus: {
16
- licensingInfo: { type: 'MHLM', emailAddress: 'abc@mathworks.com' },
17
- matlabStatus: 'up',
18
- isFetching: false,
19
- hasFetched: true,
20
- isSubmitting: false,
21
- fetchFailCount: 0,
22
- wsEnv: 'mw'
23
- },
24
- loadUrl: null,
25
- error: null,
26
- authInfo: {
27
- authEnabled: false,
28
- authStatus: false,
29
- authToken: null,
30
- },
31
- };
14
+ initialState = _.cloneDeep(state);
15
+
16
+ // As the tests are run in a NodeJS environment whereas the correct values for document.URL and window.location.href
17
+ // are set by the browser, for tests, set the appropriate values for document.URL, window.location.href and window.location.origin
18
+ // for the component to render without errors
19
+ // Delete and redefine 'origin' and 'href' properties as they are read-only.
20
+ delete window.location;
21
+ window.location = {
22
+ origin: "/",
23
+ href : "http://127.0.0.1/"
24
+ }
25
+
26
+ initialState.serverStatus.licensingInfo.entitlements = [{ id: "1234567", label: null, license_number: "7654321" }];
27
+ initialState.serverStatus.licensingInfo.entitlementId = "1234567";
28
+
32
29
  const mockIntersectionObserver = jest.fn();
33
30
  mockIntersectionObserver.mockReturnValue({
34
31
  observe: () => null,
@@ -42,17 +39,15 @@ describe('App Component', () => {
42
39
  jest.clearAllMocks();
43
40
  });
44
41
 
45
- // it('renders app without crashing', () => {
46
- // const { getByTestId } = render(<App />);
47
- // expect(getByTestId('app')).toBeInTheDocument();
48
- // });
42
+ it('renders app without crashing', () => {
43
+ const { getByTestId } = render(<App />);
44
+ expect(getByTestId('app')).toBeInTheDocument();
45
+ });
49
46
 
50
47
  it('should render overlayTrigger (after closing the tutorial)', () => {
51
-
52
48
  // Hide the tutorial before rendering the component.
53
- initialState.tutorialHidden = true;
54
- initialState.authInfo.authEnabled = true;
55
- initialState.authInfo.authStatus = true;
49
+ initialState.tutorialHidden = true;
50
+ initialState.overlayVisibility = false;
56
51
 
57
52
  const { getByTestId } = render(<App />, {
58
53
  initialState: initialState,
@@ -67,12 +62,11 @@ describe('App Component', () => {
67
62
  });
68
63
 
69
64
  it('should render LicensingGatherer component within the App component when no licensing is provided and user is authenticated', () => {
70
-
71
65
  //Set lincensingInfo to empty object.
72
66
  initialState.overlayVisibility = true;
73
67
  initialState.serverStatus.licensingInfo = {};
74
- initialState.authInfo.authEnabled = true;
75
- initialState.authInfo.authStatus = true;
68
+ initialState.authentication.enabled = true;
69
+ initialState.authentication.status = true;
76
70
 
77
71
  const { getByRole } = render(<App />, { initialState: initialState });
78
72
 
@@ -83,28 +77,26 @@ describe('App Component', () => {
83
77
  });
84
78
 
85
79
  it('should render LicensingGatherer component within the App component when no licensing is provided and authentication is disabled', () => {
86
-
87
80
  //Set lincensingInfo to empty object.
88
81
  initialState.overlayVisibility = true;
89
82
  initialState.serverStatus.licensingInfo = {};
90
- initialState.authInfo.authEnabled = false;
83
+ initialState.authentication.enabled = false;
91
84
 
92
85
  const { getByRole } = render(<App />, { initialState: initialState });
93
86
 
94
87
  const licensingGathererComponent = getByRole(
95
88
  'dialog', { description: "licensing-dialog" });
96
-
89
+
97
90
  expect(licensingGathererComponent).toBeInTheDocument();
98
91
  });
99
92
 
100
93
  it('should render Information Component within App Component after licensing is provided and user is authenticated', () => {
101
-
102
94
  // Hide the tutorial and make the overlay visible.
103
95
  initialState.tutorialHidden = true;
104
96
  initialState.overlayVisibility = true;
105
97
 
106
- initialState.authInfo.authEnabled = true;
107
- initialState.authInfo.authStatus = true;
98
+ initialState.authentication.enabled = true;
99
+ initialState.authentication.status = true;
108
100
 
109
101
  //Rendering the App component with the above changes to the initial
110
102
  // state should render the Information Component.
@@ -118,12 +110,11 @@ describe('App Component', () => {
118
110
  });
119
111
 
120
112
  it('should render Information Component within App Component after licensing is provided and auth is not enabled', () => {
121
-
122
113
  // Hide the tutorial and make the overlay visible.
123
114
  initialState.tutorialHidden = true;
124
115
  initialState.overlayVisibility = true;
125
116
 
126
- initialState.authInfo.authEnabled = false;
117
+ initialState.authentication.enabled = false;
127
118
 
128
119
  //Rendering the App component with the above changes to the initial
129
120
  // state should render the Information Component.
@@ -138,7 +129,6 @@ describe('App Component', () => {
138
129
  });
139
130
 
140
131
  it('should display integration terminated error', () => {
141
-
142
132
  //Hide the tutorial, make the overlay visible and set fetchFailCount to 10
143
133
  initialState.tutorialHidden = true;
144
134
  initialState.overlayVisibility = true;
@@ -183,7 +173,6 @@ describe('App Component', () => {
183
173
  });
184
174
 
185
175
  it('should display Confirmation component ', () => {
186
-
187
176
  //Hide the tutorial and make the overlay visible
188
177
  initialState.tutorialHidden = true;
189
178
  initialState.overlayVisibility = true;
@@ -208,16 +197,14 @@ describe('App Component', () => {
208
197
  });
209
198
 
210
199
  it('should display Help Component', () => {
211
-
212
200
  //Hide the tutorial and make the overlay visible
213
201
  initialState.tutorialHidden = true;
214
202
  initialState.overlayVisibility = true;
215
203
 
216
- const { getByTestId, container, getByRole } = render(<App />, {
204
+ const { getByTestId, container } = render(<App />, {
217
205
  initialState: initialState,
218
206
  });
219
207
 
220
-
221
208
  // Grab the help button and click it.
222
209
  const helpBtn = getByTestId('helpBtn');
223
210
  fireEvent.click(helpBtn);
@@ -231,19 +218,9 @@ describe('App Component', () => {
231
218
  const url = 'http://localhost.com:5555/matlab/index.html'
232
219
 
233
220
  // define new complete url for document.URL for baseUrl variable to evaluate correctly
234
- // As the tests are run in a NodeJS environment where as the correct values for document.URL and window.location.href
235
- // are set by the browser, set the appropriate values for document.URL, window.location.href and window.location.origin
236
- // for the component to render without errors
237
221
  delete document.URL;
238
222
  document = {URL: url}
239
223
 
240
- // Delete and redefine 'origin' and 'href' properties as they are read-only.
241
- delete window.location;
242
- window.location = {
243
- origin: "/",
244
- href : "http://127.0.0.1/"
245
- }
246
-
247
224
  initialState.loadUrl = url;
248
225
  render(<App />, { initialState: initialState });
249
226
  // Check if href has been set to loadUrl by the useEffect
@@ -259,7 +236,6 @@ describe('App Component', () => {
259
236
  ("should pick the token correctly when the query parameters are '%s'", (queryParams, expectedToken) => {
260
237
  const url = `http://localhost.com:5555`
261
238
  const mockUpdateAuthStatus = jest.spyOn(actionCreators, 'updateAuthStatus');
262
- delete window.location;
263
239
  window.location = {
264
240
  origin: '/',
265
241
  href: url,
@@ -1,4 +1,4 @@
1
- // Copyright 2020-2023 The MathWorks, Inc.
1
+ // Copyright 2020-2024 The MathWorks, Inc.
2
2
 
3
3
  import React, { useState, useCallback, useEffect, useMemo } from 'react';
4
4
  import { useSelector, useDispatch } from 'react-redux';
@@ -30,6 +30,9 @@ import {
30
30
  selectLicensingInfo,
31
31
  selectUseMOS,
32
32
  selectUseMRE,
33
+ selectIsConcurrent,
34
+ selectWasEverActive,
35
+ selectIsConcurrencyEnabled,
33
36
  } from "../../selectors";
34
37
 
35
38
  import {
@@ -55,11 +58,14 @@ function App() {
55
58
  const error = useSelector(selectError);
56
59
  const loadUrl = useSelector(selectLoadUrl);
57
60
  const isConnectionError = useSelector(selectIsConnectionError);
58
- const isAuthenticated = useSelector(selectIsAuthenticated)
61
+ const isAuthenticated = useSelector(selectIsAuthenticated);
59
62
  const authEnabled = useSelector(selectAuthEnabled);
60
63
  const licensingInfo = useSelector(selectLicensingInfo);
61
64
  const useMOS = useSelector(selectUseMOS);
62
65
  const useMRE = useSelector(selectUseMRE);
66
+ const isSessionConcurrent = useSelector(selectIsConcurrent);
67
+ const isConcurrencyEnabled = useSelector(selectIsConcurrencyEnabled);
68
+ const wasEverActive = useSelector(selectWasEverActive);
63
69
 
64
70
  const baseUrl = useMemo(() => {
65
71
  const url = document.URL
@@ -92,7 +98,10 @@ function App() {
92
98
  );
93
99
 
94
100
  const [dialogModel, setDialogModel] = useState(null);
101
+ const [isTerminated, setIsTerminated] = useState(false);
95
102
 
103
+ // sessionDialog stores the state of concurrent session based on which either matlab gets rendered or the concurrent session dialog gets rendered
104
+ let sessionDialog = null;
96
105
  let dialog;
97
106
  if (dialogModel) {
98
107
  const closeHandler = () => setDialogModel(null);
@@ -135,6 +144,35 @@ function App() {
135
144
  );
136
145
  } else if (error && error.type === "MatlabInstallError") {
137
146
  dialog = <Error message={error.message} />;
147
+ }
148
+ // check the user authentication before giving them the option to transfer the session.
149
+ else if ((!authEnabled || isAuthenticated) && isSessionConcurrent && isConcurrencyEnabled) {
150
+ // Transfer the session to this tab
151
+ // setting the query parameter of requestTransferSession to true
152
+ const transferSessionOnClick= () => {
153
+ dispatch(fetchServerStatus(true));
154
+ sessionDialog=null;
155
+ }
156
+ const endSession = () => {
157
+ setIsTerminated(true);
158
+ }
159
+ if(isTerminated) {
160
+ sessionDialog = <Error message="Your session has been terminated. Refresh the page to restart the session." />;
161
+ }
162
+ else {
163
+ sessionDialog = (
164
+ <Confirmation
165
+ confirm={transferSessionOnClick}
166
+ cancel={endSession}
167
+ title='MATLAB is currently open in another window'
168
+ cancelButton={wasEverActive?('Cancel'):('Continue in existing window')}
169
+ confirmButton = {wasEverActive?('Confirm'):('Continue in this window')}>
170
+ {wasEverActive
171
+ ? 'You have been disconnected because MATLAB is open in another window. Click on Confirm to continue using MATLAB here.'
172
+ : <div>MATLAB is open in another window and cannot be opened in a second window or tab at the same time.<br></br>Would you like to continue in this window?</div> }
173
+ </Confirmation>
174
+ );
175
+ }
138
176
  }
139
177
 
140
178
  useEffect(() => {
@@ -147,11 +185,11 @@ function App() {
147
185
 
148
186
  useEffect(() => {
149
187
  // Initial fetch server status
150
- if (!hasFetchedServerStatus) {
188
+ if (hasFetchedEnvConfig && !hasFetchedServerStatus) {
151
189
  dispatch(fetchServerStatus());
152
190
  }
153
191
 
154
- }, [dispatch, hasFetchedServerStatus]);
192
+ }, [dispatch, hasFetchedServerStatus, hasFetchedEnvConfig]);
155
193
 
156
194
  // Periodic fetch server status
157
195
  useInterval(() => {
@@ -233,11 +271,22 @@ function App() {
233
271
  const overlayTrigger = overlayVisible ? null : <OverlayTrigger />;
234
272
 
235
273
  return (
236
- <div data-testid="app" className="main">
237
- {overlayTrigger}
238
- {matlabJsd}
239
- {overlay}
240
- </div>
274
+ // If we use div instead of React.Fragment then the editor screen becomes white / doesn't fully render.
275
+ // Have noticed this behavior both in windows and Linux.
276
+ // If session dialog is not 'null' then render the transfer dialog or error dialog otherwise render the normal MATLAB.
277
+ <React.Fragment>
278
+ {sessionDialog?(
279
+ <Overlay>
280
+ {sessionDialog}
281
+ </Overlay>
282
+ ):(
283
+ <div data-testid="app" className="main">
284
+ {overlayTrigger}
285
+ {matlabJsd}
286
+ {overlay}
287
+ </div>
288
+ )}
289
+ </React.Fragment>
241
290
  );
242
291
  }
243
292