UNPKG

@ethersphere/swarm-cli

Version:
371 lines (331 loc) 16.6 kB
import { Reference } from '@ethersphere/bee-js' import { readFileSync, statSync, writeFileSync } from 'fs' import { Upload as FeedUpload } from '../../src/command/feed/upload' import { RootCommand } from '../../src/command/root-command' import { FORMATTED_ERROR } from '../../src/command/root-command/printer' import { Upload } from '../../src/command/upload' import { readdirDeepAsync } from '../../src/utils' import { toMatchLinesInAnyOrder, toMatchLinesInOrder } from '../custom-matcher' import { describeCommand, invokeTestCli } from '../utility' import { getStampOption } from '../utility/stamp' expect.extend({ toMatchLinesInOrder, toMatchLinesInAnyOrder, }) async function runAndGetManifest(argv: string[]): Promise<string> { if (['create', 'add', 'sync', 'merge', 'remove'].includes(argv[1])) { argv = [...argv, ...getStampOption()] } const commandBuilder = await invokeTestCli(argv) const command = commandBuilder.runnable as unknown as RootCommand return command.result.getOrThrow().toHex() } describeCommand('Test Manifest command', ({ consoleMessages, hasMessageContaining }) => { let srcHash: Reference beforeAll(async () => { const invocation = await invokeTestCli([ 'upload', 'test/data/manifest', '--index-document', 'index.txt', ...getStampOption(), ]) srcHash = (invocation.runnable as Upload).result.getOrThrow() }) it('should add file', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'add', hash, 'README.md']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', hash]) expect(hasMessageContaining('README.md')).toBeTruthy() expect(hasMessageContaining('/bzz')).toBeFalsy() await invokeTestCli(['manifest', 'list', hash, '--print-bzz']) expect(hasMessageContaining('/bzz')).toBeTruthy() expect(hasMessageContaining('/bytes')).toBeFalsy() await invokeTestCli(['manifest', 'list', hash, '--print-bytes']) expect(hasMessageContaining('/bytes')).toBeTruthy() }) it('should add folder', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'add', hash, 'test/utility']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', hash]) expect(hasMessageContaining('address.ts')).toBeTruthy() expect(hasMessageContaining('index.ts')).toBeTruthy() expect(hasMessageContaining('stamp.ts')).toBeTruthy() }) it('should add file with different name when using --as', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'add', hash, 'README.md', '--as', 'docs/README.txt']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', hash]) expect(hasMessageContaining('README.md')).toBeFalsy() expect(hasMessageContaining('docs/README.txt')).toBeTruthy() }) it('should handle both --as and --folder in add command', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'add', hash + '/misc', 'README.md', '--as', 'docs/README.txt']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', hash]) expect(hasMessageContaining('misc/docs/README.txt')).toBeTruthy() }) it('should remove file', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'add', hash, 'README.md']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', hash]) expect(hasMessageContaining('README.md')).toBeTruthy() hash = await runAndGetManifest(['manifest', 'remove', hash + '/README.md']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', hash]) expect(hasMessageContaining('README.md')).toBeFalsy() }) it('should remove folder', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'add', hash, 'README.md']) hash = await runAndGetManifest(['manifest', 'add', hash + '/utils', 'test/utility']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', hash]) expect(hasMessageContaining('README.md')).toBeTruthy() expect(hasMessageContaining('utils/address.ts')).toBeTruthy() expect(hasMessageContaining('utils/index.ts')).toBeTruthy() expect(hasMessageContaining('utils/stamp.ts')).toBeTruthy() hash = await runAndGetManifest(['manifest', 'remove', hash + '/utils']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', hash]) expect(hasMessageContaining('README.md')).toBeTruthy() expect(hasMessageContaining('utils')).toBeFalsy() }) it('should sync folder', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'sync', hash, 'test/utility']) expect(consoleMessages).toMatchLinesInAnyOrder([ ['stamp.ts', 'NEW'], ['index.ts', 'NEW'], ['address.ts', 'NEW'], ]) consoleMessages.length = 0 hash = await runAndGetManifest(['manifest', 'sync', hash, 'test/utility']) expect(consoleMessages).toMatchLinesInAnyOrder([ ['stamp.ts', 'UNCHANGED'], ['index.ts', 'UNCHANGED'], ['address.ts', 'UNCHANGED'], ]) consoleMessages.length = 0 hash = await runAndGetManifest(['manifest', 'sync', hash, 'test/testpage/images']) expect(consoleMessages).toMatchLinesInOrder([['swarm.png', 'NEW']]) consoleMessages.length = 0 await runAndGetManifest(['manifest', 'sync', hash, 'test/testpage/images', '--remove']) expect(consoleMessages).toMatchLinesInAnyOrder([ ['swarm.png', 'UNCHANGED'], ['address.ts', 'REMOVED'], ['index.ts', 'REMOVED'], ['stamp.ts', 'REMOVED'], ]) }) it('should list single file', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'add', hash, 'src']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', `bzz://${hash}/command/pss/send.ts`]) expect(consoleMessages).toMatchLinesInAnyOrder([['Nodes'], ['command/pss/send.ts']]) expect(consoleMessages).toHaveLength(3) }) it('should list folder', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'add', hash, 'src']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', `bzz://${hash}/command/pss`]) expect(consoleMessages).toMatchLinesInAnyOrder([ ['Nodes'], ['command/pss/index.ts'], ['command/pss/pss-command.ts'], ['command/pss/receive.ts'], ['command/pss/send.ts'], ['command/pss/subscribe.ts'], ]) expect(consoleMessages).toHaveLength(11) }) it('should download single file', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'add', hash, 'src']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'download', `bzz://${hash}/command/pss/index.ts`, 'test/data/4']) expect(consoleMessages).toMatchLinesInOrder([['command/pss/index.ts'], ['OK']]) }) it('should download folder via bzz link', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'add', hash, 'src']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'download', `bzz://${hash}/command/pss`, 'test/data/4']) expect(consoleMessages).toMatchLinesInOrder([ ['command/pss/index.ts'], ['OK'], ['command/pss/pss-command.ts'], ['OK'], ['command/pss/receive.ts'], ['OK'], ['command/pss/send.ts'], ['OK'], ['command/pss/subscribe.ts'], ['OK'], ]) }) it('should download folder', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'add', hash + '/test/utility', 'test/utility']) consoleMessages.length = 0 await invokeTestCli(['manifest', 'download', hash, 'test/data/1']) expect(statSync('test/data/1/test/utility/address.ts')).toBeTruthy() expect(statSync('test/data/1/test/utility/index.ts')).toBeTruthy() expect(statSync('test/data/1/test/utility/stamp.ts')).toBeTruthy() }) it('should download only the specified folder', async () => { let hash = await runAndGetManifest(['manifest', 'create']) hash = await runAndGetManifest(['manifest', 'add', hash, 'README.md']) hash = await runAndGetManifest(['manifest', 'add', hash + '/utils', 'test/utility']) await invokeTestCli(['manifest', 'download', hash + '/utils', 'test/data/2']) const entries = await readdirDeepAsync('test/data/2', 'test/data/2') expect(entries).toHaveLength(3) // instead of 4 }) it('should merge manifests', async () => { let hash1 = await runAndGetManifest(['manifest', 'create']) hash1 = await runAndGetManifest(['manifest', 'add', hash1, 'README.md']) let hash2 = await runAndGetManifest(['manifest', 'create']) hash2 = await runAndGetManifest(['manifest', 'add', hash2, 'test/utility']) const hash = await runAndGetManifest(['manifest', 'merge', hash1, hash2]) consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', hash]) expect(hasMessageContaining('README.md')).toBeTruthy() expect(hasMessageContaining('address.ts')).toBeTruthy() expect(hasMessageContaining('index.ts')).toBeTruthy() expect(hasMessageContaining('stamp.ts')).toBeTruthy() }) it('should merge manifests and overwrite destination', async () => { writeFileSync('test/data/alpha.txt', '1') writeFileSync('test/data/bravo.txt', '2') let hash1 = await runAndGetManifest(['manifest', 'create']) hash1 = await runAndGetManifest(['manifest', 'add', hash1, 'test/data/alpha.txt']) hash1 = await runAndGetManifest(['manifest', 'add', hash1, 'test/data/bravo.txt']) let hash2 = await runAndGetManifest(['manifest', 'create']) hash2 = await runAndGetManifest(['manifest', 'add', hash2, 'test/data/alpha.txt', '--as', 'bravo.txt']) hash2 = await runAndGetManifest(['manifest', 'add', hash2, 'test/data/bravo.txt', '--as', 'alpha.txt']) const hash = await runAndGetManifest(['manifest', 'merge', hash1, hash2]) await invokeTestCli(['manifest', 'download', hash, 'test/data/3']) expect(readFileSync('test/data/3/alpha.txt').toString()).toBe('2') expect(readFileSync('test/data/3/bravo.txt').toString()).toBe('1') }) it.skip('should list feed content', async () => { const identityName = `feed-resolve-test-${Date.now()}` await invokeTestCli(['identity', 'create', identityName, '--only-keypair']) const invocation = await invokeTestCli([ 'feed', 'upload', 'README.md', '--identity', identityName, ...getStampOption(), ]) const command = invocation.runnable as unknown as FeedUpload consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', `${command.feedManifest}`]) expect(consoleMessages).toMatchLinesInOrder([['README.md']]) }) it('should list single file when specified partially', async () => { await invokeTestCli(['manifest', 'list', `${srcHash}/ind`]) expect(consoleMessages).toMatchLinesInOrder([['index.txt']]) }) it('should list single file when specified fully', async () => { await invokeTestCli(['manifest', 'list', `${srcHash}/index.txt`]) expect(consoleMessages).toMatchLinesInOrder([['index.txt']]) }) it('should list files in folder when specified partially', async () => { await invokeTestCli(['manifest', 'list', `${srcHash}/lev`]) expect(consoleMessages).toMatchLinesInOrder([['level-one/level-two/1.txt'], ['level-one/level-two/2.txt']]) }) it('should list files in folder when specified fully without trailing slash', async () => { await invokeTestCli(['manifest', 'list', `${srcHash}/level-one/level-two`]) expect(consoleMessages).toMatchLinesInOrder([['level-one/level-two/1.txt'], ['level-one/level-two/2.txt']]) }) it('should list files in folder when specified fully with trailing slash', async () => { await invokeTestCli(['manifest', 'list', `${srcHash}/level-one/level-two/`]) expect(consoleMessages).toMatchLinesInOrder([['level-one/level-two/1.txt'], ['level-one/level-two/2.txt']]) }) it('should download single file when specified partially', async () => { await invokeTestCli(['manifest', 'download', `${srcHash}/in`, 'test/data/6']) expect(consoleMessages).toMatchLinesInOrder([['index.txt']]) }) it('should download single file when specified fully', async () => { await invokeTestCli(['manifest', 'download', `${srcHash}/index.txt`, 'test/data/6']) expect(consoleMessages).toMatchLinesInOrder([['index.txt']]) }) it('should download files in folder when specified partially', async () => { await invokeTestCli(['manifest', 'download', `${srcHash}/level-one/l`, 'test/data/6']) expect(consoleMessages).toMatchLinesInOrder([['level-one/level-two/1.txt'], ['level-one/level-two/2.txt']]) }) it('should download files in folder when specified fully without trailing slash', async () => { await invokeTestCli(['manifest', 'download', `${srcHash}/level-one/level-two`, 'test/data/6']) expect(consoleMessages).toMatchLinesInOrder([['level-one/level-two/1.txt'], ['level-one/level-two/2.txt']]) }) it('should download files in folder when specified fully with trailing slash', async () => { await invokeTestCli(['manifest', 'download', `${srcHash}/level-one/level-two/`, 'test/data/6']) expect(consoleMessages).toMatchLinesInOrder([['level-one/level-two/1.txt'], ['level-one/level-two/2.txt']]) }) it('should handle error for invalid download hash', async () => { await invokeTestCli(['manifest', 'download', 'g'.repeat(64)]) expect(consoleMessages[0]).toContain( FORMATTED_ERROR + ' Expected hex string for Bytes#constructor(bytes), got: gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg', ) }) it('should handle error for invalid list hash', async () => { await invokeTestCli(['manifest', 'list', 'g'.repeat(64)]) expect(consoleMessages[0]).toContain( FORMATTED_ERROR + ' Expected hex string for Bytes#constructor(bytes), got: gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg', ) }) it('should handle error for 404 download hash', async () => { await invokeTestCli(['manifest', 'download', '1'.repeat(64)]) expect(consoleMessages[0]).toContain('Bee responded with HTTP 404 (Not Found).') }) it('should handle error for 404 list hash', async () => { await invokeTestCli(['manifest', 'list', '1'.repeat(64)]) expect(consoleMessages[0]).toContain('Bee responded with HTTP 404 (Not Found).') }) it('should handle error for invalid download path', async () => { await invokeTestCli(['manifest', 'download', `${srcHash}/b`]) expect(consoleMessages[0]).toContain('No files found under the given path') }) it('should handle error for invalid list path', async () => { await invokeTestCli(['manifest', 'list', `${srcHash}/b`]) expect(consoleMessages[0]).toContain('No files found under the given path') }) it('should be able to upload and download folder with default index.html', async () => { const invocation = await invokeTestCli(['upload', 'test/testpage', ...getStampOption()]) const hash = (invocation.runnable as Upload).result.getOrThrow() consoleMessages.length = 0 await invokeTestCli(['manifest', 'download', hash.toHex()]) expect(consoleMessages).toMatchLinesInOrder([['images/swarm.png'], ['index.html'], ['swarm.bzz']]) }) it('should show root manifest metadata', async () => { const invocation = await invokeTestCli([ 'upload', 'docs', ...getStampOption(), '--index-document', 'index.txt', '--error-document', 'error.txt', ]) const hash = (invocation.runnable as Upload).result.getOrThrow() consoleMessages.length = 0 await invokeTestCli(['manifest', 'list', hash.toHex(), '--verbose']) expect(consoleMessages).toMatchLinesInOrder([ ['Root (/) metadata'], ['website-error-document: error.txt'], ['website-index-document: index.txt'], ['Nodes'], ]) }) })