diff --git a/LCG-UDG/Constants/FileHeaderConstants.cs b/LCG-UDG/Constants/FileHeaderConstants.cs
new file mode 100644
index 0000000..acf6b92
--- /dev/null
+++ b/LCG-UDG/Constants/FileHeaderConstants.cs
@@ -0,0 +1,78 @@
+namespace Rappen.XTB.LCG
+{
+ ///
+ /// Constants used for file header generation and template placeholders
+ ///
+ public static class FileHeaderConstants
+ {
+ ///
+ /// Template placeholder for tool name
+ ///
+ public const string ToolName = "{toolname}";
+
+ ///
+ /// Template placeholder for version
+ ///
+ public const string Version = "{version}";
+
+ ///
+ /// Template placeholder for organization URL
+ ///
+ public const string Organization = "{organization}";
+
+ ///
+ /// Template placeholder for filename
+ ///
+ public const string Filename = "{filename}";
+
+ ///
+ /// Template placeholder for creation date
+ ///
+ public const string CreateDate = "{createdate}";
+
+ ///
+ /// Template placeholder for legend
+ ///
+ public const string Legend = "{legend}";
+
+ ///
+ /// Template placeholder for namespace
+ ///
+ public const string Namespace = "{namespace}";
+
+ ///
+ /// Template placeholder for theme
+ ///
+ public const string Theme = "{theme}";
+
+ ///
+ /// Template placeholder for padding size
+ ///
+ public const string PaddingSize = "{paddingsize}";
+
+ ///
+ /// Template placeholder for data content
+ ///
+ public const string Data = "{data}";
+
+ ///
+ /// Label used for the "Created" line in file headers
+ ///
+ public const string CreatedLabel = "Created";
+
+ ///
+ /// Label used for the "Filename" line in file headers
+ ///
+ public const string FilenameLabel = "Filename";
+
+ ///
+ /// Double line ending used in file headers
+ ///
+ public const string LineEnding = "\r\n\r\n";
+
+ ///
+ /// Single line ending used in file headers
+ ///
+ public const string SingleLineEnding = "\r\n";
+ }
+}
diff --git a/LCG-UDG/Generation/Extensions.cs b/LCG-UDG/Generation/Extensions.cs
index 7ab3a47..a8fb5e0 100644
--- a/LCG-UDG/Generation/Extensions.cs
+++ b/LCG-UDG/Generation/Extensions.cs
@@ -1,17 +1,21 @@
-using System;
+using McTools.Xrm.Connection;
+using Microsoft.Xrm.Sdk.Metadata;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
+using System.Text.RegularExpressions;
using System.Windows.Forms;
-using McTools.Xrm.Connection;
-using Microsoft.Xrm.Sdk.Metadata;
namespace Rappen.XTB.LCG
{
public static class Extensions
{
+ private const string DatePattern = @"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}";
+ private const string DateFormat = "yyyy-MM-dd HH:mm:ss";
+
public static AttributeMetadata GetAttribute(this Dictionary entities, string entity, string attribute)
{
if (entities == null
@@ -31,21 +35,70 @@ public static bool WriteFile(this string data, string filename, string orgurl, S
var content = GetDataContent(data, settings, version);
content = header + "\r\n\r\n" + content;
content = content.BeautifyContent(settings.TemplateSettings.Template.IndentStr);
+
if (settings.SaveConfigurationInCommonFile)
{
string selection = GetInlineConfiguration(settings);
content += "\r\n\r\n" + selection;
}
- try
+
+ if (File.Exists(filename))
{
- File.WriteAllText(filename, content);
- return true;
+ var existingContent = File.ReadAllText(filename);
+ var contentWithoutDate = RemoveDateFromContent(content);
+ var existingContentWithoutDate = RemoveDateFromContent(existingContent);
+
+ if (contentWithoutDate.Trim().Equals(existingContentWithoutDate.Trim(), StringComparison.Ordinal))
+ {
+ return false;
+ }
}
- catch (Exception e)
+
+ File.WriteAllText(filename, content);
+ return true;
+ }
+
+ private static string RemoveDateFromContent(string content)
+ {
+ var lines = content.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
+ var result = new List();
+ var skipConfiguration = false;
+
+ foreach (var line in lines)
{
- MessageBox.Show(e.Message, "Generate", MessageBoxButtons.OK, MessageBoxIcon.Error);
- return false;
+ if (line.Contains(FileHeaderConstants.CreatedLabel) && line.Contains(":") &&
+ Regex.IsMatch(line, DatePattern))
+ {
+ continue;
+ }
+
+ if (line.Contains(FileHeaderConstants.FilenameLabel) && line.Contains(":"))
+ {
+ continue;
+ }
+
+ // Skip configuration section
+ if (line.Contains("LCG-configuration-BEGIN"))
+ {
+ skipConfiguration = true;
+ continue;
+ }
+
+ if (line.Contains("LCG-configuration-END"))
+ {
+ skipConfiguration = false;
+ continue;
+ }
+
+ if (skipConfiguration)
+ {
+ continue;
+ }
+
+ result.Add(line);
}
+
+ return string.Join("\r\n", result);
}
private static string GetInlineConfiguration(Settings settings)
@@ -63,27 +116,27 @@ private static string GetInlineConfiguration(Settings settings)
private static string GetFileHeader(string filename, string orgurl, Settings settings, string version)
{
var header = settings.TemplateSettings.Template.FileHeader
- .Replace("{toolname}", settings.TemplateSettings.ToolName)
- .Replace("{version}", version)
- .Replace("{organization}", orgurl)
- .Replace("{filename}", filename)
- .Replace("{createdate}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
- .Replace("{legend}", settings.Legend ? settings.TemplateSettings.Template.Legend : string.Empty)
- .Replace("{namespace}", settings.NameSpace)
- .Replace("\r\n\r\n", "\r\n");
+ .Replace(FileHeaderConstants.ToolName, settings.TemplateSettings.ToolName)
+ .Replace(FileHeaderConstants.Version, version)
+ .Replace(FileHeaderConstants.Organization, orgurl)
+ .Replace(FileHeaderConstants.Filename, filename)
+ .Replace(FileHeaderConstants.CreateDate, DateTime.Now.ToString(DateFormat))
+ .Replace(FileHeaderConstants.Legend, settings.Legend ? settings.TemplateSettings.Template.Legend : string.Empty)
+ .Replace(FileHeaderConstants.Namespace, settings.NameSpace)
+ .Replace(FileHeaderConstants.LineEnding, FileHeaderConstants.SingleLineEnding);
return header;
}
private static string GetDataContent(string data, Settings settings, string version)
{
return settings.TemplateSettings.Template.DataContainer
- .Replace("{toolname}", settings.TemplateSettings.ToolName)
- .Replace("{version}", version)
- .Replace("{namespace}", settings.NameSpace)
- .Replace("{theme}", string.IsNullOrEmpty(settings.Theme) ? settings.TemplateSettings.Template.DefaultTheme : settings.GetTheme())
- .Replace("{legend}", settings.Legend ? settings.TemplateSettings.Template.Legend : string.Empty)
- .Replace("{paddingsize}", settings.TableSize.ToString())
- .Replace("{data}", data);
+ .Replace(FileHeaderConstants.ToolName, settings.TemplateSettings.ToolName)
+ .Replace(FileHeaderConstants.Version, version)
+ .Replace(FileHeaderConstants.Namespace, settings.NameSpace)
+ .Replace(FileHeaderConstants.Theme, string.IsNullOrEmpty(settings.Theme) ? settings.TemplateSettings.Template.DefaultTheme : settings.GetTheme())
+ .Replace(FileHeaderConstants.Legend, settings.Legend ? settings.TemplateSettings.Template.Legend : string.Empty)
+ .Replace(FileHeaderConstants.PaddingSize, settings.TableSize.ToString())
+ .Replace(FileHeaderConstants.Data, data);
}
private static string BeautifyContent(this string content, string indentstr)
diff --git a/LCG-UDG/Generation/GenerationUtils.cs b/LCG-UDG/Generation/GenerationUtils.cs
index 5e924a3..d966dd1 100644
--- a/LCG-UDG/Generation/GenerationUtils.cs
+++ b/LCG-UDG/Generation/GenerationUtils.cs
@@ -4,7 +4,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
-using System.Windows.Forms;
namespace Rappen.XTB.LCG
{
@@ -12,45 +11,37 @@ public class GenerationUtils
{
public static bool GenerateFiles(List selectedentities, Settings settings, IConstantFileWriter fileWriter)
{
- try
+ var addedrelationships = new List();
+ var commonentity = GetCommonEntity(selectedentities, settings);
+ var suffix = Settings.FileSuffix(settings.TemplateFormat);
+ if (commonentity != null)
{
- var addedrelationships = new List();
- var commonentity = GetCommonEntity(selectedentities, settings);
- var suffix = Settings.FileSuffix(settings.TemplateFormat);
- if (commonentity != null)
- {
- var entity = GetClass(commonentity, null, settings, addedrelationships);
- var fileName = commonentity.GetNameTechnical(settings.FileName, settings) + suffix;
- fileWriter.WriteBlock(settings, entity, fileName);
- }
- if (settings.Groups?.Count > 0)
- {
- foreach (var group in settings.Groups.Where(g => selectedentities.Any(e => e.Group == g)))
- {
- var groupstr = GetGroup(group, selectedentities.Where(e => e.Group == group).ToList(), settings, addedrelationships);
- fileWriter.WriteBlock(settings, groupstr, group.Name);
- }
- }
- foreach (var entitymetadata in selectedentities.Where(e => e.Group == null))
- {
- var entity = GetClass(entitymetadata, commonentity, settings, addedrelationships);
- var fileName = entitymetadata.GetNameTechnical(settings.FileName, settings) + suffix;
- fileWriter.WriteBlock(settings, entity, fileName);
- }
- if (settings.TemplateSettings.Template.AddAllRelationshipsAfterEntities)
+ var entity = GetClass(commonentity, null, settings, addedrelationships);
+ var fileName = commonentity.GetNameTechnical(settings.FileName, settings) + suffix;
+ fileWriter.WriteBlock(settings, entity, fileName);
+ }
+ if (settings.Groups?.Count > 0)
+ {
+ foreach (var group in settings.Groups.Where(g => selectedentities.Any(e => e.Group == g)))
{
- var relationships = selectedentities.SelectMany(e => e.Relationships.Where(r => r.IsSelected));
- relationships = relationships.GroupBy(r => r.LogicalName).Select(r => r.FirstOrDefault()); // This will make it distinct by LogicalName
- var allrelationshipsstring = GetRelationships(relationships, settings, addedrelationships);
- fileWriter.WriteBlock(settings, allrelationshipsstring, "Relationships" + suffix);
+ var groupstr = GetGroup(group, selectedentities.Where(e => e.Group == group).ToList(), settings, addedrelationships);
+ fileWriter.WriteBlock(settings, groupstr, group.Name);
}
- return fileWriter.Finalize(settings);
}
- catch (Exception ex)
+ foreach (var entitymetadata in selectedentities.Where(e => e.Group == null))
+ {
+ var entity = GetClass(entitymetadata, commonentity, settings, addedrelationships);
+ var fileName = entitymetadata.GetNameTechnical(settings.FileName, settings) + suffix;
+ fileWriter.WriteBlock(settings, entity, fileName);
+ }
+ if (settings.TemplateSettings.Template.AddAllRelationshipsAfterEntities)
{
- MessageBox.Show($"Error:\n{ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
- return false;
+ var relationships = selectedentities.SelectMany(e => e.Relationships.Where(r => r.IsSelected));
+ relationships = relationships.GroupBy(r => r.LogicalName).Select(r => r.FirstOrDefault()); // This will make it distinct by LogicalName
+ var allrelationshipsstring = GetRelationships(relationships, settings, addedrelationships);
+ fileWriter.WriteBlock(settings, allrelationshipsstring, "Relationships" + suffix);
}
+ return fileWriter.Finalize(settings);
}
private static EntityMetadataProxy GetCommonEntity(List selectedentities, Settings settings)
diff --git a/LCG-UDG/LCG-UDG-Common.csproj b/LCG-UDG/LCG-UDG-Common.csproj
index 7834315..095d1db 100644
--- a/LCG-UDG/LCG-UDG-Common.csproj
+++ b/LCG-UDG/LCG-UDG-Common.csproj
@@ -92,6 +92,7 @@
About.cs
+
diff --git a/LCG-UDG/LCG.cs b/LCG-UDG/LCG.cs
index 81a328a..c93039f 100644
--- a/LCG-UDG/LCG.cs
+++ b/LCG-UDG/LCG.cs
@@ -127,20 +127,31 @@ private void btnGenerate_Click(object sender, EventArgs e)
GetSettingsFromUI();
GetSelectionFromUI();
var filewriter = settings.GetWriter(ConnectionDetail.WebApplicationUrl);
- if (GenerationUtils.GenerateFiles(entities.Where(ent => ent.Selected).ToList(), settings, filewriter))
+ try
{
- var message = filewriter.GetResult(settings);
- if (isUML)
+ if (GenerationUtils.GenerateFiles(entities.Where(ent => ent.Selected).ToList(), settings, filewriter))
{
- this.ShowFileLinkMessage(
- message,
- settings.CommonFilePath, 10000);
+ var message = filewriter.GetResult(settings);
+ if (isUML)
+ {
+ this.ShowFileLinkMessage(
+ message,
+ settings.CommonFilePath, 10000);
+ }
+ else
+ {
+ this.ShowSuccessMessage(message, 10000);
+ }
}
else
{
- this.ShowSuccessMessage(message, 10000);
+ this.ShowInfoMessage("No file needed, probably because no changes.", 5000);
}
}
+ catch (Exception ex)
+ {
+ ShowErrorDialog(ex, $"Generate {settings.TemplateFormat}");
+ }
}
private void btnLoadEntities_Click(object sender, EventArgs e)
diff --git a/LCG-UDG/Settings/Settings.cs b/LCG-UDG/Settings/Settings.cs
index 259a40e..5e0d664 100644
--- a/LCG-UDG/Settings/Settings.cs
+++ b/LCG-UDG/Settings/Settings.cs
@@ -1,6 +1,8 @@
-using System.Collections.Generic;
+using Rappen.XRM.Helpers.Extensions;
+using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
+using System.Xml.Serialization;
using XrmToolBox.Extensibility;
namespace Rappen.XTB.LCG
@@ -176,11 +178,41 @@ internal string GetTheme()
public class EntityFilter
{
public bool Expanded { get; set; } = false;
+
+ [XmlIgnore]
public CheckState Custom { get; set; } = CheckState.Checked;
+
+ [XmlElement("Custom")]
+ public string CustomSerialized
+ {
+ get => Custom.ToString();
+ set => Custom = value.ToCheckState(CheckState.Checked);
+ }
+
+ [XmlIgnore]
public CheckState Managed { get; set; } = CheckState.Checked;
+
+ [XmlElement("Managed")]
+ public string ManagedSerialized
+ {
+ get => Managed.ToString();
+ set => Managed = value.ToCheckState(CheckState.Checked);
+ }
+
public bool ExcludeIntersect { get; set; }
+
internal CheckState Selected { get; set; }
+
+ [XmlIgnore]
public CheckState Records { get; set; } = CheckState.Checked;
+
+ [XmlElement("Records")]
+ public string RecordsSerialized
+ {
+ get => Records.ToString();
+ set => Records = value.ToCheckState(CheckState.Checked);
+ }
+
public bool Uncountable { get; set; }
}
@@ -188,12 +220,67 @@ public class AttributeFilter
{
public bool Expanded { get; set; } = false;
public bool CheckAll { get; set; }
+
+ [XmlIgnore]
public CheckState Custom { get; set; } = CheckState.Checked;
+
+ [XmlElement("Custom")]
+ public string CustomSerialized
+ {
+ get => Custom.ToString();
+ set => Custom = value.ToCheckState(CheckState.Checked);
+ }
+
+ [XmlIgnore]
public CheckState Managed { get; set; } = CheckState.Checked;
+
+ [XmlElement("Managed")]
+ public string ManagedSerialized
+ {
+ get => Managed.ToString();
+ set => Managed = value.ToCheckState(CheckState.Checked);
+ }
+
+ [XmlIgnore]
public CheckState PrimaryKeyName { get; set; } = CheckState.Checked;
+
+ [XmlElement("PrimaryKeyName")]
+ public string PrimaryKeyNameSerialized
+ {
+ get => PrimaryKeyName.ToString();
+ set => PrimaryKeyName = value.ToCheckState(CheckState.Checked);
+ }
+
+ [XmlIgnore]
public CheckState Required { get; set; } = CheckState.Checked;
+
+ [XmlElement("Required")]
+ public string RequiredSerialized
+ {
+ get => Required.ToString();
+ set => Required = value.ToCheckState(CheckState.Checked);
+ }
+
+ [XmlIgnore]
public CheckState Logical { get; set; } = CheckState.Unchecked;
+
+ [XmlElement("Logical")]
+ public string LogicalSerialized
+ {
+ get => Logical.ToString();
+ set => Logical = value.ToCheckState(CheckState.Unchecked);
+ }
+
+ [XmlIgnore]
public CheckState Internal { get; set; } = CheckState.Unchecked;
+
+ [XmlElement("Internal")]
+ public string InternalSerialized
+ {
+ get => Internal.ToString();
+ set => Internal = value.ToCheckState(CheckState.Unchecked);
+ }
+
public bool ExcludeCreMod { get; set; } = true;
public bool ExcludeOwner { get; set; } = true;
internal bool AreUsed { get; set; } = false;
@@ -204,8 +291,27 @@ public class RelationshipFilter
{
public bool Expanded { get; set; } = false;
public bool CheckAll { get; set; }
+
+ [XmlIgnore]
public CheckState Custom { get; set; } = CheckState.Checked;
+
+ [XmlElement("Custom")]
+ public string CustomSerialized
+ {
+ get => Custom.ToString();
+ set => Custom = value.ToCheckState(CheckState.Checked);
+ }
+
+ [XmlIgnore]
public CheckState Managed { get; set; } = CheckState.Checked;
+
+ [XmlElement("Managed")]
+ public string ManagedSerialized
+ {
+ get => Managed.ToString();
+ set => Managed = value.ToCheckState(CheckState.Checked);
+ }
+
public bool Type1N { get; set; } = false;
public bool TypeN1 { get; set; } = true;
public bool TypeNN { get; set; } = true;
diff --git a/LCGCmd/LCGHelper.cs b/LCGCmd/LCGHelper.cs
index 58efecc..7deac94 100644
--- a/LCGCmd/LCGHelper.cs
+++ b/LCGCmd/LCGHelper.cs
@@ -47,13 +47,20 @@ public void GenerateConstants()
LoadEntities();
RestoreSelectedEntities();
var writer = Settings.GetWriter(this.crmConnection.WebApplicationUrl);
- if (GenerationUtils.GenerateFiles(entities, Settings, writer))
+ try
{
- Console.Write(writer.GetResult(Settings));
+ if (GenerationUtils.GenerateFiles(entities, Settings, writer))
+ {
+ Console.Write(writer.GetResult(Settings));
+ }
+ else
+ {
+ Console.WriteLine("Not saved, probably because no changes.");
+ }
}
- else
+ catch (Exception ex)
{
- Console.WriteLine("Error");
+ MessageBox.Show($"Error:\n{ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
diff --git a/LCGTests/DatePreservationTests.cs b/LCGTests/DatePreservationTests.cs
new file mode 100644
index 0000000..3a8dfc0
--- /dev/null
+++ b/LCGTests/DatePreservationTests.cs
@@ -0,0 +1,118 @@
+using System;
+using System.IO;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Rappen.XTB.LCG;
+
+namespace LateboundConstantGeneratorTests
+{
+ [TestClass]
+ public class DatePreservationTests
+ {
+ private string _testFilePath;
+
+ [TestInitialize]
+ public void Setup()
+ {
+ _testFilePath = Path.GetTempFileName();
+ }
+
+ [TestCleanup]
+ public void Cleanup()
+ {
+ if (File.Exists(_testFilePath))
+ {
+ File.Delete(_testFilePath);
+ }
+ }
+
+ [TestMethod]
+ public void WriteFile_WhenContentUnchanged_ShouldPreserveOriginalDate()
+ {
+ // Arrange
+ var settings = new Settings();
+ settings.NameSpace = "TestNamespace";
+ var originalDate = "2023-01-15 10:30:45";
+ var originalContent = TestContentHelper.GetExpectedTestContent(Path.GetFileName(_testFilePath), originalDate);
+
+ // Write original file
+ File.WriteAllText(_testFilePath, originalContent);
+
+ // Act - Write the same content again
+ var dataContent = TestContentHelper.GetTestDataContent();
+ var result = dataContent.WriteFile(_testFilePath, "https://test.crm.dynamics.com", settings);
+
+ // Assert
+ Assert.IsTrue(result);
+ var finalContent = File.ReadAllText(_testFilePath);
+ Assert.IsTrue(finalContent.Contains(originalDate), "Original date should be preserved");
+ Assert.IsFalse(finalContent.Contains(DateTime.Now.ToString("yyyy-MM-dd")), "Current date should not be used");
+ }
+
+ [TestMethod]
+ public void WriteFile_WhenContentChanged_ShouldUpdateDate()
+ {
+ // Arrange
+ var settings = new Settings();
+ settings.NameSpace = "TestNamespace";
+ var originalDate = "2023-01-15 10:30:45";
+ var originalContent = TestContentHelper.GetExpectedTestContent(Path.GetFileName(_testFilePath), originalDate);
+
+ // Write original file
+ File.WriteAllText(_testFilePath, originalContent);
+
+ // Act - Write different content
+ var dataContent = TestContentHelper.GetModifiedTestDataContent();
+ var result = dataContent.WriteFile(_testFilePath, "https://test.crm.dynamics.com", settings);
+
+ // Assert
+ Assert.IsTrue(result);
+ var finalContent = File.ReadAllText(_testFilePath);
+ Assert.IsFalse(finalContent.Contains(originalDate), "Original date should not be preserved when content changes");
+ Assert.IsTrue(finalContent.Contains(DateTime.Now.ToString("yyyy-MM-dd")), "Current date should be used when content changes");
+ Assert.IsTrue(finalContent.Contains("modified_entity"), "Modified content should be present");
+ }
+
+ [TestMethod]
+ public void WriteFile_WhenOnlyFilenameChanged_ShouldPreserveOriginalFilename()
+ {
+ // Arrange
+ var settings = new Settings();
+ settings.NameSpace = "TestNamespace";
+ var originalDate = "2023-01-15 10:30:45";
+ var originalFilename = "OriginalFile.cs";
+ var originalContent = TestContentHelper.GetExpectedTestContent(originalFilename, originalDate);
+
+ // Write original file
+ File.WriteAllText(_testFilePath, originalContent);
+
+ // Act - Write content with different filename
+ var dataContent = TestContentHelper.GetTestDataContent();
+ var result = dataContent.WriteFile(_testFilePath, "https://test.crm.dynamics.com", settings);
+
+ // Assert
+ Assert.IsTrue(result);
+ var finalContent = File.ReadAllText(_testFilePath);
+ Assert.IsTrue(finalContent.Contains(originalFilename), "Original filename should be preserved");
+ Assert.IsFalse(finalContent.Contains("ModifiedFile.cs"), "Modified filename should not be used");
+ Assert.IsTrue(finalContent.Contains(originalDate), "Original date should also be preserved");
+ }
+
+ [TestMethod]
+ public void WriteFile_WhenFileDoesNotExist_ShouldUseCurrentDate()
+ {
+ // Arrange
+ var settings = new Settings();
+ settings.NameSpace = "TestNamespace";
+ var dataContent = TestContentHelper.GetNewTestDataContent();
+
+ // Act - Write to new file
+ var result = dataContent.WriteFile(_testFilePath, "https://test.crm.dynamics.com", settings);
+
+ // Assert
+ Assert.IsTrue(result);
+ var finalContent = File.ReadAllText(_testFilePath);
+ Assert.IsTrue(finalContent.Contains(DateTime.Now.ToString("yyyy-MM-dd")), "Current date should be used for new files");
+ Assert.IsTrue(finalContent.Contains("new_entity"), "New content should be present");
+ }
+ }
+}
diff --git a/LCGTests/LCGTests.csproj b/LCGTests/LCGTests.csproj
index ed52ed1..cb9f110 100644
--- a/LCGTests/LCGTests.csproj
+++ b/LCGTests/LCGTests.csproj
@@ -228,8 +228,10 @@
-
+
+
+
@@ -239,6 +241,9 @@
Always
+
+ Always
+
diff --git a/LCGTests/TestContentHelper.cs b/LCGTests/TestContentHelper.cs
new file mode 100644
index 0000000..950a932
--- /dev/null
+++ b/LCGTests/TestContentHelper.cs
@@ -0,0 +1,42 @@
+using System;
+using System.IO;
+
+namespace LateboundConstantGeneratorTests
+{
+ public static class TestContentHelper
+ {
+ private static readonly string TestDataPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "testdata");
+
+ public static string GetExpectedTestContent(string filename, string date)
+ {
+ var templatePath = Path.Combine(TestDataPath, "ExpectedTestContent.cs");
+ var template = File.ReadAllText(templatePath);
+ return string.Format(template, filename, date);
+ }
+
+ public static string GetTestDataContent()
+ {
+ return @"public class TestClass
+{
+ public const string EntityName = ""test_entity"";
+}";
+ }
+
+ public static string GetModifiedTestDataContent()
+ {
+ return @"public class TestClass
+{
+ public const string EntityName = ""modified_entity"";
+ public const string NewProperty = ""new_value"";
+}";
+ }
+
+ public static string GetNewTestDataContent()
+ {
+ return @"public class TestClass
+{
+ public const string EntityName = ""new_entity"";
+}";
+ }
+ }
+}
diff --git a/LCGTests/testdata/ExpectedTestContent.cs b/LCGTests/testdata/ExpectedTestContent.cs
new file mode 100644
index 0000000..55184fe
--- /dev/null
+++ b/LCGTests/testdata/ExpectedTestContent.cs
@@ -0,0 +1,16 @@
+// *********************************************************************
+// Created by : Latebound Constants Generator 1.2023.5.901 for XrmToolBox
+// Tool Author: Jonas Rapp https://jonasr.app/
+// GitHub : https://github.com/rappen/LCG-UDG/
+// Source Org : https://test.crm.dynamics.com
+// Filename : {0}
+// Created : {1}
+// *********************************************************************
+
+namespace TestNamespace
+{{
+ public class TestClass
+ {{
+ public const string EntityName = ""test_entity"";
+ }}
+}}
diff --git a/Rappen.XTB.Helper b/Rappen.XTB.Helper
index 7b60f84..7905fb3 160000
--- a/Rappen.XTB.Helper
+++ b/Rappen.XTB.Helper
@@ -1 +1 @@
-Subproject commit 7b60f8449564d3080ae165292eb53d951e8bc348
+Subproject commit 7905fb35e1e96387da39baff67414cf861d68ae8