delectusnon 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (276) hide show
  1. package/.prettierignore +2 -0
  2. package/.travis.yml +33 -0
  3. package/.vscode/launch.json +24 -0
  4. package/.vscode/settings.json +3 -0
  5. package/demos/ago-node-cli/README.md +29 -0
  6. package/demos/ago-node-cli/ago.js +32 -0
  7. package/demos/ago-node-cli/index.js +11 -0
  8. package/demos/ago-node-cli/lib/item-export-command.js +48 -0
  9. package/demos/ago-node-cli/lib/item-search-command.js +35 -0
  10. package/demos/ago-node-cli/package-lock.json +172 -0
  11. package/demos/ago-node-cli/package.json +30 -0
  12. package/demos/attachments/README.md +5 -0
  13. package/demos/attachments/index.html +164 -0
  14. package/demos/attachments/package-lock.json +182 -0
  15. package/demos/attachments/package.json +18 -0
  16. package/demos/batch-geocoder-node/NYC_Restaurant_Inspection_Results.csv +100 -0
  17. package/demos/batch-geocoder-node/README.md +15 -0
  18. package/demos/batch-geocoder-node/batch-geocode.js +118 -0
  19. package/demos/batch-geocoder-node/config-template.js +18 -0
  20. package/demos/batch-geocoder-node/package-lock.json +116 -0
  21. package/demos/batch-geocoder-node/package.json +39 -0
  22. package/demos/express/README.md +10 -0
  23. package/demos/express/config.json.template +3 -0
  24. package/demos/express/package-lock.json +473 -0
  25. package/demos/express/package.json +18 -0
  26. package/demos/express/server.js +28 -0
  27. package/demos/feature-service-browser/README.md +6 -0
  28. package/demos/feature-service-browser/index.html +122 -0
  29. package/demos/feature-service-browser/package-lock.json +182 -0
  30. package/demos/feature-service-browser/package.json +18 -0
  31. package/demos/geocoder-browser/README.md +10 -0
  32. package/demos/geocoder-browser/config.js.template +1 -0
  33. package/demos/geocoder-browser/index.html +131 -0
  34. package/demos/geocoder-browser/package-lock.json +182 -0
  35. package/demos/geocoder-browser/package.json +19 -0
  36. package/demos/geocoder-browser/post-sign-in.html +25 -0
  37. package/demos/jsapi-integration/README.md +8 -0
  38. package/demos/jsapi-integration/config.js +6 -0
  39. package/demos/jsapi-integration/index.html +79 -0
  40. package/demos/jsapi-integration/package-lock.json +184 -0
  41. package/demos/jsapi-integration/package.json +19 -0
  42. package/demos/oauth2-browser/README.md +12 -0
  43. package/demos/oauth2-browser/authenticate.html +32 -0
  44. package/demos/oauth2-browser/config.js.template +6 -0
  45. package/demos/oauth2-browser/index.html +202 -0
  46. package/demos/oauth2-browser/logo.svg +4 -0
  47. package/demos/oauth2-browser/package-lock.json +163 -0
  48. package/demos/oauth2-browser/package.json +18 -0
  49. package/demos/oauth2-browser/style.css +36 -0
  50. package/demos/oauth2-browser-retry/README.md +25 -0
  51. package/demos/oauth2-browser-retry/authenticate.html +21 -0
  52. package/demos/oauth2-browser-retry/index.html +116 -0
  53. package/demos/oauth2-browser-retry/logo.svg +4 -0
  54. package/demos/vue/.env.example +11 -0
  55. package/demos/vue/.eslintrc.js +17 -0
  56. package/demos/vue/.postcssrc.js +5 -0
  57. package/demos/vue/README.md +17 -0
  58. package/demos/vue/babel.config.js +3 -0
  59. package/demos/vue/package-lock.json +11323 -0
  60. package/demos/vue/package.json +33 -0
  61. package/demos/vue/public/favicon.ico +0 -0
  62. package/demos/vue/public/index.html +24 -0
  63. package/demos/vue/src/assets/logo.svg +29 -0
  64. package/demos/vue/src/components/App.vue +308 -0
  65. package/demos/vue/src/components/Authenticate.vue +65 -0
  66. package/demos/vue/src/components/Loader.vue +230 -0
  67. package/demos/vue/src/main.js +92 -0
  68. package/docs/FAQ.md +28 -0
  69. package/docs/HISTORY.md +62 -0
  70. package/docs/acetate.config.js +223 -0
  71. package/docs/build-typedoc.js +301 -0
  72. package/docs/src/_layout.html +82 -0
  73. package/docs/src/api/_declaration.html +496 -0
  74. package/docs/src/api/_layout.html +127 -0
  75. package/docs/src/api/_package.html +13 -0
  76. package/docs/src/api/index.html +23 -0
  77. package/docs/src/guides/_layout.html +24 -0
  78. package/docs/src/guides/amd-requirejs-dojo.md +40 -0
  79. package/docs/src/guides/babel-and-rollup.md +30 -0
  80. package/docs/src/guides/babel-and-webpack.md +30 -0
  81. package/docs/src/guides/browser-authentication.md +31 -0
  82. package/docs/src/guides/browserify.md +9 -0
  83. package/docs/src/guides/cli-authentication.md +9 -0
  84. package/docs/src/guides/client-server-authentication.md +9 -0
  85. package/docs/src/guides/from-a-cdn.md +36 -0
  86. package/docs/src/guides/index.md +52 -0
  87. package/docs/src/guides/node.md +70 -0
  88. package/docs/src/guides/package-overview.md +8 -0
  89. package/docs/src/guides/server-authentication.md +9 -0
  90. package/docs/src/guides/typescript-and-webpack.md +9 -0
  91. package/docs/src/img/icons.png +0 -0
  92. package/docs/src/img/icons@2x.png +0 -0
  93. package/docs/src/index.html +12 -0
  94. package/docs/src/js/api-search.js +112 -0
  95. package/docs/src/js/nav-toggle.js +41 -0
  96. package/docs/src/sass/_highlight.scss +96 -0
  97. package/docs/src/sass/_icons.scss +157 -0
  98. package/docs/src/sass/style.scss +169 -0
  99. package/jasmine.json +7 -0
  100. package/karma.conf.js +100 -0
  101. package/lerna.json +8 -0
  102. package/notes/README.md +88 -0
  103. package/package.json +88 -0
  104. package/packages/arcgis-rest-auth/README.md +64 -0
  105. package/packages/arcgis-rest-auth/package-lock.json +11 -0
  106. package/packages/arcgis-rest-auth/package.json +51 -0
  107. package/packages/arcgis-rest-auth/src/ApplicationSession.ts +109 -0
  108. package/packages/arcgis-rest-auth/src/UserSession.ts +873 -0
  109. package/packages/arcgis-rest-auth/src/authenticated-request-options.ts +24 -0
  110. package/packages/arcgis-rest-auth/src/fetch-token.ts +52 -0
  111. package/packages/arcgis-rest-auth/src/generate-token.ts +39 -0
  112. package/packages/arcgis-rest-auth/src/index.ts +8 -0
  113. package/packages/arcgis-rest-auth/test/ApplicationSession.test.ts +124 -0
  114. package/packages/arcgis-rest-auth/test/UserSession.test.ts +995 -0
  115. package/packages/arcgis-rest-auth/test/fetchToken.test.ts +112 -0
  116. package/packages/arcgis-rest-auth/test/generateToken.test.ts +130 -0
  117. package/packages/arcgis-rest-auth/test/utils.ts +14 -0
  118. package/packages/arcgis-rest-auth/tsconfig.json +6 -0
  119. package/packages/arcgis-rest-common-types/README.md +61 -0
  120. package/packages/arcgis-rest-common-types/package.json +38 -0
  121. package/packages/arcgis-rest-common-types/src/group.ts +54 -0
  122. package/packages/arcgis-rest-common-types/src/index.ts +467 -0
  123. package/packages/arcgis-rest-common-types/src/item.ts +45 -0
  124. package/packages/arcgis-rest-common-types/src/webmap.ts +1232 -0
  125. package/packages/arcgis-rest-common-types/tsconfig.json +11 -0
  126. package/packages/arcgis-rest-feature-service/README.md +70 -0
  127. package/packages/arcgis-rest-feature-service/package-lock.json +11 -0
  128. package/packages/arcgis-rest-feature-service/package.json +50 -0
  129. package/packages/arcgis-rest-feature-service/src/add.ts +81 -0
  130. package/packages/arcgis-rest-feature-service/src/addAttachment.ts +65 -0
  131. package/packages/arcgis-rest-feature-service/src/delete.ts +85 -0
  132. package/packages/arcgis-rest-feature-service/src/deleteAttachments.ts +68 -0
  133. package/packages/arcgis-rest-feature-service/src/getAttachments.ts +64 -0
  134. package/packages/arcgis-rest-feature-service/src/helpers.ts +80 -0
  135. package/packages/arcgis-rest-feature-service/src/index.ts +12 -0
  136. package/packages/arcgis-rest-feature-service/src/query.ts +172 -0
  137. package/packages/arcgis-rest-feature-service/src/queryRelated.ts +91 -0
  138. package/packages/arcgis-rest-feature-service/src/update.ts +81 -0
  139. package/packages/arcgis-rest-feature-service/src/updateAttachment.ts +74 -0
  140. package/packages/arcgis-rest-feature-service/test/attachments.test.ts +203 -0
  141. package/packages/arcgis-rest-feature-service/test/features.test.ts +252 -0
  142. package/packages/arcgis-rest-feature-service/test/mocks/feature.ts +279 -0
  143. package/packages/arcgis-rest-feature-service/test/mocks/foo.txt +1 -0
  144. package/packages/arcgis-rest-feature-service/tsconfig.json +6 -0
  145. package/packages/arcgis-rest-feature-service-admin/README.md +66 -0
  146. package/packages/arcgis-rest-feature-service-admin/package-lock.json +11 -0
  147. package/packages/arcgis-rest-feature-service-admin/package.json +53 -0
  148. package/packages/arcgis-rest-feature-service-admin/src/addTo.ts +70 -0
  149. package/packages/arcgis-rest-feature-service-admin/src/create.ts +195 -0
  150. package/packages/arcgis-rest-feature-service-admin/src/index.ts +2 -0
  151. package/packages/arcgis-rest-feature-service-admin/test/addTo.test.ts +310 -0
  152. package/packages/arcgis-rest-feature-service-admin/test/create.test.ts +412 -0
  153. package/packages/arcgis-rest-feature-service-admin/test/mocks/move.ts +14 -0
  154. package/packages/arcgis-rest-feature-service-admin/test/mocks/service.ts +72 -0
  155. package/packages/arcgis-rest-feature-service-admin/tsconfig.json +6 -0
  156. package/packages/arcgis-rest-geocoder/README.md +79 -0
  157. package/packages/arcgis-rest-geocoder/package-lock.json +11 -0
  158. package/packages/arcgis-rest-geocoder/package.json +52 -0
  159. package/packages/arcgis-rest-geocoder/src/bulk.ts +102 -0
  160. package/packages/arcgis-rest-geocoder/src/geocode.ts +117 -0
  161. package/packages/arcgis-rest-geocoder/src/helpers.ts +79 -0
  162. package/packages/arcgis-rest-geocoder/src/index.ts +8 -0
  163. package/packages/arcgis-rest-geocoder/src/reverse.ts +84 -0
  164. package/packages/arcgis-rest-geocoder/src/suggest.ts +72 -0
  165. package/packages/arcgis-rest-geocoder/test/bulk.test.ts +113 -0
  166. package/packages/arcgis-rest-geocoder/test/geocode.test.ts +121 -0
  167. package/packages/arcgis-rest-geocoder/test/helpers.test.ts +113 -0
  168. package/packages/arcgis-rest-geocoder/test/mocks/responses.ts +591 -0
  169. package/packages/arcgis-rest-geocoder/test/reverse.test.ts +126 -0
  170. package/packages/arcgis-rest-geocoder/test/suggest.test.ts +77 -0
  171. package/packages/arcgis-rest-geocoder/tsconfig.json +6 -0
  172. package/packages/arcgis-rest-groups/README.md +64 -0
  173. package/packages/arcgis-rest-groups/package-lock.json +11 -0
  174. package/packages/arcgis-rest-groups/package.json +52 -0
  175. package/packages/arcgis-rest-groups/src/create.ts +34 -0
  176. package/packages/arcgis-rest-groups/src/get.ts +95 -0
  177. package/packages/arcgis-rest-groups/src/helpers.ts +26 -0
  178. package/packages/arcgis-rest-groups/src/index.ts +11 -0
  179. package/packages/arcgis-rest-groups/src/notification.ts +77 -0
  180. package/packages/arcgis-rest-groups/src/protect.ts +40 -0
  181. package/packages/arcgis-rest-groups/src/remove.ts +23 -0
  182. package/packages/arcgis-rest-groups/src/search.ts +64 -0
  183. package/packages/arcgis-rest-groups/src/update.ts +36 -0
  184. package/packages/arcgis-rest-groups/test/crud.test.ts +104 -0
  185. package/packages/arcgis-rest-groups/test/get.test.ts +101 -0
  186. package/packages/arcgis-rest-groups/test/mocks/responses.ts +141 -0
  187. package/packages/arcgis-rest-groups/test/notification.test.ts +102 -0
  188. package/packages/arcgis-rest-groups/test/protect.test.ts +64 -0
  189. package/packages/arcgis-rest-groups/test/search.test.ts +85 -0
  190. package/packages/arcgis-rest-groups/tsconfig.json +6 -0
  191. package/packages/arcgis-rest-items/README.md +66 -0
  192. package/packages/arcgis-rest-items/package-lock.json +11 -0
  193. package/packages/arcgis-rest-items/package.json +52 -0
  194. package/packages/arcgis-rest-items/src/add.ts +103 -0
  195. package/packages/arcgis-rest-items/src/create.ts +110 -0
  196. package/packages/arcgis-rest-items/src/get.ts +79 -0
  197. package/packages/arcgis-rest-items/src/helpers.ts +147 -0
  198. package/packages/arcgis-rest-items/src/index.ts +11 -0
  199. package/packages/arcgis-rest-items/src/protect.ts +38 -0
  200. package/packages/arcgis-rest-items/src/remove.ts +58 -0
  201. package/packages/arcgis-rest-items/src/search.ts +78 -0
  202. package/packages/arcgis-rest-items/src/update.ts +134 -0
  203. package/packages/arcgis-rest-items/test/add.test.ts +256 -0
  204. package/packages/arcgis-rest-items/test/create.test.ts +371 -0
  205. package/packages/arcgis-rest-items/test/get.test.ts +181 -0
  206. package/packages/arcgis-rest-items/test/mocks/foo.zip +0 -0
  207. package/packages/arcgis-rest-items/test/mocks/item.ts +33 -0
  208. package/packages/arcgis-rest-items/test/mocks/resources.ts +31 -0
  209. package/packages/arcgis-rest-items/test/mocks/search.ts +63 -0
  210. package/packages/arcgis-rest-items/test/protect.test.ts +122 -0
  211. package/packages/arcgis-rest-items/test/remove.test.ts +161 -0
  212. package/packages/arcgis-rest-items/test/search.test.ts +159 -0
  213. package/packages/arcgis-rest-items/test/update.test.ts +450 -0
  214. package/packages/arcgis-rest-items/tsconfig.json +6 -0
  215. package/packages/arcgis-rest-request/README.md +65 -0
  216. package/packages/arcgis-rest-request/package-lock.json +11 -0
  217. package/packages/arcgis-rest-request/package.json +42 -0
  218. package/packages/arcgis-rest-request/src/index.ts +13 -0
  219. package/packages/arcgis-rest-request/src/request.ts +293 -0
  220. package/packages/arcgis-rest-request/src/utils/ArcGISAuthError.ts +67 -0
  221. package/packages/arcgis-rest-request/src/utils/ArcGISRequestError.ts +76 -0
  222. package/packages/arcgis-rest-request/src/utils/ErrorTypes.ts +29 -0
  223. package/packages/arcgis-rest-request/src/utils/check-for-errors.ts +65 -0
  224. package/packages/arcgis-rest-request/src/utils/encode-form-data.ts +34 -0
  225. package/packages/arcgis-rest-request/src/utils/encode-query-string.ts +23 -0
  226. package/packages/arcgis-rest-request/src/utils/get-portal-url.ts +25 -0
  227. package/packages/arcgis-rest-request/src/utils/get-portal.ts +45 -0
  228. package/packages/arcgis-rest-request/src/utils/process-params.ts +99 -0
  229. package/packages/arcgis-rest-request/test/mocks/errors.ts +68 -0
  230. package/packages/arcgis-rest-request/test/mocks/geojson-feature-collection.ts +13 -0
  231. package/packages/arcgis-rest-request/test/mocks/portal.ts +112 -0
  232. package/packages/arcgis-rest-request/test/mocks/sharing-rest-info.ts +41 -0
  233. package/packages/arcgis-rest-request/test/mocks/webmap.ts +41 -0
  234. package/packages/arcgis-rest-request/test/request.test.ts +299 -0
  235. package/packages/arcgis-rest-request/test/utils/ArcGISAuthError.test.ts +170 -0
  236. package/packages/arcgis-rest-request/test/utils/ArcGISRequestError.test.ts +51 -0
  237. package/packages/arcgis-rest-request/test/utils/check-for-errors.test.ts +111 -0
  238. package/packages/arcgis-rest-request/test/utils/encode-form-data.test.ts +133 -0
  239. package/packages/arcgis-rest-request/test/utils/get-portal-url.test.ts +37 -0
  240. package/packages/arcgis-rest-request/test/utils/portal.test.ts +97 -0
  241. package/packages/arcgis-rest-request/test/utils/process-params.test.ts +193 -0
  242. package/packages/arcgis-rest-request/tsconfig.json +6 -0
  243. package/packages/arcgis-rest-sharing/README.md +67 -0
  244. package/packages/arcgis-rest-sharing/package-lock.json +11 -0
  245. package/packages/arcgis-rest-sharing/package.json +57 -0
  246. package/packages/arcgis-rest-sharing/src/access.ts +85 -0
  247. package/packages/arcgis-rest-sharing/src/group-sharing.ts +211 -0
  248. package/packages/arcgis-rest-sharing/src/helpers.ts +82 -0
  249. package/packages/arcgis-rest-sharing/src/index.ts +5 -0
  250. package/packages/arcgis-rest-sharing/test/access.test.ts +154 -0
  251. package/packages/arcgis-rest-sharing/test/group-sharing.test.ts +566 -0
  252. package/packages/arcgis-rest-sharing/test/helpers.test.ts +55 -0
  253. package/packages/arcgis-rest-sharing/test/mocks/sharing.ts +18 -0
  254. package/packages/arcgis-rest-sharing/tsconfig.json +6 -0
  255. package/packages/arcgis-rest-users/README.md +71 -0
  256. package/packages/arcgis-rest-users/package-lock.json +11 -0
  257. package/packages/arcgis-rest-users/package.json +51 -0
  258. package/packages/arcgis-rest-users/src/get.ts +69 -0
  259. package/packages/arcgis-rest-users/src/index.ts +6 -0
  260. package/packages/arcgis-rest-users/src/invitation.ts +166 -0
  261. package/packages/arcgis-rest-users/src/notification.ts +73 -0
  262. package/packages/arcgis-rest-users/test/get.test.ts +99 -0
  263. package/packages/arcgis-rest-users/test/invitation.test.ts +169 -0
  264. package/packages/arcgis-rest-users/test/mocks/invitation.ts +70 -0
  265. package/packages/arcgis-rest-users/test/mocks/notification.ts +34 -0
  266. package/packages/arcgis-rest-users/test/mocks/user.ts +173 -0
  267. package/packages/arcgis-rest-users/test/notification.test.ts +83 -0
  268. package/packages/arcgis-rest-users/tsconfig.json +6 -0
  269. package/support/changelog.js +394 -0
  270. package/support/deploy-doc-site.js +16 -0
  271. package/support/publish.sh +43 -0
  272. package/support/test-helpers.js +8 -0
  273. package/tsconfig.json +69 -0
  274. package/tslint.json +15 -0
  275. package/umd-base-profile.js +82 -0
  276. package/umd-production-profile.js +13 -0
