@@ -131,3 +131,165 @@ test('Manifest add fork with foreign path', async () => {
131131 expect ( items [ 'c/中文/index.xml' ] ) . toBeDefined ( )
132132 expect ( items [ 'c/中文/index.html' ] ) . toBeDefined ( )
133133} )
134+
135+ test ( 'Manifest save/load with ACT stores history address in fork metadata' , async ( ) => {
136+ const bee = makeBee ( )
137+
138+ const ref1 = arbitraryReference ( )
139+ const ref2 = arbitraryReference ( )
140+
141+ const node = new MantarayNode ( )
142+ node . addFork ( 'folder/file1.txt' , ref1 , { 'Content-Type' : 'text/plain' } )
143+ node . addFork ( 'folder/file2.txt' , ref2 , { 'Content-Type' : 'text/plain' } )
144+
145+ const result = await node . saveRecursively ( bee , batch ( ) , { act : true } )
146+
147+ expect ( result . reference . toHex ( ) ) . toHaveLength ( 64 )
148+ expect ( result . historyAddress . getOrThrow ( ) . toHex ( ) ) . toHaveLength ( 64 )
149+ } )
150+
151+ test ( 'Manifest save/load with ACT preserves structure' , async ( ) => {
152+ const bee = makeBee ( )
153+ const { publicKey } = await bee . getNodeAddresses ( )
154+
155+ const fileData = 'test file content for ACT preservation'
156+ const fileUpload = await bee . uploadData ( batch ( ) , fileData )
157+
158+ const node = new MantarayNode ( )
159+ node . addFork ( 'deep/nested/file.txt' , fileUpload . reference , {
160+ 'Content-Type' : 'text/plain' ,
161+ Filename : 'file.txt' ,
162+ } )
163+
164+ const result = await node . saveRecursively ( bee , batch ( ) , { act : true } )
165+ const rootHistoryAddress = result . historyAddress . getOrThrow ( )
166+
167+ const loadedNode = await MantarayNode . unmarshal ( bee , result . reference , {
168+ actHistoryAddress : rootHistoryAddress ,
169+ actPublisher : publicKey ,
170+ } )
171+
172+ await loadedNode . loadRecursively ( bee , { actPublisher : publicKey } )
173+
174+ const mapping = loadedNode . collectAndMap ( )
175+
176+ expect ( mapping [ 'deep/nested/file.txt' ] ) . toBeDefined ( )
177+ expect ( mapping [ 'deep/nested/file.txt' ] ) . toBe ( fileUpload . reference . toHex ( ) )
178+ } )
179+
180+ test ( 'Manifest save/load with ACT nested folders' , async ( ) => {
181+ const bee = makeBee ( )
182+ const { publicKey } = await bee . getNodeAddresses ( )
183+
184+ const file1 = await bee . uploadData ( batch ( ) , 'content-1' )
185+ const file2 = await bee . uploadData ( batch ( ) , 'content-2' )
186+ const file3 = await bee . uploadData ( batch ( ) , 'content-3' )
187+
188+ const node = new MantarayNode ( )
189+ node . addFork ( 'a/b/c/file1.txt' , file1 . reference )
190+ node . addFork ( 'a/b/file2.txt' , file2 . reference )
191+ node . addFork ( 'a/file3.txt' , file3 . reference )
192+
193+ const result = await node . saveRecursively ( bee , batch ( ) , { act : true } )
194+
195+ const loadedNode = await MantarayNode . unmarshal ( bee , result . reference , {
196+ actHistoryAddress : result . historyAddress . getOrThrow ( ) ,
197+ actPublisher : publicKey ,
198+ } )
199+
200+ await loadedNode . loadRecursively ( bee , { actPublisher : publicKey } )
201+
202+ const mapping = loadedNode . collectAndMap ( )
203+
204+ expect ( Object . keys ( mapping ) ) . toHaveLength ( 3 )
205+ expect ( mapping [ 'a/b/c/file1.txt' ] ) . toBe ( file1 . reference . toHex ( ) )
206+ expect ( mapping [ 'a/b/file2.txt' ] ) . toBe ( file2 . reference . toHex ( ) )
207+ expect ( mapping [ 'a/file3.txt' ] ) . toBe ( file3 . reference . toHex ( ) )
208+ } )
209+
210+ test ( 'Manifest save/load with ACT can download and verify content' , async ( ) => {
211+ const bee = makeBee ( )
212+ const { publicKey } = await bee . getNodeAddresses ( )
213+
214+ const originalContent = 'This is the secret content that should be encrypted and decrypted correctly!'
215+ const fileUpload = await bee . uploadData ( batch ( ) , originalContent )
216+
217+ const node = new MantarayNode ( )
218+ node . addFork ( 'secret/data.txt' , fileUpload . reference , {
219+ 'Content-Type' : 'text/plain' ,
220+ Filename : 'data.txt' ,
221+ } )
222+
223+ const result = await node . saveRecursively ( bee , batch ( ) , { act : true } )
224+
225+ const loadedNode = await MantarayNode . unmarshal ( bee , result . reference , {
226+ actHistoryAddress : result . historyAddress . getOrThrow ( ) ,
227+ actPublisher : publicKey ,
228+ } )
229+
230+ await loadedNode . loadRecursively ( bee , { actPublisher : publicKey } )
231+
232+ const mapping = loadedNode . collectAndMap ( )
233+ const fileReference = mapping [ 'secret/data.txt' ]
234+
235+ expect ( fileReference ) . toBeDefined ( )
236+
237+ const downloadedData = await bee . downloadData ( fileReference )
238+ expect ( downloadedData . toUtf8 ( ) ) . toBe ( originalContent )
239+ } )
240+
241+ test ( 'Manifest save/load with ACT single file at root' , async ( ) => {
242+ const bee = makeBee ( )
243+ const { publicKey } = await bee . getNodeAddresses ( )
244+
245+ const content = 'root-level-file-content'
246+ const fileUpload = await bee . uploadData ( batch ( ) , content )
247+
248+ const node = new MantarayNode ( )
249+ node . addFork ( 'readme.txt' , fileUpload . reference )
250+
251+ const result = await node . saveRecursively ( bee , batch ( ) , { act : true } )
252+
253+ const loadedNode = await MantarayNode . unmarshal ( bee , result . reference , {
254+ actHistoryAddress : result . historyAddress . getOrThrow ( ) ,
255+ actPublisher : publicKey ,
256+ } )
257+
258+ await loadedNode . loadRecursively ( bee , { actPublisher : publicKey } )
259+
260+ const mapping = loadedNode . collectAndMap ( )
261+
262+ expect ( Object . keys ( mapping ) ) . toHaveLength ( 1 )
263+ expect ( mapping [ 'readme.txt' ] ) . toBe ( fileUpload . reference . toHex ( ) )
264+ } )
265+
266+ test ( 'Manifest save/load with ACT preserves existing metadata' , async ( ) => {
267+ const bee = makeBee ( )
268+ const { publicKey } = await bee . getNodeAddresses ( )
269+
270+ const fileUpload = await bee . uploadData ( batch ( ) , 'test-content' )
271+
272+ const node = new MantarayNode ( )
273+ node . addFork ( 'file.txt' , fileUpload . reference , {
274+ 'Content-Type' : 'text/plain' ,
275+ 'Custom-Header' : 'custom-value' ,
276+ Filename : 'file.txt' ,
277+ } )
278+
279+ const result = await node . saveRecursively ( bee , batch ( ) , { act : true } )
280+
281+ const loadedNode = await MantarayNode . unmarshal ( bee , result . reference , {
282+ actHistoryAddress : result . historyAddress . getOrThrow ( ) ,
283+ actPublisher : publicKey ,
284+ } )
285+
286+ await loadedNode . loadRecursively ( bee , { actPublisher : publicKey } )
287+
288+ const values = loadedNode . collect ( )
289+ const fileNode = values . find ( v => v . fullPathString === 'file.txt' )
290+
291+ expect ( fileNode ) . toBeDefined ( )
292+ expect ( fileNode ?. metadata ?. [ 'Content-Type' ] ) . toBe ( 'text/plain' )
293+ expect ( fileNode ?. metadata ?. [ 'Custom-Header' ] ) . toBe ( 'custom-value' )
294+ expect ( fileNode ?. metadata ?. [ 'Filename' ] ) . toBe ( 'file.txt' )
295+ } )
0 commit comments