Skip to content

Commit

Permalink
Merge pull request #4567 from viavarejo/techdocs-azure-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
OrkoHunter committed Mar 4, 2021
2 parents 141e9d3 + 29b2109 commit 9dd1e71
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 14 deletions.
24 changes: 24 additions & 0 deletions packages/techdocs-common/__mocks__/@azure/storage-blob.ts
Expand Up @@ -17,11 +17,13 @@ import type {
BlobUploadCommonResponse,
ContainerGetPropertiesResponse,
} from '@azure/storage-blob';
import { EventEmitter } from 'events';
import fs from 'fs-extra';
import os from 'os';
import path from 'path';

const rootDir = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir';

/**
* @param sourceFile Relative path to entity root dir. Contains either / or \ as file separator
* depending upon the OS.
Expand All @@ -48,6 +50,9 @@ export class BlockBlobClient {
}

uploadFile(source: string): Promise<BlobUploadCommonResponse> {
if (!fs.existsSync(source)) {
return Promise.reject(new Error(`The file ${source} does not exist`));
}
return Promise.resolve({
_response: {
request: {
Expand All @@ -62,6 +67,25 @@ export class BlockBlobClient {
exists() {
return checkFileExists(this.blobName);
}

download() {
const filePath = path.join(rootDir, this.blobName);
const emitter = new EventEmitter();
process.nextTick(() => {
if (fs.existsSync(filePath)) {
emitter.emit('data', Buffer.from(fs.readFileSync(filePath)));
emitter.emit('end');
} else {
emitter.emit(
'error',
new Error(`The file ${filePath} does not exist !`),
);
}
});
return Promise.resolve({
readableStreamBody: emitter,
});
}
}

class BlockBlobClientFailUpload extends BlockBlobClient {
Expand Down
140 changes: 138 additions & 2 deletions packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts
Expand Up @@ -14,13 +14,17 @@
* limitations under the License.
*/
import { getVoidLogger } from '@backstage/backend-common';
import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model';
import {
Entity,
EntityName,
ENTITY_DEFAULT_NAMESPACE,
} from '@backstage/catalog-model';
import { ConfigReader } from '@backstage/config';
import mockFs from 'mock-fs';
import os from 'os';
import path from 'path';
import { AzureBlobStoragePublish } from './azureBlobStorage';
import { PublisherBase } from './types';
import { PublisherBase, TechDocsMetadata } from './types';

// NOTE: /packages/techdocs-common/__mocks__ is being used to mock Azure client library

Expand All @@ -38,7 +42,14 @@ const createMockEntity = (annotations = {}) => {
};
};

const createMockEntityName = (): EntityName => ({
kind: 'TestKind',
name: 'test-component-name',
namespace: 'test-namespace',
});

const rootDir = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir';

const getEntityRootDir = (entity: Entity) => {
const {
kind,
Expand Down Expand Up @@ -163,6 +174,72 @@ describe('publishing with valid credentials', () => {
expect(await publisher.hasDocsBeenGenerated(entity)).toBe(false);
});
});

describe('fetchTechDocsMetadata', () => {
it('should return tech docs metadata', async () => {
const entityNameMock = createMockEntityName();
const entity = createMockEntity();
const entityRootDir = getEntityRootDir(entity);

mockFs({
[entityRootDir]: {
'techdocs_metadata.json':
'{"site_name": "backstage", "site_description": "site_content"}',
},
});
const expectedMetadata: TechDocsMetadata = {
site_name: 'backstage',
site_description: 'site_content',
};
expect(
await publisher.fetchTechDocsMetadata(entityNameMock),
).toStrictEqual(expectedMetadata);
mockFs.restore();
});

it('should return tech docs metadata when json encoded with single quotes', async () => {
const entityNameMock = createMockEntityName();
const entity = createMockEntity();
const entityRootDir = getEntityRootDir(entity);

mockFs({
[entityRootDir]: {
'techdocs_metadata.json': `{'site_name': 'backstage', 'site_description': 'site_content'}`,
},
});

const expectedMetadata: TechDocsMetadata = {
site_name: 'backstage',
site_description: 'site_content',
};
expect(
await publisher.fetchTechDocsMetadata(entityNameMock),
).toStrictEqual(expectedMetadata);
mockFs.restore();
});

it('should return an error if the techdocs_metadata.json file is not present', async () => {
const entityNameMock = createMockEntityName();
const entity = createMockEntity();
const entityRootDir = getEntityRootDir(entity);

let error;
try {
await publisher.fetchTechDocsMetadata(entityNameMock);
} catch (e) {
error = e;
}

expect(error).toEqual(
new Error(
`TechDocs metadata fetch failed, The file ${path.join(
entityRootDir,
'techdocs_metadata.json',
)} does not exist !`,
),
);
});
});
});