@@ -0,0 +1,995 @@
1
+ /* Copyright (c) 2018 Environmental Systems Research Institute, Inc.
2
+ * Apache-2.0 */
3
+
4
+ import { UserSession } from "../src/index";
5
+ import { ICredential } from "../src/UserSession";
6
+
7
+ import {
8
+ ArcGISRequestError,
9
+ ArcGISAuthError,
10
+ ErrorTypes
11
+ } from "@esri/arcgis-rest-request";
12
+ import * as fetchMock from "fetch-mock";
13
+ import { YESTERDAY, TOMORROW } from "./utils";
14
+
15
+ describe("UserSession", () => {
16
+ afterEach(fetchMock.restore);
17
+
18
+ it("should serialize to and from JSON", () => {
19
+ const session = new UserSession({
20
+ clientId: "clientId",
21
+ redirectUri: "https://example-app.com/redirect-uri",
22
+ token: "token",
23
+ tokenExpires: TOMORROW,
24
+ refreshToken: "refreshToken",
25
+ refreshTokenExpires: TOMORROW,
26
+ refreshTokenTTL: 1440,
27
+ username: "c@sey",
28
+ password: "123456"
29
+ });
30
+
31
+ const session2 = UserSession.deserialize(session.serialize());
32
+
33
+ expect(session2.clientId).toEqual("clientId");
34
+ expect(session2.redirectUri).toEqual(
35
+ "https://example-app.com/redirect-uri"
36
+ );
37
+ expect(session2.ssl).toBe(undefined);
38
+ expect(session2.token).toEqual("token");
39
+ expect(session2.tokenExpires).toEqual(TOMORROW);
40
+ expect(session2.refreshToken).toEqual("refreshToken");
41
+ expect(session2.refreshTokenExpires).toEqual(TOMORROW);
42
+ expect(session2.username).toEqual("c@sey");
43
+ expect(session2.password).toEqual("123456");
44
+ expect(session2.tokenDuration).toEqual(20160);
45
+ expect(session2.refreshTokenTTL).toEqual(1440);
46
+ });
47
+
48
+ describe(".getToken()", () => {
49
+ it("should return unexpired tokens for trusted arcgis.com domains", done => {
50
+ const session = new UserSession({
51
+ clientId: "id",
52
+ token: "token",
53
+ tokenExpires: TOMORROW
54
+ });
55
+
56
+ Promise.all([
57
+ session.getToken("https://www.arcgis.com/sharing/rest/portals/self"),
58
+ session.getToken(
59
+ "https://services1.arcgis.com/MOCK_ORG/arcgis/rest/services/Private_Service/FeatureServer"
60
+ )
61
+ ])
62
+ .then(([token1, token2]) => {
63
+ expect(token1).toBe("token");
64
+ expect(token2).toBe("token");
65
+ done();
66
+ })
67
+ .catch(e => {
68
+ fail(e);
69
+ });
70
+ });
71
+
72
+ it("should return unexpired tokens when an org url is passed", done => {
73
+ const session = new UserSession({
74
+ clientId: "id",
75
+ token: "token",
76
+ tokenExpires: TOMORROW,
77
+ portal: "https://custom.maps.arcgis.com/sharing/rest"
78
+ });
79
+
80
+ session
81
+ .getToken(
82
+ "https://services1.arcgis.com/MOCK_ORG/arcgis/rest/services/Private_Service/FeatureServer"
83
+ )
84
+ .then(token => {
85
+ expect(token).toBe("token");
86
+ done();
87
+ })
88
+ .catch(e => {
89
+ fail(e);
90
+ });
91
+ });
92
+
93
+ it("should return unexpired tokens for the configured portal domain", done => {
94
+ const session = new UserSession({
95
+ clientId: "id",
96
+ token: "token",
97
+ tokenExpires: TOMORROW,
98
+ portal: "https://gis.city.gov/sharing/rest"
99
+ });
100
+
101
+ session
102
+ .getToken("https://gis.city.gov/sharing/rest/portals/self")
103
+ .then(token => {
104
+ expect(token).toBe("token");
105
+ done();
106
+ })
107
+ .catch(e => {
108
+ fail(e);
109
+ });
110
+ });
111
+
112
+ it("should fetch new tokens when tokens for trusted arcgis.com domains are expired", done => {
113
+ const session = new UserSession({
114
+ clientId: "id",
115
+ token: "token",
116
+ refreshToken: "refresh",
117
+ tokenExpires: YESTERDAY
118
+ });
119
+
120
+ fetchMock.mock(
121
+ "https://www.arcgis.com/sharing/rest/oauth2/token",
122
+ {
123
+ access_token: "new",
124
+ expires_in: 1800,
125
+ username: "c@sey"
126
+ },
127
+ { times: 2, method: "POST" }
128
+ );
129
+
130
+ Promise.all([
131
+ session.getToken("https://www.arcgis.com/sharing/rest/portals/self"),
132
+ session.getToken(
133
+ "https://services1.arcgis.com/MOCK_ORG/arcgis/rest/services/Private_Service/FeatureServer"
134
+ )
135
+ ])
136
+ .then(([token1, token2]) => {
137
+ expect(token1).toBe("new");
138
+ expect(token2).toBe("new");
139
+ done();
140
+ })
141
+ .catch(e => {
142
+ fail(e);
143
+ });
144
+ });
145
+
146
+ it("should generate a token for an untrusted, federated server", done => {
147
+ const session = new UserSession({
148
+ clientId: "id",
149
+ token: "token",
150
+ refreshToken: "refresh",
151
+ tokenExpires: TOMORROW,
152
+ portal: "https://gis.city.gov/sharing/rest"
153
+ });
154
+
155
+ fetchMock.postOnce("https://gisservices.city.gov/public/rest/info", {
156
+ currentVersion: 10.51,
157
+ fullVersion: "10.5.1.120",
158
+ owningSystemUrl: "https://gis.city.gov",
159
+ authInfo: {
160
+ isTokenBasedSecurity: true,
161
+ tokenServicesUrl: "https://gis.city.gov/sharing/generateToken"
162
+ }
163
+ });
164
+
165
+ fetchMock.postOnce("https://gis.city.gov/sharing/rest/info", {
166
+ owningSystemUrl: "http://gis.city.gov",
167
+ authInfo: {
168
+ tokenServicesUrl: "https://gis.city.gov/sharing/generateToken",
169
+ isTokenBasedSecurity: true
170
+ }
171
+ });
172
+
173
+ fetchMock.postOnce("https://gis.city.gov/sharing/generateToken", {
174
+ token: "serverToken",
175
+ expires: TOMORROW
176
+ });
177
+
178
+ session
179
+ .getToken(
180
+ "https://gisservices.city.gov/public/rest/services/trees/FeatureServer/0/query"
181
+ )
182
+ .then(token => {
183
+ expect(token).toBe("serverToken");
184
+ return session.getToken(
185
+ "https://gisservices.city.gov/public/rest/services/trees/FeatureServer/0/query"
186
+ );
187
+ })
188
+ .then(token => {
189
+ expect(token).toBe("serverToken");
190
+ done();
191
+ })
192
+ .catch(e => {
193
+ fail(e);
194
+ });
195
+ });
196
+
197
+ it("should generate a token for an untrusted, federated server admin call", done => {
198
+ const session = new UserSession({
199
+ clientId: "id",
200
+ token: "token",
201
+ refreshToken: "refresh",
202
+ tokenExpires: TOMORROW,
203
+ portal: "https://gis.city.gov/sharing/rest"
204
+ });
205
+
206
+ fetchMock.postOnce("https://gisservices.city.gov/public/rest/info", {
207
+ currentVersion: 10.51,
208
+ fullVersion: "10.5.1.120",
209
+ owningSystemUrl: "https://gis.city.gov",
210
+ authInfo: {
211
+ isTokenBasedSecurity: true,
212
+ tokenServicesUrl: "https://gis.city.gov/sharing/generateToken"
213
+ }
214
+ });
215
+
216
+ fetchMock.postOnce("https://gis.city.gov/sharing/rest/info", {
217
+ owningSystemUrl: "http://gis.city.gov",
218
+ authInfo: {
219
+ tokenServicesUrl: "https://gis.city.gov/sharing/generateToken",
220
+ isTokenBasedSecurity: true
221
+ }
222
+ });
223
+
224
+ fetchMock.postOnce("https://gis.city.gov/sharing/generateToken", {
225
+ token: "serverToken",
226
+ expires: TOMORROW
227
+ });
228
+
229
+ session
230
+ .getToken(
231
+ "https://gisservices.city.gov/public/rest/admin/services/trees/FeatureServer/addToDefinition"
232
+ )
233
+ .then(token => {
234
+ expect(token).toBe("serverToken");
235
+ return session.getToken(
236
+ "https://gisservices.city.gov/public/rest/admin/services/trees/FeatureServer/addToDefinition"
237
+ );
238
+ })
239
+ .then(token => {
240
+ expect(token).toBe("serverToken");
241
+ done();
242
+ })
243
+ .catch(e => {
244
+ fail(e);
245
+ });
246
+ });
247
+
248
+ it("should generate a token for an untrusted, federated server with user credentials", done => {
249
+ const session = new UserSession({
250
+ username: "c@sey",
251
+ password: "jones",
252
+ portal: "https://gis.city.gov/sharing/rest"
253
+ });
254
+
255
+ fetchMock.postOnce("https://gisservices.city.gov/public/rest/info", {
256
+ currentVersion: 10.51,
257
+ fullVersion: "10.5.1.120",
258
+ owningSystemUrl: "https://gis.city.gov",
259
+ authInfo: {
260
+ isTokenBasedSecurity: true,
261
+ tokenServicesUrl: "https://gis.city.gov/sharing/generateToken"
262
+ }
263
+ });
264
+
265
+ fetchMock.postOnce("https://gis.city.gov/sharing/rest/info", {
266
+ owningSystemUrl: "http://gis.city.gov",
267
+ authInfo: {
268
+ tokenServicesUrl: "https://gis.city.gov/sharing/generateToken",
269
+ isTokenBasedSecurity: true
270
+ }
271
+ });
272
+
273
+ fetchMock.postOnce("https://gis.city.gov/sharing/generateToken", {
274
+ token: "serverToken",
275
+ expires: TOMORROW
276
+ });
277
+
278
+ session
279
+ .getToken(
280
+ "https://gisservices.city.gov/public/rest/services/trees/FeatureServer/0/query"
281
+ )
282
+ .then(token => {
283
+ expect(token).toBe("serverToken");
284
+ done();
285
+ })
286
+ .catch(e => {
287
+ fail(e);
288
+ });
289
+ });
290
+
291
+ it("should only make 1 token request to an untrusted portal for similar URLs", done => {
292
+ const session = new UserSession({
293
+ clientId: "id",
294
+ token: "token",
295
+ refreshToken: "refresh",
296
+ tokenExpires: TOMORROW,
297
+ portal: "https://gis.city.gov/sharing/rest"
298
+ });
299
+
300
+ fetchMock.mock(
301
+ "https://gisservices.city.gov/public/rest/info",
302
+ {
303
+ currentVersion: 10.51,
304
+ fullVersion: "10.5.1.120",
305
+ owningSystemUrl: "https://gis.city.gov",
306
+ authInfo: {
307
+ isTokenBasedSecurity: true,
308
+ tokenServicesUrl: "https://gis.city.gov/sharing/generateToken"
309
+ }
310
+ },
311
+ { times: 1, method: "POST" }
312
+ );
313
+
314
+ fetchMock.mock(
315
+ "https://gis.city.gov/sharing/rest/info",
316
+ {
317
+ owningSystemUrl: "http://gis.city.gov",
318
+ authInfo: {
319
+ tokenServicesUrl: "https://gis.city.gov/sharing/generateToken",
320
+ isTokenBasedSecurity: true
321
+ }
322
+ },
323
+ { times: 1, method: "POST" }
324
+ );
325
+
326
+ fetchMock.mock(
327
+ "https://gis.city.gov/sharing/generateToken",
328
+ {
329
+ token: "serverToken",
330
+ expires: TOMORROW
331
+ },
332
+ { times: 1, method: "POST" }
333
+ );
334
+
335
+ Promise.all([
336
+ session.getToken(
337
+ "https://gisservices.city.gov/public/rest/services/trees/FeatureServer/0/query"
338
+ ),
339
+ session.getToken(
340
+ "https://gisservices.city.gov/public/rest/services/trees/FeatureServer/0/query"
341
+ )
342
+ ])
343
+ .then(([token1, token2]) => {
344
+ expect(token1).toBe("serverToken");
345
+ expect(token2).toBe("serverToken");
346
+ expect(
347
+ fetchMock.calls("https://gis.city.gov/sharing/generateToken").length
348
+ ).toBe(1);
349
+ done();
350
+ })
351
+ .catch(e => {
352
+ fail(e);
353
+ });
354
+ });
355
+
356
+ it("should throw an ArcGISAuthError when the owning system doesn't match", done => {
357
+ const session = new UserSession({
358
+ clientId: "id",
359
+ token: "token",
360
+ refreshToken: "refresh",
361
+ tokenExpires: YESTERDAY
362
+ });
363
+
364
+ fetchMock.post("https://gisservices.city.gov/public/rest/info", {
365
+ currentVersion: 10.51,
366
+ fullVersion: "10.5.1.120",
367
+ owningSystemUrl: "https://gis.city.gov",
368
+ authInfo: {
369
+ isTokenBasedSecurity: true,
370
+ tokenServicesUrl: "https://gis.city.gov/sharing/generateToken"
371
+ }
372
+ });
373
+
374
+ fetchMock.post("https://gis.city.gov/sharing/generateToken", {
375
+ error: {
376
+ code: 400,
377
+ message: "Unable to generate token",
378
+ details: ["Unable to generate token for this server"]
379
+ }
380
+ });
381
+
382
+ session
383
+ .getToken(
384
+ "https://gisservices.city.gov/public/rest/services/trees/FeatureServer/0/query"
385
+ )
386
+ .catch(e => {
387
+ expect(e.name).toEqual(ErrorTypes.ArcGISAuthError);
388
+ expect(e.code).toEqual("NOT_FEDERATED");
389
+ expect(e.message).toEqual(
390
+ "NOT_FEDERATED: https://gisservices.city.gov/public/rest/services/trees/FeatureServer/0/query is not federated with https://www.arcgis.com/sharing/rest."
391
+ );
392
+ done();
393
+ });
394
+ });
395
+
396
+ it("should throw an ArcGISAuthError when no owning system is advertised", done => {
397
+ const session = new UserSession({
398
+ clientId: "id",
399
+ token: "token",
400
+ refreshToken: "refresh",
401
+ tokenExpires: YESTERDAY
402
+ });
403
+
404
+ fetchMock.post("https://gisservices.city.gov/public/rest/info", {
405
+ currentVersion: 10.51,
406
+ fullVersion: "10.5.1.120",
407
+ authInfo: {
408
+ isTokenBasedSecurity: true,
409
+ tokenServicesUrl: "https://gis.city.gov/sharing/generateToken"
410
+ }
411
+ });
412
+
413
+ session
414
+ .getToken(
415
+ "https://gisservices.city.gov/public/rest/services/trees/FeatureServer/0/query"
416
+ )
417
+ .catch(e => {
418
+ expect(e.name).toEqual(ErrorTypes.ArcGISAuthError);
419
+ expect(e.code).toEqual("NOT_FEDERATED");
420
+ expect(e.message).toEqual(
421
+ "NOT_FEDERATED: https://gisservices.city.gov/public/rest/services/trees/FeatureServer/0/query is not federated with https://www.arcgis.com/sharing/rest."
422
+ );
423
+ done();
424
+ });
425
+ });
426
+ });
427
+
428
+ describe(".refreshSession()", () => {
429
+ it("should refresh with a username and password if expired", done => {
430
+ const session = new UserSession({
431
+ username: "c@sey",
432
+ password: "123456"
433
+ });
434
+
435
+ fetchMock.postOnce("https://www.arcgis.com/sharing/rest/generateToken", {
436
+ token: "token",
437
+ expires: TOMORROW.getTime(),
438
+ username: " c@sey"
439
+ });
440
+
441
+ session
442
+ .refreshSession()
443
+ .then(s => {
444
+ expect(s.token).toBe("token");
445
+ expect(s.tokenExpires).toEqual(TOMORROW);
446
+ done();
447
+ })
448
+ .catch(e => {
449
+ fail(e);
450
+ });
451
+ });
452
+
453
+ it("should refresh with an unexpired refresh token", done => {
454
+ const session = new UserSession({
455
+ clientId: "clientId",
456
+ token: "token",
457
+ username: "c@sey",
458
+ refreshToken: "refreshToken",
459
+ refreshTokenExpires: TOMORROW
460
+ });
461
+
462
+ fetchMock.postOnce("https://www.arcgis.com/sharing/rest/oauth2/token", {
463
+ access_token: "newToken",
464
+ expires_in: 60,
465
+ username: " c@sey"
466
+ });
467
+
468
+ session
469
+ .refreshSession()
470
+ .then(s => {
471
+ expect(s.token).toBe("newToken");
472
+ expect(s.tokenExpires.getTime()).toBeGreaterThan(Date.now());
473
+ done();
474
+ })
475
+ .catch(e => {
476
+ fail(e);
477
+ });
478
+ });
479
+
480
+ it("should refresh with an expired refresh token", done => {
481
+ const session = new UserSession({
482
+ clientId: "clientId",
483
+ token: "token",
484
+ username: "c@sey",
485
+ refreshToken: "refreshToken",
486
+ refreshTokenExpires: YESTERDAY,
487
+ redirectUri: "https://example-app.com/redirect-uri"
488
+ });
489
+
490
+ fetchMock.postOnce("https://www.arcgis.com/sharing/rest/oauth2/token", {
491
+ access_token: "newToken",
492
+ expires_in: 60,
493
+ username: " c@sey",
494
+ refresh_token: "newRefreshToken"
495
+ });
496
+
497
+ session
498
+ .refreshSession()
499
+ .then(s => {
500
+ expect(s.token).toBe("newToken");
501
+ expect(s.tokenExpires.getTime()).toBeGreaterThan(Date.now());
502
+ expect(s.refreshToken).toBe("newRefreshToken");
503
+ expect(s.refreshTokenExpires.getTime()).toBeGreaterThan(Date.now());
504
+ done();
505
+ })
506
+ .catch(e => {
507
+ fail(e);
508
+ });
509
+ });
510
+
511
+ it("should reject if we cannot refresh the token", done => {
512
+ const session = new UserSession({
513
+ clientId: "clientId",
514
+ token: "token",
515
+ username: "c@sey"
516
+ });
517
+
518
+ session.refreshSession().catch(e => {
519
+ expect(e instanceof ArcGISAuthError).toBeTruthy();
520
+ expect(e.name).toBe("ArcGISAuthError");
521
+ expect(e.message).toBe("Unable to refresh token.");
522
+ done();
523
+ });
524
+ });
525
+
526
+ it("should only make 1 token request to the portal for similar URLs", done => {
527
+ const session = new UserSession({
528
+ clientId: "id",
529
+ token: "token",
530
+ refreshToken: "refresh",
531
+ tokenExpires: YESTERDAY
532
+ });
533
+
534
+ fetchMock.mock(
535
+ "https://www.arcgis.com/sharing/rest/oauth2/token",
536
+ {
537
+ access_token: "new",
538
+ expires_in: 1800,
539
+ username: "c@sey"
540
+ },
541
+ { times: 1, method: "POST" }
542
+ );
543
+
544
+ Promise.all([
545
+ session.getToken("https://www.arcgis.com/sharing/rest/portals/self"),
546
+ session.getToken("https://www.arcgis.com/sharing/rest/portals/self")
547
+ ])
548
+ .then(([token1, token2]) => {
549
+ expect(token1).toBe("new");
550
+ expect(token2).toBe("new");
551
+ expect(
552
+ fetchMock.calls("https://www.arcgis.com/sharing/rest/oauth2/token")
553
+ .length
554
+ ).toBe(1);
555
+ done();
556
+ })
557
+ .catch(e => {
558
+ fail(e);
559
+ });
560
+ });
561
+ });
562
+
563
+ describe(".beginOAuth2()", () => {
564
+ it("should authorize via a popup", done => {
565
+ const MockWindow: any = {
566
+ open: jasmine.createSpy("spy")
567
+ };
568
+
569
+ UserSession.beginOAuth2(
570
+ {
571
+ clientId: "clientId123",
572
+ redirectUri: "http://example-app.com/redirect",
573
+ state: "abc123"
574
+ },
575
+ MockWindow
576
+ )
577
+ .then(session => {
578
+ expect(session.token).toBe("token");
579
+ expect(session.username).toBe("c@sey");
580
+ expect(session.ssl).toBe(true);
581
+ expect(session.tokenExpires).toEqual(TOMORROW);
582
+ done();
583
+ })
584
+ .catch(e => {
585
+ fail(e);
586
+ });
587
+
588
+ expect(MockWindow.open).toHaveBeenCalledWith(
589
+ "https://www.arcgis.com/sharing/rest/oauth2/authorize?client_id=clientId123&response_type=token&expiration=20160&redirect_uri=http%3A%2F%2Fexample-app.com%2Fredirect&state=abc123&locale=",
590
+ "oauth-window",
591
+ "height=400,width=600,menubar=no,location=yes,resizable=yes,scrollbars=yes,status=yes"
592
+ );
593
+
594
+ MockWindow.__ESRI_REST_AUTH_HANDLER_clientId123(
595
+ JSON.stringify(undefined),
596
+ JSON.stringify({
597
+ token: "token",
598
+ expires: TOMORROW,
599
+ username: "c@sey",
600
+ ssl: true
601
+ })
602
+ );
603
+ });
604
+
605
+ it("should reject the promise if there is an error", done => {
606
+ const MockWindow: any = {
607
+ open: jasmine.createSpy("spy")
608
+ };
609
+
610
+ UserSession.beginOAuth2(
611
+ {
612
+ clientId: "clientId123",
613
+ redirectUri: "http://example-app.com/redirect",
614
+ locale: "fr"
615
+ },
616
+ MockWindow
617
+ ).catch(e => {
618
+ done();
619
+ });
620
+
621
+ expect(MockWindow.open).toHaveBeenCalledWith(
622
+ "https://www.arcgis.com/sharing/rest/oauth2/authorize?client_id=clientId123&response_type=token&expiration=20160&redirect_uri=http%3A%2F%2Fexample-app.com%2Fredirect&state=clientId123&locale=fr",
623
+ "oauth-window",
624
+ "height=400,width=600,menubar=no,location=yes,resizable=yes,scrollbars=yes,status=yes"
625
+ );
626
+
627
+ MockWindow.__ESRI_REST_AUTH_HANDLER_clientId123(
628
+ JSON.stringify({
629
+ errorMessage: "unable to sign in",
630
+ error: "SIGN_IN_FAILED"
631
+ })
632
+ );
633
+ });
634
+
635
+ it("should authorize in the same window/tab", () => {
636
+ const MockWindow: any = {
637
+ location: {
638
+ href: ""
639
+ }
640
+ };
641
+
642
+ // https://github.com/palantir/tslint/issues/3056
643
+ void UserSession.beginOAuth2(
644
+ {
645
+ clientId: "clientId123",
646
+ redirectUri: "http://example-app.com/redirect",
647
+ popup: false
648
+ },
649
+ MockWindow
650
+ );
651
+
652
+ expect(MockWindow.location.href).toBe(
653
+ "https://www.arcgis.com/sharing/rest/oauth2/authorize?client_id=clientId123&response_type=token&expiration=20160&redirect_uri=http%3A%2F%2Fexample-app.com%2Fredirect&state=clientId123&locale="
654
+ );
655
+ });
656
+
657
+ it("should authorize using a social media provider", () => {
658
+ const MockWindow: any = {
659
+ location: {
660
+ href: ""
661
+ }
662
+ };
663
+
664
+ // https://github.com/palantir/tslint/issues/3056
665
+ void UserSession.beginOAuth2(
666
+ {
667
+ clientId: "clientId123",
668
+ redirectUri: "http://example-app.com/redirect",
669
+ popup: false,
670
+ provider: "facebook"
671
+ },
672
+ MockWindow
673
+ );
674
+
675
+ expect(MockWindow.location.href).toBe(
676
+ "https://www.arcgis.com/sharing/rest/oauth2/social/authorize?client_id=clientId123&socialLoginProviderName=facebook&autoAccountCreateForSocial=true&response_type=token&expiration=20160&redirect_uri=http%3A%2F%2Fexample-app.com%2Fredirect&state=clientId123&locale="
677
+ );
678
+ });
679
+
680
+ it("should authorize using the other social media provider", () => {
681
+ const MockWindow: any = {
682
+ location: {
683
+ href: ""
684
+ }
685
+ };
686
+
687
+ // https://github.com/palantir/tslint/issues/3056
688
+ void UserSession.beginOAuth2(
689
+ {
690
+ clientId: "clientId123",
691
+ redirectUri: "http://example-app.com/redirect",
692
+ popup: false,
693
+ provider: "google"
694
+ },
695
+ MockWindow
696
+ );
697
+
698
+ expect(MockWindow.location.href).toBe(
699
+ "https://www.arcgis.com/sharing/rest/oauth2/social/authorize?client_id=clientId123&socialLoginProviderName=google&autoAccountCreateForSocial=true&response_type=token&expiration=20160&redirect_uri=http%3A%2F%2Fexample-app.com%2Fredirect&state=clientId123&locale="
700
+ );
701
+ });
702
+ });
703
+
704
+ describe(".completeOAuth2()", () => {
705
+ it("should return a new user session if it cannot find a valid parent", () => {
706
+ const MockWindow = {
707
+ location: {
708
+ href:
709
+ "https://example-app.com/redirect-uri#access_token=token&expires_in=1209600&username=c%40sey&ssl=true&persist=true"
710
+ },
711
+ get parent() {
712
+ return this;
713
+ }
714
+ };
715
+
716
+ const session = UserSession.completeOAuth2(
717
+ {
718
+ clientId: "clientId",
719
+ redirectUri: "https://example-app.com/redirect-uri"
720
+ },
721
+ MockWindow
722
+ );
723
+
724
+ expect(session.token).toBe("token");
725
+ expect(session.tokenExpires.getTime()).toBeGreaterThan(Date.now());
726
+ expect(session.username).toBe("c@sey");
727
+ expect(session.ssl).toBe(true);
728
+ });
729
+
730
+ it("should return a new user session with ssl as false when callback hash does not have ssl parameter", () => {
731
+ const MockWindow = {
732
+ location: {
733
+ href:
734
+ "https://example-app.com/redirect-uri#access_token=token&expires_in=1209600&username=c%40sey&persist=true"
735
+ },
736
+ get parent() {
737
+ return this;
738
+ }
739
+ };
740
+
741
+ const session = UserSession.completeOAuth2(
742
+ {
743
+ clientId: "clientId",
744
+ redirectUri: "https://example-app.com/redirect-uri"
745
+ },
746
+ MockWindow
747
+ );
748
+ expect(session.ssl).toBe(false);
749
+ });
750
+
751
+ it("should callback to create a new user session if finds a valid opener", done => {
752
+ const MockWindow = {
753
+ opener: {
754
+ parent: {
755
+ __ESRI_REST_AUTH_HANDLER_clientId(
756
+ errorString: string,
757
+ oauthInfoString: string
758
+ ) {
759
+ const oauthInfo = JSON.parse(oauthInfoString);
760
+ expect(oauthInfo.token).toBe("token");
761
+ expect(oauthInfo.username).toBe("c@sey");
762
+ expect(oauthInfo.ssl).toBe(true);
763
+ expect(new Date(oauthInfo.expires).getTime()).toBeGreaterThan(
764
+ Date.now()
765
+ );
766
+ }
767
+ }
768
+ },
769
+ close() {
770
+ done();
771
+ },
772
+ location: {
773
+ href:
774
+ "https://example-app.com/redirect-uri#access_token=token&expires_in=1209600&username=c%40sey&ssl=true"
775
+ }
776
+ };
777
+
778
+ UserSession.completeOAuth2(
779
+ {
780
+ clientId: "clientId",
781
+ redirectUri: "https://example-app.com/redirect-uri"
782
+ },
783
+ MockWindow
784
+ );
785
+ });
786
+
787
+ it("should callback to create a new user session if finds a valid parent", done => {
788
+ const MockWindow = {
789
+ parent: {
790
+ __ESRI_REST_AUTH_HANDLER_clientId(
791
+ errorString: string,
792
+ oauthInfoString: string
793
+ ) {
794
+ const oauthInfo = JSON.parse(oauthInfoString);
795
+ expect(oauthInfo.token).toBe("token");
796
+ expect(oauthInfo.username).toBe("c@sey");
797
+ expect(oauthInfo.ssl).toBe(true);
798
+ expect(new Date(oauthInfo.expires).getTime()).toBeGreaterThan(
799
+ Date.now()
800
+ );
801
+ }
802
+ },
803
+ close() {
804
+ done();
805
+ },
806
+ location: {
807
+ href:
808
+ "https://example-app.com/redirect-uri#access_token=token&expires_in=1209600&username=c%40sey&ssl=true"
809
+ }
810
+ };
811
+
812
+ UserSession.completeOAuth2(
813
+ {
814
+ clientId: "clientId",
815
+ redirectUri: "https://example-app.com/redirect-uri"
816
+ },
817
+ MockWindow
818
+ );
819
+ });
820
+
821
+ it("should throw an error from the authorization window", () => {
822
+ const MockWindow = {
823
+ location: {
824
+ href:
825
+ "https://example-app.com/redirect-uri#error=Invalid_Signin&error_description=Invalid_Signin"
826
+ },
827
+ get parent() {
828
+ return this;
829
+ }
830
+ };
831
+
832
+ expect(function() {
833
+ UserSession.completeOAuth2(
834
+ {
835
+ clientId: "clientId",
836
+ redirectUri: "https://example-app.com/redirect-uri"
837
+ },
838
+ MockWindow
839
+ );
840
+ }).toThrowError(ArcGISRequestError, "Invalid_Signin: Invalid_Signin");
841
+ });
842
+ });
843
+
844
+ describe(".authorize()", () => {
845
+ it("should redirect the request to the authorization page", done => {
846
+ const spy = jasmine.createSpy("spy");
847
+ const MockResponse: any = {
848
+ writeHead: spy,
849
+ end() {
850
+ expect(spy.calls.mostRecent().args[0]).toBe(301);
851
+ expect(spy.calls.mostRecent().args[1].Location).toBe(
852
+ "https://arcgis.com/sharing/rest/oauth2/authorize?client_id=clientId&duration=20160&response_type=code&redirect_uri=https%3A%2F%2Fexample-app.com%2Fredirect-uri"
853
+ );
854
+ done();
855
+ }
856
+ };
857
+
858
+ UserSession.authorize(
859
+ {
860
+ clientId: "clientId",
861
+ redirectUri: "https://example-app.com/redirect-uri"
862
+ },
863
+ MockResponse
864
+ );
865
+ });
866
+ });
867
+
868
+ describe(".exchangeAuthorizationCode()", () => {
869
+ let paramsSpy: jasmine.Spy;
870
+
871
+ beforeEach(() => {
872
+ paramsSpy = spyOn(FormData.prototype, "append").and.callThrough();
873
+ });
874
+
875
+ afterAll(() => {
876
+ paramsSpy.calls.reset();
877
+ });
878
+
879
+ it("should exchange an authorization code for a new UserSession", done => {
880
+ fetchMock.postOnce("https://www.arcgis.com/sharing/rest/oauth2/token", {
881
+ access_token: "token",
882
+ expires_in: 1800,
883
+ refresh_token: "refreshToken",
884
+ username: "Casey",
885
+ ssl: true
886
+ });
887
+
888
+ UserSession.exchangeAuthorizationCode(
889
+ {
890
+ clientId: "clientId",
891
+ redirectUri: "https://example-app.com/redirect-uri"
892
+ },
893
+ "code"
894
+ )
895
+ .then(session => {
896
+ expect(session.token).toBe("token");
897
+ expect(session.tokenExpires.getTime()).toBeGreaterThan(Date.now());
898
+ expect(session.username).toBe("Casey");
899
+ expect(session.refreshToken).toBe("refreshToken");
900
+ expect(session.ssl).toBe(true);
901
+ done();
902
+ })
903
+ .catch(e => {
904
+ fail(e);
905
+ });
906
+ });
907
+ });
908
+
909
+ describe(".getUser()", () => {
910
+ afterEach(fetchMock.restore);
911
+
912
+ it("should cache metadata about the user", done => {
913
+ // we intentionally only mock one response
914
+ fetchMock.once(
915
+ "https://www.arcgis.com/sharing/rest/community/users/jsmith?f=json&token=token",
916
+ {
917
+ username: "jsmith",
918
+ fullName: "John Smith",
919
+ role: "org_publisher"
920
+ }
921
+ );
922
+
923
+ const session = new UserSession({
924
+ clientId: "clientId",
925
+ redirectUri: "https://example-app.com/redirect-uri",
926
+ token: "token",
927
+ tokenExpires: TOMORROW,
928
+ refreshToken: "refreshToken",
929
+ refreshTokenExpires: TOMORROW,
930
+ refreshTokenTTL: 1440,
931
+ username: "jsmith",
932
+ password: "123456"
933
+ });
934
+
935
+ session
936
+ .getUser()
937
+ .then(response => {
938
+ expect(response.role).toEqual("org_publisher");
939
+ session
940
+ .getUser()
941
+ .then(cachedResponse => {
942
+ expect(cachedResponse.fullName).toEqual("John Smith");
943
+ done();
944
+ })
945
+ .catch(e => {
946
+ fail(e);
947
+ });
948
+ })
949
+ .catch(e => {
950
+ fail(e);
951
+ });
952
+ });
953
+ });
954
+
955
+ describe("to/fromCredential()", () => {
956
+ const MOCK_CREDENTIAL: ICredential = {
957
+ expires: TOMORROW.getTime(),
958
+ server: "https://www.arcgis.com",
959
+ ssl: false,
960
+ token: "token",
961
+ userId: "jsmith"
962
+ };
963
+
964
+ it("should create a credential object from a session", () => {
965
+ const session = new UserSession({
966
+ clientId: "clientId",
967
+ redirectUri: "https://example-app.com/redirect-uri",
968
+ token: "token",
969
+ ssl: false,
970
+ tokenExpires: TOMORROW,
971
+ refreshToken: "refreshToken",
972
+ refreshTokenExpires: TOMORROW,
973
+ refreshTokenTTL: 1440,
974
+ username: "jsmith",
975
+ password: "123456"
976
+ });
977
+
978
+ const creds = session.toCredential();
979
+ expect(creds.userId).toEqual("jsmith");
980
+ expect(creds.server).toEqual("https://www.arcgis.com/sharing/rest");
981
+ expect(creds.ssl).toEqual(false);
982
+ expect(creds.token).toEqual("token");
983
+ expect(creds.expires).toEqual(TOMORROW.getTime());
984
+ });
985
+
986
+ it("should create a UserSession from a credential", () => {
987
+ const session = UserSession.fromCredential(MOCK_CREDENTIAL);
988
+ expect(session.username).toEqual("jsmith");
989
+ expect(session.portal).toEqual("https://www.arcgis.com/sharing/rest");
990
+ expect(session.ssl).toEqual(false);
991
+ expect(session.token).toEqual("token");
992
+ expect(session.tokenExpires).toEqual(new Date(TOMORROW));
993
+ });
994
+ });
995
+ });