mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-04-21 00:59:26 +01:00
Pk missing fix (#2094)
* fix partition key missing not being able to load the document * Implement E2E tests for documents with different partitionkeys * Implement E2E tests for documents with different partitionkeys * Implement E2E tests for documents with different partitionkeys * Updated snapshot
This commit is contained in:
parent
e3c3a8b1b7
commit
af0a890516
@ -1,5 +1,4 @@
|
|||||||
import { defineConfig, devices } from "@playwright/test";
|
import { defineConfig, devices } from "@playwright/test";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See https://playwright.dev/docs/test-configuration.
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
*/
|
*/
|
||||||
|
@ -1037,6 +1037,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
);
|
);
|
||||||
|
|
||||||
const selectedDocumentId = documentIds[clickedRowIndex as number];
|
const selectedDocumentId = documentIds[clickedRowIndex as number];
|
||||||
|
const originalPartitionKeyValue = selectedDocumentId.partitionKeyValue;
|
||||||
selectedDocumentId.partitionKeyValue = partitionKeyValueArray;
|
selectedDocumentId.partitionKeyValue = partitionKeyValueArray;
|
||||||
|
|
||||||
onExecutionErrorChange(false);
|
onExecutionErrorChange(false);
|
||||||
@ -1072,6 +1073,10 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
setColumnDefinitionsFromDocument(documentContent);
|
setColumnDefinitionsFromDocument(documentContent);
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
// in case of any kind of failures of accidently changing partition key, restore the original
|
||||||
|
// so that when user navigates away from current document and comes back,
|
||||||
|
// it doesnt fail to load due to using the invalid partition keys
|
||||||
|
selectedDocumentId.partitionKeyValue = originalPartitionKeyValue;
|
||||||
onExecutionErrorChange(true);
|
onExecutionErrorChange(true);
|
||||||
const errorMessage = getErrorMessage(error);
|
const errorMessage = getErrorMessage(error);
|
||||||
useDialog.getState().showOkModalDialog("Update document failed", errorMessage);
|
useDialog.getState().showOkModalDialog("Update document failed", errorMessage);
|
||||||
@ -2083,8 +2088,8 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<CosmosFluentProvider className={styles.container}>
|
<CosmosFluentProvider className={styles.container}>
|
||||||
<div className="tab-pane active" role="tabpanel" style={{ display: "flex" }}>
|
<div data-test={"DocumentsTab"} className="tab-pane active" role="tabpanel" style={{ display: "flex" }}>
|
||||||
<div className={styles.filterRow}>
|
<div data-test={"DocumentsTab/Filter"} className={styles.filterRow}>
|
||||||
{!isPreferredApiMongoDB && <span> SELECT * FROM c </span>}
|
{!isPreferredApiMongoDB && <span> SELECT * FROM c </span>}
|
||||||
<InputDataList
|
<InputDataList
|
||||||
dropdownOptions={getFilterChoices()}
|
dropdownOptions={getFilterChoices()}
|
||||||
@ -2126,7 +2131,11 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Allotment.Pane preferredSize={`${tabStateData.leftPaneWidthPercent}%`} minSize={55}>
|
<Allotment.Pane preferredSize={`${tabStateData.leftPaneWidthPercent}%`} minSize={55}>
|
||||||
<div style={{ height: "100%", width: "100%", overflow: "hidden" }} ref={tableContainerRef}>
|
<div
|
||||||
|
data-test={"DocumentsTab/DocumentsPane"}
|
||||||
|
style={{ height: "100%", width: "100%", overflow: "hidden" }}
|
||||||
|
ref={tableContainerRef}
|
||||||
|
>
|
||||||
<div className={styles.tableContainer}>
|
<div className={styles.tableContainer}>
|
||||||
<div
|
<div
|
||||||
style={
|
style={
|
||||||
@ -2180,7 +2189,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
</div>
|
</div>
|
||||||
</Allotment.Pane>
|
</Allotment.Pane>
|
||||||
<Allotment.Pane minSize={30}>
|
<Allotment.Pane minSize={30}>
|
||||||
<div style={{ height: "100%", width: "100%" }}>
|
<div data-test={"DocumentsTab/ResultsPane"} style={{ height: "100%", width: "100%" }}>
|
||||||
{isTabActive && selectedDocumentContent && selectedRows.size <= 1 && (
|
{isTabActive && selectedDocumentContent && selectedRows.size <= 1 && (
|
||||||
<EditorReact
|
<EditorReact
|
||||||
language={"json"}
|
language={"json"}
|
||||||
|
@ -6,6 +6,7 @@ exports[`Documents tab (noSql API) when rendered should render the page 1`] = `
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="tab-pane active"
|
className="tab-pane active"
|
||||||
|
data-test="DocumentsTab"
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
style={
|
style={
|
||||||
{
|
{
|
||||||
@ -15,6 +16,7 @@ exports[`Documents tab (noSql API) when rendered should render the page 1`] = `
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="___11ktxfv_0000000 f1o614cb fy9rknc f22iagw fsnqrgy f1f5gg8d fjodcmx f122n59 f1f09k3d fg706s2 frpde29"
|
className="___11ktxfv_0000000 f1o614cb fy9rknc f22iagw fsnqrgy f1f5gg8d fjodcmx f122n59 f1f09k3d fg706s2 frpde29"
|
||||||
|
data-test="DocumentsTab/Filter"
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
SELECT * FROM c
|
SELECT * FROM c
|
||||||
@ -65,6 +67,7 @@ exports[`Documents tab (noSql API) when rendered should render the page 1`] = `
|
|||||||
preferredSize="35%"
|
preferredSize="35%"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
data-test="DocumentsTab/DocumentsPane"
|
||||||
style={
|
style={
|
||||||
{
|
{
|
||||||
"height": "100%",
|
"height": "100%",
|
||||||
@ -126,6 +129,7 @@ exports[`Documents tab (noSql API) when rendered should render the page 1`] = `
|
|||||||
minSize={30}
|
minSize={30}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
data-test="DocumentsTab/ResultsPane"
|
||||||
style={
|
style={
|
||||||
{
|
{
|
||||||
"height": "100%",
|
"height": "100%",
|
||||||
|
@ -35,6 +35,13 @@ describe("Query Utils", () => {
|
|||||||
version: 2,
|
version: 2,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
const generatePartitionKeysForPaths = (paths: string[]): DataModels.PartitionKey => {
|
||||||
|
return {
|
||||||
|
paths: paths,
|
||||||
|
kind: "Hash",
|
||||||
|
version: 2,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
describe("buildDocumentsQueryPartitionProjections()", () => {
|
describe("buildDocumentsQueryPartitionProjections()", () => {
|
||||||
it("should return empty string if partition key is undefined", () => {
|
it("should return empty string if partition key is undefined", () => {
|
||||||
@ -89,6 +96,18 @@ describe("Query Utils", () => {
|
|||||||
|
|
||||||
expect(query).toContain("c.id");
|
expect(query).toContain("c.id");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should always include {} for any missing partition keys", () => {
|
||||||
|
const query = QueryUtils.buildDocumentsQuery(
|
||||||
|
"",
|
||||||
|
["a", "b", "c"],
|
||||||
|
generatePartitionKeysForPaths(["/a", "/b", "/c"]),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
expect(query).toContain('IIF(IS_DEFINED(c["a"]), c["a"], {})');
|
||||||
|
expect(query).toContain('IIF(IS_DEFINED(c["b"]), c["b"], {})');
|
||||||
|
expect(query).toContain('IIF(IS_DEFINED(c["c"]), c["c"], {})');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("queryPagesUntilContentPresent()", () => {
|
describe("queryPagesUntilContentPresent()", () => {
|
||||||
@ -201,18 +220,6 @@ describe("Query Utils", () => {
|
|||||||
expect(expectedPartitionKeyValues).toContain(documentContent["Category"]);
|
expect(expectedPartitionKeyValues).toContain(documentContent["Category"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should extract no partition key values in the case nested partition key", () => {
|
|
||||||
const singlePartitionKeyDefinition: PartitionKeyDefinition = {
|
|
||||||
kind: PartitionKeyKind.Hash,
|
|
||||||
paths: ["/Location.type"],
|
|
||||||
};
|
|
||||||
const partitionKeyValues: PartitionKey[] = extractPartitionKeyValues(
|
|
||||||
documentContent,
|
|
||||||
singlePartitionKeyDefinition,
|
|
||||||
);
|
|
||||||
expect(partitionKeyValues.length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should extract all partition key values for hierarchical and nested partition keys", () => {
|
it("should extract all partition key values for hierarchical and nested partition keys", () => {
|
||||||
const mixedPartitionKeyDefinition: PartitionKeyDefinition = {
|
const mixedPartitionKeyDefinition: PartitionKeyDefinition = {
|
||||||
kind: PartitionKeyKind.MultiHash,
|
kind: PartitionKeyKind.MultiHash,
|
||||||
@ -225,5 +232,52 @@ describe("Query Utils", () => {
|
|||||||
expect(partitionKeyValues.length).toBe(2);
|
expect(partitionKeyValues.length).toBe(2);
|
||||||
expect(partitionKeyValues).toEqual(["United States", "Point"]);
|
expect(partitionKeyValues).toEqual(["United States", "Point"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("if any partition key is null or empty string, the partitionKeyValues shall match", () => {
|
||||||
|
const newDocumentContent = {
|
||||||
|
...documentContent,
|
||||||
|
...{
|
||||||
|
Country: null,
|
||||||
|
Location: {
|
||||||
|
type: "",
|
||||||
|
coordinates: [-121.49, 46.206],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mixedPartitionKeyDefinition: PartitionKeyDefinition = {
|
||||||
|
kind: PartitionKeyKind.MultiHash,
|
||||||
|
paths: ["/Country", "/Location/type"],
|
||||||
|
};
|
||||||
|
const partitionKeyValues: PartitionKey[] = extractPartitionKeyValues(
|
||||||
|
newDocumentContent,
|
||||||
|
mixedPartitionKeyDefinition,
|
||||||
|
);
|
||||||
|
expect(partitionKeyValues.length).toBe(2);
|
||||||
|
expect(partitionKeyValues).toEqual([null, ""]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("if any partition key doesn't exist, it should still set partitionkey value as {}", () => {
|
||||||
|
const newDocumentContent = {
|
||||||
|
...documentContent,
|
||||||
|
...{
|
||||||
|
Country: null,
|
||||||
|
Location: {
|
||||||
|
coordinates: [-121.49, 46.206],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mixedPartitionKeyDefinition: PartitionKeyDefinition = {
|
||||||
|
kind: PartitionKeyKind.MultiHash,
|
||||||
|
paths: ["/Country", "/Location/type"],
|
||||||
|
};
|
||||||
|
const partitionKeyValues: PartitionKey[] = extractPartitionKeyValues(
|
||||||
|
newDocumentContent,
|
||||||
|
mixedPartitionKeyDefinition,
|
||||||
|
);
|
||||||
|
expect(partitionKeyValues.length).toBe(2);
|
||||||
|
expect(partitionKeyValues).toEqual([null, {}]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -47,6 +47,7 @@ export function buildDocumentsQueryPartitionProjections(
|
|||||||
for (const index in partitionKey.paths) {
|
for (const index in partitionKey.paths) {
|
||||||
// TODO: Handle "/" in partition key definitions
|
// TODO: Handle "/" in partition key definitions
|
||||||
const projectedProperties: string[] = partitionKey.paths[index].split("/").slice(1);
|
const projectedProperties: string[] = partitionKey.paths[index].split("/").slice(1);
|
||||||
|
const isSystemPartitionKey: boolean = partitionKey.systemKey || false;
|
||||||
let projectedProperty = "";
|
let projectedProperty = "";
|
||||||
|
|
||||||
projectedProperties.forEach((property: string) => {
|
projectedProperties.forEach((property: string) => {
|
||||||
@ -61,8 +62,13 @@ export function buildDocumentsQueryPartitionProjections(
|
|||||||
projectedProperty += `[${projection}]`;
|
projectedProperty += `[${projection}]`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const fullAccess = `${collectionAlias}${projectedProperty}`;
|
||||||
projections.push(`${collectionAlias}${projectedProperty}`);
|
if (!isSystemPartitionKey) {
|
||||||
|
const wrappedProjection = `IIF(IS_DEFINED(${fullAccess}), ${fullAccess}, {})`;
|
||||||
|
projections.push(wrappedProjection);
|
||||||
|
} else {
|
||||||
|
projections.push(fullAccess);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return projections.join(",");
|
return projections.join(",");
|
||||||
@ -118,7 +124,7 @@ export const extractPartitionKeyValues = (
|
|||||||
documentContent: any,
|
documentContent: any,
|
||||||
partitionKeyDefinition: PartitionKeyDefinition,
|
partitionKeyDefinition: PartitionKeyDefinition,
|
||||||
): PartitionKey[] => {
|
): PartitionKey[] => {
|
||||||
if (!partitionKeyDefinition.paths || partitionKeyDefinition.paths.length === 0) {
|
if (!partitionKeyDefinition.paths || partitionKeyDefinition.paths.length === 0 || partitionKeyDefinition.systemKey) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +136,8 @@ export const extractPartitionKeyValues = (
|
|||||||
|
|
||||||
if (value !== undefined) {
|
if (value !== undefined) {
|
||||||
partitionKeyValues.push(value);
|
partitionKeyValues.push(value);
|
||||||
|
} else {
|
||||||
|
partitionKeyValues.push({});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
33
test/fx.ts
33
test/fx.ts
@ -26,7 +26,7 @@ export function getAzureCLICredentials(): AzureCliCredential {
|
|||||||
|
|
||||||
export async function getAzureCLICredentialsToken(): Promise<string> {
|
export async function getAzureCLICredentialsToken(): Promise<string> {
|
||||||
const credentials = getAzureCLICredentials();
|
const credentials = getAzureCLICredentials();
|
||||||
const token = (await credentials.getToken("https://management.core.windows.net//.default")).token;
|
const token = (await credentials.getToken("https://management.core.windows.net//.default"))?.token || "";
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,6 +37,7 @@ export enum TestAccount {
|
|||||||
Mongo = "Mongo",
|
Mongo = "Mongo",
|
||||||
Mongo32 = "Mongo32",
|
Mongo32 = "Mongo32",
|
||||||
SQL = "SQL",
|
SQL = "SQL",
|
||||||
|
SQLReadOnly = "SQLReadOnly",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultAccounts: Record<TestAccount, string> = {
|
export const defaultAccounts: Record<TestAccount, string> = {
|
||||||
@ -46,6 +47,7 @@ export const defaultAccounts: Record<TestAccount, string> = {
|
|||||||
[TestAccount.Mongo]: "github-e2etests-mongo",
|
[TestAccount.Mongo]: "github-e2etests-mongo",
|
||||||
[TestAccount.Mongo32]: "github-e2etests-mongo32",
|
[TestAccount.Mongo32]: "github-e2etests-mongo32",
|
||||||
[TestAccount.SQL]: "github-e2etests-sql",
|
[TestAccount.SQL]: "github-e2etests-sql",
|
||||||
|
[TestAccount.SQLReadOnly]: "github-e2etests-sql-readonly",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const resourceGroupName = process.env.DE_TEST_RESOURCE_GROUP ?? "de-e2e-tests";
|
export const resourceGroupName = process.env.DE_TEST_RESOURCE_GROUP ?? "de-e2e-tests";
|
||||||
@ -214,6 +216,25 @@ export class QueryTab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class DocumentsTab {
|
||||||
|
documentsFilter: Locator;
|
||||||
|
documentsListPane: Locator;
|
||||||
|
documentResultsPane: Locator;
|
||||||
|
resultsEditor: Editor;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public frame: Frame,
|
||||||
|
public tabId: string,
|
||||||
|
public tab: Locator,
|
||||||
|
public locator: Locator,
|
||||||
|
) {
|
||||||
|
this.documentsFilter = this.locator.getByTestId("DocumentsTab/Filter");
|
||||||
|
this.documentsListPane = this.locator.getByTestId("DocumentsTab/DocumentsPane");
|
||||||
|
this.documentResultsPane = this.locator.getByTestId("DocumentsTab/ResultsPane");
|
||||||
|
this.resultsEditor = new Editor(this.frame, this.documentResultsPane.getByTestId("EditorReact/Host/Loaded"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type PanelOpenOptions = {
|
type PanelOpenOptions = {
|
||||||
closeTimeout?: number;
|
closeTimeout?: number;
|
||||||
};
|
};
|
||||||
@ -232,6 +253,12 @@ export class DataExplorer {
|
|||||||
return new QueryTab(this.frame, tabId, tab, queryTab);
|
return new QueryTab(this.frame, tabId, tab, queryTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
documentsTab(tabId: string): DocumentsTab {
|
||||||
|
const tab = this.tab(tabId);
|
||||||
|
const documentsTab = tab.getByTestId("DocumentsTab");
|
||||||
|
return new DocumentsTab(this.frame, tabId, tab, documentsTab);
|
||||||
|
}
|
||||||
|
|
||||||
/** Select the primary global command button.
|
/** Select the primary global command button.
|
||||||
*
|
*
|
||||||
* There's only a single "primary" button, but we still require you to pass the label to confirm you're selecting the right button.
|
* There's only a single "primary" button, but we still require you to pass the label to confirm you're selecting the right button.
|
||||||
@ -294,6 +321,10 @@ export class DataExplorer {
|
|||||||
return await this.waitForNode(`${databaseId}/${containerId}`);
|
return await this.waitForNode(`${databaseId}/${containerId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async waitForContainerItemsNode(databaseId: string, containerId: string): Promise<TreeNode> {
|
||||||
|
return await this.waitForNode(`${databaseId}/${containerId}/Items`);
|
||||||
|
}
|
||||||
|
|
||||||
/** Select the tree node with the specified id */
|
/** Select the tree node with the specified id */
|
||||||
treeNode(id: string): TreeNode {
|
treeNode(id: string): TreeNode {
|
||||||
return new TreeNode(this.frame.getByTestId(`TreeNode:${id}`), this.frame, id);
|
return new TreeNode(this.frame.getByTestId(`TreeNode:${id}`), this.frame, id);
|
||||||
|
45
test/sql/document.spec.ts
Normal file
45
test/sql/document.spec.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { expect, test } from "@playwright/test";
|
||||||
|
|
||||||
|
import { DataExplorer, DocumentsTab, TestAccount } from "../fx";
|
||||||
|
import { documentTestCases } from "./testCases";
|
||||||
|
|
||||||
|
let explorer: DataExplorer = null!;
|
||||||
|
let documentsTab: DocumentsTab = null!;
|
||||||
|
|
||||||
|
for (const { name, databaseId, containerId, expectedDocumentIds } of documentTestCases) {
|
||||||
|
test.describe(`Test Documents with ${name}`, () => {
|
||||||
|
test.beforeEach("Open documents tab", async ({ page }) => {
|
||||||
|
explorer = await DataExplorer.open(page, TestAccount.SQLReadOnly);
|
||||||
|
|
||||||
|
const containerNode = await explorer.waitForContainerNode(databaseId, containerId);
|
||||||
|
await containerNode.expand();
|
||||||
|
|
||||||
|
const containerMenuNode = await explorer.waitForContainerItemsNode(databaseId, containerId);
|
||||||
|
await containerMenuNode.element.click();
|
||||||
|
|
||||||
|
documentsTab = explorer.documentsTab("tab0");
|
||||||
|
|
||||||
|
await documentsTab.documentsFilter.waitFor();
|
||||||
|
await documentsTab.documentsListPane.waitFor();
|
||||||
|
await expect(documentsTab.resultsEditor.locator).toBeAttached({ timeout: 60 * 1000 });
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const docId of expectedDocumentIds) {
|
||||||
|
test.describe(`Document ID: ${docId}`, () => {
|
||||||
|
test(`should load and view document ${docId}`, async () => {
|
||||||
|
const span = documentsTab.documentsListPane.getByText(docId, { exact: true }).nth(0);
|
||||||
|
await span.waitFor();
|
||||||
|
await expect(span).toBeVisible();
|
||||||
|
|
||||||
|
await span.click();
|
||||||
|
await expect(documentsTab.resultsEditor.locator).toBeAttached({ timeout: 60 * 1000 });
|
||||||
|
|
||||||
|
const resultText = await documentsTab.resultsEditor.text();
|
||||||
|
const resultData = JSON.parse(resultText!);
|
||||||
|
expect(resultText).not.toBeNull();
|
||||||
|
expect(resultData?.id).toEqual(docId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
88
test/sql/testCases.ts
Normal file
88
test/sql/testCases.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
type ContainerTestCase = {
|
||||||
|
name: string;
|
||||||
|
databaseId: string;
|
||||||
|
containerId: string;
|
||||||
|
expectedDocumentIds: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const documentTestCases: ContainerTestCase[] = [
|
||||||
|
{
|
||||||
|
name: "System Partition Key",
|
||||||
|
databaseId: "e2etests-sql-readonly",
|
||||||
|
containerId: "systemPartitionKey",
|
||||||
|
expectedDocumentIds: ["systempartition"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Single Partition Key",
|
||||||
|
databaseId: "e2etests-sql-readonly",
|
||||||
|
containerId: "singlePartitionKey",
|
||||||
|
expectedDocumentIds: [
|
||||||
|
"singlePartitionKey",
|
||||||
|
"singlePartitionKey_empty_string",
|
||||||
|
"singlePartitionKey_null",
|
||||||
|
"singlePartitionKey_missing",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Single Nested Partition Key",
|
||||||
|
databaseId: "e2etests-sql-readonly",
|
||||||
|
containerId: "singleNestedPartitionKey",
|
||||||
|
expectedDocumentIds: [
|
||||||
|
"singlePartitionKey_nested",
|
||||||
|
"singlePartitionKey_nested_empty_string",
|
||||||
|
"singlePartitionKey_nested_null",
|
||||||
|
"singlePartitionKey_nested_missing",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "2-Level Hierarchical Partition Key",
|
||||||
|
databaseId: "e2etests-sql-readonly",
|
||||||
|
containerId: "twoLevelPartitionKey",
|
||||||
|
expectedDocumentIds: [
|
||||||
|
"twoLevelPartitionKey_value_empty",
|
||||||
|
"twoLevelPartitionKey_value_null",
|
||||||
|
"twoLevelPartitionKey_value_missing",
|
||||||
|
"twoLevelPartitionKey_empty_null",
|
||||||
|
"twoLevelPartitionKey_null_missing",
|
||||||
|
"twoLevelPartitionKey_missing_value",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "2-Level Hierarchical Nested Partition Key",
|
||||||
|
databaseId: "e2etests-sql-readonly",
|
||||||
|
containerId: "twoLevelNestedPartitionKey",
|
||||||
|
expectedDocumentIds: [
|
||||||
|
"twoLevelNestedPartitionKey_nested_value_empty",
|
||||||
|
"twoLevelNestedPartitionKey_nested_null_missing",
|
||||||
|
"twoLevelNestedPartitionKey_nested_missing_value",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "3-Level Hierarchical Partition Key",
|
||||||
|
databaseId: "e2etests-sql-readonly",
|
||||||
|
containerId: "threeLevelPartitionKey",
|
||||||
|
expectedDocumentIds: [
|
||||||
|
"threeLevelPartitionKey_value_empty_null",
|
||||||
|
"threeLevelPartitionKey_value_null_missing",
|
||||||
|
"threeLevelPartitionKey_value_missing_null",
|
||||||
|
"threeLevelPartitionKey_null_empty_value",
|
||||||
|
"threeLevelPartitionKey_missing_value_value",
|
||||||
|
"threeLevelPartitionKey_empty_value_missing",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "3-Level Nested Hierarchical Partition Key",
|
||||||
|
databaseId: "e2etests-sql-readonly",
|
||||||
|
containerId: "threeLevelNestedPartitionKey",
|
||||||
|
expectedDocumentIds: [
|
||||||
|
"threeLevelNestedPartitionKey_nested_empty_value_null",
|
||||||
|
"threeLevelNestedPartitionKey_nested_null_value_missing",
|
||||||
|
"threeLevelNestedPartitionKey_nested_missing_value_null",
|
||||||
|
"threeLevelNestedPartitionKey_nested_null_empty_missing",
|
||||||
|
"threeLevelNestedPartitionKey_nested_value_missing_empty",
|
||||||
|
"threeLevelNestedPartitionKey_nested_missing_null_empty",
|
||||||
|
"threeLevelNestedPartitionKey_nested_empty_null_value",
|
||||||
|
"threeLevelNestedPartitionKey_nested_value_null_empty",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
Loading…
x
Reference in New Issue
Block a user