@esri/solutions-components 0.5.3 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. package/dist/cjs/calcite-input-text_5.cjs.entry.js +36 -36
  2. package/dist/cjs/calcite-shell-panel_14.cjs.entry.js +1 -1
  3. package/dist/cjs/solution-configuration.cjs.entry.js +1 -1
  4. package/dist/cjs/solution-contents_3.cjs.entry.js +1 -1
  5. package/dist/cjs/{solution-store-70002b57.js → solution-store-ca4639d5.js} +3 -3
  6. package/dist/collection/components/add-record-modal/test/add-record-modal.e2e.js +24 -0
  7. package/dist/collection/components/add-record-modal/test/add-record-modal.spec.js +32 -0
  8. package/dist/collection/components/buffer-tools/test/buffer-tools.e2e.js +24 -0
  9. package/dist/collection/components/buffer-tools/test/buffer-tools.spec.js +157 -0
  10. package/dist/collection/components/card-manager/test/card-manager.e2e.js +24 -0
  11. package/dist/collection/components/card-manager/test/card-manager.spec.js +32 -0
  12. package/dist/collection/components/comment-card/test/comment-card.e2e.js +24 -0
  13. package/dist/collection/components/comment-card/test/comment-card.spec.js +32 -0
  14. package/dist/collection/components/crowdsource-manager/test/crowdsource-manager.e2e.js +24 -0
  15. package/dist/collection/components/crowdsource-manager/test/crowdsource-manager.spec.js +32 -0
  16. package/dist/collection/components/crowdsource-reporter/test/crowdsource-reporter.e2e.js +24 -0
  17. package/dist/collection/components/crowdsource-reporter/test/crowdsource-reporter.spec.js +32 -0
  18. package/dist/collection/components/deduct-calculator/test/deduct-calculator.e2e.js +24 -0
  19. package/dist/collection/components/deduct-calculator/test/deduct-calculator.spec.js +32 -0
  20. package/dist/collection/components/edit-record-modal/test/edit-record-modal.e2e.js +24 -0
  21. package/dist/collection/components/edit-record-modal/test/edit-record-modal.spec.js +32 -0
  22. package/dist/collection/components/info-card/test/info-card.e2e.js +24 -0
  23. package/dist/collection/components/info-card/test/info-card.spec.js +32 -0
  24. package/dist/collection/components/json-editor/test/json-editor.e2e.js +31 -0
  25. package/dist/collection/components/json-editor/test/json-editor.spec.js +60 -0
  26. package/dist/collection/components/layer-table/test/layer-table.e2e.js +24 -0
  27. package/dist/collection/components/layer-table/test/layer-table.spec.js +32 -0
  28. package/dist/collection/components/list-item/test/list-item.e2e.js +24 -0
  29. package/dist/collection/components/list-item/test/list-item.spec.js +32 -0
  30. package/dist/collection/components/map-card/test/map-card.e2e.js +24 -0
  31. package/dist/collection/components/map-card/test/map-card.spec.js +32 -0
  32. package/dist/collection/components/map-draw-tools/test/map-draw-tools.e2e.js +24 -0
  33. package/dist/collection/components/map-draw-tools/test/map-draw-tools.spec.js +32 -0
  34. package/dist/collection/components/map-layer-picker/test/map-layer-picker.e2e.js +24 -0
  35. package/dist/collection/components/map-layer-picker/test/map-layer-picker.spec.js +109 -0
  36. package/dist/collection/components/map-search/test/map-search.e2e.js +24 -0
  37. package/dist/collection/components/map-search/test/map-search.spec.js +53 -0
  38. package/dist/collection/components/map-select-tools/map-select-tools.js +36 -36
  39. package/dist/collection/components/map-select-tools/test/map-select-tools.e2e.js +24 -0
  40. package/dist/collection/components/map-select-tools/test/map-select-tools.spec.js +349 -0
  41. package/dist/collection/components/media-card/test/media-card.e2e.js +24 -0
  42. package/dist/collection/components/media-card/test/media-card.spec.js +32 -0
  43. package/dist/collection/components/pci-calculator/test/pci-calculator.e2e.js +24 -0
  44. package/dist/collection/components/pci-calculator/test/pci-calculator.spec.js +32 -0
  45. package/dist/collection/components/pdf-download/test/pdf-download.e2e.js +71 -0
  46. package/dist/collection/components/pdf-download/test/pdf-download.spec.js +104 -0
  47. package/dist/collection/components/public-notification/test/public-notification.e2e.js +95 -0
  48. package/dist/collection/components/public-notification/test/public-notification.spec.js +149 -0
  49. package/dist/collection/components/refine-selection/refine-selection.css +85 -85
  50. package/dist/collection/components/solution-configuration/test/solution-configuration.e2e.js +31 -0
  51. package/dist/collection/components/solution-configuration/test/solution-configuration.spec.js +114 -0
  52. package/dist/collection/components/solution-contents/test/solution-contents.e2e.js +89 -0
  53. package/dist/collection/components/solution-contents/test/solution-contents.spec.js +138 -0
  54. package/dist/collection/components/solution-item/test/solution-item.e2e.js +31 -0
  55. package/dist/collection/components/solution-item/test/solution-item.spec.js +72 -0
  56. package/dist/collection/components/solution-item-details/test/solution-item-details.e2e.js +31 -0
  57. package/dist/collection/components/solution-item-details/test/solution-item-details.spec.js +137 -0
  58. package/dist/collection/components/solution-item-icon/test/solution-item-icon.e2e.js +24 -0
  59. package/dist/collection/components/solution-item-icon/test/solution-item-icon.spec.js +34 -0
  60. package/dist/collection/components/solution-item-sharing/test/solution-item-sharing.e2e.js +31 -0
  61. package/dist/collection/components/solution-item-sharing/test/solution-item-sharing.spec.js +49 -0
  62. package/dist/collection/components/solution-organization-variables/test/solution-organization-variables.e2e.js +31 -0
  63. package/dist/collection/components/solution-organization-variables/test/solution-organization-variables.spec.js +60 -0
  64. package/dist/collection/components/solution-resource-item/test/solution-resource-item.e2e.js +31 -0
  65. package/dist/collection/components/solution-resource-item/test/solution-resource-item.spec.js +50 -0
  66. package/dist/collection/components/solution-spatial-ref/test/solution-spatial-ref.e2e.js +31 -0
  67. package/dist/collection/components/solution-spatial-ref/test/solution-spatial-ref.spec.js +170 -0
  68. package/dist/collection/components/solution-template-data/test/solution-template-data.e2e.js +31 -0
  69. package/dist/collection/components/solution-template-data/test/solution-template-data.spec.js +55 -0
  70. package/dist/collection/components/solution-variables/test/solution-variables.e2e.js +31 -0
  71. package/dist/collection/components/solution-variables/test/solution-variables.spec.js +126 -0
  72. package/dist/collection/utils/publicNotificationUtils.js +45 -0
  73. package/dist/collection/utils/templates.e2e.js +25 -0
  74. package/dist/collection/utils/test/csvUtils.spec.js +46 -0
  75. package/dist/collection/utils/test/downloadUtils.spec.js +102 -0
  76. package/dist/collection/utils/test/pciUtils.spec.js +297 -0
  77. package/dist/collection/utils/test/solution-store.spec.js +439 -0
  78. package/dist/components/map-select-tools2.js +36 -36
  79. package/dist/components/solution-store.js +3 -3
  80. package/dist/esm/calcite-input-text_5.entry.js +36 -36
  81. package/dist/esm/calcite-shell-panel_14.entry.js +1 -1
  82. package/dist/esm/solution-configuration.entry.js +1 -1
  83. package/dist/esm/solution-contents_3.entry.js +1 -1
  84. package/dist/esm/{solution-store-5d068b07.js → solution-store-70f874f8.js} +3 -3
  85. package/dist/solutions-components/{p-41802f6b.entry.js → p-16dfb254.entry.js} +1 -1
  86. package/dist/solutions-components/{p-4769a2a5.entry.js → p-5ed755a2.entry.js} +1 -1
  87. package/dist/solutions-components/{p-826a814d.js → p-78719506.js} +2 -2
  88. package/dist/solutions-components/{p-9f620303.entry.js → p-b4b19fd3.entry.js} +1 -1
  89. package/dist/solutions-components/{p-24fe6e1c.entry.js → p-d5d5942d.entry.js} +1 -1
  90. package/dist/solutions-components/solutions-components.esm.js +1 -1
  91. package/dist/solutions-components/utils/common.js +291 -0
  92. package/dist/solutions-components/utils/csvDownload.js +36 -0
  93. package/dist/solutions-components/utils/csvUtils.js +32 -0
  94. package/dist/solutions-components/utils/downloadUtils.js +386 -0
  95. package/dist/solutions-components/utils/interfaces.js +56 -0
  96. package/dist/solutions-components/utils/languageUtil.js +85 -0
  97. package/dist/solutions-components/utils/loadModules.js +20 -0
  98. package/dist/solutions-components/utils/locale.js +56 -0
  99. package/dist/solutions-components/utils/mapViewUtils.js +140 -0
  100. package/dist/solutions-components/utils/pciUtils.js +837 -0
  101. package/dist/solutions-components/utils/pdfUtils.js +62 -0
  102. package/dist/solutions-components/utils/publicNotificationStore.js +38 -0
  103. package/dist/solutions-components/utils/publicNotificationUtils.js +45 -0
  104. package/dist/solutions-components/utils/queryUtils.js +148 -0
  105. package/dist/solutions-components/utils/solution-store.js +579 -0
  106. package/dist/solutions-components/utils/templates.e2e.js +25 -0
  107. package/dist/solutions-components/utils/templates.js +341 -0
  108. package/dist/solutions-components/utils/test/csvUtils.spec.js +46 -0
  109. package/dist/solutions-components/utils/test/downloadUtils.spec.js +102 -0
  110. package/dist/solutions-components/utils/test/mocks/jsApi.js +74 -0
  111. package/dist/solutions-components/utils/test/pciUtils.spec.js +297 -0
  112. package/dist/solutions-components/utils/test/solution-store.spec.js +439 -0
  113. package/dist/solutions-components/utils/test/testUtils.js +135 -0
  114. package/dist/solutions-components/utils/types.js +14 -0
  115. package/dist/solutions-components_commit.txt +7 -0
  116. package/package.json +7 -7
