@esri/solutions-components 0.5.3 → 0.5.4

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 (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