Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2ae3455
Uses string delimeter safe value list parsing for validation
sakari-malkki Feb 5, 2026
f6e1248
Accepts 1 length time val series
sakari-malkki Feb 5, 2026
ca6e002
Tests to cover aforementioned cases
sakari-malkki Feb 5, 2026
741d9b7
Use safer list item extraction method for language validation
sakari-malkki Feb 6, 2026
66bbe44
[Fix] Validator fixes (#84)
sakari-malkki Mar 18, 2026
bc6870c
Allows missing value encoding characters as accepted data section sta…
sakari-malkki Apr 16, 2026
71c0198
Generate documentation file on build
sakari-malkki Apr 16, 2026
4dc9654
Architecture documentation
sakari-malkki Apr 16, 2026
2a5a7e9
Test cases for inconsistent linebreaks + simplified data validation t…
sakari-malkki Apr 17, 2026
6f8caf9
Validation fixes (#85)
jsaarimaa Apr 17, 2026
b75da90
Fix known issues with validation false positives when using known ali…
sakari-malkki Apr 29, 2026
31ab9a5
Rename test
sakari-malkki Apr 30, 2026
c2d5794
Support for custom dimension type aliases
sakari-malkki Apr 30, 2026
a509e40
Cleanup
sakari-malkki Apr 30, 2026
fff7b9d
More cleanup
sakari-malkki Apr 30, 2026
59688b0
Simpler implementation for accepted dimension type values
sakari-malkki Jun 1, 2026
4426723
Fixes validation and metadata building mismatch and tests
sakari-malkki Jun 1, 2026
bf37c8f
Raise minor version number due to scale of changes
sakari-malkki Jun 1, 2026
6744b02
Update documentation and make dimension type mapping case insensitive
sakari-malkki Jun 2, 2026
6a3977c
Cleanup
sakari-malkki Jun 2, 2026
3ee5b63
Invalid test name
sakari-malkki Jun 2, 2026
7ff57ae
Remove references to removed alias functionality in validation
sakari-malkki Jun 2, 2026
47ac546
Remove excess whitespace
sakari-malkki Jun 2, 2026
7e257c0
[Fix] Dimension type validation false positive (#87)
sakari-malkki Jun 3, 2026
7bce924
Release v1.5.0 RC 1 (#86)
jsaarimaa Jun 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,15 @@ Unit testing:
- Use Moq for mocking dependencies in unit tests.
- Use PascalCase for naming test methods, following the pattern: MethodNameStateUnderTestExpectedBehavior.

Architecture:
- See `docs/architecture.md` for the architecture index. It links to focused sub-files — read only the one relevant to your task:
- `docs/architecture.overview.md` — solution structure, config, patterns, file map
- `docs/architecture.validation.md` — validation pipeline, interfaces, extensibility
- `docs/architecture.models.md` — models, metadata, dimensions, builders
- `docs/architecture.readers.md` — metadata/data readers, binary codecs
- `docs/architecture.operations.md` — matrix operations
- `docs/architecture.serializers.md` — JSON converters
- `docs/architecture.testing.md` — unit tests, mocks, benchmarks

Other:
- When refactoring code, update the documentation comments to reflect the changes made.
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Px.Utils.ModelBuilders;
using Px.Utils.ModelBuilders;
using Px.Utils.Models.Metadata.Enums;
using Px.Utils.PxFile;
using System.Globalization;

namespace ModelBuilderTests.ValueParserUtilitiesTests
namespace Px.Utils.UnitTests.ModelBuilderTests.ValueParserUtilitiesTests
{
[TestClass]
public class StringToDimensionTypeTests
Expand All @@ -16,14 +18,27 @@ public void TimeTest()
}

[TestMethod]
public void ContentTest()
public void ContentsTest()
{
string input = "Content";
string input = "Contents";
DimensionType expected = DimensionType.Content;
DimensionType actual = ValueParserUtilities.StringToDimensionType(input);
Assert.AreEqual(expected, actual);
}

[TestMethod]
[DataRow("RANKING", DimensionType.Ordinal)]
[DataRow("region", DimensionType.Geographical)]
public void CustomAliasTest(string alias, DimensionType expected)
{
string input = alias.ToUpper(CultureInfo.InvariantCulture); // Testing case-insensitivity
PxFileConfiguration conf = PxFileConfiguration.Default;
conf.Tokens.VariableTypes.Mappings[alias] = expected;

DimensionType actual = ValueParserUtilities.StringToDimensionType(input, conf);
Assert.AreEqual(expected, actual);
}

[TestMethod]
public void DefaultValueTest()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
using Px.Utils.Validation;
using Px.Utils.Validation.ContentValidation;
using Px.Utils.Validation.SyntaxValidation;
using Px.Utils.PxFile;
using Px.Utils.Models.Metadata.Enums;
using System.Text;
using System.Reflection;
using System.Globalization;

namespace Px.Utils.UnitTests.Validation.ContentValidationTests
{
Expand Down Expand Up @@ -536,6 +539,60 @@ public void ValidateValueTypesCalledWithStructuredEntryArrayWithWrongValuesRetur
}
}

[TestMethod]
[DataRow("ranking", DimensionType.Ordinal)]
[DataRow("REGION", DimensionType.Geographical)]
public void ValidateValueContentsCalledWithCustomDimensionTypesValueReturnsWithoutFeedback(string alias, DimensionType dimensionType)
{
// Arrange
PxFileConfiguration conf = PxFileConfiguration.Default;
conf.Tokens.VariableTypes.Mappings[alias] = dimensionType;

ValidationStructuredEntry entry = new(
filename,
new ValidationStructuredEntryKey("VARIABLE-TYPE", "fi", "foo"),
alias.ToUpper(CultureInfo.InvariantCulture), // The value is converted to upper case to verify case insensitivity of the dimension type matching
0,
[],
0,
Utils.Validation.ValueType.StringValue);

ContentValidator validator = new(filename, encoding, [entry], conf: conf);

// Act
ValidationFeedback? result = ContentValidator.ValidateValueContents(entry, validator);

// Assert
Assert.IsNull(result);
}

[TestMethod]
public void ValidateValueContentsCalledWithUnknownDimensionTypeValueReturnsWithError()
{
// Arrange
PxFileConfiguration conf = PxFileConfiguration.Default;

ValidationStructuredEntry entry = new(
filename,
new ValidationStructuredEntryKey("VARIABLE-TYPE", "fi", "foo"),
"Ranking",
0,
[],
0,
Utils.Validation.ValueType.StringValue);

ContentValidator validator = new(filename, encoding, [entry], conf: conf);

// Act
ValidationFeedback? result = ContentValidator.ValidateValueContents(entry, validator);

// Assert
Assert.IsNotNull(result);
Assert.HasCount(1, result);
Assert.AreEqual(ValidationFeedbackRule.InvalidValueFound, result.First().Key.Rule);
Assert.AreEqual(ValidationFeedbackLevel.Error, result.First().Key.Level);
}

[TestMethod]
public void ValidateValueAmountsCalledWithUnmatchingAmountOfElementsReturnsWithError()
{
Expand All @@ -559,6 +616,27 @@ public void ValidateValueAmountsCalledWithUnmatchingAmountOfElementsReturnsWithE
Assert.AreEqual(ValidationFeedbackRule.UnmatchingValueAmount, result.First().Key.Rule);
}

[TestMethod]
public void ValidateValueAmountsCalledWithMatchingAmountOfElementsWithListDelimetersReturnsNoError()
{
// Arrange
ValidationStructuredEntry[] entries = [ContentValidationFixtures.StructuredEntryWithMatchingAmountOfElementsWithListDelimeters];
ContentValidator validator = new(filename, encoding, entries);
SetValidatorField(validator, "_defaultLanguage", defaultLanguage);
SetValidatorField(validator, "_availableLanguages", availableLanguages);
SetValidatorField(validator, "_stubDimensionNames", stubDimensionNames);
SetValidatorField(validator, "_dimensionValueNames", dimensionValueNames);

// Act
ValidationFeedback? result = ContentValidator.ValidateValueAmounts(
entries[0],
validator
);

// Assert
Assert.IsNull(result);
}

[TestMethod]
public void ValidateValueUppercaseRecommendationsCalledWithLowerCaseEntryReturnsWithWarning()
{
Expand Down
Loading
Loading