diff --git a/airbyte-webapp/src/locales/en.json b/airbyte-webapp/src/locales/en.json
index 8bff60bd0e71..d03d0fbd6ddf 100644
--- a/airbyte-webapp/src/locales/en.json
+++ b/airbyte-webapp/src/locales/en.json
@@ -164,13 +164,14 @@
"form.transformationName": "Transformation name *",
"form.transformationType": "Transformation type *",
"form.dockerUrl": "Docker image URL with dbt installed *",
- "form.repositoryUrl": "Git repository URL of the custom transformation project *",
"form.entrypoint": "Entrypoint arguments for dbt cli to run the project *",
"form.entrypoint.docs": "Learn more",
"form.entrypoint.linked": "Entrypoint arguments for dbt cli to run the project. Learn more *",
"form.gitBranch": "Git branch name (leave blank for default branch)",
"form.selectType": "Select a type",
+ "form.repositoryUrl": "Git repository URL of the custom transformation project *",
"form.repositoryUrl.placeholder": "https://github.com/organisation/git_repo.git",
+ "form.repositoryUrl.invalidUrl": "Please enter a valid Git repository URL",
"form.sourceNamespace": "Source namespace",
"form.sourceStreamName": "Source stream name",
diff --git a/airbyte-webapp/src/views/Connection/TransformationForm/TransformationForm.tsx b/airbyte-webapp/src/views/Connection/TransformationForm/TransformationForm.tsx
index 5ba2540e75fe..389ecff8df23 100644
--- a/airbyte-webapp/src/views/Connection/TransformationForm/TransformationForm.tsx
+++ b/airbyte-webapp/src/views/Connection/TransformationForm/TransformationForm.tsx
@@ -3,7 +3,6 @@ import type { FormikErrors } from "formik/dist/types";
import { getIn, useFormik } from "formik";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
-import * as yup from "yup";
import { FormChangeTracker } from "components/FormChangeTracker";
import { ControlLabels } from "components/LabeledControl";
@@ -20,6 +19,7 @@ import { links } from "utils/links";
import { equal } from "utils/objects";
import styles from "./TransformationForm.module.scss";
+import { validationSchema } from "./utils";
interface TransformationProps {
transformation: OperationCreate;
@@ -28,18 +28,6 @@ interface TransformationProps {
isNewTransformation?: boolean;
}
-const validationSchema = yup.object({
- name: yup.string().required("form.empty.error"),
- operatorConfiguration: yup.object({
- dbt: yup.object({
- gitRepoUrl: yup.string().required("form.empty.error"),
- dockerImage: yup.string().required("form.empty.error"),
- dbtArguments: yup.string().required("form.empty.error"),
- gitRepoBranch: yup.string().nullable(),
- }),
- }),
-});
-
function prepareLabelFields(
errors: FormikErrors,
name: string
diff --git a/airbyte-webapp/src/views/Connection/TransformationForm/utils.test.ts b/airbyte-webapp/src/views/Connection/TransformationForm/utils.test.ts
new file mode 100644
index 000000000000..5640544e4cbf
--- /dev/null
+++ b/airbyte-webapp/src/views/Connection/TransformationForm/utils.test.ts
@@ -0,0 +1,86 @@
+import { merge } from "lodash";
+import { InferType, ValidationError } from "yup";
+
+import { validationSchema } from "./utils";
+
+describe(" - validationSchema", () => {
+ const customTransformationFields: InferType = {
+ name: "test name",
+ operatorConfiguration: {
+ dbt: {
+ gitRepoUrl: "https://github.com/username/example.git",
+ dockerImage: "image",
+ dbtArguments: "arguments",
+ gitRepoBranch: "",
+ },
+ },
+ };
+
+ it("should successfully validate the schema", async () => {
+ const result = validationSchema.validate(customTransformationFields);
+
+ await expect(result).resolves.toBeTruthy();
+ });
+
+ it("should fail if 'name' is empty", async () => {
+ await expect(async () => {
+ await validationSchema.validateAt(
+ "name",
+ merge(customTransformationFields, {
+ name: "",
+ })
+ );
+ }).rejects.toThrow(ValidationError);
+ });
+
+ it("should fail if 'gitRepoUrl' is invalid", async () => {
+ await expect(async () => {
+ await validationSchema.validateAt(
+ "operatorConfiguration.dbt.gitRepoUrl",
+ merge(customTransformationFields, {
+ operatorConfiguration: { dbt: { gitRepoUrl: "" } },
+ })
+ );
+ }).rejects.toThrow(ValidationError);
+
+ await expect(async () => {
+ await validationSchema.validateAt(
+ "operatorConfiguration.dbt.gitRepoUrl",
+ merge(customTransformationFields, {
+ operatorConfiguration: { dbt: { gitRepoUrl: "https://github.com/username/example.git " } },
+ })
+ );
+ }).rejects.toThrow(ValidationError);
+
+ await expect(async () => {
+ await validationSchema.validateAt(
+ "operatorConfiguration.dbt.gitRepoUrl",
+ merge(customTransformationFields, {
+ operatorConfiguration: { dbt: { gitRepoUrl: "https://github.com/username/example.git/" } },
+ })
+ );
+ }).rejects.toThrow(ValidationError);
+ });
+
+ it("should fail if 'dockerImage' is empty", async () => {
+ await expect(async () => {
+ await validationSchema.validateAt(
+ "operatorConfiguration.dbt.dockerImage",
+ merge(customTransformationFields, {
+ operatorConfiguration: { dbt: { dockerImage: "" } },
+ })
+ );
+ }).rejects.toThrow(ValidationError);
+ });
+
+ it("should fail if 'dbtArguments' is empty", async () => {
+ await expect(async () => {
+ await validationSchema.validateAt(
+ "operatorConfiguration.dbt.dbtArguments",
+ merge(customTransformationFields, {
+ operatorConfiguration: { dbt: { dbtArguments: "" } },
+ })
+ );
+ }).rejects.toThrow(ValidationError);
+ });
+});
diff --git a/airbyte-webapp/src/views/Connection/TransformationForm/utils.ts b/airbyte-webapp/src/views/Connection/TransformationForm/utils.ts
new file mode 100644
index 000000000000..50fa38792737
--- /dev/null
+++ b/airbyte-webapp/src/views/Connection/TransformationForm/utils.ts
@@ -0,0 +1,16 @@
+import * as yup from "yup";
+
+export const validationSchema = yup.object({
+ name: yup.string().required("form.empty.error"),
+ operatorConfiguration: yup.object({
+ dbt: yup.object({
+ gitRepoUrl: yup
+ .string()
+ .required("form.empty.error")
+ .matches(/((http(s)?)|(git@[\w.]+))(:(\/\/)?)([\w.@:/\-~]+)(\.git)$/, "form.repositoryUrl.invalidUrl"),
+ dockerImage: yup.string().required("form.empty.error"),
+ dbtArguments: yup.string().required("form.empty.error"),
+ gitRepoBranch: yup.string().nullable(),
+ }),
+ }),
+});