@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,341 @@
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
+ //--------------------------------------------------------------------------
17
+ //
18
+ // Public Functions
19
+ //
20
+ //--------------------------------------------------------------------------
21
+ /**
22
+ * Sort the solution items
23
+ *
24
+ * @param templates a list of item templates from the solution
25
+ *
26
+ * @returns a sorted list of solution items
27
+ */
28
+ export function getInventoryItems(templates) {
29
+ const hierarchy = getItemHierarchy(templates);
30
+ const ids = hierarchy.reduce((prev, cur) => {
31
+ prev.push(cur.id);
32
+ return prev;
33
+ }, []);
34
+ return templates.reduce((prev, cur) => {
35
+ if (ids.indexOf(cur.itemId) > -1) {
36
+ const hierarchyItems = hierarchy.filter(hi => hi.id === cur.itemId);
37
+ prev.push(_getItemFromTemplate(cur, templates, hierarchyItems[0].dependencies));
38
+ }
39
+ return prev;
40
+ }, []);
41
+ }
42
+ /**
43
+ * Create item hierarchy that will avoid issues from cylical dependencies
44
+ *
45
+ * @param templates a list of item templates from the solution
46
+ *
47
+ * @returns a hierarchy for item and item dependency display
48
+ */
49
+ export function getItemHierarchy(templates) {
50
+ const hierarchy = [];
51
+ // Get the template specified by id out of a list of templates
52
+ function getTemplateInSolution(templates, id) {
53
+ const iTemplate = templates.findIndex((template) => id === template.itemId);
54
+ return iTemplate >= 0 ? templates[iTemplate] : null;
55
+ }
56
+ // Hierarchically list the dependencies of specified node
57
+ function traceItemId(id, accumulatedHierarchy, alreadyVisitedIds = []) {
58
+ // Get the dependencies of the node
59
+ const template = getTemplateInSolution(templates, id);
60
+ /* istanbul ignore else */
61
+ if (template) {
62
+ const templateEntry = {
63
+ id,
64
+ dependencies: []
65
+ };
66
+ // Visit each dependency, but only if this template is not in the alreadyVisitedIds list to avoid infinite loops
67
+ /* istanbul ignore else */
68
+ if (alreadyVisitedIds.indexOf(id) < 0) {
69
+ // Add dependency to alreadyVisitedIds list
70
+ alreadyVisitedIds.push(id);
71
+ template.dependencies.forEach((dependencyId) => {
72
+ // Remove dependency from list of templates to visit in the top-level loop
73
+ const iDependencyTemplate = templateItemIds.indexOf(dependencyId);
74
+ /* istanbul ignore else */
75
+ if (iDependencyTemplate >= 0) {
76
+ templateItemIds.splice(iDependencyTemplate, 1);
77
+ }
78
+ traceItemId(dependencyId, templateEntry.dependencies, alreadyVisitedIds);
79
+ });
80
+ }
81
+ accumulatedHierarchy.push(templateEntry);
82
+ }
83
+ }
84
+ // Start with top-level nodes and add in the rest of the nodes to catch cycles without top-level nodes
85
+ let templateItemIds = _getTopLevelItemIds(templates);
86
+ const otherItems = templates
87
+ .filter((template) => templateItemIds.indexOf(template.itemId) < 0) // only keep non-top-level nodes
88
+ .sort((a, b) => b.dependencies.length - a.dependencies.length); // sort so that nodes with more dependencies come first--reduces stubs
89
+ templateItemIds = templateItemIds.concat(otherItems.map((template) => template.itemId));
90
+ // Step through the list of nodes; we'll also remove nodes as we visit them
91
+ let itemId = templateItemIds.shift();
92
+ while (typeof itemId !== "undefined") {
93
+ traceItemId(itemId, hierarchy);
94
+ itemId = templateItemIds.shift();
95
+ }
96
+ return hierarchy;
97
+ }
98
+ /**
99
+ * Explore the solution item templates for variables we will allow users to insert at runtime
100
+ *
101
+ * @param templates a list of item templates from the solution
102
+ * @param translations nls translation object
103
+ *
104
+ * @returns a list of variables from the solution item templates
105
+ */
106
+ export function getSolutionVariables(templates, translations) {
107
+ const vars = [];
108
+ templates.forEach(t => {
109
+ const item = {
110
+ id: t.itemId,
111
+ title: t.item.title || t.item.name,
112
+ type: t.type,
113
+ value: undefined,
114
+ dependencies: [{
115
+ id: t.itemId,
116
+ title: translations.itemId,
117
+ value: `{{${t.itemId}.itemId}}`,
118
+ }]
119
+ };
120
+ if (t.item.url) {
121
+ item.dependencies.push({
122
+ id: t.itemId,
123
+ title: translations.url,
124
+ value: `{{${t.itemId}.url}}`,
125
+ });
126
+ }
127
+ if (t.type === "Feature Service") {
128
+ // TODO need to set source service name var...
129
+ // TODO need to set soure service shape field name "{{d05b3cf1ffcb4a4fa677627dfb18609e.name}}.Shape"
130
+ item.dependencies.push({
131
+ id: t.itemId,
132
+ title: translations.solutionExtent,
133
+ value: `{{${t.itemId}.solutionExtent}}`,
134
+ });
135
+ _addLayersOrTables(t.properties.layers || [], item, t, translations);
136
+ _addLayersOrTables(t.properties.tables || [], item, t, translations);
137
+ }
138
+ vars.push(item);
139
+ });
140
+ return vars;
141
+ }
142
+ /**
143
+ * Set key organization variables we will allow users to insert at runtime
144
+ *
145
+ * @param translations nls translation object
146
+ *
147
+ * @returns a list of variables for the organization
148
+ */
149
+ export function getOrganizationVariables(translations) {
150
+ const orgVars = [{
151
+ id: "",
152
+ title: translations.geocodeUrl,
153
+ value: "{{organization.helperServices.geocode:getDefaultLocatorURL}}"
154
+ }, {
155
+ id: "",
156
+ title: translations.geometryUrl,
157
+ value: "{{organization.helperServices.geometry.url}}"
158
+ }, {
159
+ id: "",
160
+ title: translations.portalBaseUrl,
161
+ value: "{{portalBaseUrl}}"
162
+ }, {
163
+ id: "",
164
+ title: translations.routeUrl,
165
+ value: "{{organization.helperServices.route.url}}"
166
+ }, {
167
+ id: "",
168
+ title: translations.solutionItemExtent,
169
+ value: "{{solutionItemExtent}}"
170
+ }];
171
+ return orgVars;
172
+ }
173
+ //--------------------------------------------------------------------------
174
+ //
175
+ // Private Functions
176
+ //
177
+ //--------------------------------------------------------------------------
178
+ /**
179
+ * Explore a solution item template for variables we will allow users to insert at runtime.
180
+ * This function will update the item argument that is passed in with the var details.
181
+ *
182
+ * @param children a list of layers or tables from a template
183
+ * @param item an object that store key details for a given variable
184
+ * @param template one of the templates from the current solution
185
+ * @param translations nls translations object
186
+ *
187
+ */
188
+ function _addLayersOrTables(children, item, template, translations) {
189
+ children.forEach(l => {
190
+ const name = l.name && l.name.indexOf("||") > -1 ? l.name.split("||")[1].replace("}}", "").trim() : l.name;
191
+ item.dependencies.push({
192
+ id: template.itemId,
193
+ title: `${name} (${translations.id})`,
194
+ value: `{{${template.itemId}.layer${l.id}.id}}`,
195
+ });
196
+ item.dependencies.push({
197
+ id: template.itemId,
198
+ title: `${name} (${translations.name})`,
199
+ value: `{{${template.itemId}.layer${l.id}.name||${name}}}`,
200
+ });
201
+ });
202
+ }
203
+ /**
204
+ * Capture key details from the solution item template
205
+ *
206
+ * @param template one of the templates from the current solution
207
+ * @param templates full list of templates
208
+ * @param dependencies list of hierarchical dependencies
209
+ *
210
+ * @returns an IInventoryItem that is used by other components to work with this template
211
+ */
212
+ function _getItemFromTemplate(template, templates, dependencies) {
213
+ return {
214
+ id: template.itemId || "",
215
+ title: template.item.title || "",
216
+ dependencies: _getDependencies(dependencies, templates),
217
+ type: template.item.type || "",
218
+ typeKeywords: template.item.typeKeywords || [] /*,
219
+ solutionItem: {
220
+ itemId: template.itemId,
221
+ itemDetails: _getItemDetails(template.item, template.type === "Group"),
222
+ isResource: _getIsResource(template),
223
+ data: template.data,
224
+ properties: template.properties,
225
+ type: template.type,
226
+ groupDetails: _getGroupDetails(template, templates)
227
+ }*/
228
+ };
229
+ }
230
+ /**
231
+ * Capture key details from the solution item template
232
+ *
233
+ * @param dependencies list of dependencies from a template
234
+ * @param templates full list of templates
235
+ *
236
+ * @returns a list of IInventoryItem that are used by other components to work with the templates
237
+ */
238
+ function _getDependencies(dependencies, templates) {
239
+ const dependencyItems = [];
240
+ const depIds = dependencies.reduce((prev, cur) => {
241
+ prev.push(cur.id);
242
+ dependencyItems.push(cur);
243
+ return prev;
244
+ }, []);
245
+ return templates.reduce((prev, curr) => {
246
+ const i = depIds.indexOf(curr.itemId);
247
+ if (i > -1) {
248
+ prev.push(_getItemFromTemplate(curr, templates, dependencyItems[i].dependencies));
249
+ }
250
+ return prev;
251
+ }, []);
252
+ }
253
+ /**
254
+ * Capture the key item details for a given template
255
+ *
256
+ * @param item the templates item
257
+ * @param isGroup boolean to indicate if the item is a group
258
+ * @param itemId the item id of the template
259
+ *
260
+ * @returns a IItemDetails object for the current item
261
+ */
262
+ /*
263
+ function _getItemDetails(
264
+ item: any,
265
+ isGroup: boolean
266
+ ): IItemDetails {
267
+ return {
268
+ title: item.title || "",
269
+ snippet: item.snippet || "",
270
+ description: item.description || "",
271
+ tags: item.tags || [],
272
+ accessInformation: !isGroup ? item.accessInformation || "" : "",
273
+ licenseInfo: !isGroup ? item.licenseInfo || "" : ""
274
+ };
275
+ }
276
+ */
277
+ /**
278
+ * Capture the key item details for a given group template
279
+ *
280
+ * @param template one of the templates from the current solution
281
+ * @param templates full list of templates
282
+ *
283
+ * @returns a list of IItemShare objects
284
+ */
285
+ /*
286
+ function _getGroupDetails(
287
+ template: any,
288
+ templates: any[]
289
+ ): IItemShare[] {
290
+ return template.type === "Group" ? templates.reduce((prev, cur) => {
291
+ if (cur.itemId !== template.itemId && cur.type !== "Group") {
292
+ prev.push({
293
+ id: cur.itemId,
294
+ title: cur.item.name || cur.item.title,
295
+ isShared: (cur.groups || []).indexOf(template.itemId) > -1,
296
+ shareItem: (cur.groups || []).indexOf(template.itemId) > -1,
297
+ type: cur.type,
298
+ typeKeywords: cur.item.typeKeywords
299
+ });
300
+ }
301
+ return prev;
302
+ }, []) : [];
303
+ }
304
+ */
305
+ /**
306
+ * Used to understand if we are dealing with a binary object that will support upload/download
307
+ *
308
+ * @param template one of the templates from the current solution
309
+ *
310
+ * @returns true if this item supports upload/download
311
+ */
312
+ /*
313
+ function _getIsResource(
314
+ template: any
315
+ ): boolean {
316
+ return template.type !== "Group" && template.resources.some(r => r.indexOf("_info_thumbnail") < 0) &&
317
+ (template.data === null || JSON.stringify(template.data) === "{}");
318
+ }
319
+ */
320
+ /**
321
+ * Sort the template ids based on their dependencies
322
+ *
323
+ * @param templates full list of templates
324
+ *
325
+ * @returns a list of Itop level item ids
326
+ */
327
+ function _getTopLevelItemIds(templates) {
328
+ // Find the top-level nodes. Start with all nodes, then remove those that other nodes depend on
329
+ const topLevelItemCandidateIds = templates.map((template) => template.itemId);
330
+ templates.forEach((template) => {
331
+ (template.dependencies || []).forEach((dependencyId) => {
332
+ const iNode = topLevelItemCandidateIds.indexOf(dependencyId);
333
+ if (iNode >= 0) {
334
+ // Node is somebody's dependency, so remove the node from the list of top-level nodes
335
+ // If iNode == -1, then it's a shared dependency and it has already been removed
336
+ topLevelItemCandidateIds.splice(iNode, 1);
337
+ }
338
+ });
339
+ });
340
+ return topLevelItemCandidateIds;
341
+ }
@@ -0,0 +1,46 @@
1
+ /** @license
2
+ * Copyright 2023 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 csvDownload from "../csvDownload";
17
+ import * as csvUtils from "../csvUtils";
18
+ import { expect, jest } from "@jest/globals";
19
+ afterEach(() => {
20
+ jest.restoreAllMocks();
21
+ });
22
+ describe("csvUtils", () => {
23
+ describe("exportCSV", () => {
24
+ it("prepares output lines 1", () => {
25
+ const title = "title";
26
+ const labels = [
27
+ ["Cyd Charise", "1922 Main St", "Amarillo, TX 79118"],
28
+ ["Fred Astaire", "1899 Main St", "Omaha, NE 68022"],
29
+ ["Gene Kelly", "1912 Main St", "Pittsburgh, PA 15215"],
30
+ ["Ginger Rogers", "1911 Main St", "Independence, MO 64050"]
31
+ ];
32
+ const expectedOutputLines = [
33
+ "\"Cyd Charise\",\"1922 Main St\",\"Amarillo, TX 79118\"\r\n",
34
+ "\"Fred Astaire\",\"1899 Main St\",\"Omaha, NE 68022\"\r\n",
35
+ "\"Gene Kelly\",\"1912 Main St\",\"Pittsburgh, PA 15215\"\r\n",
36
+ "\"Ginger Rogers\",\"1911 Main St\",\"Independence, MO 64050\"\r\n"
37
+ ];
38
+ const downloadCSVFileMock = jest.spyOn(csvDownload, "downloadCSVFile")
39
+ .mockImplementation((fileTitle, outputLines) => { });
40
+ csvUtils.exportCSV(title, labels);
41
+ expect(downloadCSVFileMock).toBeCalledTimes(1);
42
+ expect(downloadCSVFileMock.mock.calls[0][0]).toEqual(title);
43
+ expect(downloadCSVFileMock.mock.calls[0][1]).toEqual(expectedOutputLines);
44
+ });
45
+ });
46
+ });
@@ -0,0 +1,102 @@
1
+ /** @license
2
+ * Copyright 2023 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 downloadUtils from "../downloadUtils";
17
+ describe("downloadUtils", () => {
18
+ describe("_convertPopupFieldsToLabelSpec", () => {
19
+ it("handles fieldname visibility", () => {
20
+ const fieldInfos = [
21
+ { fieldName: "A", visible: true },
22
+ { fieldName: "B", visible: true },
23
+ { fieldName: "C", visible: false },
24
+ { fieldName: "D", visible: true }
25
+ ];
26
+ const bypassFieldVisiblity = false;
27
+ const expectedLabelSpec = "{A}|{B}|{D}";
28
+ const labelSpec = downloadUtils._convertPopupFieldsToLabelSpec(fieldInfos, bypassFieldVisiblity);
29
+ expect(labelSpec).toEqual(expectedLabelSpec);
30
+ });
31
+ it("handles fieldname ignoring visibility", () => {
32
+ const fieldInfos = [
33
+ { fieldName: "A", visible: true },
34
+ { fieldName: "B", visible: true },
35
+ { fieldName: "C", visible: false },
36
+ { fieldName: "D", visible: true }
37
+ ];
38
+ const bypassFieldVisiblity = true;
39
+ const expectedLabelSpec = "{A}|{B}|{C}|{D}";
40
+ const labelSpec = downloadUtils._convertPopupFieldsToLabelSpec(fieldInfos, bypassFieldVisiblity);
41
+ expect(labelSpec).toEqual(expectedLabelSpec);
42
+ });
43
+ });
44
+ describe("_convertPopupTextToLabelSpec", () => {
45
+ it("handles <br> variants", () => {
46
+ const popupInfo = "<div style='text-align: left;'>{NAME}<br />{STREET}<br/>{CITY}, {STATE} {ZIP} <br></div>";
47
+ const expectedLabelSpec = "{NAME}|{STREET}|{CITY}, {STATE} {ZIP}";
48
+ const labelSpec = downloadUtils._convertPopupTextToLabelSpec(popupInfo);
49
+ expect(labelSpec).toEqual(expectedLabelSpec);
50
+ });
51
+ it("handles <p>", () => {
52
+ const popupInfo = "<p>{NAME}</p><p>{STREET}</p><p>{CITY}, {STATE} {ZIP}</p>";
53
+ const expectedLabelSpec = "{NAME}|{STREET}|{CITY}, {STATE} {ZIP}";
54
+ const labelSpec = downloadUtils._convertPopupTextToLabelSpec(popupInfo);
55
+ expect(labelSpec).toEqual(expectedLabelSpec);
56
+ });
57
+ it("handles popup's use of \xA0", () => {
58
+ const popupInfo = "<div style='text-align: left;'>{NAME}<br />{STREET}<br />{CITY},\xA0{STATE}\xA0{ZIP}\xA0<br /></div>";
59
+ const expectedLabelSpec = "{NAME}|{STREET}|{CITY}, {STATE} {ZIP}";
60
+ const labelSpec = downloadUtils._convertPopupTextToLabelSpec(popupInfo);
61
+ expect(labelSpec).toEqual(expectedLabelSpec);
62
+ });
63
+ it("removes newlines and blank lines, and trims each line", () => {
64
+ const popupInfo = " \n\n {NAME} \n \n\n {STREET}\n{CITY}, {STATE} {ZIP}\n\n \n ";
65
+ const expectedLabelSpec = "{NAME}|{STREET}|{CITY}, {STATE} {ZIP}";
66
+ const labelSpec = downloadUtils._convertPopupTextToLabelSpec(popupInfo);
67
+ expect(labelSpec).toEqual(expectedLabelSpec);
68
+ });
69
+ it("removes extra HTML", () => {
70
+ const popupInfo = "\n<div style='text-align: left;'><span style='font-weight:bold'>{NAME}</span><br />{STREET}<br />{CITY},\xA0{STATE}\xA0{ZIP}\xA0<br /></div>\n";
71
+ const expectedLabelSpec = "{NAME}|{STREET}|{CITY}, {STATE} {ZIP}";
72
+ const labelSpec = downloadUtils._convertPopupTextToLabelSpec(popupInfo);
73
+ expect(labelSpec).toEqual(expectedLabelSpec);
74
+ });
75
+ it("handles some special characters", () => {
76
+ const popupInfo = "<div style='text-align: left;'>&lt;{NAME}&gt;<br />{STREET}<br/>{CITY},&nbsp;{STATE}&nbsp;{ZIP}<br></div>";
77
+ const expectedLabelSpec = "<{NAME}>|{STREET}|{CITY}, {STATE} {ZIP}";
78
+ const labelSpec = downloadUtils._convertPopupTextToLabelSpec(popupInfo);
79
+ expect(labelSpec).toEqual(expectedLabelSpec);
80
+ });
81
+ });
82
+ describe("_createTitle", () => {
83
+ it("handles no selection set names", () => {
84
+ const selectionSetNames = [];
85
+ const expectedTitle = "download";
86
+ const title = downloadUtils._createTitle(selectionSetNames);
87
+ expect(title).toEqual(expectedTitle);
88
+ });
89
+ it("handles one selection set name", () => {
90
+ const selectionSetNames = ["fred"];
91
+ const expectedTitle = "fred";
92
+ const title = downloadUtils._createTitle(selectionSetNames);
93
+ expect(title).toEqual(expectedTitle);
94
+ });
95
+ it("handles two selection set names", () => {
96
+ const selectionSetNames = ["fred", "ginger"];
97
+ const expectedTitle = "fred,ginger";
98
+ const title = downloadUtils._createTitle(selectionSetNames);
99
+ expect(title).toEqual(expectedTitle);
100
+ });
101
+ });
102
+ });
@@ -0,0 +1,74 @@
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
+ export class GraphicsLayer {
17
+ constructor(options) {
18
+ this.title = options.title;
19
+ this.graphics = [];
20
+ this.removeAll = () => {
21
+ this.graphics = [];
22
+ };
23
+ this.addMany = (graphics) => {
24
+ this.graphics.concat(graphics);
25
+ };
26
+ }
27
+ }
28
+ export class Graphic {
29
+ constructor(options) {
30
+ Object.assign(this, options);
31
+ }
32
+ }
33
+ export class Sketch {
34
+ constructor(options) {
35
+ Object.assign(this, options);
36
+ this.viewModel = {
37
+ pointSymbol: {},
38
+ polylineSymbol: {},
39
+ polygonSymbol: {},
40
+ };
41
+ this.on = () => { };
42
+ }
43
+ }
44
+ export class Search {
45
+ constructor(options) {
46
+ Object.assign(this, options);
47
+ this.clear = () => { };
48
+ this.on = () => { };
49
+ }
50
+ }
51
+ export class Geometry {
52
+ constructor(options) {
53
+ Object.assign(this, options);
54
+ }
55
+ }
56
+ export class geometryEngine {
57
+ constructor(options) {
58
+ Object.assign(this, options);
59
+ }
60
+ }
61
+ export class highlightHandle {
62
+ }
63
+ export class LayerView {
64
+ constructor(options) {
65
+ Object.assign(this, options);
66
+ this.layer = {
67
+ createQuery: () => {
68
+ return {};
69
+ },
70
+ queryFeatures: async () => {
71
+ }
72
+ };
73
+ }
74
+ }