Repository: ioBroker/create-adapter (ts)

Issue:
Add adapter title
Add adapter short description
Add a short description "desc" to io-package and suggest a translation with https://www.npmjs.com/package/translate-google
Add short description (optional)

Pull request:
 Ask the user for a title (mandatory) and a short description (optional) 
Fixes #4 
Fixes #24 
Fixes #5 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dc34e88..911ceda 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
 # Changelog
 
+## __WORK_IN_PROGRESS__
+* (AlCalzone) Ask the user for a title (mandatory) and a short description (optional) (#37)
+
 ## v1.2.0 (2018-12-16)
 * (AlCalzone) Initialize the git repo automatically (fixes #13)
 * (AlCalzone) When using TypeScript, perform an initial build run (fixes #27)
diff --git a/README.md b/README.md
index 239079f..b59693c 100644
--- a/README.md
+++ b/README.md
@@ -52,9 +52,7 @@ The following features did not make it into v1.0.0 and are planned for a later r
 - [ ] Package scripts for automatic semantic release of new versions
 - [ ] Choice of start mode
 - [ ] Ask for:
-  * adapter title
   * keywords
-  * short description
 - [ ] Automatically open the folder in your favorite editor
 - [ ] Scripts/Helpers for remote debugging
 
diff --git a/build/lib/actionsAndTransformers.js b/build/lib/actionsAndTransformers.js
index 1d6682e..91d4a3b 100644
--- a/build/lib/actionsAndTransformers.js
+++ b/build/lib/actionsAndTransformers.js
@@ -11,7 +11,7 @@ async function checkMinSelections(category, min, answers) {
 }
 exports.checkMinSelections = checkMinSelections;
 function isAdapterNameValid(name) {
-    if (!checkName(name)) {
+    if (!isNotEmpty(name)) {
         return "Please enter a valid name!";
     }
     const forbiddenChars = /[^a-z0-9\-_]/g;
@@ -46,11 +46,21 @@ async function checkAdapterName(name) {
     return true;
 }
 exports.checkAdapterName = checkAdapterName;
-function checkName(name) {
-    return name != undefined && name.length > 0 && name.trim().length > 0;
+function checkTitle(title) {
+    if (!isNotEmpty(title)) {
+        return "Please enter a title!";
+    }
+    if (/iobroker|adapter/i.test(title)) {
+        return `The title must not contain the words "ioBroker" or "adapter"!`;
+    }
+    return true;
+}
+exports.checkTitle = checkTitle;
+function isNotEmpty(answer) {
+    return answer != undefined && answer.length > 0 && answer.trim().length > 0;
 }
 async function checkAuthorName(name) {
-    if (!checkName(name)) {
+    if (!isNotEmpty(name)) {
         return "Please enter a valid name!";
     }
     return true;
@@ -72,6 +82,13 @@ function transformAdapterName(name) {
     return name;
 }
 exports.transformAdapterName = transformAdapterName;
+function transformDescription(description) {
+    description = description.trim();
+    if (description.length === 0)
+        return undefined;
+    return description;
+}
+exports.transformDescription = transformDescription;
 // Taken from https://api.github.com/licenses
 const licenseUrls = {
     "GNU AGPLv3": "https://api.github.com/licenses/agpl-3.0",
diff --git a/build/lib/questions.js b/build/lib/questions.js
index 8189027..29f6889 100644
--- a/build/lib/questions.js
+++ b/build/lib/questions.js
@@ -34,6 +34,20 @@ exports.questionsAndText = [
         resultTransform: actionsAndTransformers_1.transformAdapterName,
         action: actionsAndTransformers_1.checkAdapterName,
     },
+    {
+        type: "input",
+        name: "title",
+        message: "Which title should be shown in the admin UI?",
+        action: actionsAndTransformers_1.checkTitle,
+    },
+    {
+        type: "input",
+        name: "description",
+        message: "Please enter a short description:",
+        hint: "(optional)",
+        optional: true,
+        resultTransform: actionsAndTransformers_1.transformDescription,
+    },
     styledMultiselect({
         name: "features",
         message: "Which features should your project contain?",
@@ -71,7 +85,7 @@ exports.questionsAndText = [
         initial: [0],
         choices: [
             { message: "TSLint", hint: "(recommended)" },
-            { message: "Code coverage" },
+            { message: "code coverage" },
         ],
     }),
     // TODO: enable React (only TypeScript at the start)
@@ -182,7 +196,7 @@ function checkAnswers(answers) {
     for (const q of exports.questions) {
         const answer = answers[q.name];
         const conditionFulfilled = createAdapter_1.testCondition(q.condition, answers);
-        if (conditionFulfilled && answer == undefined) {
+        if (!q.optional && conditionFulfilled && answer == undefined) {
             // A required answer was not given
             throw new Error(`Missing answer "${q.name}"!`);
         }
diff --git a/build/templates/_gitignore.js b/build/templates/_gitignore.js
index 7db94d4..ff46151 100644
--- a/build/templates/_gitignore.js
+++ b/build/templates/_gitignore.js
@@ -1,6 +1,6 @@
 "use strict";
 const templateFunction = answers => {
-    const useNyc = answers.tools && answers.tools.indexOf("Code coverage") > -1;
+    const useNyc = answers.tools && answers.tools.indexOf("code coverage") > -1;
     const useTypeScript = answers.language === "TypeScript";
     const template = `
 .git
diff --git a/build/templates/_npmignore.js b/build/templates/_npmignore.js
index 10cfa49..f459929 100644
--- a/build/templates/_npmignore.js
+++ b/build/templates/_npmignore.js
@@ -1,7 +1,7 @@
 "use strict";
 const templateFunction = answers => {
     const isAdapter = answers.features.indexOf("Adapter") > -1;
-    const useNyc = answers.tools && answers.tools.indexOf("Code coverage") > -1;
+    const useNyc = answers.tools && answers.tools.indexOf("code coverage") > -1;
     const useTypeScript = answers.language === "TypeScript";
     const useTSLint = answers.tools && answers.tools.indexOf("TSLint") > -1;
     const useESLint = answers.tools && answers.tools.indexOf("ESLint") > -1;
diff --git a/build/templates/package.json.js b/build/templates/package.json.js
index c2fd2e3..0f2823b 100644
--- a/build/templates/package.json.js
+++ b/build/templates/package.json.js
@@ -8,7 +8,7 @@ const templateFunction = async (answers) => {
     const useTypeScript = answers.language === "TypeScript";
     const useTSLint = answers.tools && answers.tools.indexOf("TSLint") > -1;
     const useESLint = answers.tools && answers.tools.indexOf("ESLint") > -1;
-    const useNyc = answers.tools && answers.tools.indexOf("Code coverage") > -1;
+    const useNyc = answers.tools && answers.tools.indexOf("code coverage") > -1;
     const dependencyPromises = []
         .concat(isAdapter ? ["@iobroker/adapter-core"] : [])
         .sort()
diff --git a/src/lib/actionsAndTransformers.ts b/src/lib/actionsAndTransformers.ts
index 94eb669..ef3bcc1 100644
--- a/src/lib/actionsAndTransformers.ts
+++ b/src/lib/actionsAndTransformers.ts
@@ -11,7 +11,7 @@ export async function checkMinSelections(category: string, min: number, answers:
 }
 
 function isAdapterNameValid(name: string): CheckResult {
-	if (!checkName(name)) {
+	if (!isNotEmpty(name)) {
 		return "Please enter a valid name!";
 	}
 	const forbiddenChars = /[^a-z0-9\-_]/g;
@@ -47,12 +47,22 @@ export async function checkAdapterName(name: string): Promise<CheckResult> {
 	return true;
 }
 
-function checkName(name: string): boolean {
-	return name != undefined && name.length > 0 && name.trim().length > 0;
+export function checkTitle(title: string): CheckResult {
+	if (!isNotEmpty(title)) {
+		return "Please enter a title!";
+	}
+	if (/iobroker|adapter/i.test(title)) {
+		return `The title must not contain the words "ioBroker" or "adapter"!`;
+	}
+	return true;
+}
+
+function isNotEmpty(answer: string): boolean {
+	return answer != undefined && answer.length > 0 && answer.trim().length > 0;
 }
 
 export async function checkAuthorName(name: string): Promise<CheckResult> {
-	if (!checkName(name)) {
+	if (!isNotEmpty(name)) {
 		return "Please enter a valid name!";
 	}
 	return true;
@@ -74,6 +84,12 @@ export function transformAdapterName(name: string): string {
 	return name;
 }
 
+export function transformDescription(description: string): string | undefined {
+	description = description.trim();
+	if (description.length === 0) return undefined;
+	return description;
+}
+
 // Taken from https://api.github.com/licenses
 const licenseUrls = {
 	"GNU AGPLv3": "https://api.github.com/licenses/agpl-3.0",
diff --git a/src/lib/questions.ts b/src/lib/questions.ts
index ac1ad82..f8d510c 100644
--- a/src/lib/questions.ts
+++ b/src/lib/questions.ts
@@ -1,12 +1,12 @@
 import { bold, dim, gray, green, underline } from "ansi-colors";
 import { prompt } from "enquirer";
-import { checkAdapterName, checkAuthorName, checkEmail, checkMinSelections, CheckResult, loadLicense, transformAdapterName } from "./actionsAndTransformers";
+import { checkAdapterName, checkAuthorName, checkEmail, checkMinSelections, CheckResult, checkTitle, loadLicense, transformAdapterName, transformDescription } from "./actionsAndTransformers";
 import { testCondition } from "./createAdapter";
 
 // Sadly, Enquirer does not export the PromptOptions type
 // tslint:disable-next-line:ban-types
 type PromptOptions = Exclude<Parameters<typeof prompt>[0], Function | any[]>;
-type QuestionAction<T> = (value: T) => Promise<CheckResult>;
+type QuestionAction<T> = (value: T) => CheckResult | Promise<CheckResult>;
 // tslint:disable-next-line:interface-over-type-literal
 export type AnswerValue = string | boolean | number;
 export type Condition = { name: string } & (
@@ -16,8 +16,9 @@ export type Condition = { name: string } & (
 
 interface QuestionMeta {
 	condition?: Condition | Condition[];
-	resultTransform?: (val: AnswerValue | AnswerValue[]) => AnswerValue | AnswerValue[] | Promise<AnswerValue | AnswerValue[]>;
+	resultTransform?: (val: AnswerValue | AnswerValue[]) => AnswerValue | AnswerValue[] | undefined | Promise<AnswerValue | AnswerValue[] | undefined>;
 	action?: QuestionAction<AnswerValue | AnswerValue[]>;
+	optional?: boolean;
 }
 type Question = PromptOptions & QuestionMeta;
 
@@ -54,6 +55,20 @@ export const questionsAndText: (Question | string)[] = [
 		resultTransform: transformAdapterName,
 		action: checkAdapterName,
 	},
+	{
+		type: "input",
+		name: "title",
+		message: "Which title should be shown in the admin UI?",
+		action: checkTitle,
+	},
+	{
+		type: "input",
+		name: "description",
+		message: "Please enter a short description:",
+		hint: "(optional)",
+		optional: true,
+		resultTransform: transformDescription,
+	},
 	styledMultiselect({
 		name: "features",
 		message: "Which features should your project contain?",
@@ -91,7 +106,7 @@ export const questionsAndText: (Question | string)[] = [
 		initial: [0],
 		choices: [
 			{ message: "TSLint", hint: "(recommended)" },
-			{ message: "Code coverage" },
+			{ message: "code coverage" },
 		],
 	}),
 
@@ -204,18 +219,18 @@ export const questions = questionsAndText.filter(q => typeof q !== "string") as
 
 export interface Answers {
 	adapterName: string;
+	description?: string;
 	authorName: string;
 	authorEmail: string;
 	authorGithub: string;
-	description?: string;
-	language?: string;
-	tools?: string[];
-	features: string[];
+	language?: "JavaScript" | "TypeScript";
+	features: ("Adapter" | "VIS widget")[];
+	tools?: ("ESLint" | "TSLint" | "type checking" | "code coverage")[];
 	title?: string;
 	license: { id: string, name: string, text: string };
 	type?: string;
 	adminReact?: string;
-	indentation?: string;
+	indentation?: "Tab" | "Space (4)";
 	quotes?: "single" | "double";
 	gitCommit?: "yes" | "no";
 }
@@ -224,7 +239,7 @@ export function checkAnswers(answers: Partial<Answers>): void {
 	for (const q of questions) {
 		const answer = (answers as any)[q.name as string];
 		const conditionFulfilled = testCondition(q.condition, answers);
-		if (conditionFulfilled && answer == undefined) {
+		if (!q.optional && conditionFulfilled && answer == undefined) {
 			// A required answer was not given
 			throw new Error(`Missing answer "${q.name}"!`);
 		} else if (!conditionFulfilled && answer != undefined) {
diff --git a/src/templates/_gitignore.ts b/src/templates/_gitignore.ts
index dfd60e0..e46c5dd 100644
--- a/src/templates/_gitignore.ts
+++ b/src/templates/_gitignore.ts
@@ -3,7 +3,7 @@ import { Answers } from "../lib/questions";
 
 const templateFunction: TemplateFunction = answers => {
 
-	const useNyc = answers.tools && answers.tools.indexOf("Code coverage") > -1;
+	const useNyc = answers.tools && answers.tools.indexOf("code coverage") > -1;
 	const useTypeScript = answers.language === "TypeScript";
 
 	const template = `
diff --git a/src/templates/_npmignore.ts b/src/templates/_npmignore.ts
index ac3c2d2..f6eaada 100644
--- a/src/templates/_npmignore.ts
+++ b/src/templates/_npmignore.ts
@@ -4,7 +4,7 @@ import { Answers } from "../lib/questions";
 const templateFunction: TemplateFunction = answers => {
 
 	const isAdapter = answers.features.indexOf("Adapter") > -1;
-	const useNyc = answers.tools && answers.tools.indexOf("Code coverage") > -1;
+	const useNyc = answers.tools && answers.tools.indexOf("code coverage") > -1;
 	const useTypeScript = answers.language === "TypeScript";
 	const useTSLint = answers.tools && answers.tools.indexOf("TSLint") > -1;
 	const useESLint = answers.tools && answers.tools.indexOf("ESLint") > -1;
diff --git a/src/templates/package.json.ts b/src/templates/package.json.ts
index c0e5a42..1044d83 100644
--- a/src/templates/package.json.ts
+++ b/src/templates/package.json.ts
@@ -10,7 +10,7 @@ const templateFunction: TemplateFunction = async answers => {
 	const useTypeScript = answers.language === "TypeScript";
 	const useTSLint = answers.tools && answers.tools.indexOf("TSLint") > -1;
 	const useESLint = answers.tools && answers.tools.indexOf("ESLint") > -1;
-	const useNyc = answers.tools && answers.tools.indexOf("Code coverage") > -1;
+	const useNyc = answers.tools && answers.tools.indexOf("code coverage") > -1;
 
 	const dependencyPromises = ([] as string[])
 		.concat(isAdapter ? ["@iobroker/adapter-core"] : [])


Test patch:
diff --git a/src/index.test.ts b/src/index.test.ts
index 03c05bf..e9be503 100644
--- a/src/index.test.ts
+++ b/src/index.test.ts
@@ -3,24 +3,26 @@
 import * as fs from "fs-extra";
 import * as path from "path";
 import { createAdapter } from "./index";
-import { loadLicense } from "./lib/actionsAndTransformers";
-import { writeFiles } from "./lib/createAdapter";
+import { File, writeFiles } from "./lib/createAdapter";
 import { Answers } from "./lib/questions";
 
 const baselineDir = path.join(__dirname, "../test/baselines");
 
-async function generateBaselines(testName: string, answers: Answers) {
+async function generateBaselines(testName: string, answers: Answers, filterFilesPredicate?: (file: File) => boolean) {
 	const files = await createAdapter(answers);
 
 	const testDir = path.join(baselineDir, testName);
 	await fs.emptyDir(testDir);
-	await writeFiles(testDir, files);
+	await writeFiles(
+		testDir,
+		typeof filterFilesPredicate === "function" ? files.filter(filterFilesPredicate) : files,
+	);
 }
 
 // TODO: Mock network requests
 
-async function expectSuccess(testName: string, answers: Answers) {
-	await generateBaselines(testName, answers as Answers);
+async function expectSuccess(testName: string, answers: Answers, filterFilesPredicate?: (file: File) => boolean) {
+	await generateBaselines(testName, answers, filterFilesPredicate);
 }
 
 async function expectFail(testName: string, answers: Partial<Answers>, message: string) {
@@ -29,6 +31,20 @@ async function expectFail(testName: string, answers: Partial<Answers>, message:
 	await fs.pathExists(testDir).should.become(false);
 }
 
+const baseAnswers: Answers = {
+	adapterName: "test-adapter",
+	title: "Is used to test the creator",
+	features: ["Adapter"],
+	language: "TypeScript",
+	tools: ["TSLint"],
+	indentation: "Tab",
+	quotes: "double",
+	authorName: "Al Calzone",
+	authorGithub: "AlCalzone",
+	authorEmail: "al@calzo.ne",
+	license: "MIT License" as any,
+};
+
 describe("adapter creation =>", () => {
 
 	describe("incomplete answer sets should fail =>", () => {
@@ -38,9 +54,38 @@ describe("adapter creation =>", () => {
 			expectFail("incompleteAnswersOnlyName", answers, "Missing answer");
 		});
 
+		it("no title", () => {
+			const { title, ...noTitle } = baseAnswers;
+			expectFail("incompleteAnswersNoTitle", noTitle, "Missing answer");
+		});
+
+		it("empty title 1", () => {
+			const answers: Answers = {
+				...baseAnswers,
+				title: "",
+			};
+			expectFail("incompleteAnswersEmptyTitle", answers, "Please enter a title");
+		});
+
+		it("empty title 2", () => {
+			const answers: Answers = {
+				...baseAnswers,
+				title: "   ",
+			};
+			expectFail("incompleteAnswersEmptyTitle", answers, "Please enter a title");
+		});
+
+		it("invalid title 1", () => {
+			const answers: Answers = {
+				...baseAnswers,
+				title: "Adapter for ioBroker",
+			};
+			expectFail("incompleteAnswersEmptyTitle", answers, "must not contain the words");
+		});
+
 	});
 
-	describe("generate valid baselines =>", function() {
+	describe("generate baselines =>", function () {
 		this.timeout(60000);
 
 		before(async () => {
@@ -54,36 +99,63 @@ describe("adapter creation =>", () => {
 			);
 		});
 
-		it("Adapter, TypeScript, TSLint, Tabs, Double quotes, MIT License", async () => {
-			const answers: Answers = {
-				adapterName: "test-adapter",
-				features: ["Adapter"],
-				language: "TypeScript",
-				tools: ["TSLint"],
-				indentation: "Tab",
-				quotes: "double",
-				authorName: "Al Calzone",
-				authorGithub: "AlCalzone",
-				authorEmail: "al@calzo.ne",
-				license: "MIT License" as any,
-			};
-			await expectSuccess("adapter_TS_TSLint_Tabs_DoubleQuotes_MIT", answers);
+		describe("full adapter dir =>", () => {
+			it("Adapter, TypeScript, TSLint, Tabs, Double quotes, MIT License", async () => {
+				const answers: Answers = {
+					...baseAnswers,
+				};
+				await expectSuccess("adapter_TS_TSLint_Tabs_DoubleQuotes_MIT", answers);
+			});
+
+			it("Adapter, JavaScript, ESLint, Spaces, Single quotes, LGPLv3", async () => {
+				const answers: Answers = {
+					...baseAnswers,
+					language: "JavaScript",
+					tools: ["ESLint", "type checking"],
+					indentation: "Space (4)",
+					quotes: "single",
+					license: "GNU LGPLv3" as any,
+				};
+				await expectSuccess("adapter_JS_ESLint_TypeChecking_Spaces_SingleQuotes_LGPLv3", answers);
+			});
 		});
 
-		it("Adapter, JavaScript, ESLint, Spaces, Single quotes, LGPLv3", async () => {
-			const answers: Answers = {
-				adapterName: "test-adapter",
-				features: ["Adapter"],
-				language: "JavaScript",
-				tools: ["ESLint", "type checking"],
-				indentation: "Space (4)",
-				quotes: "single",
-				authorName: "Al Calzone",
-				authorGithub: "AlCalzone",
-				authorEmail: "al@calzo.ne",
-				license: "GNU LGPLv3" as any,
-			};
-			await expectSuccess("adapter_JS_ESLint_TypeChecking_Spaces_SingleQuotes_LGPLv3", answers);
+		describe("Single-file component tests =>", () => {
+			it("Valid description", async () => {
+				const answers: Answers = {
+					...baseAnswers,
+					description: "This is a short description",
+				};
+				await expectSuccess(
+					"description_valid",
+					answers,
+					file => file.name === "io-package.json",
+				);
+			});
+
+			it("Empty description 1", async () => {
+				const answers: Answers = {
+					...baseAnswers,
+					description: "",
+				};
+				await expectSuccess(
+					"description_empty_1",
+					answers,
+					file => file.name === "io-package.json",
+				);
+			});
+
+			it("Empty description 2", async () => {
+				const answers: Answers = {
+					...baseAnswers,
+					description: "   ",
+				};
+				await expectSuccess(
+					"description_empty_2",
+					answers,
+					file => file.name === "io-package.json",
+				);
+			});
 		});
 
 	});
diff --git a/test/baselines/adapter_JS_ESLint_TypeChecking_Spaces_SingleQuotes_LGPLv3/io-package.json b/test/baselines/adapter_JS_ESLint_TypeChecking_Spaces_SingleQuotes_LGPLv3/io-package.json
index 838ea0e..5416a37 100644
--- a/test/baselines/adapter_JS_ESLint_TypeChecking_Spaces_SingleQuotes_LGPLv3/io-package.json
+++ b/test/baselines/adapter_JS_ESLint_TypeChecking_Spaces_SingleQuotes_LGPLv3/io-package.json
@@ -15,17 +15,17 @@
                 "pl": "Pierwsze wydanie"
             }
         },
-        "title": "test-adapter",
+        "title": "Is used to test the creator",
         "titleLang": {
-            "en": "test-adapter",
-            "de": "test-adapter",
-            "ru": "test-adapter",
-            "pt": "test-adapter",
-            "nl": "test-adapter",
-            "fr": "test-adapter",
-            "it": "test-adapter",
-            "es": "test-adapter",
-            "pl": "test-adapter"
+            "en": "Is used to test the creator",
+            "de": "Is used to test the creator",
+            "ru": "Is used to test the creator",
+            "pt": "Is used to test the creator",
+            "nl": "Is used to test the creator",
+            "fr": "Is used to test the creator",
+            "it": "Is used to test the creator",
+            "es": "Is used to test the creator",
+            "pl": "Is used to test the creator"
         },
         "desc": {
             "en": "test-adapter",
diff --git a/test/baselines/adapter_JS_ESLint_TypeChecking_Spaces_SingleQuotes_LGPLv3/package.json b/test/baselines/adapter_JS_ESLint_TypeChecking_Spaces_SingleQuotes_LGPLv3/package.json
index 7fe1048..e1a6571 100644
--- a/test/baselines/adapter_JS_ESLint_TypeChecking_Spaces_SingleQuotes_LGPLv3/package.json
+++ b/test/baselines/adapter_JS_ESLint_TypeChecking_Spaces_SingleQuotes_LGPLv3/package.json
@@ -26,7 +26,7 @@
     "@types/chai-as-promised": "^7.1.0",
     "@types/gulp": "^4.0.5",
     "@types/mocha": "^5.2.5",
-    "@types/node": "^10.12.15",
+    "@types/node": "^10.12.17",
     "@types/proxyquire": "^1.3.28",
     "@types/sinon": "^7.0.0",
     "@types/sinon-chai": "^3.2.2",
diff --git a/test/baselines/adapter_TS_TSLint_Tabs_DoubleQuotes_MIT/io-package.json b/test/baselines/adapter_TS_TSLint_Tabs_DoubleQuotes_MIT/io-package.json
index 7ade7dd..3bb7780 100644
--- a/test/baselines/adapter_TS_TSLint_Tabs_DoubleQuotes_MIT/io-package.json
+++ b/test/baselines/adapter_TS_TSLint_Tabs_DoubleQuotes_MIT/io-package.json
@@ -15,17 +15,17 @@
 				"pl": "Pierwsze wydanie"
 			}
 		},
-		"title": "test-adapter",
+		"title": "Is used to test the creator",
 		"titleLang": {
-			"en": "test-adapter",
-			"de": "test-adapter",
-			"ru": "test-adapter",
-			"pt": "test-adapter",
-			"nl": "test-adapter",
-			"fr": "test-adapter",
-			"it": "test-adapter",
-			"es": "test-adapter",
-			"pl": "test-adapter"
+			"en": "Is used to test the creator",
+			"de": "Is used to test the creator",
+			"ru": "Is used to test the creator",
+			"pt": "Is used to test the creator",
+			"nl": "Is used to test the creator",
+			"fr": "Is used to test the creator",
+			"it": "Is used to test the creator",
+			"es": "Is used to test the creator",
+			"pl": "Is used to test the creator"
 		},
 		"desc": {
 			"en": "test-adapter",
diff --git a/test/baselines/adapter_TS_TSLint_Tabs_DoubleQuotes_MIT/package.json b/test/baselines/adapter_TS_TSLint_Tabs_DoubleQuotes_MIT/package.json
index 3b54d03..750d264 100644
--- a/test/baselines/adapter_TS_TSLint_Tabs_DoubleQuotes_MIT/package.json
+++ b/test/baselines/adapter_TS_TSLint_Tabs_DoubleQuotes_MIT/package.json
@@ -26,7 +26,7 @@
     "@types/chai-as-promised": "^7.1.0",
     "@types/gulp": "^4.0.5",
     "@types/mocha": "^5.2.5",
-    "@types/node": "^10.12.15",
+    "@types/node": "^10.12.17",
     "@types/proxyquire": "^1.3.28",
     "@types/sinon": "^7.0.0",
     "@types/sinon-chai": "^3.2.2",
@@ -40,7 +40,7 @@
     "sinon-chai": "^3.3.0",
     "source-map-support": "^0.5.9",
     "ts-node": "^7.0.1",
-    "tslint": "^5.11.0",
+    "tslint": "^5.12.0",
     "typescript": "^3.2.2"
   },
   "main": "build/main.js",
diff --git a/test/baselines/description_empty_1/io-package.json b/test/baselines/description_empty_1/io-package.json
new file mode 100644
index 0000000..3bb7780
--- /dev/null
+++ b/test/baselines/description_empty_1/io-package.json
@@ -0,0 +1,72 @@
+{
+	"common": {
+		"name": "test-adapter",
+		"version": "0.0.1",
+		"news": {
+			"0.0.1": {
+				"en": "initial release",
+				"de": "Erstveröffentlichung",
+				"ru": "Начальная версия",
+				"pt": "lançamento inicial",
+				"nl": "Eerste uitgave",
+				"fr": "Première version",
+				"it": "Versione iniziale",
+				"es": "Versión inicial",
+				"pl": "Pierwsze wydanie"
+			}
+		},
+		"title": "Is used to test the creator",
+		"titleLang": {
+			"en": "Is used to test the creator",
+			"de": "Is used to test the creator",
+			"ru": "Is used to test the creator",
+			"pt": "Is used to test the creator",
+			"nl": "Is used to test the creator",
+			"fr": "Is used to test the creator",
+			"it": "Is used to test the creator",
+			"es": "Is used to test the creator",
+			"pl": "Is used to test the creator"
+		},
+		"desc": {
+			"en": "test-adapter",
+			"de": "test-adapter",
+			"ru": "test-adapter",
+			"pt": "test-adapter",
+			"nl": "test-adapter",
+			"fr": "test-adapter",
+			"it": "test-adapter",
+			"es": "test-adapter",
+			"pl": "test-adapter"
+		},
+		"authors": [
+			"Al Calzone <al@calzo.ne>"
+		],
+		"keywords": [
+			"ioBroker",
+			"template",
+			"Smart Home",
+			"home automation"
+		],
+		"platform": "Javascript/Node.js",
+		"main": "build/main.js",
+		"icon": "test-adapter.png",
+		"enabled": true,
+		"extIcon": "https://raw.githubusercontent.com/AlCalzone/ioBroker.test-adapter/master/admin/test-adapter.png",
+		"readme": "https://github.com/AlCalzone/ioBroker.test-adapter/blob/master/README.md",
+		"loglevel": "info",
+		"mode": "daemon",
+		"type": "general",
+		"materialize": true,
+		"dependencies": [
+			{
+				"admin": ">=3.0.0"
+			}
+		]
+	},
+	"native": {
+		"option1": true,
+		"option2": "42"
+	},
+	"objects": [],
+	"instanceObjects": []
+}
\ No newline at end of file
diff --git a/test/baselines/description_empty_2/io-package.json b/test/baselines/description_empty_2/io-package.json
new file mode 100644
index 0000000..3bb7780
--- /dev/null
+++ b/test/baselines/description_empty_2/io-package.json
@@ -0,0 +1,72 @@
+{
+	"common": {
+		"name": "test-adapter",
+		"version": "0.0.1",
+		"news": {
+			"0.0.1": {
+				"en": "initial release",
+				"de": "Erstveröffentlichung",
+				"ru": "Начальная версия",
+				"pt": "lançamento inicial",
+				"nl": "Eerste uitgave",
+				"fr": "Première version",
+				"it": "Versione iniziale",
+				"es": "Versión inicial",
+				"pl": "Pierwsze wydanie"
+			}
+		},
+		"title": "Is used to test the creator",
+		"titleLang": {
+			"en": "Is used to test the creator",
+			"de": "Is used to test the creator",
+			"ru": "Is used to test the creator",
+			"pt": "Is used to test the creator",
+			"nl": "Is used to test the creator",
+			"fr": "Is used to test the creator",
+			"it": "Is used to test the creator",
+			"es": "Is used to test the creator",
+			"pl": "Is used to test the creator"
+		},
+		"desc": {
+			"en": "test-adapter",
+			"de": "test-adapter",
+			"ru": "test-adapter",
+			"pt": "test-adapter",
+			"nl": "test-adapter",
+			"fr": "test-adapter",
+			"it": "test-adapter",
+			"es": "test-adapter",
+			"pl": "test-adapter"
+		},
+		"authors": [
+			"Al Calzone <al@calzo.ne>"
+		],
+		"keywords": [
+			"ioBroker",
+			"template",
+			"Smart Home",
+			"home automation"
+		],
+		"platform": "Javascript/Node.js",
+		"main": "build/main.js",
+		"icon": "test-adapter.png",
+		"enabled": true,
+		"extIcon": "https://raw.githubusercontent.com/AlCalzone/ioBroker.test-adapter/master/admin/test-adapter.png",
+		"readme": "https://github.com/AlCalzone/ioBroker.test-adapter/blob/master/README.md",
+		"loglevel": "info",
+		"mode": "daemon",
+		"type": "general",
+		"materialize": true,
+		"dependencies": [
+			{
+				"admin": ">=3.0.0"
+			}
+		]
+	},
+	"native": {
+		"option1": true,
+		"option2": "42"
+	},
+	"objects": [],
+	"instanceObjects": []
+}
\ No newline at end of file
diff --git a/test/baselines/description_valid/io-package.json b/test/baselines/description_valid/io-package.json
new file mode 100644
index 0000000..f3328ef
--- /dev/null
+++ b/test/baselines/description_valid/io-package.json
@@ -0,0 +1,72 @@
+{
+	"common": {
+		"name": "test-adapter",
+		"version": "0.0.1",
+		"news": {
+			"0.0.1": {
+				"en": "initial release",
+				"de": "Erstveröffentlichung",
+				"ru": "Начальная версия",
+				"pt": "lançamento inicial",
+				"nl": "Eerste uitgave",
+				"fr": "Première version",
+				"it": "Versione iniziale",
+				"es": "Versión inicial",
+				"pl": "Pierwsze wydanie"
+			}
+		},
+		"title": "Is used to test the creator",
+		"titleLang": {
+			"en": "Is used to test the creator",
+			"de": "Is used to test the creator",
+			"ru": "Is used to test the creator",
+			"pt": "Is used to test the creator",
+			"nl": "Is used to test the creator",
+			"fr": "Is used to test the creator",
+			"it": "Is used to test the creator",
+			"es": "Is used to test the creator",
+			"pl": "Is used to test the creator"
+		},
+		"desc": {
+			"en": "This is a short description",
+			"de": "This is a short description",
+			"ru": "This is a short description",
+			"pt": "This is a short description",
+			"nl": "This is a short description",
+			"fr": "This is a short description",
+			"it": "This is a short description",
+			"es": "This is a short description",
+			"pl": "This is a short description"
+		},
+		"authors": [
+			"Al Calzone <al@calzo.ne>"
+		],
+		"keywords": [
+			"ioBroker",
+			"template",
+			"Smart Home",
+			"home automation"
+		],
+		"platform": "Javascript/Node.js",
+		"main": "build/main.js",
+		"icon": "test-adapter.png",
+		"enabled": true,
+		"extIcon": "https://raw.githubusercontent.com/AlCalzone/ioBroker.test-adapter/master/admin/test-adapter.png",
+		"readme": "https://github.com/AlCalzone/ioBroker.test-adapter/blob/master/README.md",
+		"loglevel": "info",
+		"mode": "daemon",
+		"type": "general",
+		"materialize": true,
+		"dependencies": [
+			{
+				"admin": ">=3.0.0"
+			}
+		]
+	},
+	"native": {
+		"option1": true,
+		"option2": "42"
+	},
+	"objects": [],
+	"instanceObjects": []
+}
\ No newline at end of file