lib.modules: add tests for option valueMeta

+13
lib/tests/modules.sh
···
checkConfigError 'attribute .*bar.* not found' config.sub.conditionalImportAsNixos.bar ./specialArgs-class.nix
checkConfigError 'attribute .*foo.* not found' config.sub.conditionalImportAsDarwin.foo ./specialArgs-class.nix
checkConfigOutput '"foo"' config.sub.conditionalImportAsDarwin.bar ./specialArgs-class.nix
+
# Check that some types expose the 'valueMeta'
+
checkConfigOutput '\{\}' options.str.valueMeta ./types-valueMeta.nix
+
checkConfigOutput '["foo", "bar"]' config.attrsOfResult ./types-valueMeta.nix
+
checkConfigOutput '2' config.listOfResult ./types-valueMeta.nix
+
+
# Check that composed types expose the 'valueMeta'
+
# attrsOf submodule (also on merged options,types)
+
checkConfigOutput '42' options.attrsOfModule.valueMeta.attrs.foo.options.bar.value ./composed-types-valueMeta.nix
+
checkConfigOutput '42' options.mergedAttrsOfModule.valueMeta.attrs.foo.options.bar.value ./composed-types-valueMeta.nix
+
+
# listOf submodule (also on merged options,types)
+
checkConfigOutput '42' config.listResult ./composed-types-valueMeta.nix
+
checkConfigOutput '42' config.mergedListResult ./composed-types-valueMeta.nix
cat <<EOF
====== module tests ======
+75
lib/tests/modules/composed-types-valueMeta.nix
···
+
{ lib, ... }:
+
let
+
inherit (lib) types mkOption;
+
+
attrsOfModule = mkOption {
+
type = types.attrsOf (
+
types.submodule {
+
options.bar = mkOption {
+
type = types.int;
+
};
+
}
+
);
+
};
+
+
listOfModule = mkOption {
+
type = types.listOf (
+
types.submodule {
+
options.bar = mkOption {
+
type = types.int;
+
};
+
}
+
);
+
};
+
+
in
+
{
+
imports = [
+
# Module A
+
({
+
options.attrsOfModule = attrsOfModule;
+
options.mergedAttrsOfModule = attrsOfModule;
+
options.listOfModule = listOfModule;
+
options.mergedListOfModule = listOfModule;
+
})
+
# Module B
+
({
+
options.mergedAttrsOfModule = attrsOfModule;
+
options.mergedListOfModule = listOfModule;
+
})
+
# Values
+
# It is important that the value is defined in a separate module
+
# Without valueMeta the actual value and sub-options wouldn't be accessible via:
+
# options.attrsOfModule.type.getSubOptions
+
({
+
attrsOfModule = {
+
foo.bar = 42;
+
};
+
mergedAttrsOfModule = {
+
foo.bar = 42;
+
};
+
})
+
(
+
{ options, ... }:
+
{
+
config.listOfModule = [
+
{
+
bar = 42;
+
}
+
];
+
config.mergedListOfModule = [
+
{
+
bar = 42;
+
}
+
];
+
# Result options to expose the list module to bash as plain attribute path
+
options.listResult = mkOption {
+
default = (builtins.head options.listOfModule.valueMeta.list).options.bar.value;
+
};
+
options.mergedListResult = mkOption {
+
default = (builtins.head options.mergedListOfModule.valueMeta.list).options.bar.value;
+
};
+
}
+
)
+
];
+
}
+60
lib/tests/modules/types-valueMeta.nix
···
+
{ lib, ... }:
+
let
+
inherit (lib) types mkOption;
+
+
inherit (types)
+
# attrsOf uses attrsWith internally
+
attrsOf
+
listOf
+
submoduleOf
+
str
+
;
+
in
+
{
+
imports = [
+
(
+
{ options, ... }:
+
{
+
# Should have an empty valueMeta
+
options.str = mkOption {
+
type = str;
+
};
+
+
# Should have some valueMeta which is an attribute set of the nested valueMeta
+
options.attrsOf = mkOption {
+
type = attrsOf str;
+
default = {
+
foo = "foo";
+
bar = "bar";
+
};
+
};
+
options.attrsOfResult = mkOption {
+
default = builtins.attrNames options.attrsOf.valueMeta.attrs;
+
};
+
+
# Should have some valueMeta which is the list of the nested valueMeta of types.str
+
# [ {} {} ]
+
options.listOf = mkOption {
+
type = listOf str;
+
default = [
+
"foo"
+
"bar"
+
];
+
};
+
options.listOfResult = mkOption {
+
default = builtins.length options.listOf.valueMeta.list;
+
};
+
+
# Should have some valueMeta which is the submodule evaluation
+
# { _module, options, config, ...}
+
options.submoduleOf = mkOption {
+
type = submoduleOf {
+
options.str = mkOption {
+
type = str;
+
};
+
};
+
};
+
}
+
)
+
];
+
}