mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-02 21:03:34 +03:00
Fix tools that could not run in Automate
(cherry picked from commit e7b48dbea3)
This commit is contained in:
@@ -34,13 +34,17 @@ export default function ToolSelector({
|
||||
const [shouldAutoFocus, setShouldAutoFocus] = useState(false);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Filter out excluded tools (like 'automate' itself) and tools that don't support automation
|
||||
// Filter out excluded tools (like 'automate' itself), tools that don't support
|
||||
// automation, and tools with no operationConfig - the executor resolves a step
|
||||
// through operationConfig, so offering one without it fails only at run time.
|
||||
const baseFilteredTools = useMemo(() => {
|
||||
return (
|
||||
Object.entries(toolRegistry) as [ToolId, ToolRegistryEntry][]
|
||||
).filter(
|
||||
([key, tool]) =>
|
||||
!excludeTools.includes(key) && getToolSupportsAutomate(tool),
|
||||
!excludeTools.includes(key) &&
|
||||
getToolSupportsAutomate(tool) &&
|
||||
Boolean(tool.operationConfig),
|
||||
);
|
||||
}, [toolRegistry, excludeTools]);
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Registry invariant: the Automate picker offers a tool whenever it doesn't opt out via
|
||||
* `supportsAutomate: false`, but automationExecutor resolves each step through the tool's
|
||||
* `operationConfig`. A tool that is offered without one is selectable in the builder and
|
||||
* only fails when the automation runs, with "Tool operation not supported: <toolId>".
|
||||
*
|
||||
* So a tool must either carry an operationConfig or declare supportsAutomate: false.
|
||||
*/
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
import { renderHook } from "@testing-library/react";
|
||||
import { useTranslatedToolCatalog } from "@app/data/useTranslatedToolRegistry";
|
||||
import { getToolSupportsAutomate } from "@app/data/toolsTaxonomy";
|
||||
|
||||
vi.mock("react-i18next", () => ({
|
||||
useTranslation: () => ({
|
||||
t: (key: string, fallback?: string) => fallback ?? key,
|
||||
i18n: { changeLanguage: vi.fn(), language: "en-US" },
|
||||
}),
|
||||
Trans: ({ children }: { children?: unknown }) => children,
|
||||
}));
|
||||
|
||||
describe("automatable tools", () => {
|
||||
test("every tool offered to Automate can be executed as a step", () => {
|
||||
const { result } = renderHook(() => useTranslatedToolCatalog());
|
||||
|
||||
const offeredWithoutConfig = Object.entries(result.current.regularTools)
|
||||
.filter(([, entry]) => entry && getToolSupportsAutomate(entry))
|
||||
.filter(([, entry]) => !entry.operationConfig)
|
||||
.map(([id]) => id);
|
||||
|
||||
expect(offeredWithoutConfig).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -49,6 +49,8 @@ import { changeMetadataOperationConfig } from "@app/hooks/tools/changeMetadata/u
|
||||
import { signOperationConfig } from "@app/hooks/tools/sign/useSignOperation";
|
||||
import { cropOperationConfig } from "@app/hooks/tools/crop/useCropOperation";
|
||||
import { removeAnnotationsOperationConfig } from "@app/hooks/tools/removeAnnotations/useRemoveAnnotationsOperation";
|
||||
import { removeImageOperationConfig } from "@app/hooks/tools/removeImage/useRemoveImageOperation";
|
||||
import { pageLayoutOperationConfig } from "@app/hooks/tools/pageLayout/usePageLayoutOperation";
|
||||
import { extractImagesOperationConfig } from "@app/hooks/tools/extractImages/useExtractImagesOperation";
|
||||
import { replaceColorOperationConfig } from "@app/hooks/tools/replaceColor/useReplaceColorOperation";
|
||||
import { removePagesOperationConfig } from "@app/hooks/tools/removePages/useRemovePagesOperation";
|
||||
@@ -525,6 +527,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
|
||||
maxFiles: -1,
|
||||
endpoints: ["validate-signature"],
|
||||
synonyms: getSynonyms(t, "validateSignature"),
|
||||
// Reports on signatures rather than transforming the PDF, and its hook is
|
||||
// not on the operationConfig seam, so it cannot run as an automation step.
|
||||
supportsAutomate: false,
|
||||
automationSettings: null,
|
||||
},
|
||||
|
||||
@@ -729,6 +734,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
|
||||
subcategoryId: SubcategoryId.PAGE_FORMATTING,
|
||||
maxFiles: -1,
|
||||
endpoints: ["multi-page-layout"],
|
||||
operationConfig: asRegistryConfig(pageLayoutOperationConfig),
|
||||
automationSettings: lazySettings(
|
||||
() => import("@app/components/tools/pageLayout/PageLayoutSettings"),
|
||||
),
|
||||
@@ -941,7 +947,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
|
||||
subcategoryId: SubcategoryId.REMOVAL,
|
||||
maxFiles: -1,
|
||||
endpoints: ["remove-image-pdf"],
|
||||
operationConfig: undefined,
|
||||
operationConfig: asRegistryConfig(removeImageOperationConfig),
|
||||
synonyms: getSynonyms(t, "removeImage"),
|
||||
automationSettings: null,
|
||||
},
|
||||
@@ -1170,6 +1176,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
|
||||
subcategoryId: SubcategoryId.ADVANCED_FORMATTING,
|
||||
endpoints: ["scanner-effect"],
|
||||
synonyms: getSynonyms(t, "scannerEffect"),
|
||||
// No frontend implementation yet (component is null), so it has no
|
||||
// operationConfig to execute as an automation step.
|
||||
supportsAutomate: false,
|
||||
automationSettings: null,
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user