diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json
index d08edb75fb..e44a1d94ee 100644
--- a/plugins/scaffolder-react/package.json
+++ b/plugins/scaffolder-react/package.json
@@ -57,8 +57,8 @@
"json-schema": "^0.4.0",
"json-schema-library": "^7.3.9",
"lodash": "^4.17.21",
- "react-use": "^17.2.4",
"qs": "^6.9.4",
+ "react-use": "^17.2.4",
"zen-observable": "^0.10.0",
"zod": "~3.18.0",
"zod-to-json-schema": "~3.18.0"
diff --git a/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx
index 11fb28b29c..56abc52469 100644
--- a/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx
+++ b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx
@@ -26,7 +26,7 @@ import { ParsedTemplateSchema } from '../../hooks/useTemplateSchema';
export interface ReviewStateProps {
schemas: ParsedTemplateSchema[];
formState: JsonObject;
-};
+}
/**
* The component used by the {@link Stepper} to render the review step.
diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx
index 786f45b05d..e460afbdfc 100644
--- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx
+++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx
@@ -352,4 +352,42 @@ describe('Stepper', () => {
// flush promises
return new Promise(process.nextTick);
});
+
+ it('should override the Create and Review button text', async () => {
+ const manifest: TemplateParameterSchema = {
+ title: 'Custom Fields',
+ steps: [
+ {
+ title: 'Test',
+ schema: {
+ properties: {
+ name: {
+ type: 'string',
+ },
+ },
+ },
+ },
+ ],
+ };
+
+ const { getByRole } = await renderInTestApp(
+ ,
+ );
+
+ await act(async () => {
+ await fireEvent.click(getByRole('button', { name: 'Inspect' }));
+ });
+
+ expect(getByRole('button', { name: 'Make' })).toBeInTheDocument();
+
+ await act(async () => {
+ await fireEvent.click(getByRole('button', { name: 'Make' }));
+ });
+ });
});
diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx
index 6bd3ec8c71..5d0ad29513 100644
--- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx
+++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx
@@ -61,8 +61,9 @@ export type StepperProps = {
initialState?: Record;
onComplete: (values: Record) => Promise;
- initialFormState?: Record;
ReviewStateWrapper?: (props: ReviewStateProps) => JSX.Element;
+ createButtonText?: string;
+ reviewButtonText?: string;
};
// TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly
@@ -77,6 +78,8 @@ const Form = withTheme(require('@rjsf/material-ui-v5').Theme);
export const Stepper = ({
ReviewStateWrapper = ReviewState,
+ createButtonText = 'Create',
+ reviewButtonText = 'Review',
...props
}: StepperProps) => {
const analytics = useAnalytics();
@@ -182,7 +185,7 @@ export const Stepper = ({
Back
@@ -211,7 +214,7 @@ export const Stepper = ({
);
}}
>
- Create
+ {createButtonText}
>
diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.test.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.test.tsx
new file mode 100644
index 0000000000..8be6d58407
--- /dev/null
+++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.test.tsx
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2022 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ApiProvider } from '@backstage/core-app-api';
+import {
+ MockAnalyticsApi,
+ renderInTestApp,
+ TestApiRegistry,
+} from '@backstage/test-utils';
+import { act, fireEvent } from '@testing-library/react';
+import React from 'react';
+import { Workflow } from './Workflow';
+import { analyticsApiRef } from '@backstage/core-plugin-api';
+import { ScaffolderApi } from '../../../api/types';
+import { scaffolderApiRef } from '../../../api/ref';
+
+const scaffolderApiMock: jest.Mocked = {
+ scaffold: jest.fn(),
+ getTemplateParameterSchema: jest.fn(),
+ getIntegrationsList: jest.fn(),
+ getTask: jest.fn(),
+ streamLogs: jest.fn(),
+ listActions: jest.fn(),
+ listTasks: jest.fn(),
+};
+
+const analyticsMock = new MockAnalyticsApi();
+const apis = TestApiRegistry.from(
+ [scaffolderApiRef, scaffolderApiMock],
+ [analyticsApiRef, analyticsMock],
+);
+
+describe('', () => {
+ it('should complete a workflow', async () => {
+ const onComplete = jest.fn();
+ const onError = jest.fn();
+ scaffolderApiMock.scaffold.mockResolvedValue({ taskId: 'xyz' });
+
+ scaffolderApiMock.getTemplateParameterSchema.mockResolvedValue({
+ steps: [
+ {
+ title: 'Step 1',
+ schema: {
+ properties: {
+ name: {
+ type: 'string',
+ },
+ },
+ },
+ },
+ ],
+ title: 'React JSON Schema Form Test',
+ });
+
+ const { getByRole, getAllByRole, getByText } = await renderInTestApp(
+
+ (
+ This is a different wrapper for the review page
+ )}
+ customFieldExtensions={[]}
+ />
+ ,
+ );
+
+ // Test template title is overriden
+ expect(getByRole('heading', { level: 2 }).innerHTML).toBe(
+ 'Different title than template',
+ );
+
+ const input = getByRole('textbox') as HTMLInputElement;
+
+ expect(input).toBeInTheDocument();
+
+ expect(input.value).toBe('prefilled-name');
+
+ await act(async () => {
+ fireEvent.click(getByRole('button', { name: 'Review' }));
+ });
+
+ expect(
+ getByText('This is a different wrapper for the review page'),
+ ).toBeDefined();
+
+ await act(async () => {
+ fireEvent.click(getAllByRole('button')[1] as HTMLButtonElement);
+ });
+
+ expect(onComplete).toHaveBeenCalledWith({ name: 'prefilled-name' });
+ });
+});
diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx
index 783c504cc8..095ff49fe8 100644
--- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx
+++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx
@@ -113,7 +113,7 @@ export const Workflow = ({
extensions={props.customFieldExtensions}
onComplete={props.onComplete}
FormProps={FormProps}
- initialFormState={props.initialFormState}
+ initialState={props.initialFormState}
ReviewStateWrapper={ReviewStateWrapper}
/>
diff --git a/yarn.lock b/yarn.lock
index f8df88cb37..6a6a81f40b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7459,6 +7459,7 @@ __metadata:
json-schema-library: ^7.3.9
lodash: ^4.17.21
qs: ^6.9.4
+ react-use: ^17.2.4
zen-observable: ^0.10.0
zod: ~3.18.0
zod-to-json-schema: ~3.18.0