mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-01-31 15:44:11 +00:00
Add user defined functions and trigger test
This commit is contained in:
@@ -3,7 +3,7 @@ import { AuthType } from "../../AuthType";
|
|||||||
import { userContext } from "../../UserContext";
|
import { userContext } from "../../UserContext";
|
||||||
import { createUpdateSqlTrigger, getSqlTrigger } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
|
import { createUpdateSqlTrigger, getSqlTrigger } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
|
||||||
import { SqlTriggerCreateUpdateParameters, SqlTriggerResource } from "../../Utils/arm/generatedClients/cosmos/types";
|
import { SqlTriggerCreateUpdateParameters, SqlTriggerResource } from "../../Utils/arm/generatedClients/cosmos/types";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ export async function createTrigger(
|
|||||||
): Promise<TriggerDefinition | SqlTriggerResource> {
|
): Promise<TriggerDefinition | SqlTriggerResource> {
|
||||||
const clearMessage = logConsoleProgress(`Creating trigger ${trigger.id}`);
|
const clearMessage = logConsoleProgress(`Creating trigger ${trigger.id}`);
|
||||||
try {
|
try {
|
||||||
|
let resource: SqlTriggerResource | TriggerDefinition;
|
||||||
if (
|
if (
|
||||||
userContext.authType === AuthType.AAD &&
|
userContext.authType === AuthType.AAD &&
|
||||||
!userContext.features.enableSDKoperations &&
|
!userContext.features.enableSDKoperations &&
|
||||||
@@ -52,14 +53,16 @@ export async function createTrigger(
|
|||||||
trigger.id,
|
trigger.id,
|
||||||
createTriggerParams,
|
createTriggerParams,
|
||||||
);
|
);
|
||||||
return rpResponse && rpResponse.properties?.resource;
|
resource = rpResponse && rpResponse.properties?.resource;
|
||||||
|
} else {
|
||||||
|
const sdkResponse = await client()
|
||||||
|
.database(databaseId)
|
||||||
|
.container(collectionId)
|
||||||
|
.scripts.triggers.create(trigger as unknown as TriggerDefinition); // TODO: TypeScript does not like the SQL SDK trigger type
|
||||||
|
resource = sdkResponse.resource;
|
||||||
}
|
}
|
||||||
|
logConsoleInfo(`Successfully created trigger ${trigger.id}`);
|
||||||
const response = await client()
|
return resource;
|
||||||
.database(databaseId)
|
|
||||||
.container(collectionId)
|
|
||||||
.scripts.triggers.create(trigger as unknown as TriggerDefinition); // TODO: TypeScript does not like the SQL SDK trigger type
|
|
||||||
return response.resource;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error, "CreateTrigger", `Error while creating trigger ${trigger.id}`);
|
handleError(error, "CreateTrigger", `Error while creating trigger ${trigger.id}`);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
SqlUserDefinedFunctionCreateUpdateParameters,
|
SqlUserDefinedFunctionCreateUpdateParameters,
|
||||||
SqlUserDefinedFunctionResource,
|
SqlUserDefinedFunctionResource,
|
||||||
} from "../../Utils/arm/generatedClients/cosmos/types";
|
} from "../../Utils/arm/generatedClients/cosmos/types";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
|
||||||
@@ -20,6 +20,7 @@ export async function createUserDefinedFunction(
|
|||||||
): Promise<UserDefinedFunctionDefinition & Resource> {
|
): Promise<UserDefinedFunctionDefinition & Resource> {
|
||||||
const clearMessage = logConsoleProgress(`Creating user defined function ${userDefinedFunction.id}`);
|
const clearMessage = logConsoleProgress(`Creating user defined function ${userDefinedFunction.id}`);
|
||||||
try {
|
try {
|
||||||
|
let resource: UserDefinedFunctionDefinition & Resource;
|
||||||
if (
|
if (
|
||||||
userContext.authType === AuthType.AAD &&
|
userContext.authType === AuthType.AAD &&
|
||||||
!userContext.features.enableSDKoperations &&
|
!userContext.features.enableSDKoperations &&
|
||||||
@@ -60,14 +61,17 @@ export async function createUserDefinedFunction(
|
|||||||
userDefinedFunction.id,
|
userDefinedFunction.id,
|
||||||
createUDFParams,
|
createUDFParams,
|
||||||
);
|
);
|
||||||
return rpResponse && (rpResponse.properties?.resource as UserDefinedFunctionDefinition & Resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await client()
|
resource = rpResponse && (rpResponse.properties?.resource as UserDefinedFunctionDefinition & Resource);
|
||||||
.database(databaseId)
|
} else {
|
||||||
.container(collectionId)
|
const response = await client()
|
||||||
.scripts.userDefinedFunctions.create(userDefinedFunction);
|
.database(databaseId)
|
||||||
return response?.resource;
|
.container(collectionId)
|
||||||
|
.scripts.userDefinedFunctions.create(userDefinedFunction);
|
||||||
|
resource = response.resource;
|
||||||
|
}
|
||||||
|
logConsoleInfo(`Successfully created user defined function ${userDefinedFunction.id}`);
|
||||||
|
return resource;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(
|
handleError(
|
||||||
error,
|
error,
|
||||||
|
|||||||
64
test/sql/scripts/trigger.spec.ts
Normal file
64
test/sql/scripts/trigger.spec.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { expect, test } from "@playwright/test";
|
||||||
|
import { CommandBarButton, DataExplorer, ONE_MINUTE_MS, TestAccount } from "../../fx";
|
||||||
|
import { createTestSQLContainer, TestContainerContext } from "../../testData";
|
||||||
|
|
||||||
|
test.describe("Triggers", () => {
|
||||||
|
let context: TestContainerContext = null!;
|
||||||
|
let explorer: DataExplorer = null!;
|
||||||
|
const triggerBody = `function validateToDoItemTimestamp() {
|
||||||
|
var context = getContext();
|
||||||
|
var request = context.getRequest();
|
||||||
|
|
||||||
|
var itemToCreate = request.getBody();
|
||||||
|
|
||||||
|
if (!("timestamp" in itemToCreate)) {
|
||||||
|
var ts = new Date();
|
||||||
|
itemToCreate["timestamp"] = ts.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
request.setBody(itemToCreate);
|
||||||
|
}`;
|
||||||
|
test.beforeAll("Create Test Database", async () => {
|
||||||
|
context = await createTestSQLContainer(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.beforeEach("Open container", async ({ page }) => {
|
||||||
|
explorer = await DataExplorer.open(page, TestAccount.SQL);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!process.env.CI) {
|
||||||
|
test.afterAll("Delete Test Database", async () => {
|
||||||
|
await context?.dispose();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
test("Add and delete trigger", async ({ page }) => {
|
||||||
|
// Open container context menu and click New Trigger
|
||||||
|
const containerNode = await explorer.waitForContainerNode(context.database.id, context.container.id);
|
||||||
|
await containerNode.openContextMenu();
|
||||||
|
await containerNode.contextMenuItem("New Trigger").click();
|
||||||
|
|
||||||
|
// Assign Trigger id
|
||||||
|
const triggerIdTextBox = explorer.frame.getByLabel("Trigger Id");
|
||||||
|
const triggerId: string = "validateItemTimestamp";
|
||||||
|
await triggerIdTextBox.fill(triggerId);
|
||||||
|
|
||||||
|
// Create Trigger body that validates item timestamp
|
||||||
|
const triggerBodyTextArea = explorer.frame.getByTestId("EditorReact/Host/Loaded");
|
||||||
|
await triggerBodyTextArea.click();
|
||||||
|
|
||||||
|
// Clear existing content
|
||||||
|
const isMac: boolean = process.platform === "darwin";
|
||||||
|
await page.keyboard.press(isMac ? "Meta+A" : "Control+A");
|
||||||
|
await page.keyboard.press("Backspace");
|
||||||
|
|
||||||
|
await page.keyboard.type(triggerBody);
|
||||||
|
|
||||||
|
// Save changes
|
||||||
|
const saveButton = explorer.commandBarButton(CommandBarButton.Save);
|
||||||
|
await saveButton.click();
|
||||||
|
await expect(explorer.getConsoleMessage()).toContainText(`Successfully created trigger ${triggerId}`, {
|
||||||
|
timeout: 2 * ONE_MINUTE_MS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -5,11 +5,11 @@ import { createTestSQLContainer, TestContainerContext } from "../../testData";
|
|||||||
test.describe("User Defined Functions", () => {
|
test.describe("User Defined Functions", () => {
|
||||||
let context: TestContainerContext = null!;
|
let context: TestContainerContext = null!;
|
||||||
let explorer: DataExplorer = null!;
|
let explorer: DataExplorer = null!;
|
||||||
const udfBody = `function extractDocumentId(doc) {
|
const udfBody: string = `function extractDocumentId(doc) {
|
||||||
return {
|
return {
|
||||||
id: doc.id
|
id: doc.id
|
||||||
};
|
};
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
test.beforeAll("Create Test Database", async () => {
|
test.beforeAll("Create Test Database", async () => {
|
||||||
context = await createTestSQLContainer(true);
|
context = await createTestSQLContainer(true);
|
||||||
@@ -19,9 +19,11 @@ test.describe("User Defined Functions", () => {
|
|||||||
explorer = await DataExplorer.open(page, TestAccount.SQL);
|
explorer = await DataExplorer.open(page, TestAccount.SQL);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.afterAll("Delete Test Database", async () => {
|
if (!process.env.CI) {
|
||||||
await context?.dispose();
|
test.afterAll("Delete Test Database", async () => {
|
||||||
});
|
await context?.dispose();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
test("Add, execute, and delete user defined function", async ({ page }) => {
|
test("Add, execute, and delete user defined function", async ({ page }) => {
|
||||||
// Open container context menu and click New UDF
|
// Open container context menu and click New UDF
|
||||||
@@ -31,8 +33,8 @@ test.describe("User Defined Functions", () => {
|
|||||||
|
|
||||||
// Assign UDF id
|
// Assign UDF id
|
||||||
const udfIdTextBox = explorer.frame.getByLabel("User Defined Function Id");
|
const udfIdTextBox = explorer.frame.getByLabel("User Defined Function Id");
|
||||||
const udfName: string = "extractDocumentId";
|
const udfId: string = "extractDocumentId";
|
||||||
await udfIdTextBox.fill(udfName);
|
await udfIdTextBox.fill(udfId);
|
||||||
|
|
||||||
// Create UDF body that extracts the document id from a document
|
// Create UDF body that extracts the document id from a document
|
||||||
const udfBodyTextArea = explorer.frame.getByTestId("EditorReact/Host/Loaded");
|
const udfBodyTextArea = explorer.frame.getByTestId("EditorReact/Host/Loaded");
|
||||||
@@ -49,7 +51,7 @@ test.describe("User Defined Functions", () => {
|
|||||||
const saveButton = explorer.commandBarButton(CommandBarButton.Save);
|
const saveButton = explorer.commandBarButton(CommandBarButton.Save);
|
||||||
await expect(saveButton).toBeEnabled();
|
await expect(saveButton).toBeEnabled();
|
||||||
await saveButton.click();
|
await saveButton.click();
|
||||||
await expect(explorer.getConsoleMessage()).toContainText(`Sucessfully created user defined function ${udfName}`, {
|
await expect(explorer.getConsoleMessage()).toContainText(`Successfully created user defined function ${udfId}`, {
|
||||||
timeout: ONE_MINUTE_MS,
|
timeout: ONE_MINUTE_MS,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -60,14 +62,14 @@ test.describe("User Defined Functions", () => {
|
|||||||
);
|
);
|
||||||
await udfsNode.expand();
|
await udfsNode.expand();
|
||||||
const udfNode = await explorer.waitForNode(
|
const udfNode = await explorer.waitForNode(
|
||||||
`${context.database.id}/${context.container.id}/User Defined Functions/${udfName}`,
|
`${context.database.id}/${context.container.id}/User Defined Functions/${udfId}`,
|
||||||
);
|
);
|
||||||
await udfNode.openContextMenu();
|
await udfNode.openContextMenu();
|
||||||
await udfNode.contextMenuItem("Delete User Defined Function").click();
|
await udfNode.contextMenuItem("Delete User Defined Function").click();
|
||||||
const deleteUserDefinedFunctionButton = explorer.frame.getByTestId("DialogButton:Delete");
|
const deleteUserDefinedFunctionButton = explorer.frame.getByTestId("DialogButton:Delete");
|
||||||
await deleteUserDefinedFunctionButton.click();
|
await deleteUserDefinedFunctionButton.click();
|
||||||
|
|
||||||
await expect(explorer.getConsoleMessage()).toContainText(`Successfully deleted user defined function ${udfName}`, {
|
await expect(explorer.getConsoleMessage()).toContainText(`Successfully deleted user defined function ${udfId}`, {
|
||||||
timeout: ONE_MINUTE_MS,
|
timeout: ONE_MINUTE_MS,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user