@@ -0,0 +1,439 @@
1
+ /** @license
2
+ * Copyright 2022 Esri
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import * as common from "@esri/solution-common";
17
+ import * as testUtils from "./testUtils";
18
+ import solution_734164 from "./solution_734164.json";
19
+ import solution_ca924c from "./solution_ca924c.json";
20
+ import state from "../solution-store";
21
+ import { EUpdateType } from '../interfaces';
22
+ let MOCK_USER_SESSION;
23
+ jest.setTimeout(30000);
24
+ beforeEach(() => {
25
+ MOCK_USER_SESSION = testUtils.createRuntimeMockUserSession();
26
+ state._testAccess("_emptyTheStore");
27
+ });
28
+ afterEach(() => {
29
+ jest.restoreAllMocks();
30
+ });
31
+ let itemEdit;
32
+ describe("solution-store", () => {
33
+ it("creates store", () => {
34
+ expect(state.getStoreInfo("solutionItemId")).toEqual("");
35
+ });
36
+ it("loads a solution", async () => {
37
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => solution_ca924c);
38
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
39
+ expect(state.getStoreInfo("solutionItemId")).toEqual("ca924c6db7d247b9a31fa30532fb5913");
40
+ });
41
+ it("loads a solution, and then another one", async () => {
42
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => solution_ca924c);
43
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
44
+ expect(state.getStoreInfo("solutionItemId")).toEqual("ca924c6db7d247b9a31fa30532fb5913");
45
+ // Replace the solution with a different one
46
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => solution_734164);
47
+ await state.loadSolution("7341644e455e4a068eba58f1939caac4", MOCK_USER_SESSION);
48
+ expect(state.getStoreInfo("solutionItemId")).toEqual("7341644e455e4a068eba58f1939caac4");
49
+ expect(state.getStoreInfo("solutionData").templates.length).toEqual(12);
50
+ });
51
+ describe("replaceItemThumbnail", () => {
52
+ beforeEach(() => {
53
+ itemEdit = testUtils.getSampleItemEdit();
54
+ });
55
+ it("queues a thumbnail for replacement", () => {
56
+ // Set a new thumbnail
57
+ itemEdit.thumbnail = testUtils.getSampleImageAsFile("thumb1");
58
+ // Register it in the store
59
+ state.replaceItemThumbnail(itemEdit);
60
+ // Check that the previous thumbnail is marked for removal and the new one is queued for adding
61
+ expect(itemEdit.resourceFilePaths.length).toEqual(3);
62
+ expect(itemEdit.resourceFilePaths[0].filename).toEqual("qc.project.json");
63
+ expect(itemEdit.resourceFilePaths[0].updateType).toEqual(3);
64
+ expect(itemEdit.resourceFilePaths[1].filename).toEqual("esri_133.png");
65
+ expect(itemEdit.resourceFilePaths[1].updateType).toEqual(2);
66
+ expect(itemEdit.resourceFilePaths[2].filename).toEqual("thumb1");
67
+ expect(itemEdit.resourceFilePaths[2].updateType).toEqual(0);
68
+ });
69
+ it("twice queues thumbnails for replacement", () => {
70
+ // Set a new thumbnail
71
+ itemEdit.thumbnail = testUtils.getSampleImageAsFile("thumb1");
72
+ // Register it in the store
73
+ state.replaceItemThumbnail(itemEdit);
74
+ // Set a new thumbnail
75
+ itemEdit.thumbnail = testUtils.getSampleImageAsFile("thumb2");
76
+ // Register it in the store
77
+ state.replaceItemThumbnail(itemEdit);
78
+ // Check that the previous thumbnail is marked for removal and the new one is queued for adding
79
+ expect(itemEdit.resourceFilePaths.length).toEqual(3);
80
+ expect(itemEdit.resourceFilePaths[0].filename).toEqual("qc.project.json");
81
+ expect(itemEdit.resourceFilePaths[0].updateType).toEqual(3);
82
+ expect(itemEdit.resourceFilePaths[1].filename).toEqual("esri_133.png");
83
+ expect(itemEdit.resourceFilePaths[1].updateType).toEqual(2);
84
+ expect(itemEdit.resourceFilePaths[2].filename).toEqual("thumb2");
85
+ expect(itemEdit.resourceFilePaths[2].updateType).toEqual(0);
86
+ });
87
+ it("thrice queues thumbnails for replacement", () => {
88
+ // Set a new thumbnail
89
+ itemEdit.thumbnail = testUtils.getSampleImageAsFile("thumb1");
90
+ // Register it in the store
91
+ state.replaceItemThumbnail(itemEdit);
92
+ // Set a new thumbnail
93
+ itemEdit.thumbnail = testUtils.getSampleImageAsFile("thumb2");
94
+ // Register it in the store
95
+ state.replaceItemThumbnail(itemEdit);
96
+ // Set a new thumbnail
97
+ itemEdit.thumbnail = testUtils.getSampleImageAsFile("thumb3");
98
+ // Register it in the store
99
+ state.replaceItemThumbnail(itemEdit);
100
+ // Check that the previous thumbnail is marked for removal and the new one is queued for adding
101
+ expect(itemEdit.resourceFilePaths.length).toEqual(3);
102
+ expect(itemEdit.resourceFilePaths[0].filename).toEqual("qc.project.json");
103
+ expect(itemEdit.resourceFilePaths[0].updateType).toEqual(3);
104
+ expect(itemEdit.resourceFilePaths[1].filename).toEqual("esri_133.png");
105
+ expect(itemEdit.resourceFilePaths[1].updateType).toEqual(2);
106
+ expect(itemEdit.resourceFilePaths[2].filename).toEqual("thumb3");
107
+ expect(itemEdit.resourceFilePaths[2].updateType).toEqual(0);
108
+ });
109
+ });
110
+ it("fails to find an item when fetching its value", async () => {
111
+ const item = state.getItemInfo("79036430a6274e17ae915d0278b8569c");
112
+ expect(item).toBeUndefined();
113
+ });
114
+ it("changes an item's value", async () => {
115
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => JSON.parse(JSON.stringify(solution_ca924c)));
116
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
117
+ expect(state.getStoreInfo("solutionData").templates.length).toEqual(25);
118
+ const item = state.getItemInfo("9c1311d827f44fdc9680651420a63484");
119
+ expect(item.item.description).toEqual("An ArcGIS Survey123 form used by operations managers and yard supervisors to report materials used by each vehicle during winter weather operations.");
120
+ // Change the item's description
121
+ item.item.description = "Nullam ac urna mattis, maximus urna sit amet.";
122
+ state.setItemInfo(item);
123
+ const updatedItem = state.getItemInfo("9c1311d827f44fdc9680651420a63484");
124
+ expect(updatedItem.item.description).toEqual("Nullam ac urna mattis, maximus urna sit amet.");
125
+ });
126
+ it("changes a store value", async () => {
127
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => JSON.parse(JSON.stringify(solution_ca924c)));
128
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
129
+ const origDefaultWkid = state.getStoreInfo("defaultWkid");
130
+ expect(origDefaultWkid).toBeUndefined();
131
+ state.setStoreInfo("defaultWkid", "2865");
132
+ const modifiedDefaultWkid = state.getStoreInfo("defaultWkid");
133
+ expect(modifiedDefaultWkid).toEqual("2865");
134
+ });
135
+ describe("saveSolution", () => {
136
+ it("saves a solution with a custom spatial reference", async () => {
137
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => {
138
+ return Object.assign(Object.assign({}, JSON.parse(JSON.stringify(solution_ca924c))), { "params": {
139
+ "wkid": {
140
+ "label": "Spatial Reference",
141
+ "default": 102100,
142
+ "valueType": "spatialReference",
143
+ "attributes": {
144
+ "required": "true"
145
+ }
146
+ }
147
+ } });
148
+ });
149
+ const updateSpy = jest.spyOn(common, "updateItem").mockImplementation((itemInfo, _authentication, _folderId) => {
150
+ expect(itemInfo.id).toEqual("ca924c6db7d247b9a31fa30532fb5913");
151
+ return Promise.resolve(null);
152
+ });
153
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
154
+ await state.saveSolution();
155
+ expect(updateSpy).toHaveBeenCalled();
156
+ });
157
+ it("saves a solution without a custom spatial reference", async () => {
158
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => JSON.parse(JSON.stringify(solution_ca924c)));
159
+ const updateSpy = jest.spyOn(common, "updateItem").mockImplementation((itemInfo, _authentication, _folderId) => {
160
+ expect(itemInfo.id).toEqual("ca924c6db7d247b9a31fa30532fb5913");
161
+ return Promise.resolve(null);
162
+ });
163
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
164
+ await state.saveSolution();
165
+ expect(updateSpy).toHaveBeenCalled();
166
+ });
167
+ });
168
+ it("directly empties the store", async () => {
169
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => JSON.parse(JSON.stringify(solution_ca924c)));
170
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
171
+ expect(state.getStoreInfo("solutionItemId")).toEqual("ca924c6db7d247b9a31fa30532fb5913");
172
+ state._testAccess("_emptyTheStore");
173
+ expect(state.getStoreInfo("solutionItemId")).toEqual("");
174
+ });
175
+ it("gets feature services", async () => {
176
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => JSON.parse(JSON.stringify(solution_ca924c)));
177
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
178
+ const result = state._testAccess("_getFeatureServices", state.getStoreInfo("solutionData").templates);
179
+ expect(result.length).toEqual(5);
180
+ expect(result[0].name).toEqual("Driver_Activity"); // name fetched from `name` prop because `title` empty
181
+ expect(result[0].enabled).toBeFalsy();
182
+ expect(result[1].name).toEqual("OperationsManagement"); // name fetched from higher-priority `title` prop
183
+ });
184
+ it("gets items shared with a group", async () => {
185
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => JSON.parse(JSON.stringify(solution_ca924c)));
186
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
187
+ const result = state._testAccess("_getItemsSharedWithThisGroup", state.getStoreInfo("solutionData").templates[0], state.getStoreInfo("solutionData").templates);
188
+ expect(result.length).toEqual(23);
189
+ expect(result[0]).toEqual({
190
+ "id": "9c1311d827f44fdc9680651420a63484",
191
+ "title": "Material_Use_Reporting.zip",
192
+ "isShared": false,
193
+ "shareItem": false,
194
+ "type": "Form",
195
+ "typeKeywords": [
196
+ "Form",
197
+ "Survey123",
198
+ "Survey123 Connect",
199
+ "xForm"
200
+ ]
201
+ });
202
+ });
203
+ it("gets resource file paths", async () => {
204
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => JSON.parse(JSON.stringify(solution_ca924c)));
205
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
206
+ const result = state._testAccess("_getResourceFilePaths", "ca924c6db7d247b9a31fa30532fb5913", state.getStoreInfo("solutionData").templates[0], MOCK_USER_SESSION.portal);
207
+ expect(result.length).toEqual(2);
208
+ expect(result[0]).toEqual({
209
+ "url": "https://myorg.maps.arcgis.com/sharing/rest/content/items/ca924c6db7d247b9a31fa30532fb5913/resources/79036430a6274e17ae915d0278b8569c_info_metadata/metadata.xml",
210
+ "type": 2,
211
+ "folder": "",
212
+ "filename": "metadata.xml",
213
+ "updateType": 3
214
+ });
215
+ });
216
+ it("gets resource storage name", async () => {
217
+ const resourcePaths = [
218
+ { type: common.EFileType.Data, filename: "def.txt" },
219
+ { type: common.EFileType.Data, filename: "def.doc" },
220
+ { type: common.EFileType.Info, filename: "def" },
221
+ { type: common.EFileType.Metadata, filename: "def" },
222
+ { type: common.EFileType.Resource, filename: "def" },
223
+ { type: common.EFileType.Thumbnail, filename: "def" }
224
+ ];
225
+ const storageNames = resourcePaths.map((path) => state._testAccess("_getResourceStorageName", "abc", path));
226
+ expect(storageNames).toEqual([
227
+ "abc_info_data/def.txt",
228
+ "abc_info_dataz/def.doc.zip",
229
+ "abc_info/def",
230
+ "abc_info_metadata/def",
231
+ "abc/def",
232
+ "abc_info_thumbnail/def"
233
+ ]);
234
+ });
235
+ describe("_getSpatialReferenceInfo", () => {
236
+ it("gets spatial reference info using a string wkid", async () => {
237
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => JSON.parse(JSON.stringify(solution_ca924c)));
238
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
239
+ const featureServices = state._testAccess("_getFeatureServices", state.getStoreInfo("solutionData").templates);
240
+ const result = await state._testAccess("_getSpatialReferenceInfo", featureServices, "2865");
241
+ expect(result).toEqual({
242
+ "enabled": true,
243
+ "services": {
244
+ "Driver_Activity": false,
245
+ "OperationsManagement": false,
246
+ "SnowRoutes": false,
247
+ "ServiceAreas": true,
248
+ "Requests": true
249
+ },
250
+ "spatialReference": "2865"
251
+ });
252
+ });
253
+ it("gets spatial reference info using a numeric wkid", async () => {
254
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => JSON.parse(JSON.stringify(solution_ca924c)));
255
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
256
+ const featureServices = state._testAccess("_getFeatureServices", state.getStoreInfo("solutionData").templates);
257
+ const result = await state._testAccess("_getSpatialReferenceInfo", featureServices, 2865);
258
+ expect(result).toEqual({
259
+ "enabled": true,
260
+ "services": {
261
+ "Driver_Activity": false,
262
+ "OperationsManagement": false,
263
+ "SnowRoutes": false,
264
+ "ServiceAreas": true,
265
+ "Requests": true
266
+ },
267
+ "spatialReference": 2865
268
+ });
269
+ });
270
+ it("gets spatial reference info using no wkid", async () => {
271
+ jest.spyOn(common, "getItemDataAsJson").mockImplementation(() => JSON.parse(JSON.stringify(solution_ca924c)));
272
+ await state.loadSolution("ca924c6db7d247b9a31fa30532fb5913", MOCK_USER_SESSION);
273
+ const featureServices = state._testAccess("_getFeatureServices", state.getStoreInfo("solutionData").templates);
274
+ const result = await state._testAccess("_getSpatialReferenceInfo", featureServices);
275
+ expect(result).toEqual({
276
+ "enabled": false,
277
+ "services": {
278
+ "Driver_Activity": false,
279
+ "OperationsManagement": false,
280
+ "SnowRoutes": false,
281
+ "ServiceAreas": true,
282
+ "Requests": true
283
+ },
284
+ "spatialReference": undefined
285
+ });
286
+ });
287
+ });
288
+ it("prepares a solution for editing", async () => {
289
+ // Get the templates; parse+stringify seems only working way to avoid modifying data file
290
+ const solutionData = JSON.parse(JSON.stringify(solution_ca924c));
291
+ // Provide thumbnail images for the templates
292
+ const sampleImageFile = testUtils.getSampleImageAsFile();
293
+ jest.spyOn(common, "getThumbnailFromStorageItem").mockResolvedValue(sampleImageFile);
294
+ await state._testAccess("_prepareSolutionItemsForEditing", "ca924c6db7d247b9a31fa30532fb5913", solutionData.templates, MOCK_USER_SESSION);
295
+ // Check that the augmentation has been added to each template
296
+ expect(solutionData.templates.filter(t => t.hasOwnProperty("resourceFilePaths")).length).toEqual(solutionData.templates.length);
297
+ expect(solutionData.templates.filter(t => t.hasOwnProperty("thumbnail")).length).toEqual(solutionData.templates.length);
298
+ expect(solutionData.templates.filter(t => t.hasOwnProperty("groupDetails")).length).toEqual(solutionData.templates.length);
299
+ });
300
+ describe("_prepareSolutionItemsForStorage", () => {
301
+ const originalConsoleLog = console.log;
302
+ beforeEach(() => {
303
+ console.log = jest.fn();
304
+ });
305
+ afterEach(() => {
306
+ console.log = originalConsoleLog;
307
+ });
308
+ it("prepares a solution for storage", async () => {
309
+ // Get the templates; parse+stringify seems only working way to avoid modifying data file
310
+ const solutionData = JSON.parse(JSON.stringify(solution_ca924c));
311
+ // Provide thumbnail images for the templates and prepare the templates for editing
312
+ const sampleImageFile = testUtils.getSampleImageAsFile();
313
+ jest.spyOn(common, "getThumbnailFromStorageItem").mockResolvedValue(sampleImageFile);
314
+ await state._testAccess("_prepareSolutionItemsForEditing", "ca924c6db7d247b9a31fa30532fb5913", solutionData.templates, MOCK_USER_SESSION);
315
+ // Provide some resource mods
316
+ const template = solutionData.templates[0];
317
+ template.resourceFilePaths.push({
318
+ blob: sampleImageFile,
319
+ filename: sampleImageFile.name,
320
+ type: common.EFileType.Resource,
321
+ updateType: EUpdateType.Add
322
+ });
323
+ template.resourceFilePaths.push({
324
+ blob: sampleImageFile,
325
+ filename: template.resourceFilePaths[1].filename,
326
+ type: common.EFileType.Thumbnail,
327
+ updateType: EUpdateType.Update
328
+ });
329
+ template.resourceFilePaths.push({
330
+ filename: template.resourceFilePaths[0].filename,
331
+ type: common.EFileType.Metadata,
332
+ updateType: EUpdateType.Remove
333
+ });
334
+ // Run the prep
335
+ jest.spyOn(common, "copyFilesToStorageItem").mockResolvedValue([template.itemId + "_info_dataz/" + sampleImageFile.name]);
336
+ jest.spyOn(common, "removeItemResourceFile").mockResolvedValue({ success: true });
337
+ jest.spyOn(common, "updateItemResourceFile").mockResolvedValue({ success: true, itemId: "abc", owner: "def", folder: "ghi" });
338
+ expect(template.resourceFilePaths.length).toEqual(5);
339
+ await state._testAccess("_prepareSolutionItemsForStorage", "ca924c6db7d247b9a31fa30532fb5913", solutionData.templates, MOCK_USER_SESSION);
340
+ expect(template.resources).toEqual([
341
+ "79036430a6274e17ae915d0278b8569c_info_thumbnail/thumbnail.JPEG",
342
+ "79036430a6274e17ae915d0278b8569c/" + sampleImageFile.name
343
+ ]);
344
+ // Check that the augmentation has been removed from each template
345
+ expect(solutionData.templates.some(t => t.hasOwnProperty("resourceFilePaths"))).toBeFalsy();
346
+ expect(solutionData.templates.some(t => t.hasOwnProperty("thumbnail"))).toBeFalsy();
347
+ expect(solutionData.templates.some(t => t.hasOwnProperty("groupDetails"))).toBeFalsy();
348
+ });
349
+ it("catches errors updating or removing resources while preparing a solution for storage", async () => {
350
+ jest.spyOn(console, "log").mockImplementation(() => { });
351
+ // Get the templates; parse+stringify seems only working way to avoid modifying data file
352
+ const solutionData = JSON.parse(JSON.stringify(solution_ca924c));
353
+ // Provide thumbnail images for the templates and prepare the templates for editing
354
+ const sampleImageFile = testUtils.getSampleImageAsFile();
355
+ jest.spyOn(common, "getThumbnailFromStorageItem").mockResolvedValue(sampleImageFile);
356
+ await state._testAccess("_prepareSolutionItemsForEditing", "ca924c6db7d247b9a31fa30532fb5913", solutionData.templates, MOCK_USER_SESSION);
357
+ // Provide some resource mods
358
+ const template = solutionData.templates[0];
359
+ template.resourceFilePaths.push({
360
+ blob: sampleImageFile,
361
+ filename: template.resourceFilePaths[1].filename,
362
+ type: common.EFileType.Thumbnail,
363
+ updateType: EUpdateType.Update
364
+ });
365
+ template.resourceFilePaths.push({
366
+ filename: template.resourceFilePaths[0].filename,
367
+ type: common.EFileType.Metadata,
368
+ updateType: EUpdateType.Remove
369
+ });
370
+ // Run the prep
371
+ jest.spyOn(console, "log").mockImplementation(() => { }); // hide error messages from _prepareSolutionItemsForStorage
372
+ jest.spyOn(common, "removeItemResourceFile").mockImplementation(() => { throw new Error("Item does not exist or is inaccessible."); });
373
+ jest.spyOn(common, "updateItemResourceFile").mockImplementation(() => { throw new Error("Item does not exist or is inaccessible."); });
374
+ expect(template.resourceFilePaths.length).toEqual(4);
375
+ await state._testAccess("_prepareSolutionItemsForStorage", "ca924c6db7d247b9a31fa30532fb5913", solutionData.templates, MOCK_USER_SESSION);
376
+ expect(template.resources).toEqual([
377
+ "79036430a6274e17ae915d0278b8569c_info_metadata/metadata.xml",
378
+ "79036430a6274e17ae915d0278b8569c_info_thumbnail/thumbnail.JPEG"
379
+ ]);
380
+ // Check that the augmentation has been removed from each template
381
+ expect(solutionData.templates.some(t => t.hasOwnProperty("resourceFilePaths"))).toBeFalsy();
382
+ expect(solutionData.templates.some(t => t.hasOwnProperty("thumbnail"))).toBeFalsy();
383
+ expect(solutionData.templates.some(t => t.hasOwnProperty("groupDetails"))).toBeFalsy();
384
+ });
385
+ });
386
+ describe("_setSpatialReferenceInfo", () => {
387
+ it("handles an enabled custom spatial reference", () => {
388
+ jest.spyOn(common, "setCreateProp").mockImplementation(() => { });
389
+ const spatialReferenceInfo = {
390
+ enabled: true,
391
+ services: {
392
+ "Driver_Activity": false,
393
+ "OperationsManagement": true,
394
+ "Requests": false,
395
+ "ServiceAreas": true,
396
+ "SnowRoutes": false // has "wkid": 4326
397
+ },
398
+ spatialReference: 2865
399
+ };
400
+ const solutionTemplates = JSON.parse(JSON.stringify(solution_ca924c)).templates;
401
+ const updatedWkid = state._testAccess("_setSpatialReferenceInfo", spatialReferenceInfo, solutionTemplates);
402
+ expect(updatedWkid).toEqual(2865);
403
+ });
404
+ it("handles a disabled custom spatial reference", () => {
405
+ jest.spyOn(common, "setCreateProp").mockImplementation(() => { });
406
+ const spatialReferenceInfo = {
407
+ enabled: false,
408
+ services: {
409
+ "Driver_Activity": false,
410
+ "OperationsManagement": true,
411
+ "Requests": false,
412
+ "ServiceAreas": true,
413
+ "SnowRoutes": false // has "wkid": 4326
414
+ },
415
+ spatialReference: 2865
416
+ };
417
+ const solutionTemplates = JSON.parse(JSON.stringify(solution_ca924c)).templates;
418
+ const updatedWkid = state._testAccess("_setSpatialReferenceInfo", spatialReferenceInfo, solutionTemplates);
419
+ expect(updatedWkid).toBeUndefined();
420
+ });
421
+ });
422
+ describe("_splitFilename", () => {
423
+ it("handles filename without prefix", () => {
424
+ const { prefix, suffix } = state._testAccess("_splitFilename", "sample.txt");
425
+ expect(prefix).toBeUndefined();
426
+ expect(suffix).toEqual("sample.txt");
427
+ });
428
+ it("handles filename with single prefix", () => {
429
+ const { prefix, suffix } = state._testAccess("_splitFilename", "folder/sample.txt");
430
+ expect(prefix).toEqual("folder");
431
+ expect(suffix).toEqual("sample.txt");
432
+ });
433
+ it("handles filename with multiple prefixes", () => {
434
+ const { prefix, suffix } = state._testAccess("_splitFilename", "folder/subfolder/sample.txt");
435
+ expect(prefix).toEqual("folder/subfolder");
436
+ expect(suffix).toEqual("sample.txt");
437
+ });
438
+ });
439
+ });
@@ -429,34 +429,37 @@ const MapSelectTools = /*@__PURE__*/ proxyCustomElement(class extends HTMLElemen
429
429
  */
430
430
  async _sketchGraphicsChanged(event, forceUpdate = false) {
431
431
  const graphics = event.detail.graphics;
432
- if (!forceUpdate) {
433
- this._sketchGraphic = graphics[0];
434
- }
435
- this._workflowType = this._useLayerFeaturesEnabled ? EWorkflowType.SELECT : EWorkflowType.SKETCH;
436
- if (this._workflowType === EWorkflowType.SKETCH) {
437
- this._drawTools.updateGraphics();
438
- }
439
- this._updateLabel();
440
- this._clearSearchWidget();
441
- if (this._useLayerFeaturesEnabled && !forceUpdate) {
442
- const geometries = Array.isArray(graphics) && graphics.length > 0 && graphics[0] ? graphics.map(g => g.geometry) : this.geometries;
443
- await this._selectLayerFeatures(geometries[0]);
444
- }
445
- else {
446
- const oids = graphics.reduce((prev, cur) => {
447
- var _a;
448
- if ((_a = cur === null || cur === void 0 ? void 0 : cur.layer) === null || _a === void 0 ? void 0 : _a.objectIdField) {
449
- prev.push(cur.attributes[cur.layer.objectIdField]);
450
- }
451
- else if (cur.getObjectId) {
452
- prev.push(cur.getObjectId());
432
+ if (graphics.length > 0 && graphics[0]) {
433
+ if (!forceUpdate) {
434
+ this._sketchGraphic = graphics[0];
435
+ }
436
+ this._workflowType = this._useLayerFeaturesEnabled ? EWorkflowType.SELECT : EWorkflowType.SKETCH;
437
+ if (this._workflowType === EWorkflowType.SKETCH) {
438
+ this._drawTools.updateGraphics();
439
+ }
440
+ this._updateLabel();
441
+ this._clearSearchWidget();
442
+ if (this._useLayerFeaturesEnabled && !forceUpdate) {
443
+ // Will only ever be a single graphic
444
+ const geometries = Array.isArray(graphics) ? graphics.map(g => g.geometry) : this.geometries;
445
+ await this._selectLayerFeatures(geometries[0]);
446
+ }
447
+ else {
448
+ const oids = graphics.reduce((prev, cur) => {
449
+ var _a;
450
+ if ((_a = cur === null || cur === void 0 ? void 0 : cur.layer) === null || _a === void 0 ? void 0 : _a.objectIdField) {
451
+ prev.push(cur.attributes[cur.layer.objectIdField]);
452
+ }
453
+ else if (cur.getObjectId) {
454
+ prev.push(cur.getObjectId());
455
+ }
456
+ return prev;
457
+ }, []);
458
+ const useOIDs = event.detail.useOIDs && oids.length > 0;
459
+ this._updateSelection(graphics, useOIDs, oids);
460
+ if (useOIDs) {
461
+ await this._highlightFeatures(oids);
453
462
  }
454
- return prev;
455
- }, []);
456
- const useOIDs = event.detail.useOIDs && oids.length > 0;
457
- this._updateSelection(graphics, useOIDs, oids);
458
- if (useOIDs) {
459
- await this._highlightFeatures(oids);
460
463
  }
461
464
  }
462
465
  }
@@ -578,7 +581,6 @@ const MapSelectTools = /*@__PURE__*/ proxyCustomElement(class extends HTMLElemen
578
581
  this._selectedIds = [];
579
582
  this._distance = undefined;
580
583
  this._unit = undefined;
581
- this._sketchGraphic = undefined;
582
584
  if (clearLabel) {
583
585
  this._selectionLabel = "";
584
586
  this._labelName.value = "";
@@ -745,14 +747,12 @@ const MapSelectTools = /*@__PURE__*/ proxyCustomElement(class extends HTMLElemen
745
747
  */
746
748
  _useLayerFeaturesEnabledChanged() {
747
749
  this._useLayerFeaturesEnabled = !this._useLayerFeaturesEnabled;
748
- if (this._sketchGraphic) {
749
- void this._sketchGraphicsChanged({
750
- detail: {
751
- graphics: [this._sketchGraphic],
752
- useOIDs: false
753
- }
754
- });
755
- }
750
+ void this._sketchGraphicsChanged({
751
+ detail: {
752
+ graphics: [this._sketchGraphic],
753
+ useOIDs: false
754
+ }
755
+ });
756
756
  }
757
757
  /**
758
758
  * Fetches the component's translations
@@ -897,7 +897,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
897
897
  });
898
898
 
899
899
  /*!
900
- * @esri/arcgis-html-sanitizer - v3.0.0 - Mon Aug 22 2022 11:29:01 GMT-0400 (Eastern Daylight Time)
900
+ * @esri/arcgis-html-sanitizer - v3.0.1 - Tue Nov 15 2022 09:46:54 GMT-0800 (Pacific Standard Time)
901
901
  * Copyright (c) 2022 - Environmental Systems Research Institute, Inc.
902
902
  * Apache-2.0
903
903
  *
@@ -2132,7 +2132,7 @@ function parseTag$1(html, onTag, escapeHtml) {
2132
2132
  lastPos = currentPos;
2133
2133
  continue;
2134
2134
  }
2135
- if (c === ">" || currentPos === len - 1) {
2135
+ if (c === ">") {
2136
2136
  rethtml += escapeHtml(html.slice(lastPos, tagStart));
2137
2137
  currentHtml = html.slice(tagStart, currentPos + 1);
2138
2138
  currentTagName = getTagName(currentHtml);
@@ -2167,7 +2167,7 @@ function parseTag$1(html, onTag, escapeHtml) {
2167
2167
  }
2168
2168
  }
2169
2169
  }
2170
- if (lastPos < len) {
2170
+ if (lastPos < html.length) {
2171
2171
  rethtml += escapeHtml(html.substr(lastPos));
2172
2172
  }
2173
2173
 
@@ -870,34 +870,37 @@ const MapSelectTools = class {
870
870
  */
871
871
  async _sketchGraphicsChanged(event, forceUpdate = false) {
872
872
  const graphics = event.detail.graphics;
873
- if (!forceUpdate) {
874
- this._sketchGraphic = graphics[0];
875
- }
876
- this._workflowType = this._useLayerFeaturesEnabled ? EWorkflowType.SELECT : EWorkflowType.SKETCH;
877
- if (this._workflowType === EWorkflowType.SKETCH) {
878
- this._drawTools.updateGraphics();
879
- }
880
- this._updateLabel();
881
- this._clearSearchWidget();
882
- if (this._useLayerFeaturesEnabled && !forceUpdate) {
883
- const geometries = Array.isArray(graphics) && graphics.length > 0 && graphics[0] ? graphics.map(g => g.geometry) : this.geometries;
884
- await this._selectLayerFeatures(geometries[0]);
885
- }
886
- else {
887
- const oids = graphics.reduce((prev, cur) => {
888
- var _a;
889
- if ((_a = cur === null || cur === void 0 ? void 0 : cur.layer) === null || _a === void 0 ? void 0 : _a.objectIdField) {
890
- prev.push(cur.attributes[cur.layer.objectIdField]);
891
- }
892
- else if (cur.getObjectId) {
893
- prev.push(cur.getObjectId());
873
+ if (graphics.length > 0 && graphics[0]) {
874
+ if (!forceUpdate) {
875
+ this._sketchGraphic = graphics[0];
876
+ }
877
+ this._workflowType = this._useLayerFeaturesEnabled ? EWorkflowType.SELECT : EWorkflowType.SKETCH;
878
+ if (this._workflowType === EWorkflowType.SKETCH) {
879
+ this._drawTools.updateGraphics();
880
+ }
881
+ this._updateLabel();
882
+ this._clearSearchWidget();
883
+ if (this._useLayerFeaturesEnabled && !forceUpdate) {
884
+ // Will only ever be a single graphic
885
+ const geometries = Array.isArray(graphics) ? graphics.map(g => g.geometry) : this.geometries;
886
+ await this._selectLayerFeatures(geometries[0]);
887
+ }
888
+ else {
889
+ const oids = graphics.reduce((prev, cur) => {
890
+ var _a;
891
+ if ((_a = cur === null || cur === void 0 ? void 0 : cur.layer) === null || _a === void 0 ? void 0 : _a.objectIdField) {
892
+ prev.push(cur.attributes[cur.layer.objectIdField]);
893
+ }
894
+ else if (cur.getObjectId) {
895
+ prev.push(cur.getObjectId());
896
+ }
897
+ return prev;
898
+ }, []);
899
+ const useOIDs = event.detail.useOIDs && oids.length > 0;
900
+ this._updateSelection(graphics, useOIDs, oids);
901
+ if (useOIDs) {
902
+ await this._highlightFeatures(oids);
894
903
  }
895
- return prev;
896
- }, []);
897
- const useOIDs = event.detail.useOIDs && oids.length > 0;
898
- this._updateSelection(graphics, useOIDs, oids);
899
- if (useOIDs) {
900
- await this._highlightFeatures(oids);
901
904
  }
902
905
  }
903
906
  }
@@ -1019,7 +1022,6 @@ const MapSelectTools = class {
1019
1022
  this._selectedIds = [];
1020
1023
  this._distance = undefined;
1021
1024
  this._unit = undefined;
1022
- this._sketchGraphic = undefined;
1023
1025
  if (clearLabel) {
1024
1026
  this._selectionLabel = "";
1025
1027
  this._labelName.value = "";
@@ -1186,14 +1188,12 @@ const MapSelectTools = class {
1186
1188
  */
1187
1189
  _useLayerFeaturesEnabledChanged() {
1188
1190
  this._useLayerFeaturesEnabled = !this._useLayerFeaturesEnabled;
1189
- if (this._sketchGraphic) {
1190
- void this._sketchGraphicsChanged({
1191
- detail: {
1192
- graphics: [this._sketchGraphic],
1193
- useOIDs: false
1194
- }
1195
- });
1196
- }
1191
+ void this._sketchGraphicsChanged({
1192
+ detail: {
1193
+ graphics: [this._sketchGraphic],
1194
+ useOIDs: false
1195
+ }
1196
+ });
1197
1197
  }
1198
1198
  /**
1199
1199
  * Fetches the component's translations