Add story and tests for LibraryRow
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A class that keeps track of which methods are in progress for each package.
|
||||
*
|
||||
* This class is immutable and therefore is safe to be used in a react useState hook.
|
||||
* This class is immutable and therefore is safe to be used in a React useState hook.
|
||||
*/
|
||||
export class InProgressMethods {
|
||||
// A map of in-progress method signatures for each package.
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { Meta, StoryFn } from "@storybook/react";
|
||||
|
||||
import { Mode } from "../../model-editor/shared/mode";
|
||||
import { LibraryRow as LibraryRowComponent } from "../../view/model-editor/LibraryRow";
|
||||
import { CallClassification } from "../../model-editor/method";
|
||||
import { InProgressMethods } from "../../model-editor/shared/in-progress-methods";
|
||||
import { createMockExtensionPack } from "../../../test/factories/model-editor/extension-pack";
|
||||
|
||||
export default {
|
||||
title: "CodeQL Model Editor/Library Row",
|
||||
component: LibraryRowComponent,
|
||||
} as Meta<typeof LibraryRowComponent>;
|
||||
|
||||
const Template: StoryFn<typeof LibraryRowComponent> = (args) => (
|
||||
<LibraryRowComponent {...args} />
|
||||
);
|
||||
|
||||
export const LibraryRow = Template.bind({});
|
||||
LibraryRow.args = {
|
||||
title: "sql2o",
|
||||
libraryVersion: "1.6.0",
|
||||
methods: [
|
||||
{
|
||||
library: "sql2o",
|
||||
libraryVersion: "1.6.0",
|
||||
signature: "org.sql2o.Connection#createQuery(String)",
|
||||
packageName: "org.sql2o",
|
||||
typeName: "Connection",
|
||||
methodName: "createQuery",
|
||||
methodParameters: "(String)",
|
||||
supported: true,
|
||||
supportedType: "summary",
|
||||
usages: Array(10).fill({
|
||||
label: "createQuery(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 15,
|
||||
startColumn: 13,
|
||||
endLine: 15,
|
||||
endColumn: 56,
|
||||
},
|
||||
classification: CallClassification.Source,
|
||||
}),
|
||||
},
|
||||
{
|
||||
library: "sql2o",
|
||||
libraryVersion: "1.6.0",
|
||||
signature: "org.sql2o.Query#executeScalar(Class)",
|
||||
packageName: "org.sql2o",
|
||||
typeName: "Query",
|
||||
methodName: "executeScalar",
|
||||
methodParameters: "(Class)",
|
||||
supported: true,
|
||||
supportedType: "neutral",
|
||||
usages: Array(2).fill({
|
||||
label: "executeScalar(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 15,
|
||||
startColumn: 13,
|
||||
endLine: 15,
|
||||
endColumn: 85,
|
||||
},
|
||||
classification: CallClassification.Source,
|
||||
}),
|
||||
},
|
||||
{
|
||||
library: "sql2o",
|
||||
libraryVersion: "1.6.0",
|
||||
signature: "org.sql2o.Sql2o#open()",
|
||||
packageName: "org.sql2o",
|
||||
typeName: "Sql2o",
|
||||
methodName: "open",
|
||||
methodParameters: "()",
|
||||
supported: false,
|
||||
supportedType: "none",
|
||||
usages: Array(28).fill({
|
||||
label: "open(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 14,
|
||||
startColumn: 24,
|
||||
endLine: 14,
|
||||
endColumn: 35,
|
||||
},
|
||||
classification: CallClassification.Source,
|
||||
}),
|
||||
},
|
||||
{
|
||||
library: "sql2o",
|
||||
libraryVersion: "1.6.0",
|
||||
signature: "org.sql2o.Sql2o#Sql2o(String,String,String)",
|
||||
packageName: "org.sql2o",
|
||||
typeName: "Sql2o",
|
||||
methodName: "Sql2o",
|
||||
methodParameters: "(String,String,String)",
|
||||
supported: false,
|
||||
supportedType: "none",
|
||||
usages: Array(106).fill({
|
||||
label: "new Sql2o(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 10,
|
||||
startColumn: 33,
|
||||
endLine: 10,
|
||||
endColumn: 88,
|
||||
classification: CallClassification.Test,
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
library: "sql2o",
|
||||
libraryVersion: "1.6.0",
|
||||
signature: "org.sql2o.Sql2o#Sql2o(String)",
|
||||
packageName: "org.sql2o",
|
||||
typeName: "Sql2o",
|
||||
methodName: "Sql2o",
|
||||
methodParameters: "(String)",
|
||||
supported: false,
|
||||
supportedType: "none",
|
||||
usages: [
|
||||
...Array(4).fill({
|
||||
label: "new Sql2o(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 23,
|
||||
startColumn: 23,
|
||||
endLine: 23,
|
||||
endColumn: 36,
|
||||
},
|
||||
classification: CallClassification.Test,
|
||||
}),
|
||||
{
|
||||
label: "new Sql2o(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/build/generated/java/org/example/HelloControllerGenerated.java",
|
||||
startLine: 23,
|
||||
startColumn: 23,
|
||||
endLine: 23,
|
||||
endColumn: 36,
|
||||
},
|
||||
classification: CallClassification.Generated,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
modeledMethods: {
|
||||
"org.sql2o.Sql2o#Sql2o(String)": {
|
||||
type: "sink",
|
||||
input: "Argument[0]",
|
||||
output: "",
|
||||
kind: "jndi-injection",
|
||||
provenance: "df-generated",
|
||||
signature: "org.sql2o.Sql2o#Sql2o(String)",
|
||||
packageName: "org.sql2o",
|
||||
typeName: "Sql2o",
|
||||
methodName: "Sql2o",
|
||||
methodParameters: "(String)",
|
||||
},
|
||||
"org.sql2o.Connection#createQuery(String)": {
|
||||
type: "summary",
|
||||
input: "Argument[this]",
|
||||
output: "ReturnValue",
|
||||
kind: "taint",
|
||||
provenance: "df-manual",
|
||||
signature: "org.sql2o.Connection#createQuery(String)",
|
||||
packageName: "org.sql2o",
|
||||
typeName: "Connection",
|
||||
methodName: "createQuery",
|
||||
methodParameters: "(String)",
|
||||
},
|
||||
"org.sql2o.Sql2o#open()": {
|
||||
type: "summary",
|
||||
input: "Argument[this]",
|
||||
output: "ReturnValue",
|
||||
kind: "taint",
|
||||
provenance: "manual",
|
||||
signature: "org.sql2o.Sql2o#open()",
|
||||
packageName: "org.sql2o",
|
||||
typeName: "Sql2o",
|
||||
methodName: "open",
|
||||
methodParameters: "()",
|
||||
},
|
||||
"org.sql2o.Query#executeScalar(Class)": {
|
||||
type: "neutral",
|
||||
input: "",
|
||||
output: "",
|
||||
kind: "",
|
||||
provenance: "df-generated",
|
||||
signature: "org.sql2o.Query#executeScalar(Class)",
|
||||
packageName: "org.sql2o",
|
||||
typeName: "Query",
|
||||
methodName: "executeScalar",
|
||||
methodParameters: "(Class)",
|
||||
},
|
||||
"org.sql2o.Sql2o#Sql2o(String,String,String)": {
|
||||
type: "neutral",
|
||||
input: "",
|
||||
output: "",
|
||||
kind: "",
|
||||
provenance: "df-generated",
|
||||
signature: "org.sql2o.Sql2o#Sql2o(String,String,String)",
|
||||
packageName: "org.sql2o",
|
||||
typeName: "Sql2o",
|
||||
methodName: "Sql2o",
|
||||
methodParameters: "(String,String,String)",
|
||||
},
|
||||
},
|
||||
modifiedSignatures: new Set(["org.sql2o.Sql2o#Sql2o(String)"]),
|
||||
inProgressMethods: new InProgressMethods(),
|
||||
viewState: {
|
||||
extensionPack: createMockExtensionPack(),
|
||||
showFlowGeneration: true,
|
||||
showLlmButton: true,
|
||||
mode: Mode.Application,
|
||||
},
|
||||
hideModeledMethods: false,
|
||||
};
|
||||
@@ -67,7 +67,7 @@ const ButtonsContainer = styled.div`
|
||||
margin-right: 1rem;
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
export type LibraryRowProps = {
|
||||
title: string;
|
||||
libraryVersion?: string;
|
||||
methods: Method[];
|
||||
@@ -110,7 +110,7 @@ export const LibraryRow = ({
|
||||
onStopGenerateFromLlmClick,
|
||||
onGenerateFromSourceClick,
|
||||
onModelDependencyClick,
|
||||
}: Props) => {
|
||||
}: LibraryRowProps) => {
|
||||
const modeledPercentage = useMemo(() => {
|
||||
return calculateModeledPercentage(methods);
|
||||
}, [methods]);
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
import * as React from "react";
|
||||
import { render as reactRender, screen } from "@testing-library/react";
|
||||
import { createMethod } from "../../../../test/factories/data-extension/method-factories";
|
||||
import { LibraryRow, LibraryRowProps } from "../LibraryRow";
|
||||
import { InProgressMethods } from "../../../model-editor/shared/in-progress-methods";
|
||||
import { createMockExtensionPack } from "../../../../test/factories/model-editor/extension-pack";
|
||||
import { Mode } from "../../../model-editor/shared/mode";
|
||||
import { ModelEditorViewState } from "../../../model-editor/shared/view-state";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
describe(LibraryRow.name, () => {
|
||||
const method = createMethod();
|
||||
const onChange = jest.fn();
|
||||
const onSaveModelClick = jest.fn();
|
||||
const onGenerateFromLlmClick = jest.fn();
|
||||
const onStopGenerateFromLlmClick = jest.fn();
|
||||
const onModelDependencyClick = jest.fn();
|
||||
|
||||
const viewState: ModelEditorViewState = {
|
||||
mode: Mode.Application,
|
||||
showFlowGeneration: false,
|
||||
showLlmButton: false,
|
||||
extensionPack: createMockExtensionPack(),
|
||||
};
|
||||
|
||||
const render = (props: Partial<LibraryRowProps> = {}) =>
|
||||
reactRender(
|
||||
<LibraryRow
|
||||
title="sql2o"
|
||||
libraryVersion="1.6.0"
|
||||
methods={[method]}
|
||||
modeledMethods={{
|
||||
[method.signature]: {
|
||||
...method,
|
||||
type: "sink",
|
||||
input: "Argument[0]",
|
||||
output: "",
|
||||
kind: "jndi-injection",
|
||||
provenance: "df-generated",
|
||||
},
|
||||
}}
|
||||
modifiedSignatures={new Set([method.signature])}
|
||||
inProgressMethods={new InProgressMethods()}
|
||||
viewState={viewState}
|
||||
hideModeledMethods={false}
|
||||
onChange={onChange}
|
||||
onSaveModelClick={onSaveModelClick}
|
||||
onGenerateFromLlmClick={onGenerateFromLlmClick}
|
||||
onStopGenerateFromLlmClick={onStopGenerateFromLlmClick}
|
||||
onGenerateFromSourceClick={jest.fn()}
|
||||
onModelDependencyClick={onModelDependencyClick}
|
||||
{...props}
|
||||
/>,
|
||||
);
|
||||
|
||||
it("renders the row", () => {
|
||||
render();
|
||||
|
||||
expect(screen.queryByText("sql2o@1.6.0")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Model from source")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Model with AI")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Model dependency")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders the row when flow generation is enabled", () => {
|
||||
render({
|
||||
viewState: {
|
||||
...viewState,
|
||||
showFlowGeneration: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(screen.queryByText("Model from source")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Model with AI")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Model dependency")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders the row when LLM is enabled", () => {
|
||||
render({
|
||||
viewState: {
|
||||
...viewState,
|
||||
showLlmButton: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(screen.queryByText("Model from source")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Model with AI")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Model dependency")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders the row when flow generation and LLM are enabled", () => {
|
||||
render({
|
||||
viewState: {
|
||||
...viewState,
|
||||
showFlowGeneration: true,
|
||||
showLlmButton: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(screen.queryByText("Model from source")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Model with AI")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Model dependency")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("can expand the row", async () => {
|
||||
render();
|
||||
|
||||
expect(screen.queryByText("Save")).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.click(
|
||||
screen.getByRole("button", {
|
||||
name: /sql2o@1.6.0/,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(screen.getByText("Save")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
import { ExtensionPack } from "../../../src/model-editor/shared/extension-pack";
|
||||
import { join } from "path";
|
||||
|
||||
export function createMockExtensionPack({
|
||||
path = "/path/to/extension-pack",
|
||||
...data
|
||||
}: Partial<ExtensionPack> = {}): ExtensionPack {
|
||||
return {
|
||||
path,
|
||||
yamlPath: join(path, "codeql-pack.yml"),
|
||||
name: "sql2o",
|
||||
version: "0.0.0",
|
||||
language: "java",
|
||||
extensionTargets: {
|
||||
"codeql/java-all": "*",
|
||||
},
|
||||
dataExtensions: ["models/**/*.yml"],
|
||||
...data,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user