diff --git a/__tests__/html-outlook-outlook.test.ts b/__tests__/html-outlook-outlook.test.ts
index a38be006d909912467d2add8e69563419d8b4ce3..0fa3d3a460de421a0894b366391e0481a22345de 100644
--- a/__tests__/html-outlook-outlook.test.ts
+++ b/__tests__/html-outlook-outlook.test.ts
@@ -1,85 +1,20 @@
-import { describe, test, expect } from "@jest/globals";
-import { JSDOM } from "jsdom";
-import HTMLNormalizer from "../src/HTMLNormalizer";
+import { describe } from "@jest/globals";
 import { EMAIL_VENDORS } from "../src";
-const fs = require("fs");
+import { createDescribeHtmlTestCases } from "./utils";
 const path = require("path");
 
-// Test cases from https://code.vereign.com/alexey.lunin/outlook-files-upload
-
 const TESTS_GLOBAL_PATH = "/files/outlook-outlook";
-const SENT_HTML_NAME = "s_htmlContent.html";
-const RECEIVED_HTML_NAME = "r_htmlContent.html";
-
 const testsPath = path.resolve(__dirname, `.${TESTS_GLOBAL_PATH}`);
-const getTestCasesDirs = (testCasesPath: string) => {
-  return fs.readdirSync(testCasesPath).filter(function (file) {
-    return fs.statSync(testCasesPath + "/" + file).isDirectory();
-  });
-};
-
-const getNormalizedHtml = (
-  testCasePath: string
-): {
-  sentHtml: string;
-  receivedHtml: string;
-} => {
-  const sentHtml = fs
-    .readFileSync(`${testCasePath}/${SENT_HTML_NAME}`)
-    .toString();
-  const receivedHtml = fs
-    .readFileSync(`${testCasePath}/${RECEIVED_HTML_NAME}`)
-    .toString();
-
-  const sentDOM = new JSDOM(sentHtml);
-  const receivedDOM = new JSDOM(receivedHtml);
 
-  const sentNormalizedHtml = HTMLNormalizer.normalizeVendorHtml(
-    sentDOM.window.document,
-    EMAIL_VENDORS.OUTLOOK
-  );
-  const receivedNormalizedHtml = HTMLNormalizer.normalizeVendorHtml(
-    receivedDOM.window.document,
+describe("Outlook emails HTML normalization", () => {
+  const describeFunction = createDescribeHtmlTestCases(
+    testsPath,
     EMAIL_VENDORS.OUTLOOK
   );
 
-  return {
-    sentHtml: sentNormalizedHtml,
-    receivedHtml: receivedNormalizedHtml,
-  };
-};
-
-describe("Outlook emails HTML normalization", () => {
-  const describeTestCases = (
-    casesGroupName: string,
-    failingCases: Array<string> = []
-  ) => () => {
-    const testsCasesPath = testsPath + "/" + casesGroupName;
-    const testCasesDirs = getTestCasesDirs(testsCasesPath).filter(
-      (dir) => !failingCases.includes(dir)
-    );
-
-    test.each(testCasesDirs)("Case %s", (dirName: string) => {
-      const testCasePath = testsCasesPath + "/" + dirName;
-      let normalizedHtmls;
-      try {
-        normalizedHtmls = getNormalizedHtml(testCasePath);
-      } catch (e) {
-        console.log(`Invalid test case: ${casesGroupName}/${dirName}`);
-        return;
-      }
-
-      const { sentHtml, receivedHtml } = normalizedHtmls;
-
-      expect(receivedHtml.length).toBeGreaterThan(0);
-      expect(sentHtml.length).toBeGreaterThan(0);
-      expect(receivedHtml).toContain(sentHtml);
-    });
-  };
-
   describe(
     "Emails Chrome",
-    describeTestCases("chrome", [
+    describeFunction("chrome", [
       "20",
       "20forward",
       "20reply",
@@ -97,7 +32,7 @@ describe("Outlook emails HTML normalization", () => {
 
   describe(
     "Emails Edge",
-    describeTestCases("edge", [
+    describeFunction("edge", [
       "20",
       "20forward",
       "20reply",
@@ -112,7 +47,7 @@ describe("Outlook emails HTML normalization", () => {
   );
   describe(
     "Emails Safari",
-    describeTestCases("safari", [
+    describeFunction("safari", [
       "04",
       "20",
       "20forward",
@@ -130,11 +65,11 @@ describe("Outlook emails HTML normalization", () => {
   );
   // describe(
   //   "Emails MacOS",
-  //   describeTestCases("macos", ["20", "21", "22", "23", "24", "25", "26"])
+  //   describeFunction("macos", ["20", "21", "22", "23", "24", "25", "26"])
   // );
   describe(
     "Emails Windows",
-    describeTestCases("windows", [
+    describeFunction("windows", [
       "06",
       "20",
       "20forward",
diff --git a/__tests__/plain-outlook-outlook.test.ts b/__tests__/plain-outlook-outlook.test.ts
index 9c3e7adb2c4e1433d532eadc41929e9340625ffb..d71f0f07c088a9b5ce69166103ed888f06ef21a4 100644
--- a/__tests__/plain-outlook-outlook.test.ts
+++ b/__tests__/plain-outlook-outlook.test.ts
@@ -1,74 +1,18 @@
-import { describe, test, expect } from "@jest/globals";
-import { PlainNormalizer } from "../src";
-const fs = require("fs");
+import { describe } from "@jest/globals";
+import { createDescribePlainTestCases } from "./utils";
 const path = require("path");
 
 // Test cases from https://code.vereign.com/alexey.lunin/outlook-files-upload
 
 const TESTS_GLOBAL_PATH = "/files/outlook-outlook";
-const SENT_HTML_NAME = "s_plainContent.data";
-const RECEIVED_HTML_NAME = "r_plainContent.data";
 
 const testsPath = path.resolve(__dirname, `.${TESTS_GLOBAL_PATH}`);
-const getTestCasesDirs = (testCasesPath: string) => {
-  return fs.readdirSync(testCasesPath).filter(function (file) {
-    return fs.statSync(testCasesPath + "/" + file).isDirectory();
-  });
-};
-
-const getNormalizedHtml = (
-  testCasePath: string
-): {
-  sentPlain: string;
-  receivedPlain: string;
-} => {
-  const sentPlain = fs
-    .readFileSync(`${testCasePath}/${SENT_HTML_NAME}`)
-    .toString();
-  const receivedPlain = fs
-    .readFileSync(`${testCasePath}/${RECEIVED_HTML_NAME}`)
-    .toString();
-
-  const sentNormalizedPlain = PlainNormalizer.normalizePlain(sentPlain);
-  const receivedNormalizedPlain = PlainNormalizer.normalizePlain(receivedPlain);
-
-  return {
-    sentPlain: sentNormalizedPlain,
-    receivedPlain: receivedNormalizedPlain,
-  };
-};
 
 describe("Outlook emails Plain normalization", () => {
-  const describeTestCases = (
-    casesName: string,
-    failingCases: Array<string> = []
-  ) => () => {
-    const testsCasesPath = testsPath + "/" + casesName;
-    const testCasesDirs = getTestCasesDirs(testsCasesPath).filter(
-      (dir) => !failingCases.includes(dir)
-    );
-
-    test.each(testCasesDirs)("Case %s", (dirName: string) => {
-      const testCasePath = testsCasesPath + "/" + dirName;
-      let normalizedPlain;
-      try {
-        normalizedPlain = getNormalizedHtml(testCasePath);
-      } catch (e) {
-        console.log(`Invalid test case: ${casesName}/${dirName}`);
-        return;
-      }
-
-      const { sentPlain, receivedPlain } = normalizedPlain;
-
-      expect(sentPlain.length).toBeGreaterThan(0);
-      expect(receivedPlain.length).toBeGreaterThan(0);
-      expect(receivedPlain).toContain(sentPlain);
-    });
-  };
-
-  describe("Emails Chrome", describeTestCases("chrome"));
-  describe("Emails Edge", describeTestCases("edge", ["21"]));
-  describe("Emails Safari", describeTestCases("safari"));
-  describe("Emails MacOS", describeTestCases("macos", ["21", "23", "25"]));
-  describe("Emails Windows", describeTestCases("windows", ["25"]));
+  const describeFunction = createDescribePlainTestCases(testsPath);
+  describe("Emails Chrome", describeFunction("chrome"));
+  describe("Emails Edge", describeFunction("edge", ["21"]));
+  describe("Emails Safari", describeFunction("safari"));
+  describe("Emails MacOS", describeFunction("macos", ["21", "23", "25"]));
+  describe("Emails Windows", describeFunction("windows", ["25"]));
 });
diff --git a/__tests__/utils.ts b/__tests__/utils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..decebccb08e0119dc3e46dd76d2301795e927821
--- /dev/null
+++ b/__tests__/utils.ts
@@ -0,0 +1,123 @@
+import { JSDOM } from "jsdom";
+const fs = require("fs");
+
+const SENT_HTML_NAME = "s_htmlContent.html";
+const RECEIVED_HTML_NAME = "r_htmlContent.html";
+const SENT_PLAIN_NAME = "s_plainContent.data";
+const RECEIVED_PLAIN_NAME = "r_plainContent.data";
+import { PlainNormalizer, HTMLNormalizer } from "../src";
+import { expect, test } from "@jest/globals";
+
+export const getNormalizedPlain = (
+  testCasePath: string
+): {
+  sentPlain: string;
+  receivedPlain: string;
+} => {
+  const sentPlain = fs
+    .readFileSync(`${testCasePath}/${SENT_PLAIN_NAME}`)
+    .toString();
+  const receivedPlain = fs
+    .readFileSync(`${testCasePath}/${RECEIVED_PLAIN_NAME}`)
+    .toString();
+
+  const sentNormalizedPlain = PlainNormalizer.normalizePlain(sentPlain);
+  const receivedNormalizedPlain = PlainNormalizer.normalizePlain(receivedPlain);
+
+  return {
+    sentPlain: sentNormalizedPlain,
+    receivedPlain: receivedNormalizedPlain,
+  };
+};
+
+export const getTestCasesDirs = (testCasesPath: string): Array<string> => {
+  return fs.readdirSync(testCasesPath).filter(function (file) {
+    return fs.statSync(testCasesPath + "/" + file).isDirectory();
+  });
+};
+
+export const getNormalizedHtml = (
+  testCasePath: string,
+  vendor: string
+): {
+  sentHtml: string;
+  receivedHtml: string;
+} => {
+  const sentHtml = fs
+    .readFileSync(`${testCasePath}/${SENT_HTML_NAME}`)
+    .toString();
+  const receivedHtml = fs
+    .readFileSync(`${testCasePath}/${RECEIVED_HTML_NAME}`)
+    .toString();
+
+  const sentDOM = new JSDOM(sentHtml);
+  const receivedDOM = new JSDOM(receivedHtml);
+
+  const sentNormalizedHtml = HTMLNormalizer.normalizeVendorHtml(
+    sentDOM.window.document,
+    vendor
+  );
+  const receivedNormalizedHtml = HTMLNormalizer.normalizeVendorHtml(
+    receivedDOM.window.document,
+    vendor
+  );
+
+  return {
+    sentHtml: sentNormalizedHtml,
+    receivedHtml: receivedNormalizedHtml,
+  };
+};
+
+export const createDescribeHtmlTestCases = (
+  testsPath: string,
+  vendor: string
+) => (casesGroupName: string, failingCases: Array<string> = []) => (): void => {
+  const testsCasesPath = testsPath + "/" + casesGroupName;
+  const testCasesDirs = getTestCasesDirs(testsCasesPath).filter(
+    (dir) => !failingCases.includes(dir)
+  );
+
+  test.each(testCasesDirs)("Case %s", (dirName: string) => {
+    const testCasePath = testsCasesPath + "/" + dirName;
+    let normalizedHtmls;
+    try {
+      normalizedHtmls = getNormalizedHtml(testCasePath, vendor);
+    } catch (e) {
+      console.log(`Invalid test case: ${casesGroupName}/${dirName}`);
+      return;
+    }
+
+    const { sentHtml, receivedHtml } = normalizedHtmls;
+
+    expect(receivedHtml.length).toBeGreaterThan(0);
+    expect(sentHtml.length).toBeGreaterThan(0);
+    expect(receivedHtml).toContain(sentHtml);
+  });
+};
+
+export const createDescribePlainTestCases = (testsPath: string) => (
+  casesName: string,
+  failingCases: Array<string> = []
+) => (): void => {
+  const testsCasesPath = testsPath + "/" + casesName;
+  const testCasesDirs = getTestCasesDirs(testsCasesPath).filter(
+    (dir) => !failingCases.includes(dir)
+  );
+
+  test.each(testCasesDirs)("Case %s", (dirName: string) => {
+    const testCasePath = testsCasesPath + "/" + dirName;
+    let normalizedPlain;
+    try {
+      normalizedPlain = getNormalizedPlain(testCasePath);
+    } catch (e) {
+      console.log(`Invalid test case: ${casesName}/${dirName}`);
+      return;
+    }
+
+    const { sentPlain, receivedPlain } = normalizedPlain;
+
+    expect(sentPlain.length).toBeGreaterThan(0);
+    expect(receivedPlain.length).toBeGreaterThan(0);
+    expect(receivedPlain).toContain(sentPlain);
+  });
+};
diff --git a/jest.config.js b/jest.config.js
index 36404fa586704e71e467945335b40fc3304a5457..216e02ed6b0bfb29264c3d559ea89249c600c2df 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -82,7 +82,7 @@ module.exports = {
   // moduleNameMapper: {},
 
   // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
-  modulePathIgnorePatterns: ["testData.ts"],
+  modulePathIgnorePatterns: ["__tests__/utils.ts"],
 
   // Activates notifications for test results
   // notify: false,