Comparar commits

...

6 Commits

Autor SHA1 Mensagem Data
Tess DiStefano 2b104e7f02 add new unit test, start tweak azureBlobStorage 2020-11-03 17:44:43 +00:00
Tess DiStefano 269e0d42f2 better variable name 2020-11-02 23:22:04 +00:00
Tess DiStefano e02d806006 add test for getting filename 2020-11-02 23:21:24 +00:00
Tess DiStefano e66d4d6bd2 unused using 2020-11-02 19:28:51 +00:00
Tess DiStefano b73ab4b7ae Merge branch 'master' of https://github.com/microsoft/vott into tess/connection_strings_for_blob 2020-11-02 18:34:28 +00:00
Wallace Breza b524085d52 Update node-sass 2020-10-26 11:27:50 -07:00
2 arquivos alterados com 69 adições e 53 exclusões
+57 -51
Ver Arquivo
@@ -9,17 +9,23 @@ import { AssetType } from "../../models/applicationState";
describe("Azure blob functions", () => {
const ad = MockFactory.createAzureData();
const options = ad.options;
const globalCloudRoot = `https://account.blob.core.windows.net`;
const chinacCloudRoot = `https://blob.core.chinacloudapi.cn`;
const azureData = MockFactory.createAzureData();
const optionsForGlobalBlob = azureData.options;
optionsForGlobalBlob.blobEndpoint = globalCloudRoot; // may not be used if using sas
const optionsForChinaBlob = azureData.options;
optionsForChinaBlob.blobEndpoint = chinacCloudRoot;
const serviceURL = ServiceURL as jest.Mocked<typeof ServiceURL>;
serviceURL.prototype.listContainersSegment = jest.fn(() => Promise.resolve(ad.containers));
serviceURL.prototype.listContainersSegment = jest.fn(() => Promise.resolve(azureData.containers));
ContainerURL.fromServiceURL = jest.fn(() => new ContainerURL(null, null));
const containerURL = ContainerURL as jest.Mocked<typeof ContainerURL>;
containerURL.prototype.create = jest.fn(() => Promise.resolve({ statusCode: 201 }));
containerURL.prototype.delete = jest.fn(() => Promise.resolve({ statusCode: 204 }));
containerURL.prototype.listBlobFlatSegment = jest.fn(() => Promise.resolve(ad.blobs));
containerURL.prototype.listBlobFlatSegment = jest.fn(() => Promise.resolve(azureData.blobs));
BlockBlobURL.fromContainerURL = jest.fn(() => new BlockBlobURL(null, null));
@@ -28,132 +34,132 @@ describe("Azure blob functions", () => {
it("Reads text from a blob", async () => {
const blockBlobURL = BlockBlobURL as jest.Mocked<typeof BlockBlobURL>;
const blob = MockFactory.blob(ad.blobName, ad.blobText, ad.fileType);
const blob = MockFactory.blob(azureData.blobName, azureData.blobText, azureData.fileType);
blockBlobURL.prototype.download = jest.fn(() => Promise.resolve({
blobBody: Promise.resolve(blob),
}));
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
const content = await provider.readText(ad.blobName);
const content = await provider.readText(azureData.blobName);
expect(ContainerURL.fromServiceURL).toBeCalledWith(
expect.any(ServiceURL),
ad.containerName,
azureData.containerName,
);
expect(BlockBlobURL.fromContainerURL).toBeCalledWith(
expect.any(ContainerURL),
ad.blobName,
azureData.blobName,
);
expect(content).toEqual(ad.blobText);
expect(content).toEqual(azureData.blobText);
});
it("Reads buffer from a blob", async () => {
const blockBlobURL = BlockBlobURL as jest.Mocked<typeof BlockBlobURL>;
const blob = MockFactory.blob(
ad.blobName, Buffer.from(ad.blobText), ad.fileType,
azureData.blobName, Buffer.from(azureData.blobText), azureData.fileType,
);
blockBlobURL.prototype.download = jest.fn(() => Promise.resolve({
blobBody: Promise.resolve(blob),
}));
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
const content = await provider.readBinary(ad.blobName);
const content = await provider.readBinary(azureData.blobName);
expect(ContainerURL.fromServiceURL).toBeCalledWith(
expect.any(ServiceURL),
ad.containerName,
azureData.containerName,
);
expect(BlockBlobURL.fromContainerURL).toBeCalledWith(
expect.any(ContainerURL),
ad.blobName,
azureData.blobName,
);
expect(content).toEqual(Buffer.from(ad.blobText));
expect(content).toEqual(Buffer.from(azureData.blobText));
});
it("Writes text to a blob", () => {
const blockBlobURL = BlockBlobURL as jest.Mocked<typeof BlockBlobURL>;
const blob = MockFactory.blob(ad.blobName, ad.blobText, ad.fileType);
const blob = MockFactory.blob(azureData.blobName, azureData.blobText, azureData.fileType);
blockBlobURL.prototype.download = jest.fn(() => Promise.resolve({
blobBody: Promise.resolve(blob),
}));
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
provider.writeText(ad.blobName, ad.blobText);
provider.writeText(azureData.blobName, azureData.blobText);
expect(ContainerURL.fromServiceURL).toBeCalledWith(
expect.any(ServiceURL),
ad.containerName,
azureData.containerName,
);
expect(BlockBlobURL.fromContainerURL).toBeCalledWith(
expect.any(ContainerURL),
ad.blobName,
azureData.blobName,
);
expect(blockBlobURL.prototype.upload).toBeCalledWith(
Aborter.none,
ad.blobText,
ad.blobText.length,
azureData.blobText,
azureData.blobText.length,
);
});
it("Writes a buffer to a blob", () => {
const blockBlobURL = BlockBlobURL as jest.Mocked<typeof BlockBlobURL>;
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
provider.writeText(ad.blobName, Buffer.from(ad.blobText));
provider.writeText(azureData.blobName, Buffer.from(azureData.blobText));
expect(ContainerURL.fromServiceURL).toBeCalledWith(
expect.any(ServiceURL),
ad.containerName,
azureData.containerName,
);
expect(BlockBlobURL.fromContainerURL).toBeCalledWith(
expect.any(ContainerURL),
ad.blobName,
azureData.blobName,
);
expect(blockBlobURL.prototype.upload).toBeCalledWith(
Aborter.none,
Buffer.from(ad.blobText),
ad.blobText.length,
Buffer.from(azureData.blobText),
azureData.blobText.length,
);
});
it("Lists the blobs within a container", async () => {
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
const blobs = await provider.listFiles(null);
expect(containerURL.prototype.listBlobFlatSegment).toBeCalled();
expect(blobs).toEqual(ad.blobs.segment.blobItems.map((element) => element.name));
expect(blobs).toEqual(azureData.blobs.segment.blobItems.map((element) => element.name));
});
it("Deletes a blob within a container", async () => {
const blockBlobURL = BlockBlobURL as jest.Mocked<typeof BlockBlobURL>;
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
provider.deleteFile(ad.blobName);
provider.deleteFile(azureData.blobName);
expect(ContainerURL.fromServiceURL).toBeCalledWith(
expect.any(ServiceURL),
ad.containerName,
azureData.containerName,
);
expect(BlockBlobURL.fromContainerURL).toBeCalledWith(
expect.any(ContainerURL),
ad.blobName,
azureData.blobName,
);
expect(blockBlobURL.prototype.delete).toBeCalledWith(Aborter.none);
});
it("Lists the containers within an account", async () => {
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
const containers = await provider.listContainers(null);
expect(serviceURL.prototype.listContainersSegment).toBeCalled();
expect(containers).toEqual(ad.containers.containerItems.map((element) => element.name));
expect(containers).toEqual(azureData.containers.containerItems.map((element) => element.name));
});
it("Creates a container in the account", async () => {
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
await expect(provider.createContainer(null)).resolves.not.toBeNull();
expect(ContainerURL.fromServiceURL).toBeCalledWith(
expect.any(ServiceURL),
ad.containerName,
azureData.containerName,
);
expect(containerURL.prototype.create).toBeCalled();
});
@@ -163,27 +169,27 @@ describe("Azure blob functions", () => {
return Promise.reject({ statusCode: 409 });
});
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
await expect(provider.createContainer(null)).resolves.not.toBeNull();
expect(ContainerURL.fromServiceURL).toBeCalledWith(
expect.any(ServiceURL),
ad.containerName,
azureData.containerName,
);
expect(containerURL.prototype.create).toBeCalled();
});
it("Deletes a container in the account", () => {
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
provider.deleteContainer(null);
expect(ContainerURL.fromServiceURL).toBeCalledWith(
expect.any(ServiceURL),
ad.containerName,
azureData.containerName,
);
expect(containerURL.prototype.delete).toBeCalled();
});
it("getAssets", async () => {
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
AssetService.createAssetFromFilePath = jest.fn(() => {
return {
type: AssetType.Image,
@@ -192,19 +198,19 @@ describe("Azure blob functions", () => {
provider.getFileName = jest.fn();
const assets = await provider.getAssets();
expect(provider.getFileName).toBeCalled();
expect(assets).toHaveLength(ad.blobs.segment.blobItems.length);
expect(assets).toHaveLength(azureData.blobs.segment.blobItems.length);
});
it("get file name from url", async () => {
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const url = "https://account.blob.core.windows.net/container/filename.jpg?aBcDeFGHiJkLMnoP";
it.each([globalCloudRoot, chinacCloudRoot])("get file name from non global url", async (path) => {
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
const url = `${path}/container/filename.jpg?aBcDeFGHiJkLMnoP`;
const fileName = provider.getFileName(url);
expect(fileName).toEqual("filename.jpg");
});
it("creates a container when specified in options", () => {
const newOptions = {
...options,
...optionsForGlobalBlob,
containerName: "newContainer",
createContainer: true,
};
@@ -218,7 +224,7 @@ describe("Azure blob functions", () => {
});
it("does not create a container when not specified", async () => {
const provider: AzureBlobStorage = new AzureBlobStorage(options);
const provider: AzureBlobStorage = new AzureBlobStorage(optionsForGlobalBlob);
await provider.initialize();
expect(serviceURL.prototype.listContainersSegment).toBeCalled();
});
@@ -226,7 +232,7 @@ describe("Azure blob functions", () => {
it("throws an error if container not found and not created", async () => {
const newContainerName = "newContainer";
const provider: AzureBlobStorage = new AzureBlobStorage({
...options,
...optionsForGlobalBlob,
containerName: newContainerName,
});
try {
+12 -2
Ver Arquivo
@@ -5,7 +5,6 @@ import {
TokenCredential, AnonymousCredential, ContainerURL,
StorageURL, ServiceURL, Credential, Aborter, BlockBlobURL,
} from "@azure/storage-blob";
import { BlobDeleteResponse } from "@azure/storage-blob/typings/lib/generated/lib/models";
/**
* Options for Azure Cloud Storage
@@ -14,6 +13,10 @@ import { BlobDeleteResponse } from "@azure/storage-blob/typings/lib/generated/li
* @member createContainer - Option for creating container in `initialize()`
* @member sas - Shared Access Signature (SAS) token for accessing Azure Blob Storage
* @member oauthToken - Not yet implemented. Optional token for accessing Azure Blob Storage
* @member blobEndpoint - Endpoint of the blob
* @member defaultEndpointsProtocol - https or http
* @member accountKey - Account access key
* @member endpointSuffix - Account access key
*/
export interface IAzureCloudStorageOptions {
accountName: string;
@@ -21,6 +24,12 @@ export interface IAzureCloudStorageOptions {
createContainer: boolean;
sas?: string;
oauthToken?: string;
blobEndpoint?: string;
accountKey?: string;
defaultEndpointsProtocol?: string;
endpointSuffix?: string;
}
/**
@@ -218,7 +227,8 @@ export class AzureBlobStorage implements IStorageProvider {
* @returns - URL for Azure Blob Storage account with SAS token appended if specified
*/
public getAccountUrl(): string {
return `https://${this.options.accountName}.blob.core.windows.net` + (this.options.sas || "");
return (this.options.blobEndpoint || `https://${this.options.accountName}.blob.core.windows.net`) +
(this.options.sas || "");
}
/**