Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stu-346 placeholder test #1159

Merged
merged 28 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
104497b
[stu-346-placeholder-test] feat: new Test type: "Placeholder"
LatentDream Apr 17, 2024
97b030c
[stu-346-placeholder-test] feat: Change the path and test type of pla…
LatentDream Apr 17, 2024
8d88709
chore: all test step can be edited
LatentDream Apr 17, 2024
4dc4795
Merge branch 'main' into stu-346-placeholder-test
LatentDream Apr 17, 2024
7180c82
fix: css overflow
LatentDream Apr 17, 2024
79a706d
chore: display error as toast
LatentDream Apr 17, 2024
1c11d96
formatting
LatentDream Apr 17, 2024
fde3542
fix: Eslint
LatentDream Apr 17, 2024
68361b0
chore: python formatting
LatentDream Apr 17, 2024
07221df
Merge branch 'main' into stu-346-placeholder-test
39bytes Apr 17, 2024
be7f5ca
Update src/renderer/routes/test_sequencer_panel/components/modals/Cha…
LatentDream Apr 17, 2024
e22897d
Merge branch 'main' into stu-346-placeholder-test
LatentDream Apr 18, 2024
c8e8a14
chore: EsLint fix
LatentDream Apr 20, 2024
87e9d12
chore: removing dead code
LatentDream Apr 20, 2024
702512e
chore: fix Eslint
LatentDream Apr 20, 2024
781b9fd
chore: Eslint fix
LatentDream Apr 20, 2024
9cbcd8c
chore: formatting
LatentDream Apr 20, 2024
c1f0de1
fix: new return Result when test are duplicated doesn't close Modal. …
LatentDream Apr 20, 2024
747c2a1
[stu-346-placeholder-test] chore: placeholder test => Using form
LatentDream Apr 21, 2024
c776372
[stu-346-placeholder-test] chore: Using object as input for better cl…
LatentDream Apr 21, 2024
407976f
chore: formatting
LatentDream Apr 21, 2024
6a3ac11
Merge branch 'main' into stu-346-placeholder-test
LatentDream Apr 21, 2024
55ac040
Merge branch 'main' into stu-346-placeholder-test
LatentDream Apr 22, 2024
875ac9c
chore: pruned useless abstraction
LatentDream Apr 24, 2024
cd140f6
Merge branch 'main' into stu-346-placeholder-test
39bytes Apr 25, 2024
cf54e4e
Merge branch 'main' into stu-346-placeholder-test
LatentDream Apr 25, 2024
7b2a57c
build: remove duplicated div
LatentDream Apr 25, 2024
729d2d0
chore: formatting
LatentDream Apr 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions captain/models/test_sequencer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class TestTypes(StrEnum):
python = "python"
flojoy = "flojoy"
matlab = "matlab"
placeholder = "placeholder"


class StatusTypes(StrEnum):
Expand Down
22 changes: 22 additions & 0 deletions captain/utils/test_sequencer/run_test_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,27 @@ def _run_pytest(node: TestNode) -> Extract:
)


@_with_stream_test_result
def _run_placeholder(node: TestNode) -> Extract:
"""
@params file_path: path to the file
@returns:
bool: result of the test
float: time taken to execute the test
str: error message if any
"""
return (
lambda _: None,
TestResult(
node,
False,
0,
"Placeholder test not implemented",
utcnow_str(),
),
)


