📝 (index.tsx): add convertTestName function to utils.ts to convert card names to test ids
📝 (index.tsx): add `data-testid` attribute to Card component to improve testability 📝 (index.tsx): remove unnecessary parentheses in ternary operator 📝 (index.tsx): remove unnecessary `undefined` in ternary operator 📝 (index.tsx): add `data-testid` attribute to delete button to improve testability 📝 (index.tsx): add `convertTestName` function to utils.ts to convert card names to test ids 📝 (utils.ts): add `convertTestName` function to convert card names to test ids 📝 (deleteComponentFlows.spec.ts): add end-to-end tests for deleting a flow and a component
This commit is contained in:
parent
8121151a8f
commit
5ef34e48f3
3 changed files with 94 additions and 43 deletions
|
|
@ -8,7 +8,7 @@ import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
|||
import { useStoreStore } from "../../stores/storeStore";
|
||||
import { storeComponent } from "../../types/store";
|
||||
import cloneFLowWithParent from "../../utils/storeUtils";
|
||||
import { cn } from "../../utils/utils";
|
||||
import { cn, convertTestName } from "../../utils/utils";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import ShadTooltip from "../shadTooltipComponent";
|
||||
import { Badge } from "../ui/badge";
|
||||
|
|
@ -48,11 +48,11 @@ export default function CollectionCardComponent({
|
|||
const [loading, setLoading] = useState(false);
|
||||
const [loadingLike, setLoadingLike] = useState(false);
|
||||
const [liked_by_user, setLiked_by_user] = useState(
|
||||
data?.liked_by_user ?? false
|
||||
data?.liked_by_user ?? false,
|
||||
);
|
||||
const [likes_count, setLikes_count] = useState(data?.liked_by_count ?? 0);
|
||||
const [downloads_count, setDownloads_count] = useState(
|
||||
data?.downloads_count ?? 0
|
||||
data?.downloads_count ?? 0,
|
||||
);
|
||||
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
|
||||
|
|
@ -63,7 +63,7 @@ export default function CollectionCardComponent({
|
|||
const [openPlayground, setOpenPlayground] = useState(false);
|
||||
const [openDelete, setOpenDelete] = useState(false);
|
||||
const setCurrentFlowId = useFlowsManagerStore(
|
||||
(state) => state.setCurrentFlowId
|
||||
(state) => state.setCurrentFlowId,
|
||||
);
|
||||
const [loadingPlayground, setLoadingPlayground] = useState(false);
|
||||
|
||||
|
|
@ -106,16 +106,18 @@ export default function CollectionCardComponent({
|
|||
addFlow(true, newFlow)
|
||||
.then((id) => {
|
||||
setSuccessData({
|
||||
title: `${name} ${isStore ? "Downloaded" : "Installed"
|
||||
} Successfully.`,
|
||||
title: `${name} ${
|
||||
isStore ? "Downloaded" : "Installed"
|
||||
} Successfully.`,
|
||||
});
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
setLoading(false);
|
||||
setErrorData({
|
||||
title: `Error ${isStore ? "downloading" : "installing"
|
||||
} the ${name}`,
|
||||
title: `Error ${
|
||||
isStore ? "downloading" : "installing"
|
||||
} the ${name}`,
|
||||
list: [error["response"]["data"]["detail"]],
|
||||
});
|
||||
});
|
||||
|
|
@ -167,10 +169,11 @@ export default function CollectionCardComponent({
|
|||
return (
|
||||
<>
|
||||
<Card
|
||||
data-testid={`card-${convertTestName(data.name)}`}
|
||||
className={cn(
|
||||
"group relative flex min-h-[11rem] flex-col justify-between overflow-hidden transition-all hover:shadow-md",
|
||||
disabled ? "pointer-events-none opacity-50" : "",
|
||||
onClick ? "cursor-pointer" : ""
|
||||
onClick ? "cursor-pointer" : "",
|
||||
)}
|
||||
onClick={onClick}
|
||||
>
|
||||
|
|
@ -183,7 +186,7 @@ export default function CollectionCardComponent({
|
|||
"flex-shrink-0",
|
||||
data.is_component
|
||||
? "mx-0.5 h-6 w-6 text-component-icon"
|
||||
: "h-7 w-7 flex-shrink-0 text-flow-icon"
|
||||
: "h-7 w-7 flex-shrink-0 text-flow-icon",
|
||||
)}
|
||||
name={data.is_component ? "ToyBrick" : "Group"}
|
||||
/>
|
||||
|
|
@ -235,17 +238,17 @@ export default function CollectionCardComponent({
|
|||
)}
|
||||
|
||||
{onDelete && data?.metadata === undefined && (
|
||||
<button onClick={(e) => {
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setOpenDelete(true);
|
||||
}}
|
||||
>
|
||||
|
||||
<IconComponent
|
||||
name="Trash2"
|
||||
className="h-5 w-5 text-primary opacity-0 transition-all hover:text-destructive group-hover:opacity-100"
|
||||
/>
|
||||
</button>
|
||||
>
|
||||
<IconComponent
|
||||
name="Trash2"
|
||||
className="h-5 w-5 text-primary opacity-0 transition-all hover:text-destructive group-hover:opacity-100"
|
||||
/>
|
||||
</button>
|
||||
)}
|
||||
</CardTitle>
|
||||
</div>
|
||||
|
|
@ -326,9 +329,7 @@ export default function CollectionCardComponent({
|
|||
)}
|
||||
Playground
|
||||
</Button>
|
||||
) : (
|
||||
undefined
|
||||
)}
|
||||
) : undefined}
|
||||
{data.liked_by_count != undefined && (
|
||||
<div className="flex gap-0.5">
|
||||
{onDelete && data?.metadata !== undefined ? (
|
||||
|
|
@ -351,10 +352,11 @@ export default function CollectionCardComponent({
|
|||
}
|
||||
>
|
||||
<IconComponent
|
||||
data-testid={`delete-${convertTestName(data.name)}`}
|
||||
name="Trash2"
|
||||
className={cn(
|
||||
"h-5 w-5",
|
||||
!authorized ? " text-ring" : ""
|
||||
!authorized ? " text-ring" : "",
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
|
|
@ -389,7 +391,7 @@ export default function CollectionCardComponent({
|
|||
liked_by_user
|
||||
? "fill-destructive stroke-destructive"
|
||||
: "",
|
||||
!authorized ? " text-ring" : ""
|
||||
!authorized ? " text-ring" : "",
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
|
|
@ -427,7 +429,7 @@ export default function CollectionCardComponent({
|
|||
}
|
||||
className={cn(
|
||||
loading ? "h-5 w-5 animate-spin" : "h-5 w-5",
|
||||
!authorized ? " text-ring" : ""
|
||||
!authorized ? " text-ring" : "",
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
|
|
@ -490,13 +492,12 @@ export default function CollectionCardComponent({
|
|||
open={openDelete}
|
||||
setOpen={setOpenDelete}
|
||||
onConfirm={() => {
|
||||
if(onDelete) onDelete();
|
||||
if (onDelete) onDelete();
|
||||
}}
|
||||
>
|
||||
<></>
|
||||
</DeleteConfirmationModal>
|
||||
)
|
||||
}
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ export function normalCaseToSnakeCase(str: string): string {
|
|||
|
||||
export function toTitleCase(
|
||||
str: string | undefined,
|
||||
isNodeField?: boolean
|
||||
isNodeField?: boolean,
|
||||
): string {
|
||||
if (!str) return "";
|
||||
let result = str
|
||||
|
|
@ -70,7 +70,7 @@ export function toTitleCase(
|
|||
if (isNodeField) return word;
|
||||
if (index === 0) {
|
||||
return checkUpperWords(
|
||||
word[0].toUpperCase() + word.slice(1).toLowerCase()
|
||||
word[0].toUpperCase() + word.slice(1).toLowerCase(),
|
||||
);
|
||||
}
|
||||
return checkUpperWords(word.toLowerCase());
|
||||
|
|
@ -83,7 +83,7 @@ export function toTitleCase(
|
|||
if (isNodeField) return word;
|
||||
if (index === 0) {
|
||||
return checkUpperWords(
|
||||
word[0].toUpperCase() + word.slice(1).toLowerCase()
|
||||
word[0].toUpperCase() + word.slice(1).toLowerCase(),
|
||||
);
|
||||
}
|
||||
return checkUpperWords(word.toLowerCase());
|
||||
|
|
@ -93,8 +93,8 @@ export function toTitleCase(
|
|||
|
||||
export function getUnavailableFields(variables: {
|
||||
[key: string]: { default_fields?: string[] };
|
||||
}): {[name: string]: string} {
|
||||
const unVariables:{[name: string]: string} = {};
|
||||
}): { [name: string]: string } {
|
||||
const unVariables: { [name: string]: string } = {};
|
||||
Object.keys(variables).forEach((key) => {
|
||||
if (variables[key].default_fields) {
|
||||
variables[key].default_fields!.forEach((field) => {
|
||||
|
|
@ -123,7 +123,7 @@ export function groupByFamily(
|
|||
data: APIDataType,
|
||||
baseClasses: string,
|
||||
left: boolean,
|
||||
flow?: NodeType[]
|
||||
flow?: NodeType[],
|
||||
): groupedObjType[] {
|
||||
const baseClassesSet = new Set(baseClasses.split("\n"));
|
||||
let arrOfPossibleInputs: Array<{
|
||||
|
|
@ -149,7 +149,7 @@ export function groupByFamily(
|
|||
baseClassesSet.has(template.type)) ||
|
||||
(template.input_types &&
|
||||
template.input_types.some((inputType) =>
|
||||
baseClassesSet.has(inputType)
|
||||
baseClassesSet.has(inputType),
|
||||
)))
|
||||
);
|
||||
};
|
||||
|
|
@ -169,7 +169,7 @@ export function groupByFamily(
|
|||
hasBaseClassInBaseClasses:
|
||||
foundNode?.hasBaseClassInBaseClasses ||
|
||||
nodeData.node!.base_classes.some((baseClass) =>
|
||||
baseClassesSet.has(baseClass)
|
||||
baseClassesSet.has(baseClass),
|
||||
), //seta como anterior ou verifica se o node tem base class
|
||||
displayName: nodeData.node?.display_name,
|
||||
});
|
||||
|
|
@ -186,10 +186,10 @@ export function groupByFamily(
|
|||
if (!foundNode) {
|
||||
foundNode = {
|
||||
hasBaseClassInTemplate: Object.values(node!.template).some(
|
||||
checkBaseClass
|
||||
checkBaseClass,
|
||||
),
|
||||
hasBaseClassInBaseClasses: node!.base_classes.some((baseClass) =>
|
||||
baseClassesSet.has(baseClass)
|
||||
baseClassesSet.has(baseClass),
|
||||
),
|
||||
displayName: node?.display_name,
|
||||
};
|
||||
|
|
@ -246,7 +246,7 @@ export function getRandomDescription(): string {
|
|||
export function getRandomName(
|
||||
retry: number = 0,
|
||||
noSpace: boolean = false,
|
||||
maxRetries: number = 3
|
||||
maxRetries: number = 3,
|
||||
): string {
|
||||
const left: string[] = ADJECTIVES;
|
||||
const right: string[] = NOUNS;
|
||||
|
|
@ -325,7 +325,7 @@ export function getChatInputField(flowState?: FlowState) {
|
|||
export function getPythonApiCode(
|
||||
flow: FlowType,
|
||||
isAuth: boolean,
|
||||
tweak?: any[]
|
||||
tweak?: any[],
|
||||
): string {
|
||||
const flowId = flow.id;
|
||||
|
||||
|
|
@ -393,7 +393,7 @@ print(run_flow(message=message, flow_id=FLOW_ID, tweaks=TWEAKS${
|
|||
export function getCurlCode(
|
||||
flow: FlowType,
|
||||
isAuth: boolean,
|
||||
tweak?: any[]
|
||||
tweak?: any[],
|
||||
): string {
|
||||
const flowId = flow.id;
|
||||
const tweaks = buildTweaks(flow);
|
||||
|
|
@ -463,7 +463,7 @@ result = run_flow_from_json(flow="${flowName}.json",
|
|||
export function getWidgetCode(
|
||||
flow: FlowType,
|
||||
isAuth: boolean,
|
||||
flowState?: FlowState
|
||||
flowState?: FlowState,
|
||||
): string {
|
||||
const flowId = flow.id;
|
||||
const flowName = flow.name;
|
||||
|
|
@ -593,7 +593,7 @@ export function checkLocalStorageKey(key: string): boolean {
|
|||
|
||||
export function IncrementObjectKey(
|
||||
object: object,
|
||||
key: string
|
||||
key: string,
|
||||
): { newKey: string; increment: number } {
|
||||
let count = 1;
|
||||
const type = removeCountFromString(key);
|
||||
|
|
@ -665,7 +665,7 @@ export function getSetFromObject(obj: object, key?: string): Set<string> {
|
|||
|
||||
export function getFieldTitle(
|
||||
template: APITemplateType,
|
||||
templateField: string
|
||||
templateField: string,
|
||||
): string {
|
||||
return template[templateField].display_name
|
||||
? template[templateField].display_name!
|
||||
|
|
@ -715,3 +715,7 @@ export function freezeObject(obj: any) {
|
|||
if (!obj) return obj;
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
|
||||
export function convertTestName(name: string): string {
|
||||
return name.replace(/ /g, "-").toLowerCase();
|
||||
}
|
||||
|
|
|
|||
46
src/frontend/tests/end-to-end/deleteComponentFlows.spec.ts
Normal file
46
src/frontend/tests/end-to-end/deleteComponentFlows.spec.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import { test } from "@playwright/test";
|
||||
|
||||
test("shoud delete a flow", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByText("Store").nth(0).click();
|
||||
await page.getByTestId("install-Website Content QA").click();
|
||||
await page.waitForTimeout(5000);
|
||||
await page.getByText("My Collection").nth(0).click();
|
||||
await page.getByText("Website Content QA").first().isVisible();
|
||||
await page
|
||||
.getByTestId("card-website-content-qa")
|
||||
.first()
|
||||
.hover()
|
||||
.then(async () => {
|
||||
await page.getByTestId("icon-Trash2").first().click();
|
||||
await page.waitForTimeout(2000);
|
||||
});
|
||||
await page.getByText("Confirm deletion of component?").isVisible();
|
||||
await page.getByText("Delete").nth(1).click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByText("Successfully").first().isVisible();
|
||||
});
|
||||
|
||||
test("shoud delete a component", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByText("Store").nth(0).click();
|
||||
await page.getByTestId("install-Basic RAG").click();
|
||||
await page.waitForTimeout(5000);
|
||||
await page.getByText("My Collection").nth(0).click();
|
||||
await page.getByText("Components").first().click();
|
||||
await page.getByText("Basic RAG").first().isVisible();
|
||||
await page
|
||||
.getByTestId("card-basic-rag")
|
||||
.first()
|
||||
.hover()
|
||||
.then(async () => {
|
||||
await page.getByTestId("icon-Trash2").first().click();
|
||||
await page.waitForTimeout(2000);
|
||||
});
|
||||
await page.getByText("Confirm deletion of component?").isVisible();
|
||||
await page.getByText("Delete").nth(1).click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByText("Successfully").first().isVisible();
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue