import * as path from 'path' import * as core from '@actions/core' import {URL} from 'url' import {getDownloadSpecification} from '../src/internal/download-specification' import {ContainerEntry} from '../src/internal/contracts' const artifact1Name = 'my-artifact' const artifact2Name = 'my-artifact-extra' // Populating with only the information that is necessary function getPartialContainerEntry(): ContainerEntry { return { containerId: 10, scopeIdentifier: '00000000-0000-0000-0000-000000000000', path: 'ADD_INFORMATION', itemType: 'ADD_INFORMATION', status: 'created', dateCreated: '2020-02-06T22:13:35.373Z', dateLastModified: '2020-02-06T22:13:35.453Z', createdBy: '82f0bf89-6e55-4e5a-b8b6-f75eb992578c', lastModifiedBy: '82f0bf89-6e55-4e5a-b8b6-f75eb992578c', itemLocation: 'ADD_INFORMATION', contentLocation: 'ADD_INFORMATION', contentId: '', fileLength: 100 } } function createFileEntry(entryPath: string): ContainerEntry { const newFileEntry = getPartialContainerEntry() newFileEntry.path = entryPath newFileEntry.itemType = 'file' newFileEntry.itemLocation = createItemLocation(entryPath) newFileEntry.contentLocation = createContentLocation(entryPath) return newFileEntry } function createDirectoryEntry(directoryPath: string): ContainerEntry { const newDirectoryEntry = getPartialContainerEntry() newDirectoryEntry.path = directoryPath newDirectoryEntry.itemType = 'folder' newDirectoryEntry.itemLocation = createItemLocation(directoryPath) newDirectoryEntry.contentLocation = createContentLocation(directoryPath) return newDirectoryEntry } function createItemLocation(relativePath: string): string { const itemLocation = new URL( 'https://testing/_apis/resources/Containers/10000' ) itemLocation.searchParams.append('itemPath', relativePath) itemLocation.searchParams.append('metadata', 'true') return itemLocation.toString() } function createContentLocation(relativePath: string): string { const itemLocation = new URL( 'https://testing/_apis/resources/Containers/10000' ) itemLocation.searchParams.append('itemPath', relativePath) return itemLocation.toString() } /* Represents a set of container entries for two artifacts with the following directory structure /my-artifact /file1.txt /file2.txt /dir1 /file3.txt /dir2 /dir3 /dir4 file4.txt file5.txt (no length property) file6.txt (empty file) /my-artifact-extra /file1.txt */ // main artifact const file1Path = path.join(artifact1Name, 'file1.txt') const file2Path = path.join(artifact1Name, 'file2.txt') const dir1Path = path.join(artifact1Name, 'dir1') const file3Path = path.join(dir1Path, 'file3.txt') const dir2Path = path.join(dir1Path, 'dir2') const dir3Path = path.join(dir2Path, 'dir3') const dir4Path = path.join(dir3Path, 'dir4') const file4Path = path.join(dir4Path, 'file4.txt') const file5Path = path.join(dir4Path, 'file5.txt') const file6Path = path.join(dir4Path, 'file6.txt') const rootDirectoryEntry = createDirectoryEntry(artifact1Name) const directoryEntry1 = createDirectoryEntry(dir1Path) const directoryEntry2 = createDirectoryEntry(dir2Path) const directoryEntry3 = createDirectoryEntry(dir3Path) const directoryEntry4 = createDirectoryEntry(dir4Path) const fileEntry1 = createFileEntry(file1Path) const fileEntry2 = createFileEntry(file2Path) const fileEntry3 = createFileEntry(file3Path) const fileEntry4 = createFileEntry(file4Path) const missingLengthFileEntry = createFileEntry(file5Path) missingLengthFileEntry.fileLength = undefined // one file does not have a fileLength const emptyLengthFileEntry = createFileEntry(file6Path) emptyLengthFileEntry.fileLength = 0 // empty file path // extra artifact const artifact2File1Path = path.join(artifact2Name, 'file1.txt') const rootDirectoryEntry2 = createDirectoryEntry(artifact2Name) const extraFileEntry = createFileEntry(artifact2File1Path) const artifactContainerEntries: ContainerEntry[] = [ rootDirectoryEntry, fileEntry1, fileEntry2, directoryEntry1, fileEntry3, directoryEntry2, directoryEntry3, directoryEntry4, fileEntry4, missingLengthFileEntry, emptyLengthFileEntry, rootDirectoryEntry2, extraFileEntry ] describe('Search', () => { beforeAll(async () => { // mock all output so that there is less noise when running tests jest.spyOn(console, 'log').mockImplementation(() => {}) jest.spyOn(core, 'debug').mockImplementation(() => {}) jest.spyOn(core, 'info').mockImplementation(() => {}) jest.spyOn(core, 'warning').mockImplementation(() => {}) }) it('Download Specification - Absolute Path with no root directory', () => { const testDownloadPath = path.join( __dirname, 'some', 'destination', 'folder' ) const specification = getDownloadSpecification( artifact1Name, artifactContainerEntries, testDownloadPath, false ) expect(specification.rootDownloadLocation).toEqual(testDownloadPath) expect(specification.filesToDownload.length).toEqual(5) const item1ExpectedTargetPath = path.join(testDownloadPath, 'file1.txt') const item2ExpectedTargetPath = path.join(testDownloadPath, 'file2.txt') const item3ExpectedTargetPath = path.join( testDownloadPath, 'dir1', 'file3.txt' ) const item4ExpectedTargetPath = path.join( testDownloadPath, 'dir1', 'dir2', 'dir3', 'dir4', 'file4.txt' ) const item5ExpectedTargetPath = path.join( testDownloadPath, 'dir1', 'dir2', 'dir3', 'dir4', 'file5.txt' ) const item6ExpectedTargetPath = path.join( testDownloadPath, 'dir1', 'dir2', 'dir3', 'dir4', 'file6.txt' ) const targetLocations = specification.filesToDownload.map( item => item.targetPath ) expect(targetLocations).toContain(item1ExpectedTargetPath) expect(targetLocations).toContain(item2ExpectedTargetPath) expect(targetLocations).toContain(item3ExpectedTargetPath) expect(targetLocations).toContain(item4ExpectedTargetPath) expect(targetLocations).toContain(item5ExpectedTargetPath) for (const downloadItem of specification.filesToDownload) { if (downloadItem.targetPath === item1ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file1Path) ) } else if (downloadItem.targetPath === item2ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file2Path) ) } else if (downloadItem.targetPath === item3ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file3Path) ) } else if (downloadItem.targetPath === item4ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file4Path) ) } else if (downloadItem.targetPath === item5ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file5Path) ) } else { throw new Error('this should never be reached') } } expect(specification.directoryStructure.length).toEqual(3) expect(specification.directoryStructure).toContain(testDownloadPath) expect(specification.directoryStructure).toContain( path.join(testDownloadPath, 'dir1') ) expect(specification.directoryStructure).toContain( path.join(testDownloadPath, 'dir1', 'dir2', 'dir3', 'dir4') ) expect(specification.emptyFilesToCreate.length).toEqual(1) expect(specification.emptyFilesToCreate).toContain(item6ExpectedTargetPath) }) it('Download Specification - Relative Path with no root directory', () => { const testDownloadPath = path.join('some', 'destination', 'folder') const specification = getDownloadSpecification( artifact1Name, artifactContainerEntries, testDownloadPath, false ) expect(specification.rootDownloadLocation).toEqual(testDownloadPath) expect(specification.filesToDownload.length).toEqual(5) const item1ExpectedTargetPath = path.join(testDownloadPath, 'file1.txt') const item2ExpectedTargetPath = path.join(testDownloadPath, 'file2.txt') const item3ExpectedTargetPath = path.join( testDownloadPath, 'dir1', 'file3.txt' ) const item4ExpectedTargetPath = path.join( testDownloadPath, 'dir1', 'dir2', 'dir3', 'dir4', 'file4.txt' ) const item5ExpectedTargetPath = path.join( testDownloadPath, 'dir1', 'dir2', 'dir3', 'dir4', 'file5.txt' ) const item6ExpectedTargetPath = path.join( testDownloadPath, 'dir1', 'dir2', 'dir3', 'dir4', 'file6.txt' ) const targetLocations = specification.filesToDownload.map( item => item.targetPath ) expect(targetLocations).toContain(item1ExpectedTargetPath) expect(targetLocations).toContain(item2ExpectedTargetPath) expect(targetLocations).toContain(item3ExpectedTargetPath) expect(targetLocations).toContain(item4ExpectedTargetPath) expect(targetLocations).toContain(item5ExpectedTargetPath) for (const downloadItem of specification.filesToDownload) { if (downloadItem.targetPath === item1ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file1Path) ) } else if (downloadItem.targetPath === item2ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file2Path) ) } else if (downloadItem.targetPath === item3ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file3Path) ) } else if (downloadItem.targetPath === item4ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file4Path) ) } else if (downloadItem.targetPath === item5ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file5Path) ) } else { throw new Error('this should never be reached') } } expect(specification.directoryStructure.length).toEqual(3) expect(specification.directoryStructure).toContain(testDownloadPath) expect(specification.directoryStructure).toContain( path.join(testDownloadPath, 'dir1') ) expect(specification.directoryStructure).toContain( path.join(testDownloadPath, 'dir1', 'dir2', 'dir3', 'dir4') ) expect(specification.emptyFilesToCreate.length).toEqual(1) expect(specification.emptyFilesToCreate).toContain(item6ExpectedTargetPath) }) it('Download Specification - Absolute Path with root directory', () => { const testDownloadPath = path.join( __dirname, 'some', 'destination', 'folder' ) const specification = getDownloadSpecification( artifact1Name, artifactContainerEntries, testDownloadPath, true ) expect(specification.rootDownloadLocation).toEqual( path.join(testDownloadPath, artifact1Name) ) expect(specification.filesToDownload.length).toEqual(5) const item1ExpectedTargetPath = path.join( testDownloadPath, artifact1Name, 'file1.txt' ) const item2ExpectedTargetPath = path.join( testDownloadPath, artifact1Name, 'file2.txt' ) const item3ExpectedTargetPath = path.join( testDownloadPath, artifact1Name, 'dir1', 'file3.txt' ) const item4ExpectedTargetPath = path.join( testDownloadPath, artifact1Name, 'dir1', 'dir2', 'dir3', 'dir4', 'file4.txt' ) const item5ExpectedTargetPath = path.join( testDownloadPath, artifact1Name, 'dir1', 'dir2', 'dir3', 'dir4', 'file5.txt' ) const item6ExpectedTargetPath = path.join( testDownloadPath, artifact1Name, 'dir1', 'dir2', 'dir3', 'dir4', 'file6.txt' ) const targetLocations = specification.filesToDownload.map( item => item.targetPath ) expect(targetLocations).toContain(item1ExpectedTargetPath) expect(targetLocations).toContain(item2ExpectedTargetPath) expect(targetLocations).toContain(item3ExpectedTargetPath) expect(targetLocations).toContain(item4ExpectedTargetPath) expect(targetLocations).toContain(item5ExpectedTargetPath) for (const downloadItem of specification.filesToDownload) { if (downloadItem.targetPath === item1ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file1Path) ) } else if (downloadItem.targetPath === item2ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file2Path) ) } else if (downloadItem.targetPath === item3ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file3Path) ) } else if (downloadItem.targetPath === item4ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file4Path) ) } else if (downloadItem.targetPath === item5ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file5Path) ) } else { throw new Error('this should never be reached') } } expect(specification.directoryStructure.length).toEqual(3) expect(specification.directoryStructure).toContain( path.join(testDownloadPath, artifact1Name) ) expect(specification.directoryStructure).toContain( path.join(testDownloadPath, dir1Path) ) expect(specification.directoryStructure).toContain( path.join(testDownloadPath, dir4Path) ) expect(specification.emptyFilesToCreate.length).toEqual(1) expect(specification.emptyFilesToCreate).toContain(item6ExpectedTargetPath) }) it('Download Specification - Relative Path with root directory', () => { const testDownloadPath = path.join('some', 'destination', 'folder') const specification = getDownloadSpecification( artifact1Name, artifactContainerEntries, testDownloadPath, true ) expect(specification.rootDownloadLocation).toEqual( path.join(testDownloadPath, artifact1Name) ) expect(specification.filesToDownload.length).toEqual(5) const item1ExpectedTargetPath = path.join( testDownloadPath, artifact1Name, 'file1.txt' ) const item2ExpectedTargetPath = path.join( testDownloadPath, artifact1Name, 'file2.txt' ) const item3ExpectedTargetPath = path.join( testDownloadPath, artifact1Name, 'dir1', 'file3.txt' ) const item4ExpectedTargetPath = path.join( testDownloadPath, artifact1Name, 'dir1', 'dir2', 'dir3', 'dir4', 'file4.txt' ) const item5ExpectedTargetPath = path.join( testDownloadPath, artifact1Name, 'dir1', 'dir2', 'dir3', 'dir4', 'file5.txt' ) const item6ExpectedTargetPath = path.join( testDownloadPath, artifact1Name, 'dir1', 'dir2', 'dir3', 'dir4', 'file6.txt' ) const targetLocations = specification.filesToDownload.map( item => item.targetPath ) expect(targetLocations).toContain(item1ExpectedTargetPath) expect(targetLocations).toContain(item2ExpectedTargetPath) expect(targetLocations).toContain(item3ExpectedTargetPath) expect(targetLocations).toContain(item4ExpectedTargetPath) expect(targetLocations).toContain(item5ExpectedTargetPath) for (const downloadItem of specification.filesToDownload) { if (downloadItem.targetPath === item1ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file1Path) ) } else if (downloadItem.targetPath === item2ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file2Path) ) } else if (downloadItem.targetPath === item3ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file3Path) ) } else if (downloadItem.targetPath === item4ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file4Path) ) } else if (downloadItem.targetPath === item5ExpectedTargetPath) { expect(downloadItem.sourceLocation).toEqual( createContentLocation(file5Path) ) } else { throw new Error('this should never be reached') } } expect(specification.directoryStructure.length).toEqual(3) expect(specification.directoryStructure).toContain( path.join(testDownloadPath, artifact1Name) ) expect(specification.directoryStructure).toContain( path.join(testDownloadPath, dir1Path) ) expect(specification.directoryStructure).toContain( path.join(testDownloadPath, dir4Path) ) expect(specification.emptyFilesToCreate.length).toEqual(1) expect(specification.emptyFilesToCreate).toContain(item6ExpectedTargetPath) }) })