@fgv/ts-web-extras 5.1.0-2 → 5.1.0-21

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 (263) hide show
  1. package/dist/packlets/crypto-utils/browserCryptoProvider.js +208 -18
  2. package/dist/packlets/crypto-utils/browserCryptoProvider.js.map +1 -1
  3. package/dist/packlets/file-tree/fileApiTreeAccessors.js +1 -1
  4. package/dist/packlets/file-tree/fileApiTreeAccessors.js.map +1 -1
  5. package/dist/packlets/file-tree/httpTreeAccessors.js +72 -42
  6. package/dist/packlets/file-tree/httpTreeAccessors.js.map +1 -1
  7. package/dist/ts-web-extras.d.ts +59 -7
  8. package/dist/tsdoc-metadata.json +1 -1
  9. package/lib/packlets/crypto-utils/browserCryptoProvider.d.ts +52 -5
  10. package/lib/packlets/crypto-utils/browserCryptoProvider.d.ts.map +1 -1
  11. package/lib/packlets/crypto-utils/browserCryptoProvider.js +207 -17
  12. package/lib/packlets/crypto-utils/browserCryptoProvider.js.map +1 -1
  13. package/lib/packlets/file-tree/fileApiTreeAccessors.d.ts +1 -1
  14. package/lib/packlets/file-tree/fileApiTreeAccessors.js +1 -1
  15. package/lib/packlets/file-tree/fileApiTreeAccessors.js.map +1 -1
  16. package/lib/packlets/file-tree/httpTreeAccessors.d.ts +6 -0
  17. package/lib/packlets/file-tree/httpTreeAccessors.d.ts.map +1 -1
  18. package/lib/packlets/file-tree/httpTreeAccessors.js +72 -42
  19. package/lib/packlets/file-tree/httpTreeAccessors.js.map +1 -1
  20. package/package.json +27 -26
  21. package/.rush/temp/chunked-rush-logs/ts-web-extras.build.chunks.jsonl +0 -75
  22. package/.rush/temp/chunked-rush-logs/ts-web-extras.test.chunks.jsonl +0 -75
  23. package/.rush/temp/operation/build/all.log +0 -75
  24. package/.rush/temp/operation/build/error.log +0 -18
  25. package/.rush/temp/operation/build/log-chunks.jsonl +0 -75
  26. package/.rush/temp/operation/build/state.json +0 -3
  27. package/.rush/temp/operation/test/all.log +0 -75
  28. package/.rush/temp/operation/test/error.log +0 -18
  29. package/.rush/temp/operation/test/log-chunks.jsonl +0 -75
  30. package/.rush/temp/operation/test/state.json +0 -3
  31. package/.rush/temp/shrinkwrap-deps.json +0 -635
  32. package/CHANGELOG.md +0 -23
  33. package/config/api-extractor.json +0 -343
  34. package/config/jest.config.json +0 -19
  35. package/config/rig.json +0 -16
  36. package/config/typedoc.json +0 -6
  37. package/dist/test/mocks/idb-keyval.js +0 -6
  38. package/dist/test/mocks/idb-keyval.js.map +0 -1
  39. package/dist/test/setupTests.js +0 -74
  40. package/dist/test/setupTests.js.map +0 -1
  41. package/dist/test/unit/browserHashProvider.test.js +0 -140
  42. package/dist/test/unit/browserHashProvider.test.js.map +0 -1
  43. package/dist/test/unit/directoryHandleStore.test.js +0 -190
  44. package/dist/test/unit/directoryHandleStore.test.js.map +0 -1
  45. package/dist/test/unit/fileApiTreeAccessors.test.js +0 -1188
  46. package/dist/test/unit/fileApiTreeAccessors.test.js.map +0 -1
  47. package/dist/test/unit/fileApiTypes.test.js +0 -472
  48. package/dist/test/unit/fileApiTypes.test.js.map +0 -1
  49. package/dist/test/unit/fileSystemAccessTreeAccessors.test.js +0 -622
  50. package/dist/test/unit/fileSystemAccessTreeAccessors.test.js.map +0 -1
  51. package/dist/test/unit/fileTreeHelpers.test.js +0 -590
  52. package/dist/test/unit/fileTreeHelpers.test.js.map +0 -1
  53. package/dist/test/unit/httpTreeAccessors.test.js +0 -1229
  54. package/dist/test/unit/httpTreeAccessors.test.js.map +0 -1
  55. package/dist/test/unit/localStorageTreeAccessors.test.js +0 -812
  56. package/dist/test/unit/localStorageTreeAccessors.test.js.map +0 -1
  57. package/dist/test/unit/urlParams.test.js +0 -393
  58. package/dist/test/unit/urlParams.test.js.map +0 -1
  59. package/dist/test/utils/fileSystemAccessMocks.js +0 -271
  60. package/dist/test/utils/fileSystemAccessMocks.js.map +0 -1
  61. package/dist/test/utils/testHelpers.js +0 -124
  62. package/dist/test/utils/testHelpers.js.map +0 -1
  63. package/docs/@fgv/namespaces/CryptoUtils/README.md +0 -18
  64. package/docs/@fgv/namespaces/CryptoUtils/classes/BrowserCryptoProvider.md +0 -203
  65. package/docs/@fgv/namespaces/CryptoUtils/classes/BrowserHashProvider.md +0 -63
  66. package/docs/@fgv/namespaces/CryptoUtils/functions/createBrowserCryptoProvider.md +0 -18
  67. package/docs/@fgv/namespaces/FileTreeHelpers/README.md +0 -19
  68. package/docs/@fgv/namespaces/FileTreeHelpers/functions/extractFileListMetadata.md +0 -23
  69. package/docs/@fgv/namespaces/FileTreeHelpers/functions/extractFileMetadata.md +0 -23
  70. package/docs/@fgv/namespaces/FileTreeHelpers/functions/fromDirectoryUpload.md +0 -33
  71. package/docs/@fgv/namespaces/FileTreeHelpers/functions/fromFileList.md +0 -33
  72. package/docs/@fgv/namespaces/FileTreeHelpers/functions/getOriginalFile.md +0 -25
  73. package/docs/@fgv/namespaces/FileTreeHelpers/variables/defaultFileApiTreeInitParams.md +0 -11
  74. package/docs/README.md +0 -78
  75. package/docs/classes/DirectoryHandleStore.md +0 -116
  76. package/docs/classes/FileApiTreeAccessors.md +0 -286
  77. package/docs/classes/FileSystemAccessTreeAccessors.md +0 -557
  78. package/docs/classes/HttpTreeAccessors.md +0 -508
  79. package/docs/classes/LocalStorageTreeAccessors.md +0 -520
  80. package/docs/functions/exportAsJson.md +0 -23
  81. package/docs/functions/exportUsingFileSystemAPI.md +0 -26
  82. package/docs/functions/extractDirectoryPath.md +0 -23
  83. package/docs/functions/isDirectoryHandle.md +0 -23
  84. package/docs/functions/isFileHandle.md +0 -23
  85. package/docs/functions/isFilePath.md +0 -21
  86. package/docs/functions/parseContextFilter.md +0 -22
  87. package/docs/functions/parseQualifierDefaults.md +0 -22
  88. package/docs/functions/parseResourceTypes.md +0 -22
  89. package/docs/functions/parseUrlParameters.md +0 -15
  90. package/docs/functions/safeShowDirectoryPicker.md +0 -24
  91. package/docs/functions/safeShowOpenFilePicker.md +0 -24
  92. package/docs/functions/safeShowSaveFilePicker.md +0 -24
  93. package/docs/functions/supportsFileSystemAccess.md +0 -23
  94. package/docs/interfaces/FilePickerAcceptType.md +0 -16
  95. package/docs/interfaces/FileSystemCreateWritableOptions.md +0 -15
  96. package/docs/interfaces/FileSystemDirectoryHandle.md +0 -187
  97. package/docs/interfaces/FileSystemFileHandle.md +0 -106
  98. package/docs/interfaces/FileSystemGetDirectoryOptions.md +0 -15
  99. package/docs/interfaces/FileSystemGetFileOptions.md +0 -15
  100. package/docs/interfaces/FileSystemHandle.md +0 -69
  101. package/docs/interfaces/FileSystemHandlePermissionDescriptor.md +0 -15
  102. package/docs/interfaces/FileSystemRemoveOptions.md +0 -15
  103. package/docs/interfaces/FileSystemWritableFileStream.md +0 -127
  104. package/docs/interfaces/IDirectoryHandleTreeInitializer.md +0 -17
  105. package/docs/interfaces/IFileHandleTreeInitializer.md +0 -16
  106. package/docs/interfaces/IFileListTreeInitializer.md +0 -15
  107. package/docs/interfaces/IFileMetadata.md +0 -19
  108. package/docs/interfaces/IFileSystemAccessTreeParams.md +0 -30
  109. package/docs/interfaces/IFsAccessApis.md +0 -57
  110. package/docs/interfaces/IHttpTreeParams.md +0 -32
  111. package/docs/interfaces/ILocalStorageTreeParams.md +0 -30
  112. package/docs/interfaces/IUrlConfigOptions.md +0 -27
  113. package/docs/interfaces/ShowDirectoryPickerOptions.md +0 -17
  114. package/docs/interfaces/ShowOpenFilePickerOptions.md +0 -19
  115. package/docs/interfaces/ShowSaveFilePickerOptions.md +0 -19
  116. package/docs/type-aliases/TreeInitializer.md +0 -11
  117. package/docs/type-aliases/WellKnownDirectory.md +0 -11
  118. package/docs/type-aliases/WindowWithFsAccess.md +0 -11
  119. package/docs/variables/DEFAULT_DIRECTORY_HANDLE_DB.md +0 -11
  120. package/docs/variables/DEFAULT_DIRECTORY_HANDLE_STORE.md +0 -11
  121. package/etc/ts-web-extras.api.md +0 -433
  122. package/lib/test/mocks/idb-keyval.d.ts +0 -6
  123. package/lib/test/mocks/idb-keyval.d.ts.map +0 -1
  124. package/lib/test/mocks/idb-keyval.js +0 -9
  125. package/lib/test/mocks/idb-keyval.js.map +0 -1
  126. package/lib/test/setupTests.d.ts +0 -2
  127. package/lib/test/setupTests.d.ts.map +0 -1
  128. package/lib/test/setupTests.js +0 -76
  129. package/lib/test/setupTests.js.map +0 -1
  130. package/lib/test/unit/browserHashProvider.test.d.ts +0 -2
  131. package/lib/test/unit/browserHashProvider.test.d.ts.map +0 -1
  132. package/lib/test/unit/browserHashProvider.test.js +0 -142
  133. package/lib/test/unit/browserHashProvider.test.js.map +0 -1
  134. package/lib/test/unit/directoryHandleStore.test.d.ts +0 -2
  135. package/lib/test/unit/directoryHandleStore.test.d.ts.map +0 -1
  136. package/lib/test/unit/directoryHandleStore.test.js +0 -192
  137. package/lib/test/unit/directoryHandleStore.test.js.map +0 -1
  138. package/lib/test/unit/fileApiTreeAccessors.test.d.ts +0 -2
  139. package/lib/test/unit/fileApiTreeAccessors.test.d.ts.map +0 -1
  140. package/lib/test/unit/fileApiTreeAccessors.test.js +0 -1190
  141. package/lib/test/unit/fileApiTreeAccessors.test.js.map +0 -1
  142. package/lib/test/unit/fileApiTypes.test.d.ts +0 -2
  143. package/lib/test/unit/fileApiTypes.test.d.ts.map +0 -1
  144. package/lib/test/unit/fileApiTypes.test.js +0 -474
  145. package/lib/test/unit/fileApiTypes.test.js.map +0 -1
  146. package/lib/test/unit/fileSystemAccessTreeAccessors.test.d.ts +0 -2
  147. package/lib/test/unit/fileSystemAccessTreeAccessors.test.d.ts.map +0 -1
  148. package/lib/test/unit/fileSystemAccessTreeAccessors.test.js +0 -624
  149. package/lib/test/unit/fileSystemAccessTreeAccessors.test.js.map +0 -1
  150. package/lib/test/unit/fileTreeHelpers.test.d.ts +0 -2
  151. package/lib/test/unit/fileTreeHelpers.test.d.ts.map +0 -1
  152. package/lib/test/unit/fileTreeHelpers.test.js +0 -592
  153. package/lib/test/unit/fileTreeHelpers.test.js.map +0 -1
  154. package/lib/test/unit/httpTreeAccessors.test.d.ts +0 -2
  155. package/lib/test/unit/httpTreeAccessors.test.d.ts.map +0 -1
  156. package/lib/test/unit/httpTreeAccessors.test.js +0 -1231
  157. package/lib/test/unit/httpTreeAccessors.test.js.map +0 -1
  158. package/lib/test/unit/localStorageTreeAccessors.test.d.ts +0 -2
  159. package/lib/test/unit/localStorageTreeAccessors.test.d.ts.map +0 -1
  160. package/lib/test/unit/localStorageTreeAccessors.test.js +0 -814
  161. package/lib/test/unit/localStorageTreeAccessors.test.js.map +0 -1
  162. package/lib/test/unit/urlParams.test.d.ts +0 -2
  163. package/lib/test/unit/urlParams.test.d.ts.map +0 -1
  164. package/lib/test/unit/urlParams.test.js +0 -395
  165. package/lib/test/unit/urlParams.test.js.map +0 -1
  166. package/lib/test/utils/fileSystemAccessMocks.d.ts +0 -53
  167. package/lib/test/utils/fileSystemAccessMocks.d.ts.map +0 -1
  168. package/lib/test/utils/fileSystemAccessMocks.js +0 -277
  169. package/lib/test/utils/fileSystemAccessMocks.js.map +0 -1
  170. package/lib/test/utils/testHelpers.d.ts +0 -51
  171. package/lib/test/utils/testHelpers.d.ts.map +0 -1
  172. package/lib/test/utils/testHelpers.js +0 -133
  173. package/lib/test/utils/testHelpers.js.map +0 -1
  174. package/rush-logs/ts-web-extras.build.cache.log +0 -0
  175. package/rush-logs/ts-web-extras.build.error.log +0 -18
  176. package/rush-logs/ts-web-extras.build.log +0 -75
  177. package/rush-logs/ts-web-extras.test.cache.log +0 -1
  178. package/rush-logs/ts-web-extras.test.error.log +0 -18
  179. package/rush-logs/ts-web-extras.test.log +0 -75
  180. package/src/index.browser.ts +0 -24
  181. package/src/index.ts +0 -47
  182. package/src/packlets/crypto-utils/browserCryptoProvider.ts +0 -311
  183. package/src/packlets/crypto-utils/browserHashProvider.ts +0 -73
  184. package/src/packlets/crypto-utils/index.ts +0 -29
  185. package/src/packlets/file-api-types/index.ts +0 -366
  186. package/src/packlets/file-tree/directoryHandleStore.ts +0 -136
  187. package/src/packlets/file-tree/fileApiTreeAccessors.ts +0 -528
  188. package/src/packlets/file-tree/fileSystemAccessTreeAccessors.ts +0 -519
  189. package/src/packlets/file-tree/httpTreeAccessors.ts +0 -448
  190. package/src/packlets/file-tree/index.ts +0 -32
  191. package/src/packlets/file-tree/localStorageTreeAccessors.ts +0 -430
  192. package/src/packlets/helpers/fileTreeHelpers.ts +0 -107
  193. package/src/packlets/helpers/index.ts +0 -28
  194. package/src/packlets/url-utils/index.ts +0 -28
  195. package/src/packlets/url-utils/urlParams.ts +0 -245
  196. package/src/test/mocks/idb-keyval.ts +0 -5
  197. package/src/test/setupTests.ts +0 -87
  198. package/src/test/unit/browserHashProvider.test.ts +0 -155
  199. package/src/test/unit/browserHashProvider.test.ts.bak +0 -376
  200. package/src/test/unit/directoryHandleStore.test.ts +0 -251
  201. package/src/test/unit/fileApiTreeAccessors.test.ts +0 -1387
  202. package/src/test/unit/fileApiTypes.test.ts +0 -587
  203. package/src/test/unit/fileSystemAccessTreeAccessors.test.ts +0 -885
  204. package/src/test/unit/fileTreeHelpers.test.ts +0 -694
  205. package/src/test/unit/httpTreeAccessors.test.ts +0 -1571
  206. package/src/test/unit/localStorageTreeAccessors.test.ts +0 -1014
  207. package/src/test/unit/urlParams.test.ts +0 -464
  208. package/src/test/utils/fileSystemAccessMocks.ts +0 -353
  209. package/src/test/utils/testHelpers.ts +0 -155
  210. package/temp/build/typescript/ts_8nwakTlr.json +0 -1
  211. package/temp/coverage/base.css +0 -224
  212. package/temp/coverage/block-navigation.js +0 -87
  213. package/temp/coverage/crypto/browserHashProvider.ts.html +0 -304
  214. package/temp/coverage/crypto/index.html +0 -116
  215. package/temp/coverage/crypto-utils/browserCryptoProvider.ts.html +0 -1018
  216. package/temp/coverage/crypto-utils/browserHashProvider.ts.html +0 -304
  217. package/temp/coverage/crypto-utils/index.html +0 -131
  218. package/temp/coverage/favicon.png +0 -0
  219. package/temp/coverage/file-tree/directoryHandleStore.ts.html +0 -493
  220. package/temp/coverage/file-tree/fileApiTreeAccessors.ts.html +0 -1669
  221. package/temp/coverage/file-tree/fileSystemAccessTreeAccessors.ts.html +0 -1642
  222. package/temp/coverage/file-tree/httpTreeAccessors.ts.html +0 -1429
  223. package/temp/coverage/file-tree/index.html +0 -176
  224. package/temp/coverage/file-tree/localStorageTreeAccessors.ts.html +0 -1375
  225. package/temp/coverage/helpers/fileTreeHelpers.ts.html +0 -406
  226. package/temp/coverage/helpers/index.html +0 -116
  227. package/temp/coverage/index.html +0 -161
  228. package/temp/coverage/lcov-report/base.css +0 -224
  229. package/temp/coverage/lcov-report/block-navigation.js +0 -87
  230. package/temp/coverage/lcov-report/crypto/browserHashProvider.ts.html +0 -304
  231. package/temp/coverage/lcov-report/crypto/index.html +0 -116
  232. package/temp/coverage/lcov-report/crypto-utils/browserCryptoProvider.ts.html +0 -1018
  233. package/temp/coverage/lcov-report/crypto-utils/browserHashProvider.ts.html +0 -304
  234. package/temp/coverage/lcov-report/crypto-utils/index.html +0 -131
  235. package/temp/coverage/lcov-report/favicon.png +0 -0
  236. package/temp/coverage/lcov-report/file-tree/directoryHandleStore.ts.html +0 -493
  237. package/temp/coverage/lcov-report/file-tree/fileApiTreeAccessors.ts.html +0 -1669
  238. package/temp/coverage/lcov-report/file-tree/fileSystemAccessTreeAccessors.ts.html +0 -1642
  239. package/temp/coverage/lcov-report/file-tree/httpTreeAccessors.ts.html +0 -1429
  240. package/temp/coverage/lcov-report/file-tree/index.html +0 -176
  241. package/temp/coverage/lcov-report/file-tree/localStorageTreeAccessors.ts.html +0 -1375
  242. package/temp/coverage/lcov-report/helpers/fileTreeHelpers.ts.html +0 -406
  243. package/temp/coverage/lcov-report/helpers/index.html +0 -116
  244. package/temp/coverage/lcov-report/index.html +0 -161
  245. package/temp/coverage/lcov-report/prettify.css +0 -1
  246. package/temp/coverage/lcov-report/prettify.js +0 -2
  247. package/temp/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  248. package/temp/coverage/lcov-report/sorter.js +0 -210
  249. package/temp/coverage/lcov-report/url-utils/index.html +0 -116
  250. package/temp/coverage/lcov-report/url-utils/urlParams.ts.html +0 -820
  251. package/temp/coverage/lcov.info +0 -3597
  252. package/temp/coverage/prettify.css +0 -1
  253. package/temp/coverage/prettify.js +0 -2
  254. package/temp/coverage/sort-arrow-sprite.png +0 -0
  255. package/temp/coverage/sorter.js +0 -210
  256. package/temp/coverage/url-utils/index.html +0 -116
  257. package/temp/coverage/url-utils/urlParams.ts.html +0 -820
  258. package/temp/test/jest/haste-map-b931e4e63102f86c5bd4949f7dced44f-9d713eb41149188b4e5c0ae3d86d0a57-2ad8e16b24e391b8cdbe50b55c137169 +0 -0
  259. package/temp/test/jest/jest-transform-cache-b931e4e63102f86c5bd4949f7dced44f-79ef2876fae7ca75eedb2aa53dc48338/b5/package_b5f57afc9ec2c011239b1608ee5bdfa5 +0 -53
  260. package/temp/test/jest/perf-cache-b931e4e63102f86c5bd4949f7dced44f-da39a3ee5e6b4b0d3255bfef95601890 +0 -1
  261. package/temp/ts-web-extras.api.json +0 -8850
  262. package/temp/ts-web-extras.api.md +0 -433
  263. package/tsconfig.json +0 -7