def _eval_condition(
result_dict: dict[str, TestResult], condition: str, identifiers: set[str]
):
Expand Down Expand Up @@ -244,6 +265,7 @@ def get_next_children_from_context(context: Context):
{
TestTypes.python: (None, _run_python),
TestTypes.pytest: (None, _run_pytest),
TestTypes.placeholder: (None, _run_placeholder),
},
),
"conditional": (
Expand Down
19 changes: 1 addition & 18 deletions playwright-test/13_create_test_sequence.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,8 @@ test.describe("Create a test sequence", () => {
await expect(window.getByTestId(Selectors.newDropdown)).toBeEnabled({
timeout: 15000,
});
await window.getByTestId(Selectors.newDropdown).click();
await window.getByTestId(Selectors.importTestBtn).click();

// Select the fixture file
const customTestFile = join(__dirname, "fixtures/custom-sequences/test.py");
await app.evaluate(async ({ dialog }, customTestFile) => {
dialog.showOpenDialog = () =>
Promise.resolve({ filePaths: [customTestFile], canceled: false });
}, customTestFile);

// Click on Pytest test to open modal
await window.getByTestId(Selectors.pytestBtn).click();

// Expect test to be loaded
await expect(
window.locator("div", { hasText: "test_one" }).first(),
).toBeVisible();

// Ctrl/meta + p key shortcut to save the sequence
// Ctrl/meta + s key shortcut to save the sequence
if (process.platform === "darwin") {
await window.keyboard.press("Meta+s");
} else {
Expand Down
58 changes: 52 additions & 6 deletions src/renderer/hooks/useTestImport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ function parseDiscoverContainer(
settings: ImportTestSettings,
) {
return map(data.response, (container) => {
const new_elem = createNewTest(
container.testName,
container.path,
settings.importType,
);
const new_elem = createNewTest({
name: container.testName,
path: container.path,
type: settings.importType,
});
return new_elem;
});
}

export const useTestImport = () => {
export const useDiscoverAndImportTests = () => {
const { addNewElems } = useDisplayedSequenceState();
const { openErrorModal } = useSequencerModalStore();

Expand Down Expand Up @@ -125,3 +125,49 @@ export const useTestImport = () => {

return openFilePicker;
};

export const useDiscoverPytestElements = () => {
const handleUserDepInstall = useCallback(async (depName: string) => {
const promise = () => window.api.poetryInstallDepUserGroup(depName);
toast.promise(promise, {
loading: `Installing ${depName}...`,
success: () => {
return `${depName} has been added.`;
},
error:
"Could not install the library. Please consult the Dependency Manager in the settings.",
});
}, []);

async function getTests(path: string) {
const res = await discoverPytest(path, false);
if (res.isErr()) {
return err(res.error);
}
const data = res.value;
if (data.error) {
return err(Error(data.error));
}
for (const lib of data.missingLibraries) {
toast.error(`Missing Python Library: ${lib}`, {
action: {
label: "Install",
onClick: () => {
handleUserDepInstall(lib);
},
},
});
return err(Error("Please retry after installing the missing libraries."));
}
const newElems = parseDiscoverContainer(data, {
importAsOneRef: false,
importType: "pytest",
});
if (newElems.length === 0) {
return err(Error("No tests were found in the specified file."));
}
return ok(newElems);
}

return getTests;
};
56 changes: 31 additions & 25 deletions src/renderer/hooks/useTestSequencerState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import useWithPermission from "@/renderer/hooks/useWithPermission";
import { useSequencerStore } from "@/renderer/stores/sequencer";
import { useShallow } from "zustand/react/shallow";
import { v4 as uuidv4 } from "uuid";
import { Err, Ok, Result } from "neverthrow";
import { Err, Result, err, ok } from "neverthrow";
import { verifyElementCompatibleWithSequence } from "@/renderer/routes/test_sequencer_panel/utils/SequenceHandler";
import { toast } from "sonner";
import { SendJsonMessage } from "react-use-websocket/dist/lib/types";
Expand All @@ -28,6 +28,7 @@ import {
testSequenceStopRequest,
} from "../routes/test_sequencer_panel/models/models";
import { produce } from "immer";
import { z } from "zod";

// sync this with the definition of setElems
export type SetElemsFn = {
Expand Down Expand Up @@ -98,34 +99,38 @@ const validateElements = (
return !validators.some((validator) => !validator(elems), validators);
};

export function createNewTest(
name: string,
path: string,
export const NewTest = z.object({
name: z.string(),
path: z.string(),
type: TestType,
exportToCloud?: boolean,
id?: string,
groupId?: string,
minValue?: number,
maxValue?: number,
unit?: string,
): Test {
exportToCloud: z.boolean().optional(),
id: z.string().optional(),
groupId: z.string().optional(),
minValue: z.number().optional(),
maxValue: z.number().optional(),
unit: z.string().optional(),
});

export type NewTest = z.infer<typeof NewTest>;

export function createNewTest(test: NewTest): Test {
const newTest: Test = {
type: "test",
id: id || uuidv4(),
groupId: groupId || uuidv4(),
path: path,
testName: name,
id: test.id || uuidv4(),
groupId: test.groupId || uuidv4(),
path: test.path,
testName: test.name,
runInParallel: false,
testType: type,
testType: test.type,
status: "pending",
completionTime: undefined,
error: null,
isSavedToCloud: false,
exportToCloud: exportToCloud === undefined ? true : exportToCloud,
exportToCloud: test.exportToCloud === undefined ? true : test.exportToCloud,
createdAt: new Date().toISOString(),
minValue: minValue,
maxValue: maxValue,
unit: unit,
minValue: test.minValue,
maxValue: test.maxValue,
unit: test.unit,
};
return newTest;
}
Expand Down Expand Up @@ -172,7 +177,7 @@ export function useDisplayedSequenceState() {
p:
| TestSequenceElement[]
| ((elems: TestSequenceElement[]) => TestSequenceElement[]),
) {
): Result<void, Error> {
let candidateElems: TestSequenceElement[];

// handle overloads
Expand All @@ -189,7 +194,7 @@ export function useDisplayedSequenceState() {
);
if (!res) {
console.error("Validation failed");
return;
return err(new Error("Validation failed"));
}

// PASS
Expand All @@ -198,13 +203,14 @@ export function useDisplayedSequenceState() {

// creates tree to send to backend
setTree(createTestSequenceTree(candidateElems));
return ok(undefined);
}

const setElemsWithPermissions = withPermissionCheck(setElems);

async function AddNewElems(
newElems: TestSequenceElement[],
): Promise<Result<null, Error>> {
): Promise<Result<void, Error>> {
// Validate with project
if (project !== null) {
const result = await verifyElementCompatibleWithSequence(
Expand All @@ -216,8 +222,8 @@ export function useDisplayedSequenceState() {
}
}
// Add new elements
setElems((elems) => [...elems, ...newElems]);
return new Ok(null);
const result = setElems((elems) => [...elems, ...newElems]);
return result;
}

const addNewElemsWithPermissions = withPermissionCheck(AddNewElems);
Expand Down
32 changes: 21 additions & 11 deletions src/renderer/routes/test_sequencer_panel/components/DesignBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
HoverCardTrigger,
} from "@/renderer/components/ui/hover-card";
import _ from "lodash";
import { CreatePlaceholderTestModal } from "./modals/CreatePlaceholderTestModal";
import { SequencerGalleryModal } from "./modals/SequencerGalleryModal";

export function DesignBar() {
Expand Down Expand Up @@ -64,10 +65,18 @@ export function DesignBar() {
}, [elems, sequences, cycleRuns]);

const [displayTotal, setDisplayTotal] = useState(false);
const [
isCreatePlaceholderTestModalOpen,
setIsCreatePlaceholderTestModalOpen,
] = useState(false);
const [isGalleryOpen, setIsGalleryOpen] = useState(false);

return (
<div className=" border-b" style={{ height: ACTIONS_HEIGHT }}>
<CreatePlaceholderTestModal
isModalOpen={isCreatePlaceholderTestModalOpen}
setModalOpen={setIsCreatePlaceholderTestModalOpen}
/>
<SequencerGalleryModal
isGalleryOpen={isGalleryOpen}
setIsGalleryOpen={setIsGalleryOpen}
Expand Down Expand Up @@ -100,6 +109,18 @@ export function DesignBar() {
/>
New Test
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => {
setIsCreatePlaceholderTestModalOpen(true);
}}
data-testid="placeholder-test-button"
>
<FlaskConical
size={16}
className="mr-2 stroke-muted-foreground"
/>
New Placeholder
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => {
setIsCreateProjectModalOpen(true);
Expand Down Expand Up @@ -136,17 +157,6 @@ export function DesignBar() {
<div className="grow" />
</>
)}
{/* Comming soon
<Button
data-testid="add-text-button"
className="gap-2"
variant="ghost"
disabled={true}
>
<HardDriveDownload size={20} className="stroke-muted-foreground" />
Load Test Profile From Cloud
</Button>
*/}

{sequences.length <= 1 ? (
<code className="inline-flex items-center justify-center p-3 text-sm text-muted-foreground">
Expand Down
Loading
Loading