Migrate unit test to DocumentsTabV2
This commit is contained in:
parent
6c3aa7e625
commit
3c6c32ecc2
|
@ -0,0 +1,99 @@
|
||||||
|
import { buildQuery, showPartitionKey } from "Explorer/Tabs/DocumentsTabV2/DocumentsTabV2";
|
||||||
|
import * as ko from "knockout";
|
||||||
|
import { DatabaseAccount } from "../../../Contracts/DataModels";
|
||||||
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
|
import { updateUserContext } from "../../../UserContext";
|
||||||
|
import Explorer from "../../Explorer";
|
||||||
|
|
||||||
|
describe("Documents tab", () => {
|
||||||
|
describe("buildQuery", () => {
|
||||||
|
it("should generate the right select query for SQL API", () => {
|
||||||
|
expect(buildQuery(false, "")).toContain("select");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("showPartitionKey", () => {
|
||||||
|
const explorer = new Explorer();
|
||||||
|
const mongoExplorer = new Explorer();
|
||||||
|
updateUserContext({
|
||||||
|
databaseAccount: {
|
||||||
|
properties: {
|
||||||
|
capabilities: [{ name: "EnableGremlin" }],
|
||||||
|
},
|
||||||
|
} as DatabaseAccount,
|
||||||
|
});
|
||||||
|
|
||||||
|
const collectionWithoutPartitionKey = <ViewModels.Collection>(<unknown>{
|
||||||
|
id: ko.observable<string>("foo"),
|
||||||
|
database: {
|
||||||
|
id: ko.observable<string>("foo"),
|
||||||
|
},
|
||||||
|
container: explorer,
|
||||||
|
});
|
||||||
|
|
||||||
|
const collectionWithSystemPartitionKey = <ViewModels.Collection>(<unknown>{
|
||||||
|
id: ko.observable<string>("foo"),
|
||||||
|
database: {
|
||||||
|
id: ko.observable<string>("foo"),
|
||||||
|
},
|
||||||
|
partitionKey: {
|
||||||
|
paths: ["/foo"],
|
||||||
|
kind: "Hash",
|
||||||
|
version: 2,
|
||||||
|
systemKey: true,
|
||||||
|
},
|
||||||
|
container: explorer,
|
||||||
|
});
|
||||||
|
|
||||||
|
const collectionWithNonSystemPartitionKey = <ViewModels.Collection>(<unknown>{
|
||||||
|
id: ko.observable<string>("foo"),
|
||||||
|
database: {
|
||||||
|
id: ko.observable<string>("foo"),
|
||||||
|
},
|
||||||
|
partitionKey: {
|
||||||
|
paths: ["/foo"],
|
||||||
|
kind: "Hash",
|
||||||
|
version: 2,
|
||||||
|
systemKey: false,
|
||||||
|
},
|
||||||
|
container: explorer,
|
||||||
|
});
|
||||||
|
|
||||||
|
const mongoCollectionWithSystemPartitionKey = <ViewModels.Collection>(<unknown>{
|
||||||
|
id: ko.observable<string>("foo"),
|
||||||
|
database: {
|
||||||
|
id: ko.observable<string>("foo"),
|
||||||
|
},
|
||||||
|
partitionKey: {
|
||||||
|
paths: ["/foo"],
|
||||||
|
kind: "Hash",
|
||||||
|
version: 2,
|
||||||
|
systemKey: true,
|
||||||
|
},
|
||||||
|
container: mongoExplorer,
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be false for null or undefined collection", () => {
|
||||||
|
expect(showPartitionKey(undefined, false)).toBe(false);
|
||||||
|
expect(showPartitionKey(null, false)).toBe(false);
|
||||||
|
expect(showPartitionKey(undefined, true)).toBe(false);
|
||||||
|
expect(showPartitionKey(null, true)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be false for null or undefined partitionKey", () => {
|
||||||
|
expect(showPartitionKey(collectionWithoutPartitionKey, false)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be true for non-Mongo accounts with system partitionKey", () => {
|
||||||
|
expect(showPartitionKey(collectionWithSystemPartitionKey, false)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be false for Mongo accounts with system partitionKey", () => {
|
||||||
|
expect(showPartitionKey(mongoCollectionWithSystemPartitionKey, true)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be true for non-system partitionKey", () => {
|
||||||
|
expect(showPartitionKey(collectionWithNonSystemPartitionKey, false)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -375,6 +375,37 @@ const _loadNextPageInternal = (
|
||||||
return iterator.fetchNext().then((response) => response.resources);
|
return iterator.fetchNext().then((response) => response.resources);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Export for testing purposes
|
||||||
|
export const showPartitionKey = (collection: ViewModels.CollectionBase, isPreferredApiMongoDB: boolean) => {
|
||||||
|
if (!collection) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!collection.partitionKey) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (collection.partitionKey.systemKey && isPreferredApiMongoDB) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Export for testing purposes
|
||||||
|
export const buildQuery = (
|
||||||
|
isMongo: boolean,
|
||||||
|
filter: string,
|
||||||
|
partitionKeyProperties?: string[],
|
||||||
|
partitionKey?: DataModels.PartitionKey,
|
||||||
|
): string => {
|
||||||
|
if (isMongo) {
|
||||||
|
return filter || "{}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return QueryUtils.buildDocumentsQuery(filter, partitionKeyProperties, partitionKey);
|
||||||
|
};
|
||||||
|
|
||||||
const DocumentsTabComponent: React.FunctionComponent<{
|
const DocumentsTabComponent: React.FunctionComponent<{
|
||||||
isPreferredApiMongoDB: boolean;
|
isPreferredApiMongoDB: boolean;
|
||||||
documentIds: DocumentId[]; // TODO: this contains ko observables. We need to convert them to React state.
|
documentIds: DocumentId[]; // TODO: this contains ko observables. We need to convert them to React state.
|
||||||
|
@ -882,18 +913,11 @@ const DocumentsTabComponent: React.FunctionComponent<{
|
||||||
[isPreferredApiMongoDB],
|
[isPreferredApiMongoDB],
|
||||||
);
|
);
|
||||||
|
|
||||||
let buildQuery = useCallback(
|
|
||||||
(filter: string): string => {
|
|
||||||
return QueryUtils.buildDocumentsQuery(filter, partitionKeyProperties, partitionKey);
|
|
||||||
},
|
|
||||||
[partitionKeyProperties, partitionKey],
|
|
||||||
);
|
|
||||||
|
|
||||||
const createIterator = useCallback((): QueryIterator<ItemDefinition & Resource> => {
|
const createIterator = useCallback((): QueryIterator<ItemDefinition & Resource> => {
|
||||||
const _queryAbortController = new AbortController();
|
const _queryAbortController = new AbortController();
|
||||||
setQueryAbortController(_queryAbortController);
|
setQueryAbortController(_queryAbortController);
|
||||||
const filter: string = filterContent.trim();
|
const filter: string = filterContent.trim();
|
||||||
const query: string = buildQuery(filter);
|
const query: string = buildQuery(isPreferredApiMongoDB, filter, partitionKeyProperties, partitionKey);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const options: any = {};
|
const options: any = {};
|
||||||
// TODO: Property 'enableCrossPartitionQuery' does not exist on type 'FeedOptions'.
|
// TODO: Property 'enableCrossPartitionQuery' does not exist on type 'FeedOptions'.
|
||||||
|
@ -908,7 +932,7 @@ const DocumentsTabComponent: React.FunctionComponent<{
|
||||||
return isQueryCopilotSampleContainer
|
return isQueryCopilotSampleContainer
|
||||||
? querySampleDocuments(query, options)
|
? querySampleDocuments(query, options)
|
||||||
: queryDocuments(_collection.databaseId, _collection.id(), query, options);
|
: queryDocuments(_collection.databaseId, _collection.id(), query, options);
|
||||||
}, [filterContent, buildQuery, resourceTokenPartitionKey, isQueryCopilotSampleContainer, _collection]);
|
}, [isPreferredApiMongoDB, filterContent, resourceTokenPartitionKey, isQueryCopilotSampleContainer, _collection]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query first page of documents
|
* Query first page of documents
|
||||||
|
@ -1115,23 +1139,6 @@ const DocumentsTabComponent: React.FunctionComponent<{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: use this when generating column headers
|
|
||||||
const showPartitionKey = (() => {
|
|
||||||
if (!_collection) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_collection.partitionKey) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_collection.partitionKey.systemKey && isPreferredApiMongoDB) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
})();
|
|
||||||
|
|
||||||
const _isQueryCopilotSampleContainer =
|
const _isQueryCopilotSampleContainer =
|
||||||
_collection?.isSampleCollection &&
|
_collection?.isSampleCollection &&
|
||||||
_collection?.databaseId === QueryCopilotSampleDatabaseId &&
|
_collection?.databaseId === QueryCopilotSampleDatabaseId &&
|
||||||
|
@ -1259,7 +1266,7 @@ const DocumentsTabComponent: React.FunctionComponent<{
|
||||||
|
|
||||||
const columnHeaders = {
|
const columnHeaders = {
|
||||||
idHeader: isPreferredApiMongoDB ? "_id" : "id",
|
idHeader: isPreferredApiMongoDB ? "_id" : "id",
|
||||||
partitionKeyHeaders: (showPartitionKey && partitionKeyPropertyHeaders) || [],
|
partitionKeyHeaders: (showPartitionKey(_collection, isPreferredApiMongoDB) && partitionKeyPropertyHeaders) || [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSelectedRowsChange = (selectedRows: Set<TableRowId>) => {
|
const onSelectedRowsChange = (selectedRows: Set<TableRowId>) => {
|
||||||
|
@ -1549,15 +1556,11 @@ const DocumentsTabComponent: React.FunctionComponent<{
|
||||||
.finally(() => setIsExecuting(false));
|
.finally(() => setIsExecuting(false));
|
||||||
};
|
};
|
||||||
|
|
||||||
buildQuery = (filter: string): string => {
|
|
||||||
return filter || "{}";
|
|
||||||
};
|
|
||||||
|
|
||||||
loadNextPage = (): Promise<unknown> => {
|
loadNextPage = (): Promise<unknown> => {
|
||||||
setIsExecuting(true);
|
setIsExecuting(true);
|
||||||
onExecutionErrorChange(false);
|
onExecutionErrorChange(false);
|
||||||
const filter: string = filterContent.trim();
|
const filter: string = filterContent.trim();
|
||||||
const query: string = buildQuery(filter);
|
const query: string = buildQuery(isPreferredApiMongoDB, filter);
|
||||||
|
|
||||||
return MongoProxyClient.queryDocuments(
|
return MongoProxyClient.queryDocuments(
|
||||||
_collection.databaseId,
|
_collection.databaseId,
|
||||||
|
@ -1668,12 +1671,12 @@ const DocumentsTabComponent: React.FunctionComponent<{
|
||||||
<div
|
<div
|
||||||
className="tab-pane active"
|
className="tab-pane active"
|
||||||
/* data-bind="
|
/* data-bind="
|
||||||
setTemplateReady: true,
|
setTemplateReady: true,
|
||||||
attr:{
|
attr:{
|
||||||
id: tabId
|
id: tabId
|
||||||
},
|
},
|
||||||
visible: isActive"
|
visible: isActive"
|
||||||
*/
|
*/
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
style={{ display: "flex" }}
|
style={{ display: "flex" }}
|
||||||
>
|
>
|
||||||
|
@ -1766,9 +1769,9 @@ const DocumentsTabComponent: React.FunctionComponent<{
|
||||||
onClick={() => refreshDocumentsGrid(true)}
|
onClick={() => refreshDocumentsGrid(true)}
|
||||||
disabled={!applyFilterButton.enabled}
|
disabled={!applyFilterButton.enabled}
|
||||||
/* data-bind="
|
/* data-bind="
|
||||||
click: refreshDocumentsGrid.bind($data, true),
|
click: refreshDocumentsGrid.bind($data, true),
|
||||||
enable: applyFilterButton.enabled"
|
enable: applyFilterButton.enabled"
|
||||||
*/
|
*/
|
||||||
aria-label="Apply filter"
|
aria-label="Apply filter"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
|
@ -1781,9 +1784,9 @@ const DocumentsTabComponent: React.FunctionComponent<{
|
||||||
style={filterButtonStyle}
|
style={filterButtonStyle}
|
||||||
appearance="primary"
|
appearance="primary"
|
||||||
/* data-bind="
|
/* data-bind="
|
||||||
visible: !isPreferredApiMongoDB && isExecuting,
|
visible: !isPreferredApiMongoDB && isExecuting,
|
||||||
click: onAbortQueryClick"
|
click: onAbortQueryClick"
|
||||||
*/
|
*/
|
||||||
aria-label="Cancel Query"
|
aria-label="Cancel Query"
|
||||||
onClick={() => queryAbortController.abort()}
|
onClick={() => queryAbortController.abort()}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
|
|
Loading…
Reference in New Issue