Skip to content

Commit d83ca35

Browse files
authored
Merge pull request #2817 from github/koesie10/model-editor-row-tests
Add tests for model editor row and grid components
2 parents 8bc8ffe + 17e0291 commit d83ca35

14 files changed

Lines changed: 730 additions & 45 deletions

File tree

extensions/ql-vscode/src/model-editor/shared/in-progress-methods.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* A class that keeps track of which methods are in progress for each package.
33
*
4-
* This class is immutable and therefore is safe to be used in a react useState hook.
4+
* This class is immutable and therefore is safe to be used in a React useState hook.
55
*/
66
export class InProgressMethods {
77
// A map of in-progress method signatures for each package.
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
import * as React from "react";
2+
3+
import { Meta, StoryFn } from "@storybook/react";
4+
5+
import { Mode } from "../../model-editor/shared/mode";
6+
import { LibraryRow as LibraryRowComponent } from "../../view/model-editor/LibraryRow";
7+
import { CallClassification } from "../../model-editor/method";
8+
import { InProgressMethods } from "../../model-editor/shared/in-progress-methods";
9+
import { createMockExtensionPack } from "../../../test/factories/model-editor/extension-pack";
10+
11+
export default {
12+
title: "CodeQL Model Editor/Library Row",
13+
component: LibraryRowComponent,
14+
} as Meta<typeof LibraryRowComponent>;
15+
16+
const Template: StoryFn<typeof LibraryRowComponent> = (args) => (
17+
<LibraryRowComponent {...args} />
18+
);
19+
20+
export const LibraryRow = Template.bind({});
21+
LibraryRow.args = {
22+
title: "sql2o",
23+
libraryVersion: "1.6.0",
24+
methods: [
25+
{
26+
library: "sql2o",
27+
libraryVersion: "1.6.0",
28+
signature: "org.sql2o.Connection#createQuery(String)",
29+
packageName: "org.sql2o",
30+
typeName: "Connection",
31+
methodName: "createQuery",
32+
methodParameters: "(String)",
33+
supported: true,
34+
supportedType: "summary",
35+
usages: Array(10).fill({
36+
label: "createQuery(...)",
37+
url: {
38+
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
39+
startLine: 15,
40+
startColumn: 13,
41+
endLine: 15,
42+
endColumn: 56,
43+
},
44+
classification: CallClassification.Source,
45+
}),
46+
},
47+
{
48+
library: "sql2o",
49+
libraryVersion: "1.6.0",
50+
signature: "org.sql2o.Query#executeScalar(Class)",
51+
packageName: "org.sql2o",
52+
typeName: "Query",
53+
methodName: "executeScalar",
54+
methodParameters: "(Class)",
55+
supported: true,
56+
supportedType: "neutral",
57+
usages: Array(2).fill({
58+
label: "executeScalar(...)",
59+
url: {
60+
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
61+
startLine: 15,
62+
startColumn: 13,
63+
endLine: 15,
64+
endColumn: 85,
65+
},
66+
classification: CallClassification.Source,
67+
}),
68+
},
69+
{
70+
library: "sql2o",
71+
libraryVersion: "1.6.0",
72+
signature: "org.sql2o.Sql2o#open()",
73+
packageName: "org.sql2o",
74+
typeName: "Sql2o",
75+
methodName: "open",
76+
methodParameters: "()",
77+
supported: false,
78+
supportedType: "none",
79+
usages: Array(28).fill({
80+
label: "open(...)",
81+
url: {
82+
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
83+
startLine: 14,
84+
startColumn: 24,
85+
endLine: 14,
86+
endColumn: 35,
87+
},
88+
classification: CallClassification.Source,
89+
}),
90+
},
91+
{
92+
library: "sql2o",
93+
libraryVersion: "1.6.0",
94+
signature: "org.sql2o.Sql2o#Sql2o(String,String,String)",
95+
packageName: "org.sql2o",
96+
typeName: "Sql2o",
97+
methodName: "Sql2o",
98+
methodParameters: "(String,String,String)",
99+
supported: false,
100+
supportedType: "none",
101+
usages: Array(106).fill({
102+
label: "new Sql2o(...)",
103+
url: {
104+
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
105+
startLine: 10,
106+
startColumn: 33,
107+
endLine: 10,
108+
endColumn: 88,
109+
classification: CallClassification.Test,
110+
},
111+
}),
112+
},
113+
{
114+
library: "sql2o",
115+
libraryVersion: "1.6.0",
116+
signature: "org.sql2o.Sql2o#Sql2o(String)",
117+
packageName: "org.sql2o",
118+
typeName: "Sql2o",
119+
methodName: "Sql2o",
120+
methodParameters: "(String)",
121+
supported: false,
122+
supportedType: "none",
123+
usages: [
124+
...Array(4).fill({
125+
label: "new Sql2o(...)",
126+
url: {
127+
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
128+
startLine: 23,
129+
startColumn: 23,
130+
endLine: 23,
131+
endColumn: 36,
132+
},
133+
classification: CallClassification.Test,
134+
}),
135+
{
136+
label: "new Sql2o(...)",
137+
url: {
138+
uri: "file:/home/runner/work/sql2o-example/sql2o-example/build/generated/java/org/example/HelloControllerGenerated.java",
139+
startLine: 23,
140+
startColumn: 23,
141+
endLine: 23,
142+
endColumn: 36,
143+
},
144+
classification: CallClassification.Generated,
145+
},
146+
],
147+
},
148+
],
149+
modeledMethods: {
150+
"org.sql2o.Sql2o#Sql2o(String)": {
151+
type: "sink",
152+
input: "Argument[0]",
153+
output: "",
154+
kind: "jndi-injection",
155+
provenance: "df-generated",
156+
signature: "org.sql2o.Sql2o#Sql2o(String)",
157+
packageName: "org.sql2o",
158+
typeName: "Sql2o",
159+
methodName: "Sql2o",
160+
methodParameters: "(String)",
161+
},
162+
"org.sql2o.Connection#createQuery(String)": {
163+
type: "summary",
164+
input: "Argument[this]",
165+
output: "ReturnValue",
166+
kind: "taint",
167+
provenance: "df-manual",
168+
signature: "org.sql2o.Connection#createQuery(String)",
169+
packageName: "org.sql2o",
170+
typeName: "Connection",
171+
methodName: "createQuery",
172+
methodParameters: "(String)",
173+
},
174+
"org.sql2o.Sql2o#open()": {
175+
type: "summary",
176+
input: "Argument[this]",
177+
output: "ReturnValue",
178+
kind: "taint",
179+
provenance: "manual",
180+
signature: "org.sql2o.Sql2o#open()",
181+
packageName: "org.sql2o",
182+
typeName: "Sql2o",
183+
methodName: "open",
184+
methodParameters: "()",
185+
},
186+
"org.sql2o.Query#executeScalar(Class)": {
187+
type: "neutral",
188+
input: "",
189+
output: "",
190+
kind: "",
191+
provenance: "df-generated",
192+
signature: "org.sql2o.Query#executeScalar(Class)",
193+
packageName: "org.sql2o",
194+
typeName: "Query",
195+
methodName: "executeScalar",
196+
methodParameters: "(Class)",
197+
},
198+
"org.sql2o.Sql2o#Sql2o(String,String,String)": {
199+
type: "neutral",
200+
input: "",
201+
output: "",
202+
kind: "",
203+
provenance: "df-generated",
204+
signature: "org.sql2o.Sql2o#Sql2o(String,String,String)",
205+
packageName: "org.sql2o",
206+
typeName: "Sql2o",
207+
methodName: "Sql2o",
208+
methodParameters: "(String,String,String)",
209+
},
210+
},
211+
modifiedSignatures: new Set(["org.sql2o.Sql2o#Sql2o(String)"]),
212+
inProgressMethods: new InProgressMethods(),
213+
viewState: {
214+
extensionPack: createMockExtensionPack(),
215+
showFlowGeneration: true,
216+
showLlmButton: true,
217+
mode: Mode.Application,
218+
},
219+
hideModeledMethods: false,
220+
};

extensions/ql-vscode/src/view/common/Dropdown.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ type Props = {
2121
disabled?: boolean;
2222
disabledPlaceholder?: string;
2323
onChange?: (event: ChangeEvent<HTMLSelectElement>) => void;
24+
25+
"aria-label"?: string;
2426
};
2527

2628
/**
@@ -39,13 +41,15 @@ export function Dropdown({
3941
disabled,
4042
disabledPlaceholder,
4143
onChange,
44+
...props
4245
}: Props) {
4346
const disabledValue = disabledPlaceholder ?? DISABLED_VALUE;
4447
return (
4548
<StyledDropdown
4649
value={disabled ? disabledValue : value}
4750
disabled={disabled}
4851
onChange={onChange}
52+
{...props}
4953
>
5054
{disabled ? (
5155
<option key={disabledValue} value={disabledValue}>

extensions/ql-vscode/src/view/model-editor/KindInput.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,17 @@ type Props = {
99
value: ModeledMethod["kind"] | undefined;
1010
disabled?: boolean;
1111
onChange: (value: ModeledMethod["kind"]) => void;
12+
13+
"aria-label"?: string;
1214
};
1315

14-
export const KindInput = ({ kinds, value, disabled, onChange }: Props) => {
16+
export const KindInput = ({
17+
kinds,
18+
value,
19+
disabled,
20+
onChange,
21+
...props
22+
}: Props) => {
1523
const options = useMemo(
1624
() => kinds.map((kind) => ({ value: kind, label: kind })),
1725
[kinds],
@@ -42,6 +50,7 @@ export const KindInput = ({ kinds, value, disabled, onChange }: Props) => {
4250
options={options}
4351
disabled={disabled}
4452
onChange={handleInput}
53+
{...props}
4554
/>
4655
);
4756
};

extensions/ql-vscode/src/view/model-editor/LibraryRow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ const ButtonsContainer = styled.div`
6767
margin-right: 1rem;
6868
`;
6969

70-
type Props = {
70+
export type LibraryRowProps = {
7171
title: string;
7272
libraryVersion?: string;
7373
methods: Method[];
@@ -110,7 +110,7 @@ export const LibraryRow = ({
110110
onStopGenerateFromLlmClick,
111111
onGenerateFromSourceClick,
112112
onModelDependencyClick,
113-
}: Props) => {
113+
}: LibraryRowProps) => {
114114
const modeledPercentage = useMemo(() => {
115115
return calculateModeledPercentage(methods);
116116
}, [methods]);

extensions/ql-vscode/src/view/model-editor/MethodRow.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const modelTypeOptions: Array<{ value: ModeledMethodType; label: string }> = [
6060
{ value: "neutral", label: "Neutral" },
6161
];
6262

63-
type Props = {
63+
export type MethodRowProps = {
6464
method: Method;
6565
methodCanBeModeled: boolean;
6666
modeledMethod: ModeledMethod | undefined;
@@ -70,7 +70,7 @@ type Props = {
7070
onChange: (method: Method, modeledMethod: ModeledMethod) => void;
7171
};
7272

73-
export const MethodRow = (props: Props) => {
73+
export const MethodRow = (props: MethodRowProps) => {
7474
const { methodCanBeModeled } = props;
7575

7676
if (methodCanBeModeled) {
@@ -80,7 +80,7 @@ export const MethodRow = (props: Props) => {
8080
}
8181
};
8282

83-
function ModelableMethodRow(props: Props) {
83+
function ModelableMethodRow(props: MethodRowProps) {
8484
const { method, modeledMethod, methodIsUnsaved, mode, onChange } = props;
8585

8686
const argumentsList = useMemo(() => {
@@ -203,7 +203,7 @@ function ModelableMethodRow(props: Props) {
203203
const modelingStatus = getModelingStatus(modeledMethod, methodIsUnsaved);
204204

205205
return (
206-
<VSCodeDataGridRow>
206+
<VSCodeDataGridRow data-testid="modelable-method-row">
207207
<ApiOrMethodCell gridColumn={1}>
208208
<ModelingStatusIndicator status={modelingStatus} />
209209
<MethodClassifications method={method} />
@@ -239,6 +239,7 @@ function ModelableMethodRow(props: Props) {
239239
value={modeledMethod?.type ?? "none"}
240240
options={modelTypeOptions}
241241
onChange={handleTypeInput}
242+
aria-label="Model type"
242243
/>
243244
</VSCodeDataGridCell>
244245
<VSCodeDataGridCell gridColumn={3}>
@@ -247,6 +248,7 @@ function ModelableMethodRow(props: Props) {
247248
options={inputOptions}
248249
disabled={!showInputCell}
249250
onChange={handleInputInput}
251+
aria-label="Input"
250252
/>
251253
</VSCodeDataGridCell>
252254
<VSCodeDataGridCell gridColumn={4}>
@@ -255,6 +257,7 @@ function ModelableMethodRow(props: Props) {
255257
options={outputOptions}
256258
disabled={!showOutputCell}
257259
onChange={handleOutputInput}
260+
aria-label="Output"
258261
/>
259262
</VSCodeDataGridCell>
260263
<VSCodeDataGridCell gridColumn={5}>
@@ -263,6 +266,7 @@ function ModelableMethodRow(props: Props) {
263266
value={modeledMethod?.kind}
264267
disabled={!showKindCell}
265268
onChange={handleKindChange}
269+
aria-label="Kind"
266270
/>
267271
</VSCodeDataGridCell>
268272
</>
@@ -271,7 +275,7 @@ function ModelableMethodRow(props: Props) {
271275
);
272276
}
273277

274-
function UnmodelableMethodRow(props: Props) {
278+
function UnmodelableMethodRow(props: MethodRowProps) {
275279
const { method, mode } = props;
276280

277281
const jumpToUsage = useCallback(
@@ -280,7 +284,7 @@ function UnmodelableMethodRow(props: Props) {
280284
);
281285

282286
return (
283-
<VSCodeDataGridRow>
287+
<VSCodeDataGridRow data-testid="unmodelable-method-row">
284288
<ApiOrMethodCell gridColumn={1}>
285289
<ModelingStatusIndicator status="saved" />
286290
<MethodName {...props.method} />

0 commit comments

Comments
 (0)