@@ -1,1190 +0,0 @@
1
- "use strict";
2
- /*
3
- * Copyright (c) 2025 Erik Fortune
4
- *
5
- * Permission is hereby granted, free of charge, to any person obtaining a copy
6
- * of this software and associated documentation files (the "Software"), to deal
7
- * in the Software without restriction, including without limitation the rights
8
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- * copies of the Software, and to permit persons to whom the Software is
10
- * furnished to do so, subject to the following conditions:
11
- *
12
- * The above copyright notice and this permission notice shall be included in all
13
- * copies or substantial portions of the Software.
14
- *
15
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- * SOFTWARE.
22
- */
23
- var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
24
- var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
25
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
26
- var g = generator.apply(thisArg, _arguments || []), i, q = [];
27
- return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
28
- function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
29
- function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
30
- function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
31
- function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
32
- function fulfill(value) { resume("next", value); }
33
- function reject(value) { resume("throw", value); }
34
- function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
35
- };
36
- Object.defineProperty(exports, "__esModule", { value: true });
37
- require("@fgv/ts-utils-jest");
38
- const file_tree_1 = require("../../packlets/file-tree");
39
- const ts_json_base_1 = require("@fgv/ts-json-base");
40
- const helpers_1 = require("../../packlets/helpers");
41
- const testHelpers_1 = require("../utils/testHelpers");
42
- function makeMockHttpResponse(options) {
43
- const { ok, status = ok ? 200 : 400, jsonValue, textValue, throwOnJson } = options;
44
- return {
45
- ok,
46
- status,
47
- json: throwOnJson
48
- ? () => Promise.reject(new Error('JSON parse error'))
49
- : () => Promise.resolve(jsonValue),
50
- text: () => Promise.resolve(textValue !== null && textValue !== void 0 ? textValue : `HTTP ${status}`)
51
- };
52
- }
53
- function makeMockHttpFetch(responses) {
54
- let callIndex = 0;
55
- return (url, _init) => {
56
- const response = responses[callIndex++];
57
- if (response === undefined) {
58
- return Promise.reject(new Error(`Unexpected fetch call to ${url.toString()}`));
59
- }
60
- return Promise.resolve(makeMockHttpResponse(response));
61
- };
62
- }
63
- describe('FileApiTreeAccessors', () => {
64
- describe('Static factory methods', () => {
65
- describe('create', () => {
66
- test('creates FileTree from FileList using create method', async () => {
67
- const fileList = (0, testHelpers_1.createMockFileList)([{ name: 'test.txt', content: 'test content' }]);
68
- const initializers = [{ fileList }];
69
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
70
- expect(result).toSucceedAndSatisfy((fileTree) => {
71
- // Verify the FileTree was created successfully
72
- expect(fileTree).toBeDefined();
73
- // Test file access with absolute path (FileTree expects leading slash)
74
- const fileResult = fileTree.getFile('/test.txt');
75
- expect(fileResult).toSucceed();
76
- });
77
- });
78
- test('creates FileTree with prefix (basic functionality)', async () => {
79
- const fileList = (0, testHelpers_1.createMockFileList)([{ name: 'test.txt', content: 'test content' }]);
80
- const initializers = [{ fileList }];
81
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers, { prefix: '/prefix' });
82
- // Just verify the creation succeeds - the prefix handling is complex
83
- expect(result).toSucceed();
84
- });
85
- test('handles multiple files', async () => {
86
- const fileList = (0, testHelpers_1.createMockFileList)([
87
- { name: 'file1.txt', content: 'content1' },
88
- { name: 'file2.txt', content: 'content2' }
89
- ]);
90
- const initializers = [{ fileList }];
91
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
92
- expect(result).toSucceedAndSatisfy((fileTree) => {
93
- expect(fileTree.getFile('/file1.txt')).toSucceed();
94
- expect(fileTree.getFile('/file2.txt')).toSucceed();
95
- });
96
- });
97
- test('handles nested directory structure', async () => {
98
- const fileList = (0, testHelpers_1.createMockDirectoryFileList)([
99
- { path: 'src/index.js', content: 'console.log("hello");' },
100
- { path: 'config/config.json', content: '{"name": "test"}' }
101
- ]);
102
- const initializers = [{ fileList }];
103
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
104
- expect(result).toSucceedAndSatisfy((fileTree) => {
105
- expect(fileTree.getFile('/src/index.js')).toSucceed();
106
- expect(fileTree.getFile('/config/config.json')).toSucceed();
107
- // Check directory access
108
- expect(fileTree.getDirectory('/src')).toSucceed();
109
- expect(fileTree.getDirectory('/config')).toSucceed();
110
- });
111
- });
112
- test('fails when file reading fails', async () => {
113
- // Create a file object without text method to simulate failure
114
- const badFile = {
115
- name: 'bad.txt',
116
- size: 10,
117
- type: 'text/plain',
118
- lastModified: Date.now(),
119
- text: () => Promise.reject(new Error('File read error'))
120
- };
121
- // Create FileList with bad file
122
- const dt = new DataTransfer();
123
- dt.items.add(badFile);
124
- const fileList = dt.files;
125
- const initializers = [{ fileList }];
126
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
127
- expect(result).toFailWith(/Failed to read file bad\.txt/);
128
- });
129
- test('handles empty files array', async () => {
130
- const fileList = (0, testHelpers_1.createMockFileList)([]);
131
- const initializers = [{ fileList }];
132
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
133
- expect(result).toSucceedAndSatisfy((fileTree) => {
134
- expect(fileTree).toBeDefined();
135
- });
136
- });
137
- test('normalizes paths correctly (critical bug fix verification)', async () => {
138
- const fileList = (0, testHelpers_1.createMockFileList)([{ name: 'test.txt', content: 'content' }]);
139
- const initializers = [{ fileList }];
140
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
141
- expect(result).toSucceedAndSatisfy((fileTree) => {
142
- // Path should be normalized to start with / for FileTree compatibility
143
- const fileResult = fileTree.getFile('/test.txt');
144
- expect(fileResult).toSucceed();
145
- // Content should be accessible
146
- const content = fileTree.hal.getFileContents('/test.txt');
147
- expect(content).toSucceedWith('content');
148
- });
149
- });
150
- test('normalizes paths with prefix correctly', async () => {
151
- const fileList = (0, testHelpers_1.createMockDirectoryFileList)([{ path: 'subdir/test.txt', content: 'content' }]);
152
- const initializers = [{ fileList }];
153
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers, { prefix: '/prefix' });
154
- // Just verify the creation succeeds with nested paths
155
- expect(result).toSucceed();
156
- });
157
- test('handles paths with leading slash correctly', async () => {
158
- const fileList = (0, testHelpers_1.createMockDirectoryFileList)([
159
- { path: 'already/absolute.txt', content: 'absolute content' },
160
- { path: 'relative/path.txt', content: 'relative content' }
161
- ]);
162
- const initializers = [{ fileList }];
163
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
164
- expect(result).toSucceedAndSatisfy((fileTree) => {
165
- // Both paths should be normalized to start with /
166
- expect(fileTree.getFile('/already/absolute.txt')).toSucceedAndSatisfy((file) => {
167
- expect(file.name).toBe('absolute.txt');
168
- });
169
- expect(fileTree.getFile('/relative/path.txt')).toSucceedAndSatisfy((file) => {
170
- expect(file.name).toBe('path.txt');
171
- });
172
- // Verify content is accessible
173
- expect(fileTree.hal.getFileContents('/already/absolute.txt')).toSucceedWith('absolute content');
174
- expect(fileTree.hal.getFileContents('/relative/path.txt')).toSucceedWith('relative content');
175
- });
176
- });
177
- });
178
- describe('fromFileList', () => {
179
- test('creates FileTree from FileList', async () => {
180
- const fileList = (0, testHelpers_1.createMockFileList)([
181
- { name: 'file1.txt', content: 'content1' },
182
- { name: 'file2.txt', content: 'content2' }
183
- ]);
184
- const result = await file_tree_1.FileApiTreeAccessors.fromFileList(fileList);
185
- expect(result).toSucceedAndSatisfy((fileTree) => {
186
- expect(fileTree.getFile('/file1.txt')).toSucceed();
187
- expect(fileTree.getFile('/file2.txt')).toSucceed();
188
- });
189
- });
190
- test('creates FileTree from FileList with prefix', async () => {
191
- const fileList = (0, testHelpers_1.createMockFileList)([{ name: 'test.txt', content: 'content' }]);
192
- const result = await file_tree_1.FileApiTreeAccessors.fromFileList(fileList, { prefix: '/uploads' });
193
- // Just verify the creation succeeds with prefix
194
- expect(result).toSucceed();
195
- });
196
- test('handles empty FileList', async () => {
197
- const fileList = (0, testHelpers_1.createMockFileList)([]);
198
- const result = await file_tree_1.FileApiTreeAccessors.fromFileList(fileList);
199
- expect(result).toSucceed();
200
- });
201
- test('verifies File API compatibility', async () => {
202
- const fileList = (0, testHelpers_1.createMockFileList)([{ name: 'test.txt', content: 'test content' }]);
203
- // Verify our mock files have the correct API
204
- for (let i = 0; i < fileList.length; i++) {
205
- const file = fileList[i];
206
- const isValid = await (0, testHelpers_1.verifyFileAPI)(file);
207
- expect(isValid).toBe(true);
208
- }
209
- });
210
- });
211
- describe('fromDirectoryUpload', () => {
212
- test('creates FileTree from directory structure', async () => {
213
- const fileList = (0, testHelpers_1.createMockDirectoryFileList)([
214
- { path: 'project/src/index.js', content: 'console.log("main");' },
215
- { path: 'project/src/utils.js', content: 'export const helper = () => {};' },
216
- { path: 'project/package.json', content: '{"name": "test-project"}' }
217
- ]);
218
- const result = await file_tree_1.FileApiTreeAccessors.fromDirectoryUpload(fileList);
219
- expect(result).toSucceedAndSatisfy((fileTree) => {
220
- expect(fileTree.getFile('/project/src/index.js')).toSucceed();
221
- expect(fileTree.getFile('/project/src/utils.js')).toSucceed();
222
- expect(fileTree.getFile('/project/package.json')).toSucceed();
223
- // Check directory structure
224
- expect(fileTree.getDirectory('/project')).toSucceed();
225
- expect(fileTree.getDirectory('/project/src')).toSucceed();
226
- });
227
- });
228
- test('creates FileTree from directory with prefix', async () => {
229
- const fileList = (0, testHelpers_1.createMockDirectoryFileList)([
230
- { path: 'app/config.json', content: '{"setting": "value"}' }
231
- ]);
232
- const result = await file_tree_1.FileApiTreeAccessors.fromDirectoryUpload(fileList, { prefix: '/upload' });
233
- // Just verify the creation succeeds with directory prefix
234
- expect(result).toSucceed();
235
- });
236
- test('handles nested directory structures', async () => {
237
- const fileList = (0, testHelpers_1.createMockDirectoryFileList)([
238
- { path: 'deep/nested/structure/file.txt', content: 'deep content' },
239
- { path: 'deep/other/file.txt', content: 'other content' }
240
- ]);
241
- const result = await file_tree_1.FileApiTreeAccessors.fromDirectoryUpload(fileList);
242
- expect(result).toSucceedAndSatisfy((fileTree) => {
243
- expect(fileTree.getFile('/deep/nested/structure/file.txt')).toSucceed();
244
- expect(fileTree.getFile('/deep/other/file.txt')).toSucceed();
245
- expect(fileTree.getDirectory('/deep')).toSucceed();
246
- expect(fileTree.getDirectory('/deep/nested')).toSucceed();
247
- expect(fileTree.getDirectory('/deep/nested/structure')).toSucceed();
248
- expect(fileTree.getDirectory('/deep/other')).toSucceed();
249
- });
250
- });
251
- });
252
- describe('getOriginalFile', () => {
253
- test('finds file by exact path match', () => {
254
- const fileList = (0, testHelpers_1.createMockFileList)([
255
- { name: 'target.txt', content: 'target content' },
256
- { name: 'other.txt', content: 'other content' }
257
- ]);
258
- const result = file_tree_1.FileApiTreeAccessors.getOriginalFile(fileList, 'target.txt');
259
- expect(result).toSucceedAndSatisfy((file) => {
260
- expect(file.name).toBe('target.txt');
261
- });
262
- });
263
- test('finds file by webkitRelativePath', () => {
264
- const fileList = (0, testHelpers_1.createMockDirectoryFileList)([{ path: 'folder/file.txt', content: 'content' }]);
265
- const result = file_tree_1.FileApiTreeAccessors.getOriginalFile(fileList, 'folder/file.txt');
266
- expect(result).toSucceedAndSatisfy((file) => {
267
- expect(file.webkitRelativePath).toBe('folder/file.txt');
268
- });
269
- });
270
- test('fails for non-existent file', () => {
271
- const fileList = (0, testHelpers_1.createMockFileList)([{ name: 'exists.txt', content: 'content' }]);
272
- const result = file_tree_1.FileApiTreeAccessors.getOriginalFile(fileList, 'missing.txt');
273
- expect(result).toFailWith(/File not found: missing\.txt/);
274
- });
275
- test('handles empty FileList', () => {
276
- const fileList = (0, testHelpers_1.createMockFileList)([]);
277
- const result = file_tree_1.FileApiTreeAccessors.getOriginalFile(fileList, 'any.txt');
278
- expect(result).toFailWith(/File not found/);
279
- });
280
- });
281
- describe('extractFileMetadata', () => {
282
- test('extracts metadata from regular files', () => {
283
- const testTime = Date.now();
284
- const file = (0, testHelpers_1.createMockFile)({
285
- name: 'test.txt',
286
- content: 'content',
287
- type: 'text/plain',
288
- lastModified: testTime
289
- });
290
- const metadata = file_tree_1.FileApiTreeAccessors.extractFileMetadata(file);
291
- expect(metadata).toEqual({
292
- path: 'test.txt',
293
- name: 'test.txt',
294
- size: expect.any(Number),
295
- type: 'text/plain',
296
- lastModified: testTime
297
- });
298
- });
299
- test('extracts metadata with webkitRelativePath', () => {
300
- const file = (0, testHelpers_1.createMockFile)({
301
- name: 'file.txt',
302
- content: 'content',
303
- type: 'text/plain',
304
- webkitRelativePath: 'folder/file.txt'
305
- });
306
- const metadata = file_tree_1.FileApiTreeAccessors.extractFileMetadata(file);
307
- expect(metadata).toEqual({
308
- path: 'folder/file.txt',
309
- name: 'file.txt',
310
- size: expect.any(Number),
311
- type: 'text/plain',
312
- lastModified: expect.any(Number)
313
- });
314
- });
315
- test('handles multiple files with different types', () => {
316
- var _a, _b, _c;
317
- const files = [
318
- (0, testHelpers_1.createMockFile)({ name: 'text.txt', content: 'text', type: 'text/plain' }),
319
- (0, testHelpers_1.createMockFile)({ name: 'data.json', content: '{}', type: 'application/json' }),
320
- (0, testHelpers_1.createMockFile)({ name: 'script.js', content: 'console.log("hi");', type: 'application/javascript' })
321
- ];
322
- const metadata = files.map((file) => file_tree_1.FileApiTreeAccessors.extractFileMetadata(file));
323
- expect(metadata).toHaveLength(3);
324
- expect((_a = metadata.find((m) => m.name === 'text.txt')) === null || _a === void 0 ? void 0 : _a.type).toBe('text/plain');
325
- expect((_b = metadata.find((m) => m.name === 'data.json')) === null || _b === void 0 ? void 0 : _b.type).toBe('application/json');
326
- expect((_c = metadata.find((m) => m.name === 'script.js')) === null || _c === void 0 ? void 0 : _c.type).toBe('application/javascript');
327
- });
328
- test('handles empty file array', () => {
329
- const files = [];
330
- const metadata = files.map((file) => file_tree_1.FileApiTreeAccessors.extractFileMetadata(file));
331
- expect(metadata).toHaveLength(0);
332
- });
333
- test('includes file sizes', () => {
334
- const shortContent = 'hi';
335
- const longContent = 'a'.repeat(1000);
336
- const files = [
337
- (0, testHelpers_1.createMockFile)({ name: 'short.txt', content: shortContent }),
338
- (0, testHelpers_1.createMockFile)({ name: 'long.txt', content: longContent })
339
- ];
340
- const metadata = files.map((file) => file_tree_1.FileApiTreeAccessors.extractFileMetadata(file));
341
- const shortMeta = metadata.find((m) => m.name === 'short.txt');
342
- const longMeta = metadata.find((m) => m.name === 'long.txt');
343
- expect(shortMeta === null || shortMeta === void 0 ? void 0 : shortMeta.size).toBeGreaterThan(0);
344
- expect(longMeta === null || longMeta === void 0 ? void 0 : longMeta.size).toBeGreaterThan(shortMeta === null || shortMeta === void 0 ? void 0 : shortMeta.size);
345
- });
346
- });
347
- });
348
- describe('Integration with FileTree', () => {
349
- test('created FileTree supports standard operations', async () => {
350
- const fileList = (0, testHelpers_1.createMockDirectoryFileList)([
351
- { path: 'config/data.json', content: '{"key": "value"}' },
352
- { path: 'docs/readme.txt', content: 'This is a readme file' }
353
- ]);
354
- const initializers = [{ fileList }];
355
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
356
- expect(result).toSucceedAndSatisfy((fileTree) => {
357
- // Test file access
358
- const jsonFile = fileTree.getFile('/config/data.json');
359
- expect(jsonFile).toSucceedAndSatisfy((file) => {
360
- expect(file.name).toBe('data.json');
361
- expect(file.extension).toBe('.json');
362
- expect(file.baseName).toBe('data');
363
- });
364
- // Test directory access
365
- const configDir = fileTree.getDirectory('/config');
366
- expect(configDir).toSucceedAndSatisfy((dir) => {
367
- expect(dir.name).toBe('config');
368
- });
369
- // Test content retrieval
370
- const content = fileTree.hal.getFileContents('/config/data.json');
371
- expect(content).toSucceedWith('{"key": "value"}');
372
- });
373
- });
374
- test('handles JSON file parsing through FileTree', async () => {
375
- const jsonContent = '{"name": "test", "version": "1.0.0"}';
376
- const fileList = (0, testHelpers_1.createMockFileList)([{ name: 'package.json', content: jsonContent }]);
377
- const initializers = [{ fileList }];
378
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
379
- expect(result).toSucceedAndSatisfy((fileTree) => {
380
- const file = fileTree.getFile('/package.json');
381
- expect(file).toSucceedAndSatisfy((fileItem) => {
382
- const jsonResult = fileItem.getContents();
383
- expect(jsonResult).toSucceedAndSatisfy((parsed) => {
384
- expect(parsed).toEqual({ name: 'test', version: '1.0.0' });
385
- });
386
- });
387
- });
388
- });
389
- test('supports directory traversal', async () => {
390
- const fileList = (0, testHelpers_1.createMockDirectoryFileList)([
391
- { path: 'src/file1.txt', content: 'content1' },
392
- { path: 'src/file2.txt', content: 'content2' }
393
- ]);
394
- const initializers = [{ fileList }];
395
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
396
- expect(result).toSucceedAndSatisfy((fileTree) => {
397
- const srcDir = fileTree.getDirectory('/src');
398
- expect(srcDir).toSucceedAndSatisfy((dir) => {
399
- const children = dir.getChildren();
400
- expect(children).toSucceedAndSatisfy((childItems) => {
401
- expect(childItems).toHaveLength(2);
402
- const fileNames = childItems.map((item) => item.name).sort();
403
- expect(fileNames).toEqual(['file1.txt', 'file2.txt']);
404
- });
405
- });
406
- });
407
- });
408
- });
409
- describe('Error handling', () => {
410
- test('handles file read errors gracefully', async () => {
411
- // Create a file object with a failing text method
412
- const errorFile = {
413
- name: 'error.txt',
414
- size: 10,
415
- type: 'text/plain',
416
- lastModified: Date.now(),
417
- text: () => Promise.reject(new Error('Disk error'))
418
- };
419
- // Create FileList with bad file
420
- const dt = new DataTransfer();
421
- dt.items.add(errorFile);
422
- const fileList = dt.files;
423
- const initializers = [{ fileList }];
424
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
425
- expect(result).toFailWith(/Failed to read file error\.txt.*Disk error/);
426
- });
427
- test('handles invalid file paths gracefully', async () => {
428
- // Create files with problematic paths - test with empty name
429
- const fileList = (0, testHelpers_1.createMockFileList)([
430
- { name: '', content: 'content' } // Empty name might cause issues
431
- ]);
432
- const initializers = [{ fileList }];
433
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
434
- // Should either succeed by handling empty name or fail gracefully
435
- if (result.isFailure()) {
436
- expect(result.message).toContain('');
437
- }
438
- else {
439
- expect(result).toSucceed();
440
- }
441
- });
442
- });
443
- describe('create() method with different initializers', () => {
444
- describe('FileList initializers', () => {
445
- test('creates FileTree from FileList initializer', async () => {
446
- const fileList = (0, testHelpers_1.createMockFileList)([
447
- { name: 'file1.txt', content: 'content1' },
448
- { name: 'file2.txt', content: 'content2' }
449
- ]);
450
- const initializers = [{ fileList }];
451
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
452
- expect(result).toSucceedAndSatisfy((fileTree) => {
453
- expect(fileTree.hal.getFileContents('/file1.txt')).toSucceedWith('content1');
454
- expect(fileTree.hal.getFileContents('/file2.txt')).toSucceedWith('content2');
455
- });
456
- });
457
- test('creates FileTree from multiple FileList initializers', async () => {
458
- const fileList1 = (0, testHelpers_1.createMockFileList)([{ name: 'group1-file1.txt', content: 'group1-content1' }]);
459
- const fileList2 = (0, testHelpers_1.createMockFileList)([{ name: 'group2-file1.txt', content: 'group2-content1' }]);
460
- const initializers = [{ fileList: fileList1 }, { fileList: fileList2 }];
461
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
462
- expect(result).toSucceedAndSatisfy((fileTree) => {
463
- expect(fileTree.hal.getFileContents('/group1-file1.txt')).toSucceedWith('group1-content1');
464
- expect(fileTree.hal.getFileContents('/group2-file1.txt')).toSucceedWith('group2-content1');
465
- });
466
- });
467
- test('handles empty FileList initializer', async () => {
468
- const fileList = (0, testHelpers_1.createMockFileList)([]);
469
- const initializers = [{ fileList }];
470
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
471
- expect(result).toSucceedAndSatisfy((fileTree) => {
472
- expect(fileTree).toBeDefined();
473
- });
474
- });
475
- test('handles file read errors in FileList processing', async () => {
476
- // Create a file that will fail when .text() is called
477
- const failingFile = {
478
- name: 'failing.txt',
479
- size: 10,
480
- type: 'text/plain',
481
- lastModified: Date.now(),
482
- webkitRelativePath: '',
483
- text: () => Promise.reject(new Error('File read error')),
484
- stream: () => new ReadableStream(),
485
- arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)),
486
- slice: () => new Blob()
487
- };
488
- // Create a FileList containing the failing file
489
- const fileList = {
490
- length: 1,
491
- item: (index) => (index === 0 ? failingFile : null),
492
- [0]: failingFile,
493
- [Symbol.iterator]: function* () {
494
- yield failingFile;
495
- }
496
- };
497
- const initializers = [{ fileList }];
498
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
499
- expect(result).toFailWith(/Failed to read file failing\.txt.*File read error/);
500
- });
501
- test('handles files with absolute paths (webkitRelativePath starting with /)', async () => {
502
- // Create files where webkitRelativePath already starts with '/'
503
- const fileWithAbsolutePath = {
504
- name: 'file.txt',
505
- size: 10,
506
- type: 'text/plain',
507
- lastModified: Date.now(),
508
- webkitRelativePath: '/absolute/path/file.txt', // Already absolute
509
- text: () => Promise.resolve('absolute content'),
510
- stream: () => new ReadableStream(),
511
- arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)),
512
- slice: () => new Blob()
513
- };
514
- const fileWithAbsoluteName = {
515
- name: '/root/file2.txt', // Name itself starts with slash
516
- size: 15,
517
- type: 'text/plain',
518
- lastModified: Date.now(),
519
- webkitRelativePath: '', // Empty, so will use name
520
- text: () => Promise.resolve('name absolute content'),
521
- stream: () => new ReadableStream(),
522
- arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)),
523
- slice: () => new Blob()
524
- };
525
- // Create a FileList containing files with absolute paths
526
- const fileList = {
527
- length: 2,
528
- item: (index) => {
529
- if (index === 0)
530
- return fileWithAbsolutePath;
531
- if (index === 1)
532
- return fileWithAbsoluteName;
533
- return null;
534
- },
535
- [0]: fileWithAbsolutePath,
536
- [1]: fileWithAbsoluteName,
537
- [Symbol.iterator]: function* () {
538
- yield fileWithAbsolutePath;
539
- yield fileWithAbsoluteName;
540
- }
541
- };
542
- const initializers = [{ fileList }];
543
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
544
- expect(result).toSucceedAndSatisfy((fileTree) => {
545
- // Verify absolute webkitRelativePath is used as-is (not double-slashed)
546
- expect(fileTree.hal.getFileContents('/absolute/path/file.txt')).toSucceedWith('absolute content');
547
- // Verify absolute name is used as-is (not double-slashed)
548
- expect(fileTree.hal.getFileContents('/root/file2.txt')).toSucceedWith('name absolute content');
549
- });
550
- });
551
- });
552
- describe('FileSystemFileHandle initializers', () => {
553
- function createMockFileHandle(name, content) {
554
- const mockFile = (0, testHelpers_1.createMockFile)({ name, content });
555
- return {
556
- kind: 'file',
557
- name,
558
- isSameEntry: jest.fn(),
559
- queryPermission: jest.fn(),
560
- requestPermission: jest.fn(),
561
- getFile: jest.fn().mockResolvedValue(mockFile),
562
- createWritable: jest.fn()
563
- };
564
- }
565
- test('creates FileTree from FileSystemFileHandle initializer', async () => {
566
- const fileHandle1 = createMockFileHandle('handle1.txt', 'handle content 1');
567
- const fileHandle2 = createMockFileHandle('handle2.txt', 'handle content 2');
568
- const initializers = [{ fileHandles: [fileHandle1, fileHandle2] }];
569
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
570
- expect(result).toSucceedAndSatisfy((fileTree) => {
571
- expect(fileTree.hal.getFileContents('/handle1.txt')).toSucceedWith('handle content 1');
572
- expect(fileTree.hal.getFileContents('/handle2.txt')).toSucceedWith('handle content 2');
573
- });
574
- expect(fileHandle1.getFile).toHaveBeenCalled();
575
- expect(fileHandle2.getFile).toHaveBeenCalled();
576
- });
577
- test('creates FileTree from FileSystemFileHandle without prefix (current limitation)', async () => {
578
- const fileHandle = createMockFileHandle('data.txt', 'file content');
579
- const initializers = [{ fileHandles: [fileHandle] }];
580
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
581
- expect(result).toSucceedAndSatisfy((fileTree) => {
582
- // Verify basic functionality works
583
- expect(fileTree.hal.getFileContents('/data.txt')).toSucceedWith('file content');
584
- });
585
- });
586
- test('creates FileTree from FileSystemFileHandle with per-initializer prefix (limitation)', async () => {
587
- const fileHandle = createMockFileHandle('data.txt', 'file content');
588
- // Note: Currently IFileHandleTreeInitializer.prefix is not implemented in _processFileHandles
589
- // This is inconsistent with IDirectoryHandleTreeInitializer which does support prefix
590
- const initializers = [{ fileHandles: [fileHandle], prefix: '/uploads' }];
591
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
592
- expect(result).toSucceedAndSatisfy((fileTree) => {
593
- // Due to the implementation limitation, prefix on fileHandles initializer is ignored
594
- // File appears at root level instead of under prefix
595
- expect(fileTree.hal.getFileContents('/data.txt')).toSucceedWith('file content');
596
- });
597
- });
598
- test('handles FileSystemFileHandle read errors', async () => {
599
- const failingHandle = {
600
- kind: 'file',
601
- name: 'failing.txt',
602
- isSameEntry: jest.fn(),
603
- queryPermission: jest.fn(),
604
- requestPermission: jest.fn(),
605
- getFile: jest.fn().mockRejectedValue(new Error('File access denied')),
606
- createWritable: jest.fn()
607
- };
608
- const initializers = [{ fileHandles: [failingHandle] }];
609
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
610
- expect(result).toFailWith(/Failed to read file handle failing\.txt.*File access denied/);
611
- });
612
- test('handles empty FileSystemFileHandle array', async () => {
613
- const initializers = [{ fileHandles: [] }];
614
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
615
- expect(result).toSucceedAndSatisfy((fileTree) => {
616
- expect(fileTree).toBeDefined();
617
- });
618
- });
619
- });
620
- describe('FileSystemDirectoryHandle initializers', () => {
621
- function createMockDirectoryHandle(name, entries) {
622
- const mockEntries = entries.map((entry) => {
623
- var _a;
624
- if (entry.isDirectory) {
625
- const childEntries = ((_a = entry.children) === null || _a === void 0 ? void 0 : _a.map((child) => ({
626
- kind: 'file',
627
- name: child.name,
628
- getFile: jest
629
- .fn()
630
- .mockResolvedValue((0, testHelpers_1.createMockFile)({ name: child.name, content: child.content }))
631
- }))) || [];
632
- return {
633
- kind: 'directory',
634
- name: entry.name,
635
- values: jest.fn().mockReturnValue({
636
- [Symbol.asyncIterator]() {
637
- return __asyncGenerator(this, arguments, function* _a() {
638
- for (const child of childEntries) {
639
- yield yield __await(child);
640
- }
641
- });
642
- }
643
- })
644
- };
645
- }
646
- else {
647
- return {
648
- kind: 'file',
649
- name: entry.name,
650
- getFile: jest
651
- .fn()
652
- .mockResolvedValue((0, testHelpers_1.createMockFile)({ name: entry.name, content: entry.content || '' }))
653
- };
654
- }
655
- });
656
- return {
657
- kind: 'directory',
658
- name,
659
- isSameEntry: jest.fn(),
660
- queryPermission: jest.fn(),
661
- requestPermission: jest.fn(),
662
- getDirectoryHandle: jest.fn(),
663
- getFileHandle: jest.fn(),
664
- removeEntry: jest.fn(),
665
- resolve: jest.fn(),
666
- keys: jest.fn(),
667
- values: jest.fn().mockReturnValue({
668
- [Symbol.asyncIterator]() {
669
- return __asyncGenerator(this, arguments, function* _a() {
670
- for (const entry of mockEntries) {
671
- yield yield __await(entry);
672
- }
673
- });
674
- }
675
- }),
676
- entries: jest.fn(),
677
- [Symbol.asyncIterator]: jest.fn()
678
- };
679
- }
680
- test('creates FileTree from FileSystemDirectoryHandle initializer', async () => {
681
- const dirHandle = createMockDirectoryHandle('testdir', [
682
- { name: 'file1.txt', content: 'dir content 1' },
683
- { name: 'file2.txt', content: 'dir content 2' }
684
- ]);
685
- const initializers = [{ dirHandles: [dirHandle] }];
686
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
687
- expect(result).toSucceedAndSatisfy((fileTree) => {
688
- expect(fileTree.hal.getFileContents('/testdir/file1.txt')).toSucceedWith('dir content 1');
689
- expect(fileTree.hal.getFileContents('/testdir/file2.txt')).toSucceedWith('dir content 2');
690
- });
691
- });
692
- test('creates FileTree from FileSystemDirectoryHandle with prefix', async () => {
693
- const dirHandle = createMockDirectoryHandle('data', [
694
- { name: 'config.json', content: '{"setting": "value"}' }
695
- ]);
696
- const initializers = [{ dirHandles: [dirHandle], prefix: 'project' }];
697
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
698
- expect(result).toSucceedAndSatisfy((fileTree) => {
699
- expect(fileTree.hal.getFileContents('/project/data/config.json')).toSucceedWith('{"setting": "value"}');
700
- });
701
- });
702
- test('handles recursive directory processing', async () => {
703
- const dirHandle = createMockDirectoryHandle('root', [
704
- { name: 'file.txt', content: 'root file' },
705
- {
706
- name: 'subdir',
707
- isDirectory: true,
708
- children: [{ name: 'nested.txt', content: 'nested file' }]
709
- }
710
- ]);
711
- const initializers = [{ dirHandles: [dirHandle] }];
712
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
713
- expect(result).toSucceedAndSatisfy((fileTree) => {
714
- expect(fileTree.hal.getFileContents('/root/file.txt')).toSucceedWith('root file');
715
- expect(fileTree.hal.getFileContents('/root/subdir/nested.txt')).toSucceedWith('nested file');
716
- });
717
- });
718
- test('handles non-recursive directory processing', async () => {
719
- const dirHandle = createMockDirectoryHandle('root', [
720
- { name: 'file.txt', content: 'root file' },
721
- {
722
- name: 'subdir',
723
- isDirectory: true,
724
- children: [{ name: 'nested.txt', content: 'nested file' }]
725
- }
726
- ]);
727
- const initializers = [{ dirHandles: [dirHandle], nonRecursive: true }];
728
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
729
- expect(result).toSucceedAndSatisfy((fileTree) => {
730
- expect(fileTree.hal.getFileContents('/root/file.txt')).toSucceedWith('root file');
731
- // Should not contain nested file in non-recursive mode
732
- expect(fileTree.getFile('/root/subdir/nested.txt')).toFail();
733
- });
734
- });
735
- test('handles directory iteration errors', async () => {
736
- const failingDirHandle = {
737
- kind: 'directory',
738
- name: 'failing-dir',
739
- isSameEntry: jest.fn(),
740
- queryPermission: jest.fn(),
741
- requestPermission: jest.fn(),
742
- getDirectoryHandle: jest.fn(),
743
- getFileHandle: jest.fn(),
744
- removeEntry: jest.fn(),
745
- resolve: jest.fn(),
746
- keys: jest.fn(),
747
- values: jest.fn().mockReturnValue({
748
- [Symbol.asyncIterator]() {
749
- return __asyncGenerator(this, arguments, function* _a() {
750
- throw new Error('Directory access denied');
751
- });
752
- }
753
- }),
754
- entries: jest.fn(),
755
- [Symbol.asyncIterator]: jest.fn()
756
- };
757
- const initializers = [{ dirHandles: [failingDirHandle] }];
758
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
759
- expect(result).toFailWith(/Failed to process directory failing-dir.*Directory access denied/);
760
- });
761
- test('handles subdirectory processing failure in recursive mode', async () => {
762
- // Create a directory with a subdirectory that will fail to process
763
- const failingSubDir = {
764
- kind: 'directory',
765
- name: 'failing-subdir',
766
- isSameEntry: jest.fn(),
767
- queryPermission: jest.fn(),
768
- requestPermission: jest.fn(),
769
- getDirectoryHandle: jest.fn(),
770
- getFileHandle: jest.fn(),
771
- removeEntry: jest.fn(),
772
- resolve: jest.fn(),
773
- keys: jest.fn(),
774
- values: jest.fn().mockReturnValue({
775
- [Symbol.asyncIterator]() {
776
- return __asyncGenerator(this, arguments, function* _a() {
777
- throw new Error('Subdirectory access denied');
778
- });
779
- }
780
- }),
781
- entries: jest.fn(),
782
- [Symbol.asyncIterator]: jest.fn()
783
- };
784
- const rootDirHandle = {
785
- kind: 'directory',
786
- name: 'root',
787
- isSameEntry: jest.fn(),
788
- queryPermission: jest.fn(),
789
- requestPermission: jest.fn(),
790
- getDirectoryHandle: jest.fn(),
791
- getFileHandle: jest.fn(),
792
- removeEntry: jest.fn(),
793
- resolve: jest.fn(),
794
- keys: jest.fn(),
795
- values: jest.fn().mockReturnValue({
796
- [Symbol.asyncIterator]() {
797
- return __asyncGenerator(this, arguments, function* _a() {
798
- yield yield __await(failingSubDir); // This subdirectory will fail
799
- });
800
- }
801
- }),
802
- entries: jest.fn(),
803
- [Symbol.asyncIterator]: jest.fn()
804
- };
805
- const initializers = [{ dirHandles: [rootDirHandle] }];
806
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
807
- expect(result).toFailWith(/Failed to process directory failing-subdir.*Subdirectory access denied/);
808
- });
809
- test('handles empty directory', async () => {
810
- const emptyDirHandle = createMockDirectoryHandle('empty', []);
811
- const initializers = [{ dirHandles: [emptyDirHandle] }];
812
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
813
- expect(result).toSucceedAndSatisfy((fileTree) => {
814
- expect(fileTree).toBeDefined();
815
- });
816
- });
817
- });
818
- describe('unknown initializer types', () => {
819
- test('fails with unknown initializer type', async () => {
820
- const unknownInitializer = {
821
- unknown: 'type'
822
- };
823
- const initializers = [unknownInitializer];
824
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
825
- expect(result).toFailWith(/Unknown initializer type/);
826
- });
827
- });
828
- describe('mixed initializer types', () => {
829
- test('creates FileTree from mixed initializer types', async () => {
830
- const fileList = (0, testHelpers_1.createMockFileList)([{ name: 'fromList.txt', content: 'list content' }]);
831
- const fileHandle = {
832
- kind: 'file',
833
- name: 'fromHandle.txt',
834
- isSameEntry: jest.fn(),
835
- queryPermission: jest.fn(),
836
- requestPermission: jest.fn(),
837
- getFile: jest
838
- .fn()
839
- .mockResolvedValue((0, testHelpers_1.createMockFile)({ name: 'fromHandle.txt', content: 'handle content' })),
840
- createWritable: jest.fn()
841
- };
842
- const initializers = [{ fileList }, { fileHandles: [fileHandle] }];
843
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
844
- expect(result).toSucceedAndSatisfy((fileTree) => {
845
- expect(fileTree.hal.getFileContents('/fromList.txt')).toSucceedWith('list content');
846
- expect(fileTree.hal.getFileContents('/fromHandle.txt')).toSucceedWith('handle content');
847
- });
848
- });
849
- test('stops processing on first error from any initializer', async () => {
850
- const goodFileList = (0, testHelpers_1.createMockFileList)([{ name: 'good.txt', content: 'good content' }]);
851
- const badFileHandle = {
852
- kind: 'file',
853
- name: 'bad.txt',
854
- isSameEntry: jest.fn(),
855
- queryPermission: jest.fn(),
856
- requestPermission: jest.fn(),
857
- getFile: jest.fn().mockRejectedValue(new Error('Handle error')),
858
- createWritable: jest.fn()
859
- };
860
- const initializers = [{ fileList: goodFileList }, { fileHandles: [badFileHandle] }];
861
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers);
862
- expect(result).toFailWith(/Failed to read file handle bad\.txt.*Handle error/);
863
- });
864
- });
865
- describe('branch coverage tests', () => {
866
- function createMockDirectoryHandle(name, entries) {
867
- const mockEntries = entries.map((entry) => {
868
- var _a;
869
- if (entry.isDirectory) {
870
- const childEntries = ((_a = entry.children) === null || _a === void 0 ? void 0 : _a.map((child) => ({
871
- kind: 'file',
872
- name: child.name,
873
- getFile: jest
874
- .fn()
875
- .mockResolvedValue((0, testHelpers_1.createMockFile)({ name: child.name, content: child.content }))
876
- }))) || [];
877
- return {
878
- kind: 'directory',
879
- name: entry.name,
880
- values: jest.fn().mockReturnValue({
881
- [Symbol.asyncIterator]() {
882
- return __asyncGenerator(this, arguments, function* _a() {
883
- for (const child of childEntries) {
884
- yield yield __await(child);
885
- }
886
- });
887
- }
888
- })
889
- };
890
- }
891
- else {
892
- return {
893
- kind: 'file',
894
- name: entry.name,
895
- getFile: jest
896
- .fn()
897
- .mockResolvedValue((0, testHelpers_1.createMockFile)({ name: entry.name, content: entry.content || '' }))
898
- };
899
- }
900
- });
901
- return {
902
- kind: 'directory',
903
- name,
904
- isSameEntry: jest.fn(),
905
- queryPermission: jest.fn(),
906
- requestPermission: jest.fn(),
907
- getDirectoryHandle: jest.fn(),
908
- getFileHandle: jest.fn(),
909
- removeEntry: jest.fn(),
910
- resolve: jest.fn(),
911
- keys: jest.fn(),
912
- values: jest.fn().mockReturnValue({
913
- [Symbol.asyncIterator]() {
914
- return __asyncGenerator(this, arguments, function* _a() {
915
- for (const entry of mockEntries) {
916
- yield yield __await(entry);
917
- }
918
- });
919
- }
920
- }),
921
- entries: jest.fn(),
922
- [Symbol.asyncIterator]: jest.fn()
923
- };
924
- }
925
- test('tests prefix handling in various scenarios', async () => {
926
- // For branch coverage: Test multiple scenarios with simple, working examples
927
- const fileList = (0, testHelpers_1.createMockFileList)([{ name: 'test.txt', content: 'simple test' }]);
928
- // Test params.prefix when no initializer prefix exists
929
- const result1 = await file_tree_1.FileApiTreeAccessors.create([{ fileList }], { prefix: '/from-params' });
930
- expect(result1).toSucceedAndSatisfy((fileTree) => {
931
- expect(fileTree.hal.getFileContents('/from-params/test.txt')).toSucceedWith('simple test');
932
- });
933
- // Test when params is undefined (for line 314: params?.prefix ?? '')
934
- const result2 = await file_tree_1.FileApiTreeAccessors.create([{ fileList }]); // no params
935
- expect(result2).toSucceedAndSatisfy((fileTree) => {
936
- expect(fileTree.hal.getFileContents('/test.txt')).toSucceedWith('simple test');
937
- });
938
- });
939
- test('tests file handle processing with undefined params prefix', async () => {
940
- const fileHandle = {
941
- kind: 'file',
942
- name: 'test.txt',
943
- isSameEntry: jest.fn(),
944
- queryPermission: jest.fn(),
945
- requestPermission: jest.fn(),
946
- getFile: jest.fn().mockResolvedValue((0, testHelpers_1.createMockFile)({ name: 'test.txt', content: 'content' })),
947
- createWritable: jest.fn()
948
- };
949
- // Test line 314: params?.prefix ?? '' when params is undefined
950
- const initializers = [{ fileHandles: [fileHandle] }];
951
- const result1 = await file_tree_1.FileApiTreeAccessors.create(initializers); // no params
952
- expect(result1).toSucceedAndSatisfy((fileTree) => {
953
- expect(fileTree.hal.getFileContents('/test.txt')).toSucceedWith('content');
954
- });
955
- // Test line 314: params?.prefix ?? '' when params.prefix is undefined
956
- const result2 = await file_tree_1.FileApiTreeAccessors.create(initializers, {}); // empty params object
957
- expect(result2).toSucceedAndSatisfy((fileTree) => {
958
- expect(fileTree.hal.getFileContents('/test.txt')).toSucceedWith('content');
959
- });
960
- });
961
- test('tests directory handle processing with undefined prefix fallback', async () => {
962
- // For branch coverage of line 348: prefix ?? params?.prefix when prefix parameter is undefined
963
- // Again, let's use a simpler approach with fileList which we know works
964
- const fileList = (0, testHelpers_1.createMockFileList)([{ name: 'test.txt', content: 'content' }]);
965
- // Test the case where no prefix is provided in initializer but params has one
966
- const initializers = [{ fileList }]; // no prefix in initializer
967
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers, { prefix: '/fallback-prefix' });
968
- expect(result).toSucceedAndSatisfy((fileTree) => {
969
- expect(fileTree.hal.getFileContents('/fallback-prefix/test.txt')).toSucceedWith('content');
970
- });
971
- });
972
- test('tests inferContentType orDefault() branches with failing content type inference', async () => {
973
- const fileHandle = {
974
- kind: 'file',
975
- name: 'test.txt',
976
- isSameEntry: jest.fn(),
977
- queryPermission: jest.fn(),
978
- requestPermission: jest.fn(),
979
- getFile: jest.fn().mockResolvedValue((0, testHelpers_1.createMockFile)({ name: 'test.txt', content: 'content' })),
980
- createWritable: jest.fn()
981
- };
982
- const dirHandle = createMockDirectoryHandle('dir', [{ name: 'file.txt', content: 'dir content' }]);
983
- // Test lines 315 and 385: inferContentType returning failure, triggering orDefault()
984
- const failingInferContentType = jest.fn(() => ({
985
- isSuccess: () => false,
986
- isFailure: () => true,
987
- message: 'Content type inference failed',
988
- orDefault: () => undefined
989
- }));
990
- const fileHandleInitializers = [{ fileHandles: [fileHandle] }];
991
- const fileHandleResult = await file_tree_1.FileApiTreeAccessors.create(fileHandleInitializers, {
992
- inferContentType: failingInferContentType
993
- });
994
- expect(fileHandleResult).toSucceedAndSatisfy((fileTree) => {
995
- expect(fileTree.hal.getFileContents('/test.txt')).toSucceedWith('content');
996
- });
997
- const dirHandleInitializers = [{ dirHandles: [dirHandle] }];
998
- const dirHandleResult = await file_tree_1.FileApiTreeAccessors.create(dirHandleInitializers, {
999
- inferContentType: failingInferContentType
1000
- });
1001
- expect(dirHandleResult).toSucceedAndSatisfy((fileTree) => {
1002
- expect(fileTree.hal.getFileContents('/dir/file.txt')).toSucceedWith('dir content');
1003
- });
1004
- });
1005
- test('tests path normalization branches', async () => {
1006
- const fileList = (0, testHelpers_1.createMockFileList)([{ name: 'test.txt', content: 'content' }]);
1007
- // Test line 416: normalized.startsWith('/') ? normalized : `/${normalized}`
1008
- // Test the case where normalized path already starts with '/'
1009
- const result1 = await file_tree_1.FileApiTreeAccessors.create([{ fileList }], { prefix: '/' });
1010
- expect(result1).toSucceedAndSatisfy((fileTree) => {
1011
- expect(fileTree.hal.getFileContents('/test.txt')).toSucceedWith('content');
1012
- });
1013
- // Test the case where normalized path doesn't start with '/' (the else branch)
1014
- // This is covered functionally by the tests above where prefix is provided
1015
- // The _normalizePath method adds '/' when the combined path doesn't start with one
1016
- // Test the case where normalized path DOES start with '/' (the first branch)
1017
- // This happens when the file path itself is absolute and no prefix is used
1018
- const fileListAbsolute = (0, testHelpers_1.createMockFileList)([
1019
- { name: '/absolute/test.txt', content: 'absolute content' }
1020
- ]);
1021
- const result3 = await file_tree_1.FileApiTreeAccessors.create([{ fileList: fileListAbsolute }]);
1022
- expect(result3).toSucceedAndSatisfy((fileTree) => {
1023
- expect(fileTree.hal.getFileContents('/absolute/test.txt')).toSucceedWith('absolute content');
1024
- });
1025
- });
1026
- });
1027
- });
1028
- describe('Content Type functionality', () => {
1029
- describe('inferContentType parameter', () => {
1030
- test('uses inferContentType function when provided', async () => {
1031
- const fileList = (0, testHelpers_1.createMockFileList)([
1032
- { name: 'document.txt', content: 'text content', type: 'text/plain' },
1033
- { name: 'data.json', content: '{"key": "value"}', type: 'application/json' }
1034
- ]);
1035
- const inferContentType = jest.fn((filePath, provided) => {
1036
- if (filePath.endsWith('.txt')) {
1037
- return { isSuccess: () => true, value: 'custom-text', orDefault: () => 'custom-text' };
1038
- }
1039
- if (filePath.endsWith('.json')) {
1040
- return { isSuccess: () => true, value: 'custom-json', orDefault: () => 'custom-json' };
1041
- }
1042
- return { isSuccess: () => true, value: provided, orDefault: () => provided };
1043
- });
1044
- const result = await file_tree_1.FileApiTreeAccessors.fromFileList(fileList, { inferContentType });
1045
- expect(result).toSucceedAndSatisfy((fileTree) => {
1046
- // fromFileList now consistently passes both path and MIME type parameters
1047
- // This is consistent with _processFileList behavior
1048
- expect(inferContentType).toHaveBeenCalledWith('/document.txt', 'text/plain');
1049
- expect(inferContentType).toHaveBeenCalledWith('/data.json', 'application/json');
1050
- // The specific content type assignments depend on the internal FileTree implementation
1051
- expect(fileTree.getFile('/document.txt')).toSucceed();
1052
- expect(fileTree.getFile('/data.json')).toSucceed();
1053
- });
1054
- });
1055
- test('fromFileList only passes path parameter (current limitation)', async () => {
1056
- const fileList = (0, testHelpers_1.createMockFileList)([
1057
- { name: 'image.png', content: 'binary data', type: 'image/png' },
1058
- { name: 'unknown.xyz', content: 'unknown data', type: '' }
1059
- ]);
1060
- const inferContentType = jest.fn((filePath, provided) => {
1061
- return {
1062
- isSuccess: () => true,
1063
- value: `custom-${provided || 'unknown'}`,
1064
- orDefault: () => `custom-${provided || 'unknown'}`
1065
- };
1066
- });
1067
- const result = await file_tree_1.FileApiTreeAccessors.fromFileList(fileList, { inferContentType });
1068
- expect(result).toSucceed();
1069
- // fromFileList now passes both path and MIME type parameters
1070
- expect(inferContentType).toHaveBeenCalledWith('/image.png', 'image/png');
1071
- expect(inferContentType).toHaveBeenCalledWith('/unknown.xyz', 'text/plain');
1072
- });
1073
- test('works with fromDirectoryUpload', async () => {
1074
- const fileList = (0, testHelpers_1.createMockDirectoryFileList)([
1075
- { path: 'project/src/component.tsx', content: 'React component', type: 'text/typescript' },
1076
- { path: 'project/styles/main.css', content: 'CSS styles', type: 'text/css' }
1077
- ]);
1078
- const inferContentType = jest.fn((filePath, provided) => {
1079
- if (filePath.includes('.tsx')) {
1080
- return { isSuccess: () => true, value: 'typescript-react', orDefault: () => 'typescript-react' };
1081
- }
1082
- return { isSuccess: () => true, value: provided, orDefault: () => provided };
1083
- });
1084
- const result = await file_tree_1.FileApiTreeAccessors.fromDirectoryUpload(fileList, { inferContentType });
1085
- expect(result).toSucceed();
1086
- // fromDirectoryUpload now consistently passes both path and MIME type parameters
1087
- expect(inferContentType).toHaveBeenCalledWith('/project/src/component.tsx', 'text/typescript');
1088
- expect(inferContentType).toHaveBeenCalledWith('/project/styles/main.css', 'text/css');
1089
- });
1090
- test('receives provided MIME type when using create method (correct behavior)', async () => {
1091
- // The create method uses internal _processFileList which correctly passes both parameters
1092
- const fileList1 = (0, testHelpers_1.createMockFileList)([
1093
- { name: 'file1.txt', content: 'content1', type: 'text/plain' }
1094
- ]);
1095
- const fileList2 = (0, testHelpers_1.createMockFileList)([
1096
- { name: 'file2.md', content: '# Markdown', type: 'text/markdown' }
1097
- ]);
1098
- const inferContentType = jest.fn((filePath, provided) => {
1099
- return {
1100
- isSuccess: () => true,
1101
- value: `inferred-${provided}`,
1102
- orDefault: () => `inferred-${provided}`
1103
- };
1104
- });
1105
- const initializers = [{ fileList: fileList1 }, { fileList: fileList2 }];
1106
- const result = await file_tree_1.FileApiTreeAccessors.create(initializers, { inferContentType });
1107
- expect(result).toSucceed();
1108
- // The create method correctly passes both path and MIME type
1109
- expect(inferContentType).toHaveBeenCalledWith('/file1.txt', 'text/plain');
1110
- expect(inferContentType).toHaveBeenCalledWith('/file2.md', 'text/markdown');
1111
- });
1112
- test('handles cases where inferContentType returns undefined', async () => {
1113
- const fileList = (0, testHelpers_1.createMockFileList)([
1114
- { name: 'test.unknown', content: 'unknown content', type: 'application/octet-stream' }
1115
- ]);
1116
- const inferContentType = jest.fn((filePath, provided) => {
1117
- // Return undefined to indicate no content type could be inferred
1118
- return { isSuccess: () => true, value: undefined, orDefault: () => undefined };
1119
- });
1120
- const result = await file_tree_1.FileApiTreeAccessors.fromFileList(fileList, { inferContentType });
1121
- expect(result).toSucceed();
1122
- expect(inferContentType).toHaveBeenCalledWith('/test.unknown');
1123
- });
1124
- test('uses default behavior when inferContentType not provided', async () => {
1125
- const fileList = (0, testHelpers_1.createMockFileList)([
1126
- { name: 'default.txt', content: 'default content', type: 'text/plain' }
1127
- ]);
1128
- // No inferContentType parameter provided
1129
- const result = await file_tree_1.FileApiTreeAccessors.fromFileList(fileList);
1130
- expect(result).toSucceedAndSatisfy((fileTree) => {
1131
- expect(fileTree.getFile('/default.txt')).toSucceed();
1132
- });
1133
- });
1134
- });
1135
- describe('ContentType with FileTreeHelpers', () => {
1136
- test('fromFileList passes through inferContentType parameter', async () => {
1137
- const fileList = (0, testHelpers_1.createMockFileList)([
1138
- { name: 'helper.js', content: 'JS content', type: 'application/javascript' }
1139
- ]);
1140
- const inferContentType = jest.fn((filePath, provided) => {
1141
- return { isSuccess: () => true, value: 'helper-js', orDefault: () => 'helper-js' };
1142
- });
1143
- const result = await helpers_1.FileTreeHelpers.fromFileList(fileList, { inferContentType });
1144
- expect(result).toSucceed();
1145
- expect(inferContentType).toHaveBeenCalledWith('/helper.js', 'application/javascript');
1146
- });
1147
- test('fromDirectoryUpload passes through inferContentType parameter', async () => {
1148
- const fileList = (0, testHelpers_1.createMockDirectoryFileList)([
1149
- { path: 'dist/bundle.js', content: 'bundled JS', type: 'application/javascript' }
1150
- ]);
1151
- const inferContentType = jest.fn((filePath, provided) => {
1152
- return { isSuccess: () => true, value: 'bundled-js', orDefault: () => 'bundled-js' };
1153
- });
1154
- const result = await helpers_1.FileTreeHelpers.fromDirectoryUpload(fileList, { inferContentType });
1155
- expect(result).toSucceed();
1156
- expect(inferContentType).toHaveBeenCalledWith('/dist/bundle.js', 'application/javascript');
1157
- });
1158
- });
1159
- });
1160
- describe('createFromHttp', () => {
1161
- test('succeeds and returns a FileTree when HTTP backend loads successfully', async () => {
1162
- const fetchImpl = makeMockHttpFetch([
1163
- {
1164
- ok: true,
1165
- jsonValue: { path: '/', children: [{ path: '/data.json', name: 'data.json', type: 'file' }] }
1166
- },
1167
- { ok: true, jsonValue: { path: '/data.json', contents: '{"items":{}}' } }
1168
- ]);
1169
- const result = await file_tree_1.FileApiTreeAccessors.createFromHttp({
1170
- baseUrl: 'http://localhost:3000',
1171
- fetchImpl,
1172
- mutable: true
1173
- });
1174
- expect(result).toSucceedAndSatisfy((tree) => {
1175
- expect(tree).toBeInstanceOf(ts_json_base_1.FileTree.FileTree);
1176
- expect(tree.getFile('/data.json')).toSucceed();
1177
- expect(ts_json_base_1.FileTree.isPersistentAccessors(tree.hal)).toBe(true);
1178
- });
1179
- });
1180
- test('fails when the HTTP backend returns an error during initial load', async () => {
1181
- const fetchImpl = makeMockHttpFetch([{ ok: false, status: 503, textValue: 'Service Unavailable' }]);
1182
- const result = await file_tree_1.FileApiTreeAccessors.createFromHttp({
1183
- baseUrl: 'http://localhost:3000',
1184
- fetchImpl
1185
- });
1186
- expect(result).toFailWith(/service unavailable/i);
1187
- });
1188
- });
1189
- });
1190
- //# sourceMappingURL=fileApiTreeAccessors.test.js.map