Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
63 changes: 63 additions & 0 deletions src/ExCSS.Tests/PreferenceMediaFeaturesTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace ExCSS.Tests
{
using ExCSS;
using Xunit;

// Registration-only coverage for the preference/interaction media features
// (Media Queries 5 / 4). Evaluation/matching is out of scope; these tests
// assert only that each feature is recognized as a typed media feature and
// does not degrade to "not all" (which is what an UnknownMediaFeature does).
public class PreferenceMediaFeaturesTests : CssConstructionFunctions
{
[Theory]
[InlineData("prefers-color-scheme", "dark")]
[InlineData("prefers-color-scheme", "light")]
[InlineData("prefers-reduced-motion", "reduce")]
[InlineData("prefers-reduced-motion", "no-preference")]
[InlineData("prefers-contrast", "more")]
[InlineData("prefers-reduced-transparency", "reduce")]
[InlineData("update", "fast")]
[InlineData("any-hover", "hover")]
[InlineData("any-pointer", "fine")]
public void RegisteredPreferenceFeatureParsesAndRoundTrips(string feature, string value)
{
var source = $"@media ({feature}: {value}) {{ h1 {{ color: green }} }}";
var sheet = ParseStyleSheet(source);

Assert.Equal(1, sheet.Rules.Length);
Assert.IsType<MediaRule>(sheet.Rules[0]);
var media = (MediaRule)sheet.Rules[0];

// A registered feature round-trips; an unregistered one degrades to "not all".
Assert.NotEqual("not all", media.ConditionText);
Assert.Equal($"({feature}: {value})", media.Media.MediaText);
Assert.Equal(1, media.Media.Length);
Assert.Equal(1, media.Rules.Length);
}

[Fact]
public void PreferenceFeatureCombinedWithMediaTypeParses()
{
var source = "@media screen and (prefers-color-scheme: dark) { h1 { color: green } }";
var sheet = ParseStyleSheet(source);

Assert.Equal(1, sheet.Rules.Length);
var media = Assert.IsType<MediaRule>(sheet.Rules[0]);
Assert.Equal("screen and (prefers-color-scheme: dark)", media.Media.MediaText);
Assert.Equal(1, media.Rules.Length);
}

[Fact]
public void UnregisteredFeatureStillDegradesToNotAll()
{
// Guards the assertion above: a genuinely unknown feature must degrade,
// proving the round-trip checks are meaningful.
var source = "@media (prefers-nonsense: banana) { h1 { color: green } }";
var sheet = ParseStyleSheet(source);

Assert.Equal(1, sheet.Rules.Length);
var media = Assert.IsType<MediaRule>(sheet.Rules[0]);
Assert.Equal("not all", media.ConditionText);
}
}
}
7 changes: 7 additions & 0 deletions src/ExCSS/Enumerations/FeatureNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,12 @@ public static class FeatureNames
public static readonly string Hover = "hover";
public static readonly string BlockSize = "block-size";
public static readonly string InlineSize = "inline-size";
public static readonly string PrefersColorScheme = "prefers-color-scheme";
public static readonly string PrefersReducedMotion = "prefers-reduced-motion";
public static readonly string PrefersContrast = "prefers-contrast";
public static readonly string PrefersReducedTransparency = "prefers-reduced-transparency";
public static readonly string Update = "update";
public static readonly string AnyHover = "any-hover";
public static readonly string AnyPointer = "any-pointer";
}
}
7 changes: 7 additions & 0 deletions src/ExCSS/Factories/MediaFeatureFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ internal sealed class MediaFeatureFactory
{FeatureNames.Hover, () => new HoverMediaFeature()},
{FeatureNames.InlineSize, () => new SizeMediaFeature(FeatureNames.InlineSize)},
{FeatureNames.BlockSize, () => new SizeMediaFeature(FeatureNames.BlockSize)},
{FeatureNames.PrefersColorScheme, () => new PrefersColorSchemeMediaFeature()},
{FeatureNames.PrefersReducedMotion, () => new PrefersReducedMotionMediaFeature()},
{FeatureNames.PrefersContrast, () => new PrefersContrastMediaFeature()},
{FeatureNames.PrefersReducedTransparency, () => new PrefersReducedTransparencyMediaFeature()},
{FeatureNames.Update, () => new UpdateMediaFeature()},
{FeatureNames.AnyHover, () => new AnyHoverMediaFeature()},
{FeatureNames.AnyPointer, () => new AnyPointerMediaFeature()},
};

#endregion
Expand Down
11 changes: 11 additions & 0 deletions src/ExCSS/MediaFeatures/AnyHoverMediaFeature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ExCSS
{
internal sealed class AnyHoverMediaFeature : MediaFeature
{
public AnyHoverMediaFeature() : base(FeatureNames.AnyHover)
{
}

internal override IValueConverter Converter => Converters.Any;
}
}
11 changes: 11 additions & 0 deletions src/ExCSS/MediaFeatures/AnyPointerMediaFeature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ExCSS
{
internal sealed class AnyPointerMediaFeature : MediaFeature
{
public AnyPointerMediaFeature() : base(FeatureNames.AnyPointer)
{
}

internal override IValueConverter Converter => Converters.Any;
}
}
11 changes: 11 additions & 0 deletions src/ExCSS/MediaFeatures/PrefersColorSchemeMediaFeature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ExCSS
{
internal sealed class PrefersColorSchemeMediaFeature : MediaFeature
{
public PrefersColorSchemeMediaFeature() : base(FeatureNames.PrefersColorScheme)
{
}

internal override IValueConverter Converter => Converters.Any;
}
}
11 changes: 11 additions & 0 deletions src/ExCSS/MediaFeatures/PrefersContrastMediaFeature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ExCSS
{
internal sealed class PrefersContrastMediaFeature : MediaFeature
{
public PrefersContrastMediaFeature() : base(FeatureNames.PrefersContrast)
{
}

internal override IValueConverter Converter => Converters.Any;
}
}
11 changes: 11 additions & 0 deletions src/ExCSS/MediaFeatures/PrefersReducedMotionMediaFeature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ExCSS
{
internal sealed class PrefersReducedMotionMediaFeature : MediaFeature
{
public PrefersReducedMotionMediaFeature() : base(FeatureNames.PrefersReducedMotion)
{
}

internal override IValueConverter Converter => Converters.Any;
}
}
11 changes: 11 additions & 0 deletions src/ExCSS/MediaFeatures/PrefersReducedTransparencyMediaFeature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ExCSS
{
internal sealed class PrefersReducedTransparencyMediaFeature : MediaFeature
{
public PrefersReducedTransparencyMediaFeature() : base(FeatureNames.PrefersReducedTransparency)
{
}

internal override IValueConverter Converter => Converters.Any;
}
}
11 changes: 11 additions & 0 deletions src/ExCSS/MediaFeatures/UpdateMediaFeature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ExCSS
{
internal sealed class UpdateMediaFeature : MediaFeature
{
public UpdateMediaFeature() : base(FeatureNames.Update)
{
}

internal override IValueConverter Converter => Converters.Any;
}
}