@atlassian/atlassian-connect-js 5.3.190

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.
Files changed (190) hide show
  1. package/.depcheckrc.json +16 -0
  2. package/.editorconfig +9 -0
  3. package/.envrc +5 -0
  4. package/.eslintignore +12 -0
  5. package/.eslintrc +31 -0
  6. package/.husky/pre-commit +11 -0
  7. package/.lintstagedrc.js +6 -0
  8. package/.netrc +1 -0
  9. package/.npmrc-public +4 -0
  10. package/.nvmrc +1 -0
  11. package/LICENSE +3 -0
  12. package/README.md +281 -0
  13. package/bitbucket-pipelines.yml +33 -0
  14. package/build/bin/bin-helper.js +29 -0
  15. package/build/bin/npm-postinstall.js +9 -0
  16. package/build/configs/append-sourcemapping.js +13 -0
  17. package/build/configs/availabletasks.js +15 -0
  18. package/build/configs/clean.js +12 -0
  19. package/build/configs/concat.js +44 -0
  20. package/build/configs/copy.js +32 -0
  21. package/build/configs/index.js +19 -0
  22. package/build/configs/jshint.js +9 -0
  23. package/build/configs/karma.js +11 -0
  24. package/build/configs/replace.js +10 -0
  25. package/build/configs/requirejs.js +187 -0
  26. package/build/configs/saucelabs-launchers.js +30 -0
  27. package/build/configs/shell.js +24 -0
  28. package/build/configs/uglify.js +15 -0
  29. package/build/configs/watch.js +45 -0
  30. package/build/end.frag +13 -0
  31. package/build/start.frag +18 -0
  32. package/bundlesize.config.json +14 -0
  33. package/dist/connect-host.css +225 -0
  34. package/dist/connect-host.js +13908 -0
  35. package/dist/connect-host.min.css +1 -0
  36. package/dist/iframe-fedramp.js +13663 -0
  37. package/dist/iframe.js +13663 -0
  38. package/dist/legacy-text-colors.css +245 -0
  39. package/dist/surfaces.css +11 -0
  40. package/dist/themes/atlaskit-tokens_dark-future.css +6 -0
  41. package/dist/themes/atlaskit-tokens_dark.css +394 -0
  42. package/dist/themes/atlaskit-tokens_legacy-dark.css +394 -0
  43. package/dist/themes/atlaskit-tokens_legacy-light.css +394 -0
  44. package/dist/themes/atlaskit-tokens_light-future.css +6 -0
  45. package/dist/themes/atlaskit-tokens_light.css +394 -0
  46. package/dist/themes/atlaskit-tokens_shape.css +14 -0
  47. package/dist/themes/atlaskit-tokens_spacing.css +26 -0
  48. package/dist/themes/atlaskit-tokens_typography-adg3.css +25 -0
  49. package/dist/themes/atlaskit-tokens_typography-modernized.css +25 -0
  50. package/dist/themes/atlaskit-tokens_typography-refreshed.css +25 -0
  51. package/gulpfile.js +204 -0
  52. package/memleak-check/app.html +10 -0
  53. package/memleak-check/index.html +31 -0
  54. package/memleak-check/index.js +33 -0
  55. package/package.json +102 -0
  56. package/renovate.json +11 -0
  57. package/security-assistant.yml +2 -0
  58. package/spec/.eslintrc +10 -0
  59. package/spec/config/karma.base.conf.js +200 -0
  60. package/spec/config/karma.conf.js +20 -0
  61. package/spec/fixtures/base_dialog_component_tests.js +180 -0
  62. package/spec/mocks/mock_feature_flag.js +23 -0
  63. package/spec/tests/amd_spec.js +122 -0
  64. package/spec/tests/analytics_dispatcher_spec.js +429 -0
  65. package/spec/tests/analytics_performance_spec.js +41 -0
  66. package/spec/tests/button_spec.js +143 -0
  67. package/spec/tests/dialog_extension_spec.js +59 -0
  68. package/spec/tests/dialog_module_provider_spec.js +499 -0
  69. package/spec/tests/dialog_module_spec.js +395 -0
  70. package/spec/tests/dialog_spec.js +296 -0
  71. package/spec/tests/dialog_webitem_spec.js +183 -0
  72. package/spec/tests/dropdown_module_spec.js +77 -0
  73. package/spec/tests/env_module_spec.js +153 -0
  74. package/spec/tests/events_spec.js +77 -0
  75. package/spec/tests/extension_configuration_options_store_spec.js +25 -0
  76. package/spec/tests/flag_module_provider_spec.js +79 -0
  77. package/spec/tests/flag_module_spec.js +118 -0
  78. package/spec/tests/flag_spec.js +243 -0
  79. package/spec/tests/host-api_spec.js +220 -0
  80. package/spec/tests/iframe-create_spec.js +43 -0
  81. package/spec/tests/iframe_container_spec.js +19 -0
  82. package/spec/tests/iframe_spec.js +265 -0
  83. package/spec/tests/inline_dialog_spec.js +41 -0
  84. package/spec/tests/inline_dialog_webitem_spec.js +331 -0
  85. package/spec/tests/loading_indicator_spec.js +48 -0
  86. package/spec/tests/messages_module_spec.js +108 -0
  87. package/spec/tests/meta_spec.js +71 -0
  88. package/spec/tests/module_args_spec.js +52 -0
  89. package/spec/tests/observe_spec.js +73 -0
  90. package/spec/tests/public_events.spec.js +102 -0
  91. package/spec/tests/scroll_position_spec.js +109 -0
  92. package/spec/tests/theming_spec.js +594 -0
  93. package/spec/tests/util_spec.js +55 -0
  94. package/spec/tests/utils/base64_spec.js +20 -0
  95. package/spec/tests/utils/button_spec.js +11 -0
  96. package/spec/tests/utils/cookie_spec.js +19 -0
  97. package/spec/tests/utils/deprecate_spec.js +22 -0
  98. package/spec/tests/utils/dialog_spec.js +297 -0
  99. package/spec/tests/utils/host_util_spec.js +45 -0
  100. package/spec/tests/utils/iframe_spec.js +41 -0
  101. package/spec/tests/utils/jwt_spec.js +135 -0
  102. package/spec/tests/utils/url_spec.js +37 -0
  103. package/spec/tests/utils/waitUntilReadyNextTick.js +5 -0
  104. package/spec/tests/utils/webitem.js +219 -0
  105. package/spec/tests/webitem_spec.js +131 -0
  106. package/src/css/host/dialog.css +144 -0
  107. package/src/css/host/flags.css +5 -0
  108. package/src/css/host/host.css +64 -0
  109. package/src/css/host/messages.css +12 -0
  110. package/src/css/plugin/legacy-text-colors.less +55 -0
  111. package/src/css/plugin/surfaces.css +11 -0
  112. package/src/host/ACJSFrameworkAdaptor.js +44 -0
  113. package/src/host/actions/analytics_action.js +35 -0
  114. package/src/host/actions/button_actions.js +21 -0
  115. package/src/host/actions/dialog_actions.js +27 -0
  116. package/src/host/actions/dialog_extension_actions.js +25 -0
  117. package/src/host/actions/dom_event_actions.js +32 -0
  118. package/src/host/actions/dropdown_actions.js +12 -0
  119. package/src/host/actions/env_actions.js +57 -0
  120. package/src/host/actions/event_actions.js +33 -0
  121. package/src/host/actions/flag_actions.js +22 -0
  122. package/src/host/actions/iframe_actions.js +27 -0
  123. package/src/host/actions/inline_dialog_actions.js +26 -0
  124. package/src/host/actions/inline_dialog_webitem_actions.js +10 -0
  125. package/src/host/actions/jwt_actions.js +51 -0
  126. package/src/host/actions/loading_indicator_actions.js +10 -0
  127. package/src/host/actions/module_actions.js +14 -0
  128. package/src/host/actions/webitem_actions.js +29 -0
  129. package/src/host/components/button.js +112 -0
  130. package/src/host/components/dialog.js +447 -0
  131. package/src/host/components/dialog_extension.js +106 -0
  132. package/src/host/components/dialog_webitem.js +69 -0
  133. package/src/host/components/flag.js +102 -0
  134. package/src/host/components/iframe.js +130 -0
  135. package/src/host/components/iframe_container.js +38 -0
  136. package/src/host/components/inline_dialog.js +108 -0
  137. package/src/host/components/inline_dialog_webitem.js +157 -0
  138. package/src/host/components/loading_indicator.js +110 -0
  139. package/src/host/components/webitem.js +227 -0
  140. package/src/host/deprecate.js +20 -0
  141. package/src/host/dispatchers/analytics_dispatcher.js +512 -0
  142. package/src/host/dispatchers/event_dispatcher.js +46 -0
  143. package/src/host/dollar.js +8 -0
  144. package/src/host/host-api.js +325 -0
  145. package/src/host/iframe-create.js +7 -0
  146. package/src/host/index.js +108 -0
  147. package/src/host/module-providers.js +13 -0
  148. package/src/host/modules/_featureFlag.js +42 -0
  149. package/src/host/modules/_performance.js +54 -0
  150. package/src/host/modules/analytics.js +17 -0
  151. package/src/host/modules/dialog.js +496 -0
  152. package/src/host/modules/dropdown.js +255 -0
  153. package/src/host/modules/env.js +156 -0
  154. package/src/host/modules/events.js +28 -0
  155. package/src/host/modules/flag.js +170 -0
  156. package/src/host/modules/host.js +19 -0
  157. package/src/host/modules/inline-dialog.js +33 -0
  158. package/src/host/modules/messages.js +309 -0
  159. package/src/host/modules/page.js +29 -0
  160. package/src/host/modules/scroll-position.js +102 -0
  161. package/src/host/modules/theming.js +114 -0
  162. package/src/host/stores/extension_configuration_options_store.js +24 -0
  163. package/src/host/util.js +98 -0
  164. package/src/host/utils/access-narrowing-context.js +18 -0
  165. package/src/host/utils/base64.js +22 -0
  166. package/src/host/utils/button.js +10 -0
  167. package/src/host/utils/cookie.js +14 -0
  168. package/src/host/utils/dialog.js +239 -0
  169. package/src/host/utils/feature-flag.js +27 -0
  170. package/src/host/utils/iframe.js +23 -0
  171. package/src/host/utils/jwt.js +60 -0
  172. package/src/host/utils/observe.js +34 -0
  173. package/src/host/utils/removal-observer.js +30 -0
  174. package/src/host/utils/simplexdm.js +58 -0
  175. package/src/host/utils/url.js +23 -0
  176. package/src/host/utils/webitem.js +214 -0
  177. package/src/plugin/amd.js +115 -0
  178. package/src/plugin/analytics.js +84 -0
  179. package/src/plugin/deprecate.js +16 -0
  180. package/src/plugin/dialog.js +197 -0
  181. package/src/plugin/dollar.js +77 -0
  182. package/src/plugin/events-instance.js +2 -0
  183. package/src/plugin/events.js +246 -0
  184. package/src/plugin/extension_configuration_options_store.js +27 -0
  185. package/src/plugin/featureFlag.js +8 -0
  186. package/src/plugin/index.js +118 -0
  187. package/src/plugin/meta.js +14 -0
  188. package/src/plugin/public-events.js +73 -0
  189. package/src/plugin/theming.js +211 -0
  190. package/src/plugin/util.js +104 -0