describe('error reporting', () => {
Expand Down Expand Up @@ -255,4 +332,63 @@ describe('error reporting', () => {

mockFs.restore();
});

describe('fetchTechDocsMetadata', () => {
it('should return tech docs metadata', async () => {
const entityNameMock = createMockEntityName();
const entity = createMockEntity();
const entityRootDir = getEntityRootDir(entity);

mockFs({
[entityRootDir]: {
'techdocs_metadata.json':
'{"site_name": "backstage", "site_description": "site_content"}',
},
});
const expectedMetadata: TechDocsMetadata = {
site_name: 'backstage',
site_description: 'site_content',
};
expect(
await publisher.fetchTechDocsMetadata(entityNameMock),
).toStrictEqual(expectedMetadata);
mockFs.restore();
});

it('should return tech docs metadata when json encoded with single quotes', async () => {
const entityNameMock = createMockEntityName();
const entity = createMockEntity();
const entityRootDir = getEntityRootDir(entity);

mockFs({
[entityRootDir]: {
'techdocs_metadata.json': `{'site_name': 'backstage', 'site_description': 'site_content'}`,
},
});

const expectedMetadata: TechDocsMetadata = {
site_name: 'backstage',
site_description: 'site_content',
};
expect(
await publisher.fetchTechDocsMetadata(entityNameMock),
).toStrictEqual(expectedMetadata);
mockFs.restore();
});

it('should return an error if the techdocs_metadata.json file is not present', async () => {
const entityNameMock = createMockEntityName();

let error;
try {
await publisher.fetchTechDocsMetadata(entityNameMock);
} catch (e) {
error = e;
}

expect(error.message).toEqual(
expect.stringContaining('TechDocs metadata fetch'),
);
});
});
});
26 changes: 14 additions & 12 deletions packages/techdocs-common/src/stages/publish/azureBlobStorage.ts
Expand Up @@ -201,10 +201,7 @@ export class AzureBlobStoragePublish implements PublisherBase {
return;
}
body
.on('error', e => {
this.logger.error(e.message);
reject(e.message);
})
.on('error', reject)
.on('data', chunk => {
fileStreamChunks.push(chunk);
})
Expand All @@ -220,16 +217,21 @@ export class AzureBlobStoragePublish implements PublisherBase {
): Promise<TechDocsMetadata> {
const entityRootDir = `${entityName.namespace}/${entityName.kind}/${entityName.name}`;
try {
return await new Promise<TechDocsMetadata>(resolve => {
const download = this.download(
this.containerName,
`${entityRootDir}/techdocs_metadata.json`,
const techdocsMetadataJson = await this.download(
this.containerName,
`${entityRootDir}/techdocs_metadata.json`,
);
if (!techdocsMetadataJson) {
throw new Error(
`Unable to parse the techdocs metadata file ${entityRootDir}/techdocs_metadata.json.`,
);
resolve(JSON5.parse(download.toString()));
});
}
const techdocsMetadata = JSON5.parse(
techdocsMetadataJson.toString('utf-8'),
);
return techdocsMetadata;
} catch (e) {
this.logger.error(e.message);
throw e;
throw new Error(`TechDocs metadata fetch failed, ${e.message}`);
}
}

Expand Down

0 comments on commit 9dd1e71

Please sign in to comment.