diff --git a/dashboard/src/components/DeploymentFormBody/DeploymentFormBody.test.tsx b/dashboard/src/components/DeploymentFormBody/DeploymentFormBody.test.tsx
new file mode 100644
index 00000000000..6abda5deba9
--- /dev/null
+++ b/dashboard/src/components/DeploymentFormBody/DeploymentFormBody.test.tsx
@@ -0,0 +1,64 @@
+import * as React from "react";
+import { act } from "react-dom/test-utils";
+import { defaultStore, mountWrapper } from "shared/specs/mountWrapper";
+import { IChartState, IChartVersion } from "shared/types";
+import BasicDeploymentForm from "./BasicDeploymentForm";
+import DeploymenetFormBody, { IDeploymentFormBodyProps } from "./DeploymentFormBody";
+import DifferentialSelector from "./DifferentialSelector";
+
+const defaultProps: IDeploymentFormBodyProps = {
+ deploymentEvent: "install",
+ chartID: "foo",
+ chartVersion: "1.0.0",
+ chartsIsFetching: false,
+ selected: {} as IChartState["selected"],
+ appValues: "foo: bar\n",
+ setValues: jest.fn(),
+ setValuesModified: jest.fn(),
+};
+
+jest.useFakeTimers();
+
+const versions = [
+ { id: "foo", attributes: { version: "1.2.3" }, relationships: { chart: { data: { repo: {} } } } },
+] as IChartVersion[];
+
+// Note that most of the tests that cover DeploymentFormBody component are in
+// in the DeploymentForm and UpgradeForm parent components
+
+// Context at https://github.com/kubeapps/kubeapps/issues/1293
+it("should modify the original values of the differential component if parsed as YAML object", () => {
+ const oldValues = `a: b
+
+
+c: d
+`;
+ const schema = { properties: { a: { type: "string", form: true } } };
+ const selected = {
+ values: oldValues,
+ schema,
+ versions: [versions[0], { ...versions[0], attributes: { version: "1.2.4" } } as IChartVersion],
+ version: versions[0],
+ };
+
+ const wrapper = mountWrapper(
+ defaultStore,
+ ,
+ );
+ expect(wrapper.find(DifferentialSelector).prop("defaultValues")).toBe(oldValues);
+
+ // Trigger a change in the basic form and a YAML parse
+ const input = wrapper.find(BasicDeploymentForm).find("input");
+ act(() => {
+ input.simulate("change", { currentTarget: "e" });
+ jest.advanceTimersByTime(500);
+ });
+ wrapper.update();
+
+ // The original double empty line gets deleted
+ const expectedValues = `a: b
+
+c: d
+`;
+ expect(wrapper.find(DifferentialSelector).prop("defaultValues")).toBe(expectedValues);
+});
diff --git a/dashboard/src/components/DeploymentFormBody/DeploymentFormBody.tsx b/dashboard/src/components/DeploymentFormBody/DeploymentFormBody.tsx
index 89c3ebbd5b1..1b7cc5bcf62 100644
--- a/dashboard/src/components/DeploymentFormBody/DeploymentFormBody.tsx
+++ b/dashboard/src/components/DeploymentFormBody/DeploymentFormBody.tsx
@@ -5,7 +5,7 @@ import { CdsButton } from "@clr/react/button";
import { CdsIcon } from "@clr/react/icon";
import Alert from "components/js/Alert";
import { isEqual } from "lodash";
-import { retrieveBasicFormParams, setValue } from "../../shared/schema";
+import { parseValues, retrieveBasicFormParams, setValue } from "../../shared/schema";
import { DeploymentEvent, IBasicFormParam, IChartState } from "../../shared/types";
import { getValueFromEvent } from "../../shared/utils";
import ConfirmDialog from "../ConfirmDialog/ConfirmDialog";
@@ -40,7 +40,9 @@ function DeploymentFormBody({
}: IDeploymentFormBodyProps) {
const [basicFormParameters, setBasicFormParameters] = useState([] as IBasicFormParam[]);
const [restoreModalIsOpen, setRestoreModalOpen] = useState(false);
- const { version, versions, schema } = selected;
+ const [defaultValues, setDefaultValues] = useState("");
+
+ const { version, versions, schema, values } = selected;
useEffect(() => {
const params = retrieveBasicFormParams(appValues, schema);
@@ -49,6 +51,10 @@ function DeploymentFormBody({
}
}, [setBasicFormParameters, schema, appValues, basicFormParameters]);
+ useEffect(() => {
+ setDefaultValues(values || "");
+ }, [values]);
+
const handleValuesChange = (value: string) => {
setValues(value);
setValuesModified();
@@ -58,8 +64,12 @@ function DeploymentFormBody({
};
const handleBasicFormParamChange = (param: IBasicFormParam) => {
+ const parsedDefaultValues = parseValues(defaultValues);
return (e: React.FormEvent) => {
setValuesModified();
+ if (parsedDefaultValues !== defaultValues) {
+ setDefaultValues(parsedDefaultValues);
+ }
const value = getValueFromEvent(e);
setBasicFormParameters(
basicFormParameters.map(p => (p.path === param.path ? { ...param, value } : p)),
@@ -104,7 +114,7 @@ function DeploymentFormBody({
,
@@ -122,7 +132,7 @@ function DeploymentFormBody({
,
diff --git a/dashboard/src/shared/schema.ts b/dashboard/src/shared/schema.ts
index 362a6dbf61f..1bf8997050a 100644
--- a/dashboard/src/shared/schema.ts
+++ b/dashboard/src/shared/schema.ts
@@ -125,6 +125,11 @@ export function setValue(values: string, path: string, newValue: any) {
return doc.toString();
}
+// parseValues returns a processed version of the values without modifying anything
+export function parseValues(values: string) {
+ return YAML.parseDocument(values).toString();
+}
+
export function deleteValue(values: string, path: string) {
const doc = YAML.parseDocument(values);
const { splittedPath } = parsePathAndValue(doc, path);