@@ -0,0 +1,22 @@
1
+ import deprecateHost from '../../../src/host/deprecate';
2
+ import Analytics from '../../../src/host/modules/analytics';
3
+
4
+ const callback = () => {};
5
+ callback._id = 'some-extension-id';
6
+ callback._context = {
7
+ extension: {
8
+ addon_key: 'some-addon-key',
9
+ key: 'some-module-key',
10
+ options: jasmine.objectContaining({})
11
+ }
12
+ };
13
+ describe('host side deprecation', function () {
14
+ it('should deprecate function tracks analytics', function () {
15
+ const deprecateSpy = jasmine.createSpy('test function');
16
+ const analyticsSpy = spyOn(Analytics, 'trackDeprecatedMethodUsed');
17
+ const deprecated = deprecateHost(deprecateSpy, 'test function');
18
+ deprecated(callback);
19
+ expect(deprecateSpy).toHaveBeenCalled();
20
+ expect(analyticsSpy).toHaveBeenCalled();
21
+ });
22
+ });
@@ -0,0 +1,297 @@
1
+ import DialogUtils from 'src/host/utils/dialog';
2
+
3
+ describe('dialog utils', () => {
4
+ describe('_size', () => {
5
+ it('returns xlarge if given size is x-large', () => {
6
+ const options = {
7
+ size: 'x-large'
8
+ };
9
+ expect(DialogUtils._size(options)).toEqual('xlarge');
10
+ });
11
+
12
+ it('returns fullscreen if 100% height and width', () => {
13
+ const options = {
14
+ height: '100%',
15
+ width: '100%'
16
+ };
17
+ expect(DialogUtils._size(options)).toEqual('fullscreen');
18
+ });
19
+
20
+ it('returns maximum even if 100% height and width', () => {
21
+ const options = {
22
+ size: 'maximum',
23
+ height: '100%',
24
+ width: '100%'
25
+ };
26
+ expect(DialogUtils._size(options)).toEqual('maximum');
27
+ });
28
+
29
+ it('does nothing if size is undefined', () => {
30
+ const options = {};
31
+ expect(DialogUtils._size(options)).not.toBeDefined();
32
+ });
33
+
34
+ it('returns original size', () => {
35
+ const options = {
36
+ size: 'small'
37
+ };
38
+ expect(DialogUtils._size(options)).toEqual('small');
39
+ });
40
+
41
+ it('returns original dimensions', () => {
42
+ const options = {
43
+ width: '100px',
44
+ height: '200px'
45
+ };
46
+ expect(DialogUtils._size(options)).not.toBeDefined();
47
+ });
48
+ });
49
+
50
+ describe('_header', () => {
51
+ it('handles string', () => {
52
+ const text = 'this is my header';
53
+ expect(DialogUtils._header(text)).toEqual(text);
54
+ });
55
+
56
+ it('handles object', () => {
57
+ const text = {
58
+ value: 'this is my header'
59
+ };
60
+ expect(DialogUtils._header(text)).toEqual(text.value);
61
+ });
62
+ });
63
+
64
+ describe('_hint', () => {
65
+ it('handles string', () => {
66
+ const text = 'this is a hint';
67
+ expect(DialogUtils._hint(text)).toEqual(text);
68
+ });
69
+
70
+ it('everything else returns blank', () => {
71
+ const text = {
72
+ value: 'this is a hint'
73
+ };
74
+ expect(DialogUtils._hint(text)).toEqual('');
75
+ });
76
+ });
77
+
78
+ describe('_chrome', () => {
79
+ it('defaults to false', () => {
80
+ const options = {};
81
+ expect(DialogUtils._chrome(options)).toBe(false);
82
+ });
83
+
84
+ it('returns original if defined and boolean', () => {
85
+ const options = {
86
+ chrome: true
87
+ };
88
+ expect(DialogUtils._chrome(options)).toBe(options.chrome);
89
+ });
90
+
91
+ it('returns false if chrome is not a boolean', () => {
92
+ const options = {
93
+ chrome: 'yes'
94
+ };
95
+ expect(DialogUtils._chrome(options)).toBe(false);
96
+ });
97
+
98
+ it('returns true if size is fullscreen', () => {
99
+ const options = {
100
+ size: 'fullscreen'
101
+ };
102
+ expect(DialogUtils._chrome(options)).toBe(true);
103
+ });
104
+
105
+ it('returns false if size is maximum', () => {
106
+ const options = {
107
+ size: 'maximum'
108
+ };
109
+ expect(DialogUtils._chrome(options)).toBe(false);
110
+ });
111
+ });
112
+
113
+ describe('_width', () => {
114
+ it('returns undefined if size is defined', () => {
115
+ const options = {
116
+ size: 'medium'
117
+ };
118
+ expect(DialogUtils._width(options)).not.toBeDefined();
119
+ });
120
+
121
+ it('returns formatted width', () => {
122
+ const options = {
123
+ width: '100'
124
+ };
125
+ expect(DialogUtils._width(options)).toEqual(`${options.width}px`);
126
+ });
127
+
128
+ it('returns formatted width width %', () => {
129
+ const options = {
130
+ width: '100%'
131
+ };
132
+ expect(DialogUtils._width(options)).toEqual(options.width);
133
+ });
134
+ });
135
+
136
+ describe('_height', () => {
137
+ it('returns undefined if size is defined', () => {
138
+ const options = {
139
+ size: 'medium'
140
+ };
141
+ expect(DialogUtils._height(options)).not.toBeDefined();
142
+ });
143
+
144
+ it('returns formatted height', () => {
145
+ const options = {
146
+ height: '100'
147
+ };
148
+ expect(DialogUtils._height(options)).toEqual(`${options.height}px`);
149
+ });
150
+
151
+ it('returns formatted height with %', () => {
152
+ const options = {
153
+ height: '100%'
154
+ };
155
+ expect(DialogUtils._height(options)).toEqual(options.height);
156
+ });
157
+ });
158
+
159
+ describe('_actions', () => {
160
+ it('default actions if no actions defined', () => {
161
+ const options = {};
162
+ const actions = DialogUtils._actions(options);
163
+ expect(actions.length).toEqual(2);
164
+ expect(actions[0].name).toEqual('submit');
165
+ expect(actions[0].identifier).toEqual('submit');
166
+ expect(actions[0].text).toEqual('Submit');
167
+ expect(actions[0].type).toEqual('primary');
168
+ expect(actions[1].name).toEqual('cancel');
169
+ expect(actions[1].identifier).toEqual('cancel');
170
+ expect(actions[1].text).toEqual('Cancel');
171
+ expect(actions[1].type).toEqual('link');
172
+ expect(actions[1].immutable).toBe(true);
173
+ });
174
+
175
+ it('return defined actions', () => {
176
+ const options = {
177
+ actions: [
178
+ {
179
+ name: 'someaction',
180
+ identifier: 'someid',
181
+ text: 'some button',
182
+ type: 'primary'
183
+ }
184
+ ]
185
+ };
186
+ const actions = DialogUtils._actions(options);
187
+ expect(actions.length).toEqual(0);
188
+ });
189
+
190
+ it('returns buttons', () => {
191
+ const options = {
192
+ buttons: [
193
+ {
194
+ identifier: 'someid',
195
+ text: 'some button'
196
+ }
197
+ ]
198
+ };
199
+ const actions = DialogUtils._actions(options);
200
+ expect(actions.length).toEqual(3);
201
+ expect(actions[2].identifier).toEqual(options.buttons[0].identifier);
202
+ expect(actions[2].text).toEqual(options.buttons[0].text);
203
+ });
204
+ });
205
+
206
+ describe('_id', () => {
207
+ it('return random id if not a string', () => {
208
+ const str = {
209
+ some: 'thing'
210
+ };
211
+ const id = DialogUtils._id(str);
212
+ expect(id).not.toEqual(str);
213
+ expect(typeof id === 'string').toBe(true);
214
+ });
215
+
216
+ it('return original string', () => {
217
+ const str = 'somestring';
218
+ expect(DialogUtils._id(str)).toEqual(str);
219
+ });
220
+
221
+ });
222
+
223
+ describe('_buttons', () => {
224
+ it('return empty array if given buttons is not an array', () => {
225
+ const options = {
226
+ buttons: 'some string'
227
+ };
228
+ expect(DialogUtils._buttons(options)).toEqual([]);
229
+ });
230
+
231
+ it('text, identifier and disabled', () => {
232
+ const buttonText = 'some text';
233
+ const buttonIdentifier = 'some id';
234
+ const buttonDisabled = true;
235
+ const options = {
236
+ buttons: [
237
+ {
238
+ text: buttonText,
239
+ identifier: buttonIdentifier,
240
+ disabled: buttonDisabled
241
+ }
242
+ ]
243
+ };
244
+ const buttons = DialogUtils._buttons(options);
245
+ expect(buttons.length === 1).toBe(true);
246
+ expect(buttons[0].text).toEqual(buttonText);
247
+ expect(buttons[0].identifier).toEqual(buttonIdentifier);
248
+ expect(buttons[0].disabled).toEqual(buttonDisabled);
249
+ expect(buttons[0].custom).toBe(true);
250
+ expect(buttons[0].type).toEqual('secondary');
251
+ });
252
+
253
+ it('text and identifier not defined', () => {
254
+ const options = {
255
+ buttons: [
256
+ {}
257
+ ]
258
+ };
259
+ const buttons = DialogUtils._buttons(options);
260
+ expect(buttons.length === 1).toBe(true);
261
+ expect(buttons[0].text).not.toBeDefined();
262
+ expect(buttons[0].identifier).toBeDefined();
263
+ expect(buttons[0].disabled).toBe(false);
264
+ });
265
+
266
+ });
267
+
268
+ describe('moduleOptionsFromGlobal', () => {
269
+ const options = {
270
+ options: {
271
+ someKey: 'someVal'
272
+ }
273
+ };
274
+ const defaults = {
275
+ chrome: true,
276
+ hostFrameOffset: 1
277
+ };
278
+
279
+ beforeEach(() => {
280
+ window._AP = {
281
+ dialogModules: {
282
+ addonKey: {
283
+ moduleKey: options
284
+ }
285
+ }
286
+ }
287
+ });
288
+
289
+ it('returns false if not defined', () => {
290
+ expect(DialogUtils.moduleOptionsFromGlobal('notAddonKey', 'something else')).toBe(false);
291
+ });
292
+
293
+ it('returns expected options with defaults', () => {
294
+ expect(DialogUtils.moduleOptionsFromGlobal('addonKey', 'moduleKey')).toEqual($.extend({}, defaults, options.options));
295
+ });
296
+ });
297
+ });
@@ -0,0 +1,45 @@
1
+ import util from 'src/host/util';
2
+
3
+ describe('host util', () => {
4
+ describe('escapeSelector', () => {
5
+ it('throws an error when selector not defined', () => {
6
+ expect(() => {
7
+ util.escapeSelector();
8
+ }).toThrow();
9
+ });
10
+
11
+ it('escapes given string', () => {
12
+ const testString = '!"#$%&\'()*+,.\/:;<=>?@[\\\]^`{|}~test';
13
+ const expectedString = '\\!\\"\\#\\$\\%\\&\\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\\]\\^\\`\\{\\|\\}\\~test';
14
+ expect(util.escapeSelector(testString)).toEqual(expectedString);
15
+ });
16
+
17
+ it('does not escape string if there are no special characters', () => {
18
+ const testString = 'this is a string';
19
+ expect(util.escapeSelector(testString)).toEqual(testString);
20
+ });
21
+ });
22
+
23
+ describe('stringToDimension', () => {
24
+ it('return formatted string (px) given a string', () => {
25
+ const dimension = '100px';
26
+ expect(util.stringToDimension(dimension)).toEqual(dimension);
27
+ });
28
+
29
+ it('return formatted string (%) given a string', () => {
30
+ const dimension = '100%';
31
+ expect(util.stringToDimension(dimension)).toEqual(dimension);
32
+ });
33
+
34
+ it('defaults to px', () => {
35
+ const dimension = '100';
36
+ expect(util.stringToDimension(dimension)).toEqual(`${dimension}px`);
37
+ });
38
+
39
+ it('defaults to px (number)', () => {
40
+ const dimension = 100;
41
+ expect(util.stringToDimension(dimension)).toEqual(`${dimension}px`);
42
+ });
43
+ });
44
+ });
45
+
@@ -0,0 +1,41 @@
1
+ import IframeUtils from 'src/host/utils/iframe';
2
+
3
+ describe('iframe utils', () => {
4
+ describe('optionsToAttributes', () => {
5
+
6
+ it('returns empty object if options is not an object', () => {
7
+ expect(IframeUtils.optionsToAttributes('not an object')).toEqual({});
8
+ });
9
+
10
+ it('returns sanitised dimensions', () => {
11
+ const options = {
12
+ width: '100',
13
+ height: '500',
14
+ size: 'medium'
15
+ };
16
+
17
+ const attributes = IframeUtils.optionsToAttributes(options);
18
+ expect(attributes.width).toEqual(`${options.width}px`);
19
+ expect(attributes.height).toEqual(`${options.height}px`);
20
+ expect(attributes.size).not.toBeDefined();
21
+ });
22
+
23
+ it('returns sanitised sandbox', () => {
24
+ const sandbox = 'allow-downloads allow-forms allow-modals allow-popups allow-scripts allow-same-origin allow-top-navigation-by-user-activation allow-storage-access-by-user-activation';
25
+ const attributes = IframeUtils.optionsToAttributes({ sandbox });
26
+ // could be anything based on browser support, so just check not-empty
27
+ expect(attributes.sandbox.length > 0).toBe(true);
28
+ });
29
+
30
+ it('does not return sandbox if not present', () => {
31
+ const attributes = IframeUtils.optionsToAttributes({});
32
+ expect(typeof attributes.sandbox).toEqual('undefined');
33
+ });
34
+
35
+ it('does not return sandbox if wrong type', () => {
36
+ const sandbox = {};
37
+ const attributes = IframeUtils.optionsToAttributes({ sandbox });
38
+ expect(typeof attributes.sandbox).toEqual('undefined');
39
+ });
40
+ });
41
+ });
@@ -0,0 +1,135 @@
1
+ import jwtUtils from 'src/host/utils/jwt';
2
+ import base64 from 'src/host/utils/base64';
3
+
4
+ describe('jwt utils', () => {
5
+
6
+ describe('funky characters decoding', () => {
7
+ it('Accented characters', () => {
8
+ const claims = {
9
+ user: 'aàáâãäåçèéêëìíîðñòôõööz'
10
+ };
11
+ const encodedClaims = 'eyJ1c2VyIjoiYcOgw6HDosOjw6TDpcOnw6jDqcOqw6vDrMOtw67DsMOxw7LDtMO1w7bDtnoifQ';
12
+ const jwt = `alsdjfaj123.${encodedClaims}.khsadlj234`;
13
+ expect(jwtUtils.parseJwtClaims(jwt)).toEqual(claims);
14
+ });
15
+
16
+ it('Asian characters', () => {
17
+ const claims = {
18
+ user: 'a国際交流基金海外運営専門員z'
19
+ };
20
+ const encodedClaims = 'eyJ1c2VyIjoiYeWbvemam-S6pOa1geWfuumHkea1t-WklumBi-WWtuWwgumWgOWToXoifQ';
21
+ const jwt = `alsdjfaj123.${encodedClaims}.khsadlj234`;
22
+ expect(jwtUtils.parseJwtClaims(jwt)).toEqual(claims);
23
+ });
24
+
25
+ it('Good international string characters', () => {
26
+ const claims = {
27
+ user: 'àáâãäåçèéêëìíîðñòôõöö 国際交流абвгдежзبْجَدِيَّة عَرَبِيَّة‎עִבְרִיתदिंदुसरोवरλληνικ'
28
+ };
29
+ const encodedClaims = 'eyJ1c2VyIjoiw6DDocOiw6PDpMOlw6fDqMOpw6rDq8Osw63DrsOww7HDssO0w7XDtsO2IOWb' +
30
+ 'vemam-S6pOa1gdCw0LHQstCz0LTQtdC20LfYqNmS2KzZjtiv2ZDZitmO2ZHYqSDYudmO2LHZjtio2ZDZitmO2ZHYqe' +
31
+ 'KAjtei1rTXkdaw16jWtNeZ16rgpKbgpL_gpILgpKbgpYHgpLjgpLDgpYvgpLXgpLDOu867zrfOvc65zroifQ';
32
+ const jwt = `alsdjfaj123.${encodedClaims}.khsadlj234`;
33
+ expect(jwtUtils.parseJwtClaims(jwt)).toEqual(claims);
34
+ });
35
+
36
+ it('Good international string characters', () => {
37
+ const claims = {
38
+ user: 'a♬♬♫b'
39
+ };
40
+ const encodedClaims = 'eyJ1c2VyIjoiYeKZrOKZrOKZq2IifQ';
41
+ const jwt = `alsdjfaj123.${encodedClaims}.khsadlj234`;
42
+ expect(jwtUtils.parseJwtClaims(jwt)).toEqual(claims);
43
+ });
44
+
45
+
46
+ });
47
+
48
+ describe('parseJwtIssuer', () => {
49
+ it('returns iss from claim', () => {
50
+ const iss = 'jira:59975d67-4ca0-4e9e-9960-123412312';
51
+ const claim = {
52
+ iss: iss
53
+ };
54
+ const encodedClaim = base64.encode(JSON.stringify(claim));
55
+ const jwt = `alsdjfaj123.${encodedClaim}.khsadlj234`;
56
+ expect(jwtUtils.parseJwtIssuer(jwt)).toEqual(iss);
57
+ })
58
+ });
59
+
60
+ describe('parseJwtClaims', () => {
61
+ it('throws when jwt is empty of null', () => {
62
+ expect(() => {
63
+ jwtUtils.parseJwtClaims(null);
64
+ }).toThrow();
65
+
66
+ expect(() => {
67
+ jwtUtils.parseJwtClaims('');
68
+ }).toThrow();
69
+ });
70
+
71
+ it('throws when just does not contain 2 periods', () => {
72
+ expect(() => {
73
+ jwtUtils.parseJwtClaims('invalidjwt');
74
+ }).toThrow();
75
+
76
+ expect(() => {
77
+ jwtUtils.parseJwtClaims('invalid.jwt');
78
+ }).toThrow();
79
+ });
80
+
81
+ it('throws when encoded claims is empty or null', () => {
82
+ expect(() => {
83
+ jwtUtils.parseJwtClaims('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ');
84
+ }).toThrow();
85
+ });
86
+
87
+ it('returns claims', () => {
88
+ const jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ';
89
+ const expectedClaims = {
90
+ sub: '1234567890',
91
+ name: 'John Doe',
92
+ admin: true
93
+ };
94
+ expect(jwtUtils.parseJwtClaims(jwt)).toEqual(expectedClaims);
95
+ });
96
+ });
97
+
98
+ describe('isJwtExpired', () => {
99
+ it('returns true if expired', () => {
100
+ const claim = {
101
+ exp: Math.floor(Date.now() / 1000) - 60
102
+ };
103
+ const encodedClaim = base64.encode(JSON.stringify(claim));
104
+ const jwt = `alsdjfaj123.${encodedClaim}.khsadlj234`;
105
+ expect(jwtUtils.isJwtExpired(jwt)).toBe(true);
106
+ });
107
+
108
+ it('returns false if not expired', () => {
109
+ const claim = {
110
+ exp: Math.floor(Date.now() / 1000) + 60
111
+ };
112
+ const encodedClaim = base64.encode(JSON.stringify(claim));
113
+ const jwt = `alsdjfaj123.${encodedClaim}.khsadlj234`;
114
+ expect(jwtUtils.isJwtExpired(jwt)).toBe(false);
115
+ });
116
+
117
+ it('returns true if expired with skew', () => {
118
+ const claim = {
119
+ exp: Math.floor(Date.now() / 1000) + 60
120
+ };
121
+ const encodedClaim = base64.encode(JSON.stringify(claim));
122
+ const jwt = `alsdjfaj123.${encodedClaim}.khsadlj234`;
123
+ expect(jwtUtils.isJwtExpired(jwt, 120)).toBe(true);
124
+ });
125
+
126
+ it('returns false if not expired with skew', () => {
127
+ const claim = {
128
+ exp: Math.floor(Date.now() / 1000) + 120
129
+ };
130
+ const encodedClaim = base64.encode(JSON.stringify(claim));
131
+ const jwt = `alsdjfaj123.${encodedClaim}.khsadlj234`;
132
+ expect(jwtUtils.isJwtExpired(jwt, 120)).toBe(false);
133
+ });
134
+ });
135
+ });
@@ -0,0 +1,37 @@
1
+ import UrlUtils from 'src/host/utils/url';
2
+ import base64 from 'src/host/utils/base64';
3
+
4
+ describe('url utils', () => {
5
+ describe('isJwtExpired', () => {
6
+ it('returns true when jwt is expired', () => {
7
+ const claim = {
8
+ exp: Math.floor(Date.now() / 1000) - 60
9
+ };
10
+ const encodedClaim = base64.encode(JSON.stringify(claim));
11
+ const url = `https://some.url.com?jwt=alsdjfaj123.${encodedClaim}.khsadlj234`;
12
+ expect(UrlUtils.isJwtExpired(url)).toBe(true);
13
+ });
14
+
15
+ it('returns false when jwt is not expired', () => {
16
+ const claim = {
17
+ exp: Math.floor(Date.now() / 1000) + 70
18
+ };
19
+ const encodedClaim = base64.encode(JSON.stringify(claim));
20
+ const url = `https://some.url.com?jwt=alsdjfaj123.${encodedClaim}.khsadlj234`;
21
+ expect(UrlUtils.isJwtExpired(url)).toBe(false);
22
+ });
23
+ });
24
+
25
+ describe('hasJwt', () => {
26
+ it('returns false when jwt is not present in url', () => {
27
+ const url = 'https://some.url.com';
28
+ expect(!!UrlUtils.hasJwt(url)).toBe(false);
29
+ });
30
+
31
+ it('returns true when jwt is present in url', () => {
32
+ const jwt = 'test.test.test';
33
+ const url = `https://some.url.com?jwt=${jwt}`;
34
+ expect(UrlUtils.hasJwt(url)).toBe(true);
35
+ });
36
+ });
37
+ });
@@ -0,0 +1,5 @@
1
+ export function waitUntilReadyNextTick(callback) {
2
+ $(() => {
3
+ setTimeout(callback, 1);
4
+ })
5
+ }