mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-29 22:02:01 +00:00
Compare commits
12 Commits
master
...
users/jawe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff5ebda58e | ||
|
|
79e9f3a843 | ||
|
|
9bdb995e14 | ||
|
|
de293d330c | ||
|
|
e9f12298cd | ||
|
|
d6a84af0a2 | ||
|
|
5a24db2230 | ||
|
|
45049425c9 | ||
|
|
74363ddfe9 | ||
|
|
ef1e26fc0c | ||
|
|
e75af41844 | ||
|
|
7ac6a264bb |
28
.github/workflows/ci.yml
vendored
28
.github/workflows/ci.yml
vendored
@@ -164,8 +164,8 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
shardIndex: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
|
||||
shardTotal: [16]
|
||||
shardIndex: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||
shardTotal: [20]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js 18.x
|
||||
@@ -198,18 +198,18 @@ jobs:
|
||||
GREMLIN_TESTACCOUNT_TOKEN=$(az account get-access-token --scope "https://github-e2etests-gremlin.documents.azure.com/.default" -o tsv --query accessToken)
|
||||
echo "::add-mask::$GREMLIN_TESTACCOUNT_TOKEN"
|
||||
echo GREMLIN_TESTACCOUNT_TOKEN=$GREMLIN_TESTACCOUNT_TOKEN >> $GITHUB_ENV
|
||||
CASSANDRA_TESTACCOUNT_TOKEN=$(az account get-access-token --scope "https://github-e2etests-cassandra.documents.azure.com/.default" -o tsv --query accessToken)
|
||||
echo "::add-mask::$CASSANDRA_TESTACCOUNT_TOKEN"
|
||||
echo CASSANDRA_TESTACCOUNT_TOKEN=$CASSANDRA_TESTACCOUNT_TOKEN >> $GITHUB_ENV
|
||||
MONGO_TESTACCOUNT_TOKEN=$(az account get-access-token --scope "https://github-e2etests-mongo.documents.azure.com/.default" -o tsv --query accessToken)
|
||||
echo "::add-mask::$MONGO_TESTACCOUNT_TOKEN"
|
||||
echo MONGO_TESTACCOUNT_TOKEN=$MONGO_TESTACCOUNT_TOKEN >> $GITHUB_ENV
|
||||
MONGO32_TESTACCOUNT_TOKEN=$(az account get-access-token --scope "https://github-e2etests-mongo32.documents.azure.com/.default" -o tsv --query accessToken)
|
||||
echo "::add-mask::$MONGO32_TESTACCOUNT_TOKEN"
|
||||
echo MONGO32_TESTACCOUNT_TOKEN=$MONGO32_TESTACCOUNT_TOKEN >> $GITHUB_ENV
|
||||
MONGO_READONLY_TESTACCOUNT_TOKEN=$(az account get-access-token --scope "https://github-e2etests-mongo-readonly.documents.azure.com/.default" -o tsv --query accessToken)
|
||||
echo "::add-mask::$MONGO_READONLY_TESTACCOUNT_TOKEN"
|
||||
echo MONGO_READONLY_TESTACCOUNT_TOKEN=$MONGO_READONLY_TESTACCOUNT_TOKEN >> $GITHUB_ENV
|
||||
# CASSANDRA_TESTACCOUNT_TOKEN=$(az account get-access-token --scope "https://github-e2etests-cassandra.documents.azure.com/.default" -o tsv --query accessToken)
|
||||
# echo "::add-mask::$CASSANDRA_TESTACCOUNT_TOKEN"
|
||||
# echo CASSANDRA_TESTACCOUNT_TOKEN=$CASSANDRA_TESTACCOUNT_TOKEN >> $GITHUB_ENV
|
||||
# MONGO_TESTACCOUNT_TOKEN=$(az account get-access-token --scope "https://github-e2etests-mongo.documents.azure.com/.default" -o tsv --query accessToken)
|
||||
# echo "::add-mask::$MONGO_TESTACCOUNT_TOKEN"
|
||||
# echo MONGO_TESTACCOUNT_TOKEN=$MONGO_TESTACCOUNT_TOKEN >> $GITHUB_ENV
|
||||
# MONGO32_TESTACCOUNT_TOKEN=$(az account get-access-token --scope "https://github-e2etests-mongo32.documents.azure.com/.default" -o tsv --query accessToken)
|
||||
# echo "::add-mask::$MONGO32_TESTACCOUNT_TOKEN"
|
||||
# echo MONGO32_TESTACCOUNT_TOKEN=$MONGO32_TESTACCOUNT_TOKEN >> $GITHUB_ENV
|
||||
# MONGO_READONLY_TESTACCOUNT_TOKEN=$(az account get-access-token --scope "https://github-e2etests-mongo-readonly.documents.azure.com/.default" -o tsv --query accessToken)
|
||||
# echo "::add-mask::$MONGO_READONLY_TESTACCOUNT_TOKEN"
|
||||
# echo MONGO_READONLY_TESTACCOUNT_TOKEN=$MONGO_READONLY_TESTACCOUNT_TOKEN >> $GITHUB_ENV
|
||||
- name: Run test shard ${{ matrix['shardIndex'] }} of ${{ matrix['shardTotal']}}
|
||||
run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --workers=3
|
||||
- name: Upload blob report to GitHub Actions Artifacts
|
||||
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -116,8 +116,8 @@
|
||||
"tinykeys": "2.1.0",
|
||||
"underscore": "1.12.1",
|
||||
"utility-types": "3.10.0",
|
||||
"web-vitals": "4.2.4",
|
||||
"uuid": "9.0.0",
|
||||
"web-vitals": "4.2.4",
|
||||
"zustand": "3.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -11,8 +11,8 @@ export default defineConfig({
|
||||
reporter: process.env.CI ? "blob" : "html",
|
||||
timeout: 10 * 60 * 1000,
|
||||
use: {
|
||||
trace: "off",
|
||||
video: "off",
|
||||
trace: "on-all-retries",
|
||||
video: "on-first-retry",
|
||||
screenshot: "on",
|
||||
testIdAttribute: "data-test",
|
||||
contextOptions: {
|
||||
|
||||
@@ -8,7 +8,8 @@ test("Cassandra keyspace and table CRUD", async ({ page }) => {
|
||||
|
||||
const explorer = await DataExplorer.open(page, TestAccount.Cassandra);
|
||||
|
||||
await explorer.globalCommandButton("New Table").click();
|
||||
const newTableButton = await explorer.globalCommandButton("New Table");
|
||||
await newTableButton.click();
|
||||
await explorer.whilePanelOpen(
|
||||
"Add Table",
|
||||
async (panel, okButton) => {
|
||||
|
||||
@@ -352,8 +352,9 @@ export class DataExplorer {
|
||||
*
|
||||
* There's only a single "primary" button, but we still require you to pass the label to confirm you're selecting the right button.
|
||||
*/
|
||||
globalCommandButton(label: string): Locator {
|
||||
return this.frame.getByTestId("GlobalCommands").getByText(label);
|
||||
async globalCommandButton(label: string): Promise<Locator> {
|
||||
await this.frame.getByTestId("GlobalCommands").click();
|
||||
return this.frame.getByRole("menuitem", { name: label });
|
||||
}
|
||||
|
||||
/** Select the command bar button with the specified label */
|
||||
|
||||
@@ -9,7 +9,8 @@ test("Gremlin graph CRUD", async ({ page }) => {
|
||||
const explorer = await DataExplorer.open(page, TestAccount.Gremlin);
|
||||
|
||||
// Create new database and graph
|
||||
await explorer.globalCommandButton("New Graph").click();
|
||||
const newGraphButton = await explorer.globalCommandButton("New Graph");
|
||||
await newGraphButton.click();
|
||||
await explorer.whilePanelOpen(
|
||||
"New Graph",
|
||||
async (panel, okButton) => {
|
||||
|
||||
@@ -14,7 +14,8 @@ import { DataExplorer, TEST_AUTOSCALE_THROUGHPUT_RU, TestAccount, generateUnique
|
||||
|
||||
const explorer = await DataExplorer.open(page, accountType);
|
||||
|
||||
await explorer.globalCommandButton("New Collection").click();
|
||||
const newCollectionButton = await explorer.globalCommandButton("New Collection");
|
||||
await newCollectionButton.click();
|
||||
await explorer.whilePanelOpen(
|
||||
"New Collection",
|
||||
async (panel, okButton) => {
|
||||
|
||||
@@ -8,7 +8,8 @@ test("SQL database and container CRUD", async ({ page }) => {
|
||||
|
||||
const explorer = await DataExplorer.open(page, TestAccount.SQL);
|
||||
|
||||
await explorer.globalCommandButton("New Container").click();
|
||||
const newContainerButton = await explorer.globalCommandButton("New Container");
|
||||
await newContainerButton.click();
|
||||
await explorer.whilePanelOpen(
|
||||
"New Container",
|
||||
async (panel, okButton) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { expect, Locator, test } from "@playwright/test";
|
||||
import { expect, Locator, Page, test } from "@playwright/test";
|
||||
import {
|
||||
CommandBarButton,
|
||||
DataExplorer,
|
||||
@@ -10,120 +10,113 @@ import {
|
||||
import { createTestSQLContainer, TestContainerContext } from "../../testData";
|
||||
|
||||
test.describe("Autoscale and Manual throughput", () => {
|
||||
let context: TestContainerContext = null!;
|
||||
let explorer: DataExplorer = null!;
|
||||
const withScaleTab = async (
|
||||
page: Page,
|
||||
run: (args: { context: TestContainerContext; explorer: DataExplorer }) => Promise<void>,
|
||||
): Promise<void> => {
|
||||
const context = await createTestSQLContainer();
|
||||
try {
|
||||
const explorer = await DataExplorer.open(page, TestAccount.SQL);
|
||||
|
||||
test.beforeAll("Create Test Database", async () => {
|
||||
context = await createTestSQLContainer({ includeTestData: true });
|
||||
});
|
||||
await explorer.openScaleAndSettings(context);
|
||||
await explorer.frame.getByTestId("settings-tab-header/ScaleTab").click();
|
||||
|
||||
test.beforeEach("Open container settings", async ({ page }) => {
|
||||
explorer = await DataExplorer.open(page, TestAccount.SQL);
|
||||
await run({ context, explorer });
|
||||
} finally {
|
||||
await context.dispose();
|
||||
}
|
||||
};
|
||||
|
||||
// Click Scale & Settings and open Scale tab
|
||||
await explorer.openScaleAndSettings(context);
|
||||
const scaleTab = explorer.frame.getByTestId("settings-tab-header/ScaleTab");
|
||||
await scaleTab.click();
|
||||
});
|
||||
|
||||
test.afterAll("Delete Test Database", async () => {
|
||||
await context?.dispose();
|
||||
});
|
||||
|
||||
test("Update autoscale max throughput", async () => {
|
||||
// By default the created container has manual throughput (Containers created via JS SDK v4.7.0 cannot be created with autoscale throughput)
|
||||
await switchManualToAutoscaleThroughput();
|
||||
|
||||
// Update autoscale max throughput
|
||||
await getThroughputInput("autopilot").fill(TEST_AUTOSCALE_MAX_THROUGHPUT_RU_2K.toString());
|
||||
|
||||
// Save
|
||||
await explorer.commandBarButton(CommandBarButton.Save).click();
|
||||
|
||||
// Read console message
|
||||
await expect(explorer.getConsoleMessage()).toContainText(
|
||||
`Successfully updated offer for collection ${context.container.id}`,
|
||||
{
|
||||
timeout: 2 * ONE_MINUTE_MS,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test("Update autoscale max throughput passed allowed limit", async () => {
|
||||
// By default the created container has manual throughput (Containers created via JS SDK v4.7.0 cannot be created with autoscale throughput)
|
||||
await switchManualToAutoscaleThroughput();
|
||||
|
||||
// Get soft allowed max throughput and remove commas
|
||||
const softAllowedMaxThroughputString = await explorer.frame
|
||||
.getByTestId("soft-allowed-maximum-throughput")
|
||||
.innerText();
|
||||
const softAllowedMaxThroughput = Number(softAllowedMaxThroughputString.replace(/,/g, ""));
|
||||
|
||||
// Try to set autoscale max throughput above allowed limit
|
||||
await getThroughputInput("autopilot").fill((softAllowedMaxThroughput * 10).toString());
|
||||
await expect(explorer.commandBarButton(CommandBarButton.Save)).toBeDisabled();
|
||||
await expect(getThroughputInputErrorMessage("autopilot")).toContainText(
|
||||
"This update isn't possible because it would increase the total throughput",
|
||||
);
|
||||
});
|
||||
|
||||
test("Update autoscale max throughput with invalid increment", async () => {
|
||||
// By default the created container has manual throughput (Containers created via JS SDK v4.7.0 cannot be created with autoscale throughput)
|
||||
await switchManualToAutoscaleThroughput();
|
||||
|
||||
// Try to set autoscale max throughput with invalid increment
|
||||
await getThroughputInput("autopilot").fill("1100");
|
||||
await expect(explorer.commandBarButton(CommandBarButton.Save)).toBeDisabled();
|
||||
await expect(getThroughputInputErrorMessage("autopilot")).toContainText(
|
||||
"Throughput value must be in increments of 1000",
|
||||
);
|
||||
});
|
||||
|
||||
test("Update manual throughput", async () => {
|
||||
await getThroughputInput("manual").fill(TEST_MANUAL_THROUGHPUT_RU_2K.toString());
|
||||
await explorer.commandBarButton(CommandBarButton.Save).click();
|
||||
await expect(explorer.getConsoleMessage()).toContainText(
|
||||
`Successfully updated offer for collection ${context.container.id}`,
|
||||
{
|
||||
timeout: 2 * ONE_MINUTE_MS,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test("Update manual throughput passed allowed limit", async () => {
|
||||
// Get soft allowed max throughput and remove commas
|
||||
const softAllowedMaxThroughputString = await explorer.frame
|
||||
.getByTestId("soft-allowed-maximum-throughput")
|
||||
.innerText();
|
||||
const softAllowedMaxThroughput = Number(softAllowedMaxThroughputString.replace(/,/g, ""));
|
||||
|
||||
// Try to set manual throughput above allowed limit
|
||||
await getThroughputInput("manual").fill((softAllowedMaxThroughput * 10).toString());
|
||||
await expect(explorer.commandBarButton(CommandBarButton.Save)).toBeDisabled();
|
||||
await expect(getThroughputInputErrorMessage("manual")).toContainText(
|
||||
"This update isn't possible because it would increase the total throughput",
|
||||
);
|
||||
});
|
||||
|
||||
// Helper methods
|
||||
const getThroughputInput = (type: "manual" | "autopilot"): Locator => {
|
||||
const getThroughputInput = (explorer: DataExplorer, type: "manual" | "autopilot"): Locator => {
|
||||
return explorer.frame.getByTestId(`${type}-throughput-input`);
|
||||
};
|
||||
|
||||
const getThroughputInputErrorMessage = (type: "manual" | "autopilot"): Locator => {
|
||||
const getThroughputInputErrorMessage = (explorer: DataExplorer, type: "manual" | "autopilot"): Locator => {
|
||||
return explorer.frame.getByTestId(`${type}-throughput-input-error`);
|
||||
};
|
||||
|
||||
const switchManualToAutoscaleThroughput = async (): Promise<void> => {
|
||||
const switchManualToAutoscaleThroughput = async (explorer: DataExplorer, containerId: string): Promise<void> => {
|
||||
const autoscaleRadioButton = explorer.frame.getByText("Autoscale", { exact: true });
|
||||
await autoscaleRadioButton.click();
|
||||
|
||||
await expect(explorer.commandBarButton(CommandBarButton.Save)).toBeEnabled();
|
||||
await explorer.commandBarButton(CommandBarButton.Save).click();
|
||||
|
||||
await expect(explorer.getConsoleMessage()).toContainText(
|
||||
`Successfully updated offer for collection ${context.container.id}`,
|
||||
`Successfully updated offer for collection ${containerId}`,
|
||||
{
|
||||
timeout: ONE_MINUTE_MS,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
test("Update autoscale max throughput", async ({ page }) => {
|
||||
await withScaleTab(page, async ({ context, explorer }) => {
|
||||
await switchManualToAutoscaleThroughput(explorer, context.container.id);
|
||||
|
||||
await getThroughputInput(explorer, "autopilot").fill(TEST_AUTOSCALE_MAX_THROUGHPUT_RU_2K.toString());
|
||||
await explorer.commandBarButton(CommandBarButton.Save).click();
|
||||
|
||||
await expect(explorer.getConsoleMessage()).toContainText(
|
||||
`Successfully updated offer for collection ${context.container.id}`,
|
||||
{ timeout: 2 * ONE_MINUTE_MS },
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("Update autoscale max throughput passed allowed limit", async ({ page }) => {
|
||||
await withScaleTab(page, async ({ context, explorer }) => {
|
||||
await switchManualToAutoscaleThroughput(explorer, context.container.id);
|
||||
|
||||
const softAllowedMaxThroughputString = await explorer.frame
|
||||
.getByTestId("soft-allowed-maximum-throughput")
|
||||
.innerText();
|
||||
const softAllowedMaxThroughput = Number(softAllowedMaxThroughputString.replace(/,/g, ""));
|
||||
|
||||
await getThroughputInput(explorer, "autopilot").fill((softAllowedMaxThroughput * 10).toString());
|
||||
await expect(explorer.commandBarButton(CommandBarButton.Save)).toBeDisabled();
|
||||
await expect(getThroughputInputErrorMessage(explorer, "autopilot")).toContainText(
|
||||
"This update isn't possible because it would increase the total throughput",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("Update autoscale max throughput with invalid increment", async ({ page }) => {
|
||||
await withScaleTab(page, async ({ context, explorer }) => {
|
||||
await switchManualToAutoscaleThroughput(explorer, context.container.id);
|
||||
|
||||
await getThroughputInput(explorer, "autopilot").fill("1100");
|
||||
await expect(explorer.commandBarButton(CommandBarButton.Save)).toBeDisabled();
|
||||
await expect(getThroughputInputErrorMessage(explorer, "autopilot")).toContainText(
|
||||
"Throughput value must be in increments of 1000",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("Update manual throughput", async ({ page }) => {
|
||||
await withScaleTab(page, async ({ context, explorer }) => {
|
||||
await getThroughputInput(explorer, "manual").fill(TEST_MANUAL_THROUGHPUT_RU_2K.toString());
|
||||
await explorer.commandBarButton(CommandBarButton.Save).click();
|
||||
|
||||
await expect(explorer.getConsoleMessage()).toContainText(
|
||||
`Successfully updated offer for collection ${context.container.id}`,
|
||||
{ timeout: 2 * ONE_MINUTE_MS },
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("Update manual throughput passed allowed limit", async ({ page }) => {
|
||||
await withScaleTab(page, async ({ explorer }) => {
|
||||
const softAllowedMaxThroughputString = await explorer.frame
|
||||
.getByTestId("soft-allowed-maximum-throughput")
|
||||
.innerText();
|
||||
const softAllowedMaxThroughput = Number(softAllowedMaxThroughputString.replace(/,/g, ""));
|
||||
|
||||
await getThroughputInput(explorer, "manual").fill((softAllowedMaxThroughput * 10).toString());
|
||||
await expect(explorer.commandBarButton(CommandBarButton.Save)).toBeDisabled();
|
||||
await expect(getThroughputInputErrorMessage(explorer, "manual")).toContainText(
|
||||
"This update isn't possible because it would increase the total throughput",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ test.describe("Settings under Scale & Settings", () => {
|
||||
let explorer: DataExplorer = null!;
|
||||
|
||||
test.beforeAll("Create Test Database", async () => {
|
||||
context = await createTestSQLContainer({ includeTestData: true });
|
||||
context = await createTestSQLContainer();
|
||||
});
|
||||
|
||||
test.beforeEach("Open Settings tab under Scale & Settings", async ({ page }) => {
|
||||
|
||||
@@ -7,7 +7,8 @@ test("Tables CRUD", async ({ page }) => {
|
||||
|
||||
const explorer = await DataExplorer.open(page, TestAccount.Tables);
|
||||
|
||||
await explorer.globalCommandButton("New Table").click();
|
||||
const newTableButton = explorer.frame.getByTestId("GlobalCommands").getByRole("button", { name: "New Table" });
|
||||
await newTableButton.click();
|
||||
await explorer.whilePanelOpen(
|
||||
"New Table",
|
||||
async (panel, okButton) => {
|
||||
|
||||
Reference in New Issue
Block a user