aboutsummaryrefslogtreecommitdiff
path: root/home-manager/tests
diff options
context:
space:
mode:
Diffstat (limited to 'home-manager/tests')
-rw-r--r--home-manager/tests/default.nix54
-rw-r--r--home-manager/tests/lib/types/dag-merge-result.txt3
-rw-r--r--home-manager/tests/lib/types/dag-merge.nix32
-rw-r--r--home-manager/tests/lib/types/default.nix4
-rw-r--r--home-manager/tests/lib/types/list-or-dag-merge-result.txt15
-rw-r--r--home-manager/tests/lib/types/list-or-dag-merge.nix34
-rw-r--r--home-manager/tests/modules/accounts/email-test-accounts.nix27
-rw-r--r--home-manager/tests/modules/files/.hidden1
-rw-r--r--home-manager/tests/modules/files/default.nix6
-rw-r--r--home-manager/tests/modules/files/executable.nix17
-rw-r--r--home-manager/tests/modules/files/hidden-source.nix19
-rw-r--r--home-manager/tests/modules/files/source with spaces!1
-rw-r--r--home-manager/tests/modules/files/source-with-spaces.nix20
-rw-r--r--home-manager/tests/modules/files/text-expected.txt2
-rw-r--r--home-manager/tests/modules/files/text.nix18
-rw-r--r--home-manager/tests/modules/home-environment/default.nix3
-rw-r--r--home-manager/tests/modules/home-environment/session-variables-expected.txt6
-rw-r--r--home-manager/tests/modules/home-environment/session-variables.nix19
-rw-r--r--home-manager/tests/modules/misc/fontconfig/default.nix5
-rw-r--r--home-manager/tests/modules/misc/fontconfig/multiple-font-packages.nix15
-rw-r--r--home-manager/tests/modules/misc/fontconfig/no-font-package.nix17
-rw-r--r--home-manager/tests/modules/misc/fontconfig/single-font-package.nix15
-rw-r--r--home-manager/tests/modules/misc/pam/default.nix1
-rw-r--r--home-manager/tests/modules/misc/pam/session-variables-expected.txt2
-rw-r--r--home-manager/tests/modules/misc/pam/session-variables.nix19
-rw-r--r--home-manager/tests/modules/misc/xdg/default.nix1
-rw-r--r--home-manager/tests/modules/misc/xdg/mime-apps-basics-expected.ini9
-rw-r--r--home-manager/tests/modules/misc/xdg/mime-apps-basics.nix28
-rw-r--r--home-manager/tests/modules/misc/xsession/basic-setxkbmap-expected.service12
-rw-r--r--home-manager/tests/modules/misc/xsession/basic-xprofile-expected.txt16
-rw-r--r--home-manager/tests/modules/misc/xsession/basic-xsession-expected.txt18
-rw-r--r--home-manager/tests/modules/misc/xsession/basic.nix42
-rw-r--r--home-manager/tests/modules/misc/xsession/default.nix4
-rw-r--r--home-manager/tests/modules/misc/xsession/keyboard-without-layout-expected.service12
-rw-r--r--home-manager/tests/modules/misc/xsession/keyboard-without-layout.nix36
-rw-r--r--home-manager/tests/modules/programs/alacritty/default.nix4
-rw-r--r--home-manager/tests/modules/programs/alacritty/empty-settings.nix17
-rw-r--r--home-manager/tests/modules/programs/alacritty/example-settings-expected.yml1
-rw-r--r--home-manager/tests/modules/programs/alacritty/example-settings.nix34
-rw-r--r--home-manager/tests/modules/programs/bash/default.nix4
-rw-r--r--home-manager/tests/modules/programs/bash/logout-expected.txt4
-rw-r--r--home-manager/tests/modules/programs/bash/logout.nix22
-rw-r--r--home-manager/tests/modules/programs/bash/session-variables-expected.txt8
-rw-r--r--home-manager/tests/modules/programs/bash/session-variables.nix25
-rw-r--r--home-manager/tests/modules/programs/browserpass/browserpass.nix29
-rw-r--r--home-manager/tests/modules/programs/browserpass/default.nix1
-rw-r--r--home-manager/tests/modules/programs/firefox/default.nix4
-rw-r--r--home-manager/tests/modules/programs/firefox/profile-settings-expected-user.js6
-rw-r--r--home-manager/tests/modules/programs/firefox/profile-settings.nix36
-rw-r--r--home-manager/tests/modules/programs/firefox/state-version-19_09.nix31
-rw-r--r--home-manager/tests/modules/programs/getmail/default.nix1
-rw-r--r--home-manager/tests/modules/programs/getmail/getmail-expected.conf16
-rw-r--r--home-manager/tests/modules/programs/getmail/getmail.nix31
-rw-r--r--home-manager/tests/modules/programs/git/default.nix5
-rw-r--r--home-manager/tests/modules/programs/git/git-expected.conf42
-rw-r--r--home-manager/tests/modules/programs/git/git-with-email-expected.conf15
-rw-r--r--home-manager/tests/modules/programs/git/git-with-email.nix36
-rw-r--r--home-manager/tests/modules/programs/git/git-with-str-extra-config-expected.conf5
-rw-r--r--home-manager/tests/modules/programs/git/git-with-str-extra-config.nix23
-rw-r--r--home-manager/tests/modules/programs/git/git.nix77
-rw-r--r--home-manager/tests/modules/programs/gpg/default.nix1
-rw-r--r--home-manager/tests/modules/programs/gpg/override-defaults-expected.conf19
-rw-r--r--home-manager/tests/modules/programs/gpg/override-defaults.nix22
-rw-r--r--home-manager/tests/modules/programs/mbsync/default.nix1
-rw-r--r--home-manager/tests/modules/programs/mbsync/mbsync-expected.conf55
-rw-r--r--home-manager/tests/modules/programs/mbsync/mbsync.nix31
-rw-r--r--home-manager/tests/modules/programs/neomutt/default.nix1
-rw-r--r--home-manager/tests/modules/programs/neomutt/hm-example.com-expected37
-rw-r--r--home-manager/tests/modules/programs/neomutt/neomutt-expected.conf27
-rw-r--r--home-manager/tests/modules/programs/neomutt/neomutt.nix47
-rw-r--r--home-manager/tests/modules/programs/newsboat/default.nix1
-rw-r--r--home-manager/tests/modules/programs/newsboat/newsboat-basics-urls.txt3
-rw-r--r--home-manager/tests/modules/programs/newsboat/newsboat-basics.nix33
-rw-r--r--home-manager/tests/modules/programs/readline/default.nix1
-rw-r--r--home-manager/tests/modules/programs/readline/using-all-options.nix31
-rw-r--r--home-manager/tests/modules/programs/readline/using-all-options.txt11
-rw-r--r--home-manager/tests/modules/programs/rofi/assert-on-both-theme-and-colors-expected.json1
-rw-r--r--home-manager/tests/modules/programs/rofi/assert-on-both-theme-and-colors.nix29
-rw-r--r--home-manager/tests/modules/programs/rofi/default.nix3
-rw-r--r--home-manager/tests/modules/programs/ssh/default-config-expected.conf15
-rw-r--r--home-manager/tests/modules/programs/ssh/default-config.nix18
-rw-r--r--home-manager/tests/modules/programs/ssh/default.nix17
-rw-r--r--home-manager/tests/modules/programs/ssh/forwards-dynamic-bind-path-with-port-asserts.nix29
-rw-r--r--home-manager/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts-expected.conf19
-rw-r--r--home-manager/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts.nix38
-rw-r--r--home-manager/tests/modules/programs/ssh/forwards-local-bind-path-with-port-asserts.nix33
-rw-r--r--home-manager/tests/modules/programs/ssh/forwards-local-host-path-with-port-asserts.nix33
-rw-r--r--home-manager/tests/modules/programs/ssh/forwards-paths-with-ports-error.json1
-rw-r--r--home-manager/tests/modules/programs/ssh/forwards-remote-bind-path-with-port-asserts.nix33
-rw-r--r--home-manager/tests/modules/programs/ssh/forwards-remote-host-path-with-port-asserts.nix33
-rw-r--r--home-manager/tests/modules/programs/ssh/match-blocks-attrs-expected.conf29
-rw-r--r--home-manager/tests/modules/programs/ssh/match-blocks-attrs.nix55
-rw-r--r--home-manager/tests/modules/programs/ssh/no-assertions.json1
-rw-r--r--home-manager/tests/modules/programs/texlive/default.nix1
-rw-r--r--home-manager/tests/modules/programs/texlive/texlive-minimal.nix13
-rw-r--r--home-manager/tests/modules/programs/tmux/default.nix7
-rw-r--r--home-manager/tests/modules/programs/tmux/disable-confirmation-prompt.conf31
-rw-r--r--home-manager/tests/modules/programs/tmux/disable-confirmation-prompt.nix28
-rw-r--r--home-manager/tests/modules/programs/tmux/emacs-with-plugins.conf54
-rw-r--r--home-manager/tests/modules/programs/tmux/emacs-with-plugins.nix49
-rw-r--r--home-manager/tests/modules/programs/tmux/hm-session-vars.sh5
-rw-r--r--home-manager/tests/modules/programs/tmux/not-enabled.nix13
-rw-r--r--home-manager/tests/modules/programs/tmux/secure-socket-enabled.nix17
-rw-r--r--home-manager/tests/modules/programs/tmux/vi-all-true.conf31
-rw-r--r--home-manager/tests/modules/programs/tmux/vi-all-true.nix29
-rw-r--r--home-manager/tests/modules/programs/zsh/default.nix7
-rw-r--r--home-manager/tests/modules/programs/zsh/history-path-new-custom.nix20
-rw-r--r--home-manager/tests/modules/programs/zsh/history-path-new-default.nix17
-rw-r--r--home-manager/tests/modules/programs/zsh/history-path-old-custom.nix20
-rw-r--r--home-manager/tests/modules/programs/zsh/history-path-old-default.nix17
-rw-r--r--home-manager/tests/modules/programs/zsh/session-variables.nix28
-rw-r--r--home-manager/tests/modules/services/sxhkd/configuration.nix30
-rw-r--r--home-manager/tests/modules/services/sxhkd/default.nix4
-rw-r--r--home-manager/tests/modules/services/sxhkd/service.nix20
-rw-r--r--home-manager/tests/modules/services/sxhkd/sxhkdrc13
-rw-r--r--home-manager/tests/modules/services/window-managers/i3/default.nix1
-rw-r--r--home-manager/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf106
-rw-r--r--home-manager/tests/modules/services/window-managers/i3/i3-keybindings.nix35
-rw-r--r--home-manager/tests/modules/systemd/default.nix5
-rw-r--r--home-manager/tests/modules/systemd/services-expected.conf5
-rw-r--r--home-manager/tests/modules/systemd/services.nix23
-rw-r--r--home-manager/tests/modules/systemd/session-variables-expected.conf2
-rw-r--r--home-manager/tests/modules/systemd/session-variables.nix18
-rw-r--r--home-manager/tests/modules/systemd/timers-expected.conf8
-rw-r--r--home-manager/tests/modules/systemd/timers.nix25
-rw-r--r--home-manager/tests/modules/xresources/default.nix1
-rw-r--r--home-manager/tests/modules/xresources/xresources-expected.conf5
-rw-r--r--home-manager/tests/modules/xresources/xresources.nix22
128 files changed, 2428 insertions, 0 deletions
diff --git a/home-manager/tests/default.nix b/home-manager/tests/default.nix
new file mode 100644
index 00000000000..49c27239730
--- /dev/null
+++ b/home-manager/tests/default.nix
@@ -0,0 +1,54 @@
+{ pkgs ? import <nixpkgs> {} }:
+
+let
+
+ lib = import ../modules/lib/stdlib-extended.nix pkgs.lib;
+
+ nmt = pkgs.fetchFromGitLab {
+ owner = "rycee";
+ repo = "nmt";
+ rev = "6f866d1acb89fa15cd3b62baa052deae1f685c0c";
+ sha256 = "1qr1shhapjn4nnd4k6hml69ri8vgz4l8lakjll5hc516shs9a9nn";
+ };
+
+ modules = import ../modules/modules.nix {
+ inherit lib pkgs;
+ check = false;
+ };
+
+in
+
+import nmt {
+ inherit lib pkgs modules;
+ testedAttrPath = [ "home" "activationPackage" ];
+ tests = builtins.foldl' (a: b: a // (import b)) { } ([
+ ./lib/types
+ ./modules/files
+ ./modules/home-environment
+ ./modules/misc/fontconfig
+ ./modules/programs/alacritty
+ ./modules/programs/bash
+ ./modules/programs/browserpass
+ ./modules/programs/git
+ ./modules/programs/gpg
+ ./modules/programs/mbsync
+ ./modules/programs/neomutt
+ ./modules/programs/newsboat
+ ./modules/programs/readline
+ ./modules/programs/ssh
+ ./modules/programs/texlive
+ ./modules/programs/tmux
+ ./modules/programs/zsh
+ ./modules/xresources
+ ] ++ lib.optionals pkgs.stdenv.hostPlatform.isLinux [
+ ./modules/misc/pam
+ ./modules/misc/xdg
+ ./modules/misc/xsession
+ ./modules/programs/firefox
+ ./modules/programs/getmail
+ ./modules/programs/rofi
+ ./modules/services/sxhkd
+ ./modules/services/window-managers/i3
+ ./modules/systemd
+ ]);
+}
diff --git a/home-manager/tests/lib/types/dag-merge-result.txt b/home-manager/tests/lib/types/dag-merge-result.txt
new file mode 100644
index 00000000000..9779ef13c0f
--- /dev/null
+++ b/home-manager/tests/lib/types/dag-merge-result.txt
@@ -0,0 +1,3 @@
+before:before
+between:between
+after:after
diff --git a/home-manager/tests/lib/types/dag-merge.nix b/home-manager/tests/lib/types/dag-merge.nix
new file mode 100644
index 00000000000..138a0b64fb7
--- /dev/null
+++ b/home-manager/tests/lib/types/dag-merge.nix
@@ -0,0 +1,32 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ dag = config.lib.dag;
+
+ result = let
+ sorted = dag.topoSort config.tested.dag;
+ data = map (e: "${e.name}:${e.data}") sorted.result;
+ in concatStringsSep "\n" data + "\n";
+
+in {
+ options.tested.dag = mkOption { type = hm.types.dagOf types.str; };
+
+ config = {
+ tested = mkMerge [
+ { dag.after = "after"; }
+ { dag.before = dag.entryBefore [ "after" ] "before"; }
+ { dag.between = dag.entryBetween [ "after" ] [ "before" ] "between"; }
+ ];
+
+ home.file."result.txt".text = result;
+
+ nmt.script = ''
+ assertFileContent \
+ home-files/result.txt \
+ ${./dag-merge-result.txt}
+ '';
+ };
+}
diff --git a/home-manager/tests/lib/types/default.nix b/home-manager/tests/lib/types/default.nix
new file mode 100644
index 00000000000..9fce65f88f0
--- /dev/null
+++ b/home-manager/tests/lib/types/default.nix
@@ -0,0 +1,4 @@
+{
+ lib-types-dag-merge = ./dag-merge.nix;
+ lib-types-list-or-dag-merge = ./list-or-dag-merge.nix;
+}
diff --git a/home-manager/tests/lib/types/list-or-dag-merge-result.txt b/home-manager/tests/lib/types/list-or-dag-merge-result.txt
new file mode 100644
index 00000000000..5fb67a5101c
--- /dev/null
+++ b/home-manager/tests/lib/types/list-or-dag-merge-result.txt
@@ -0,0 +1,15 @@
+before:before
+between:between
+after:after
+unnamed-1.1:k
+unnamed-1.2:l
+unnamed-2.01:a
+unnamed-2.02:b
+unnamed-2.03:c
+unnamed-2.04:d
+unnamed-2.05:e
+unnamed-2.06:f
+unnamed-2.07:g
+unnamed-2.08:h
+unnamed-2.09:i
+unnamed-2.10:j
diff --git a/home-manager/tests/lib/types/list-or-dag-merge.nix b/home-manager/tests/lib/types/list-or-dag-merge.nix
new file mode 100644
index 00000000000..08216140e53
--- /dev/null
+++ b/home-manager/tests/lib/types/list-or-dag-merge.nix
@@ -0,0 +1,34 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ dag = config.lib.dag;
+
+ result = let
+ sorted = dag.topoSort config.tested.dag;
+ data = map (e: "${e.name}:${e.data}") sorted.result;
+ in concatStringsSep "\n" data + "\n";
+
+in {
+ options.tested.dag = mkOption { type = hm.types.listOrDagOf types.str; };
+
+ config = {
+ tested = mkMerge [
+ { dag = [ "k" "l" ]; }
+ { dag = [ "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" ]; }
+ { dag.after = "after"; }
+ { dag.before = dag.entryBefore [ "after" ] "before"; }
+ { dag.between = dag.entryBetween [ "after" ] [ "before" ] "between"; }
+ ];
+
+ home.file."result.txt".text = result;
+
+ nmt.script = ''
+ assertFileContent \
+ home-files/result.txt \
+ ${./list-or-dag-merge-result.txt}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/accounts/email-test-accounts.nix b/home-manager/tests/modules/accounts/email-test-accounts.nix
new file mode 100644
index 00000000000..9c9c90cf8fe
--- /dev/null
+++ b/home-manager/tests/modules/accounts/email-test-accounts.nix
@@ -0,0 +1,27 @@
+{ ... }:
+
+{
+ accounts.email = {
+ maildirBasePath = "Mail";
+
+ accounts = {
+ "hm@example.com" = {
+ address = "hm@example.com";
+ userName = "home.manager";
+ realName = "H. M. Test";
+ passwordCommand = "password-command";
+ imap.host = "imap.example.com";
+ smtp.host = "smtp.example.com";
+ };
+
+ hm-account = {
+ address = "hm@example.org";
+ userName = "home.manager.jr";
+ realName = "H. M. Test Jr.";
+ passwordCommand = "password-command 2";
+ imap.host = "imap.example.org";
+ smtp.host = "smtp.example.org";
+ };
+ };
+ };
+}
diff --git a/home-manager/tests/modules/files/.hidden b/home-manager/tests/modules/files/.hidden
new file mode 100644
index 00000000000..ca05448e7a0
--- /dev/null
+++ b/home-manager/tests/modules/files/.hidden
@@ -0,0 +1 @@
+The name of this file has a dot prefix.
diff --git a/home-manager/tests/modules/files/default.nix b/home-manager/tests/modules/files/default.nix
new file mode 100644
index 00000000000..04c61d3b886
--- /dev/null
+++ b/home-manager/tests/modules/files/default.nix
@@ -0,0 +1,6 @@
+{
+ files-executable = ./executable.nix;
+ files-hidden-source = ./hidden-source.nix;
+ files-source-with-spaces = ./source-with-spaces.nix;
+ files-text = ./text.nix;
+}
diff --git a/home-manager/tests/modules/files/executable.nix b/home-manager/tests/modules/files/executable.nix
new file mode 100644
index 00000000000..b286c2b499f
--- /dev/null
+++ b/home-manager/tests/modules/files/executable.nix
@@ -0,0 +1,17 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+ config = {
+ home.file."executable" = {
+ text = "";
+ executable = true;
+ };
+
+ nmt.script = ''
+ assertFileExists home-files/executable
+ assertFileIsExecutable home-files/executable;
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/files/hidden-source.nix b/home-manager/tests/modules/files/hidden-source.nix
new file mode 100644
index 00000000000..8169fedcd7f
--- /dev/null
+++ b/home-manager/tests/modules/files/hidden-source.nix
@@ -0,0 +1,19 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+ config = {
+ home.file.".hidden".source = ./.hidden;
+
+ nmt.script = ''
+ assertFileExists home-files/.hidden;
+ assertFileContent home-files/.hidden ${
+ builtins.path {
+ path = ./.hidden;
+ name = "expected";
+ }
+ }
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/files/source with spaces! b/home-manager/tests/modules/files/source with spaces!
new file mode 100644
index 00000000000..e1ace404174
--- /dev/null
+++ b/home-manager/tests/modules/files/source with spaces!
@@ -0,0 +1 @@
+Source with spaces!
diff --git a/home-manager/tests/modules/files/source-with-spaces.nix b/home-manager/tests/modules/files/source-with-spaces.nix
new file mode 100644
index 00000000000..1d593c64256
--- /dev/null
+++ b/home-manager/tests/modules/files/source-with-spaces.nix
@@ -0,0 +1,20 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+ config = {
+ home.file."source with spaces!".source = ./. + "/source with spaces!";
+
+ nmt.script = ''
+ assertFileExists 'home-files/source with spaces!';
+ assertFileContent 'home-files/source with spaces!' \
+ ${
+ builtins.path {
+ path = ./. + "/source with spaces!";
+ name = "source-with-spaces-expected";
+ }
+ }
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/files/text-expected.txt b/home-manager/tests/modules/files/text-expected.txt
new file mode 100644
index 00000000000..b3a0ff2db12
--- /dev/null
+++ b/home-manager/tests/modules/files/text-expected.txt
@@ -0,0 +1,2 @@
+This is the
+expected text.
diff --git a/home-manager/tests/modules/files/text.nix b/home-manager/tests/modules/files/text.nix
new file mode 100644
index 00000000000..6fc9a26fcb4
--- /dev/null
+++ b/home-manager/tests/modules/files/text.nix
@@ -0,0 +1,18 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+ config = {
+ home.file."using-text".text = ''
+ This is the
+ expected text.
+ '';
+
+ nmt.script = ''
+ assertFileExists home-files/using-text
+ assertFileIsNotExecutable home-files/using-text
+ assertFileContent home-files/using-text ${./text-expected.txt}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/home-environment/default.nix b/home-manager/tests/modules/home-environment/default.nix
new file mode 100644
index 00000000000..2a1201a2f0a
--- /dev/null
+++ b/home-manager/tests/modules/home-environment/default.nix
@@ -0,0 +1,3 @@
+{
+ home-session-variables = ./session-variables.nix;
+}
diff --git a/home-manager/tests/modules/home-environment/session-variables-expected.txt b/home-manager/tests/modules/home-environment/session-variables-expected.txt
new file mode 100644
index 00000000000..5c3868c3901
--- /dev/null
+++ b/home-manager/tests/modules/home-environment/session-variables-expected.txt
@@ -0,0 +1,6 @@
+# Only source this once.
+if [ -n "$__HM_SESS_VARS_SOURCED" ]; then return; fi
+export __HM_SESS_VARS_SOURCED=1
+
+export V1="v1"
+export V2="v2-v1"
diff --git a/home-manager/tests/modules/home-environment/session-variables.nix b/home-manager/tests/modules/home-environment/session-variables.nix
new file mode 100644
index 00000000000..9f326ebc1b8
--- /dev/null
+++ b/home-manager/tests/modules/home-environment/session-variables.nix
@@ -0,0 +1,19 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+ config = {
+ home.sessionVariables = {
+ V1 = "v1";
+ V2 = "v2-${config.home.sessionVariables.V1}";
+ };
+
+ nmt.script = ''
+ assertFileExists home-path/etc/profile.d/hm-session-vars.sh
+ assertFileContent \
+ home-path/etc/profile.d/hm-session-vars.sh \
+ ${./session-variables-expected.txt}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/misc/fontconfig/default.nix b/home-manager/tests/modules/misc/fontconfig/default.nix
new file mode 100644
index 00000000000..b669e1c343c
--- /dev/null
+++ b/home-manager/tests/modules/misc/fontconfig/default.nix
@@ -0,0 +1,5 @@
+{
+ fontconfig-no-font-package = ./no-font-package.nix;
+ fontconfig-single-font-package = ./single-font-package.nix;
+ fontconfig-multiple-font-packages = ./multiple-font-packages.nix;
+}
diff --git a/home-manager/tests/modules/misc/fontconfig/multiple-font-packages.nix b/home-manager/tests/modules/misc/fontconfig/multiple-font-packages.nix
new file mode 100644
index 00000000000..3845b4ba4b1
--- /dev/null
+++ b/home-manager/tests/modules/misc/fontconfig/multiple-font-packages.nix
@@ -0,0 +1,15 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ home.packages = [ pkgs.comic-relief pkgs.unifont ];
+
+ fonts.fontconfig.enable = true;
+
+ nmt.script = ''
+ assertDirectoryNotEmpty home-path/lib/fontconfig/cache
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/misc/fontconfig/no-font-package.nix b/home-manager/tests/modules/misc/fontconfig/no-font-package.nix
new file mode 100644
index 00000000000..c4c687a1320
--- /dev/null
+++ b/home-manager/tests/modules/misc/fontconfig/no-font-package.nix
@@ -0,0 +1,17 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ home.packages = [
+ # Look, no font!
+ ];
+
+ fonts.fontconfig.enable = true;
+
+ nmt.script = ''
+ assertPathNotExists home-path/lib/fontconfig/cache
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/misc/fontconfig/single-font-package.nix b/home-manager/tests/modules/misc/fontconfig/single-font-package.nix
new file mode 100644
index 00000000000..b70bdf8a9a7
--- /dev/null
+++ b/home-manager/tests/modules/misc/fontconfig/single-font-package.nix
@@ -0,0 +1,15 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ home.packages = [ pkgs.comic-relief ];
+
+ fonts.fontconfig.enable = true;
+
+ nmt.script = ''
+ assertDirectoryNotEmpty home-path/lib/fontconfig/cache
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/misc/pam/default.nix b/home-manager/tests/modules/misc/pam/default.nix
new file mode 100644
index 00000000000..81c435e7641
--- /dev/null
+++ b/home-manager/tests/modules/misc/pam/default.nix
@@ -0,0 +1 @@
+{ pam-session-variables = ./session-variables.nix; }
diff --git a/home-manager/tests/modules/misc/pam/session-variables-expected.txt b/home-manager/tests/modules/misc/pam/session-variables-expected.txt
new file mode 100644
index 00000000000..b84a12b7675
--- /dev/null
+++ b/home-manager/tests/modules/misc/pam/session-variables-expected.txt
@@ -0,0 +1,2 @@
+V1 OVERRIDE="v1"
+V2 OVERRIDE="v2-v1"
diff --git a/home-manager/tests/modules/misc/pam/session-variables.nix b/home-manager/tests/modules/misc/pam/session-variables.nix
new file mode 100644
index 00000000000..4fbec4163b5
--- /dev/null
+++ b/home-manager/tests/modules/misc/pam/session-variables.nix
@@ -0,0 +1,19 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+ config = {
+ pam.sessionVariables = {
+ V1 = "v1";
+ V2 = "v2-${config.pam.sessionVariables.V1}";
+ };
+
+ nmt.script = ''
+ assertFileExists home-files/.pam_environment
+ assertFileContent \
+ home-files/.pam_environment \
+ ${./session-variables-expected.txt}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/misc/xdg/default.nix b/home-manager/tests/modules/misc/xdg/default.nix
new file mode 100644
index 00000000000..e5d015759d5
--- /dev/null
+++ b/home-manager/tests/modules/misc/xdg/default.nix
@@ -0,0 +1 @@
+{ xdg-mime-apps-basics = ./mime-apps-basics.nix; }
diff --git a/home-manager/tests/modules/misc/xdg/mime-apps-basics-expected.ini b/home-manager/tests/modules/misc/xdg/mime-apps-basics-expected.ini
new file mode 100644
index 00000000000..c27181eb58f
--- /dev/null
+++ b/home-manager/tests/modules/misc/xdg/mime-apps-basics-expected.ini
@@ -0,0 +1,9 @@
+[Added Associations]
+mimetype1=foo1.desktop;foo2.desktop;foo3.desktop
+mimetype2=foo4.desktop
+
+[Default Applications]
+mimetype1=default1.desktop;default2.desktop
+
+[Removed Associations]
+mimetype1=foo5.desktop
diff --git a/home-manager/tests/modules/misc/xdg/mime-apps-basics.nix b/home-manager/tests/modules/misc/xdg/mime-apps-basics.nix
new file mode 100644
index 00000000000..e181e8206f6
--- /dev/null
+++ b/home-manager/tests/modules/misc/xdg/mime-apps-basics.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ xdg.mimeApps = {
+ enable = true;
+ associations = {
+ added = {
+ "mimetype1" = [ "foo1.desktop" "foo2.desktop" "foo3.desktop" ];
+ "mimetype2" = "foo4.desktop";
+ };
+ removed = { mimetype1 = "foo5.desktop"; };
+ };
+ defaultApplications = {
+ "mimetype1" = [ "default1.desktop" "default2.desktop" ];
+ };
+ };
+
+ nmt.script = ''
+ assertFileExists home-files/.config/mimeapps.list
+ assertFileContent \
+ home-files/.config/mimeapps.list \
+ ${./mime-apps-basics-expected.ini}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/misc/xsession/basic-setxkbmap-expected.service b/home-manager/tests/modules/misc/xsession/basic-setxkbmap-expected.service
new file mode 100644
index 00000000000..39f876dd60e
--- /dev/null
+++ b/home-manager/tests/modules/misc/xsession/basic-setxkbmap-expected.service
@@ -0,0 +1,12 @@
+[Install]
+WantedBy=graphical-session.target
+
+[Service]
+ExecStart=@setxkbmap@/bin/setxkbmap -layout 'us' -variant ''
+RemainAfterExit=true
+Type=oneshot
+
+[Unit]
+After=graphical-session-pre.target
+Description=Set up keyboard in X
+PartOf=graphical-session.target
diff --git a/home-manager/tests/modules/misc/xsession/basic-xprofile-expected.txt b/home-manager/tests/modules/misc/xsession/basic-xprofile-expected.txt
new file mode 100644
index 00000000000..05733a974ff
--- /dev/null
+++ b/home-manager/tests/modules/misc/xsession/basic-xprofile-expected.txt
@@ -0,0 +1,16 @@
+. "/test-home/.nix-profile/etc/profile.d/hm-session-vars.sh"
+
+if [ -e "$HOME/.profile" ]; then
+ . "$HOME/.profile"
+fi
+
+# If there are any running services from a previous session.
+# Need to run this in xprofile because the NixOS xsession
+# script starts up graphical-session.target.
+systemctl --user stop graphical-session.target graphical-session-pre.target
+
+systemctl --user import-environment DBUS_SESSION_BUS_ADDRESS DISPLAY SSH_AUTH_SOCK XAUTHORITY XDG_DATA_DIRS XDG_RUNTIME_DIR XDG_SESSION_ID EXTRA_IMPORTED_VARIABLE
+
+profile extra commands
+
+export HM_XPROFILE_SOURCED=1
diff --git a/home-manager/tests/modules/misc/xsession/basic-xsession-expected.txt b/home-manager/tests/modules/misc/xsession/basic-xsession-expected.txt
new file mode 100644
index 00000000000..c11b7c33048
--- /dev/null
+++ b/home-manager/tests/modules/misc/xsession/basic-xsession-expected.txt
@@ -0,0 +1,18 @@
+if [ -z "$HM_XPROFILE_SOURCED" ]; then
+ . ~/.xprofile
+fi
+unset HM_XPROFILE_SOURCED
+
+systemctl --user start hm-graphical-session.target
+
+init extra commands
+
+window manager command
+
+systemctl --user stop graphical-session.target
+systemctl --user stop graphical-session-pre.target
+
+# Wait until the units actually stop.
+while [ -n "$(systemctl --user --no-legend --state=deactivating list-units)" ]; do
+ sleep 0.5
+done
diff --git a/home-manager/tests/modules/misc/xsession/basic.nix b/home-manager/tests/modules/misc/xsession/basic.nix
new file mode 100644
index 00000000000..39df6362380
--- /dev/null
+++ b/home-manager/tests/modules/misc/xsession/basic.nix
@@ -0,0 +1,42 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ home.homeDirectory = "/test-home";
+
+ xsession = {
+ enable = true;
+ windowManager.command = "window manager command";
+ importedVariables = [ "EXTRA_IMPORTED_VARIABLE" ];
+ initExtra = "init extra commands";
+ profileExtra = "profile extra commands";
+ };
+
+ nixpkgs.overlays = [
+ (self: super: {
+ xorg = super.xorg // {
+ setxkbmap = super.xorg.setxkbmap // { outPath = "@setxkbmap@"; };
+ };
+ })
+ ];
+
+ nmt.script = ''
+ assertFileExists home-files/.xprofile
+ assertFileContent \
+ home-files/.xprofile \
+ ${./basic-xprofile-expected.txt}
+
+ assertFileExists home-files/.xsession
+ assertFileContent \
+ home-files/.xsession \
+ ${./basic-xsession-expected.txt}
+
+ assertFileExists home-files/.config/systemd/user/setxkbmap.service
+ assertFileContent \
+ home-files/.config/systemd/user/setxkbmap.service \
+ ${./basic-setxkbmap-expected.service}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/misc/xsession/default.nix b/home-manager/tests/modules/misc/xsession/default.nix
new file mode 100644
index 00000000000..2ddbf47efac
--- /dev/null
+++ b/home-manager/tests/modules/misc/xsession/default.nix
@@ -0,0 +1,4 @@
+{
+ xsession-basic = ./basic.nix;
+ xsession-keyboard-without-layout = ./keyboard-without-layout.nix;
+}
diff --git a/home-manager/tests/modules/misc/xsession/keyboard-without-layout-expected.service b/home-manager/tests/modules/misc/xsession/keyboard-without-layout-expected.service
new file mode 100644
index 00000000000..a04af53dad7
--- /dev/null
+++ b/home-manager/tests/modules/misc/xsession/keyboard-without-layout-expected.service
@@ -0,0 +1,12 @@
+[Install]
+WantedBy=graphical-session.target
+
+[Service]
+ExecStart=@setxkbmap@/bin/setxkbmap -option 'ctrl:nocaps' -option 'altwin:no_win'
+RemainAfterExit=true
+Type=oneshot
+
+[Unit]
+After=graphical-session-pre.target
+Description=Set up keyboard in X
+PartOf=graphical-session.target
diff --git a/home-manager/tests/modules/misc/xsession/keyboard-without-layout.nix b/home-manager/tests/modules/misc/xsession/keyboard-without-layout.nix
new file mode 100644
index 00000000000..015efe6154a
--- /dev/null
+++ b/home-manager/tests/modules/misc/xsession/keyboard-without-layout.nix
@@ -0,0 +1,36 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ home.stateVersion = "19.09";
+
+ home.homeDirectory = "/test-home";
+
+ home.keyboard = { options = [ "ctrl:nocaps" "altwin:no_win" ]; };
+
+ xsession = {
+ enable = true;
+ windowManager.command = "window manager command";
+ importedVariables = [ "EXTRA_IMPORTED_VARIABLE" ];
+ initExtra = "init extra commands";
+ profileExtra = "profile extra commands";
+ };
+
+ nixpkgs.overlays = [
+ (self: super: {
+ xorg = super.xorg // {
+ setxkbmap = super.xorg.setxkbmap // { outPath = "@setxkbmap@"; };
+ };
+ })
+ ];
+
+ nmt.script = ''
+ assertFileExists home-files/.config/systemd/user/setxkbmap.service
+ assertFileContent \
+ home-files/.config/systemd/user/setxkbmap.service \
+ ${./keyboard-without-layout-expected.service}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/alacritty/default.nix b/home-manager/tests/modules/programs/alacritty/default.nix
new file mode 100644
index 00000000000..f63e033d846
--- /dev/null
+++ b/home-manager/tests/modules/programs/alacritty/default.nix
@@ -0,0 +1,4 @@
+{
+ alacritty-example-settings = ./example-settings.nix;
+ alacritty-empty-settings = ./empty-settings.nix;
+}
diff --git a/home-manager/tests/modules/programs/alacritty/empty-settings.nix b/home-manager/tests/modules/programs/alacritty/empty-settings.nix
new file mode 100644
index 00000000000..65470473c1a
--- /dev/null
+++ b/home-manager/tests/modules/programs/alacritty/empty-settings.nix
@@ -0,0 +1,17 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.alacritty.enable = true;
+
+ nixpkgs.overlays = [
+ (self: super: { alacritty = pkgs.writeScriptBin "dummy-alacritty" ""; })
+ ];
+
+ nmt.script = ''
+ assertPathNotExists home-files/.config/alacritty
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/alacritty/example-settings-expected.yml b/home-manager/tests/modules/programs/alacritty/example-settings-expected.yml
new file mode 100644
index 00000000000..061624192c3
--- /dev/null
+++ b/home-manager/tests/modules/programs/alacritty/example-settings-expected.yml
@@ -0,0 +1 @@
+{"key_bindings":[{"chars":"\x0c","key":"K","mods":"Control"}],"window":{"dimensions":{"columns":200,"lines":3}}} \ No newline at end of file
diff --git a/home-manager/tests/modules/programs/alacritty/example-settings.nix b/home-manager/tests/modules/programs/alacritty/example-settings.nix
new file mode 100644
index 00000000000..46be1064ce6
--- /dev/null
+++ b/home-manager/tests/modules/programs/alacritty/example-settings.nix
@@ -0,0 +1,34 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.alacritty = {
+ enable = true;
+
+ settings = {
+ window.dimensions = {
+ lines = 3;
+ columns = 200;
+ };
+
+ key_bindings = [{
+ key = "K";
+ mods = "Control";
+ chars = "\\x0c";
+ }];
+ };
+ };
+
+ nixpkgs.overlays = [
+ (self: super: { alacritty = pkgs.writeScriptBin "dummy-alacritty" ""; })
+ ];
+
+ nmt.script = ''
+ assertFileContent \
+ home-files/.config/alacritty/alacritty.yml \
+ ${./example-settings-expected.yml}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/bash/default.nix b/home-manager/tests/modules/programs/bash/default.nix
new file mode 100644
index 00000000000..e9f431cd2b9
--- /dev/null
+++ b/home-manager/tests/modules/programs/bash/default.nix
@@ -0,0 +1,4 @@
+{
+ bash-logout = ./logout.nix;
+ bash-session-variables = ./session-variables.nix;
+}
diff --git a/home-manager/tests/modules/programs/bash/logout-expected.txt b/home-manager/tests/modules/programs/bash/logout-expected.txt
new file mode 100644
index 00000000000..9462f58f732
--- /dev/null
+++ b/home-manager/tests/modules/programs/bash/logout-expected.txt
@@ -0,0 +1,4 @@
+# -*- mode: sh -*-
+
+clear-console
+
diff --git a/home-manager/tests/modules/programs/bash/logout.nix b/home-manager/tests/modules/programs/bash/logout.nix
new file mode 100644
index 00000000000..8f96dc7e1ae
--- /dev/null
+++ b/home-manager/tests/modules/programs/bash/logout.nix
@@ -0,0 +1,22 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.bash = {
+ enable = true;
+
+ logoutExtra = ''
+ clear-console
+ '';
+ };
+
+ nmt.script = ''
+ assertFileExists home-files/.bash_logout
+ assertFileContent \
+ home-files/.bash_logout \
+ ${./logout-expected.txt}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/bash/session-variables-expected.txt b/home-manager/tests/modules/programs/bash/session-variables-expected.txt
new file mode 100644
index 00000000000..e13d63d4c78
--- /dev/null
+++ b/home-manager/tests/modules/programs/bash/session-variables-expected.txt
@@ -0,0 +1,8 @@
+# -*- mode: sh -*-
+
+. "/home/testuser/.nix-profile/etc/profile.d/hm-session-vars.sh"
+
+export V1="v1"
+export V2="v2-v1"
+
+
diff --git a/home-manager/tests/modules/programs/bash/session-variables.nix b/home-manager/tests/modules/programs/bash/session-variables.nix
new file mode 100644
index 00000000000..ea789a1d061
--- /dev/null
+++ b/home-manager/tests/modules/programs/bash/session-variables.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.bash = {
+ enable = true;
+
+ sessionVariables = {
+ V1 = "v1";
+ V2 = "v2-${config.programs.bash.sessionVariables.V1}";
+ };
+ };
+
+ home.homeDirectory = "/home/testuser";
+
+ nmt.script = ''
+ assertFileExists home-files/.profile
+ assertFileContent \
+ home-files/.profile \
+ ${./session-variables-expected.txt}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/browserpass/browserpass.nix b/home-manager/tests/modules/programs/browserpass/browserpass.nix
new file mode 100644
index 00000000000..9189a445ac0
--- /dev/null
+++ b/home-manager/tests/modules/programs/browserpass/browserpass.nix
@@ -0,0 +1,29 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.browserpass = {
+ enable = true;
+ browsers = [ "chrome" "chromium" "firefox" "vivaldi" ];
+ };
+
+ nmt.script = if pkgs.stdenv.hostPlatform.isDarwin then ''
+ for dir in "Google/Chrome" "Chromium" "Mozilla" "Vivaldi"; do
+ assertFileExists "home-files/Library/Application Support/$dir/NativeMessagingHosts/com.github.browserpass.native.json"
+ done
+
+ for dir in "Google/Chrome" "Chromium" "Vivaldi"; do
+ assertFileExists "home-files/Library/Application Support/$dir/policies/managed/com.github.browserpass.native.json"
+ done
+ '' else ''
+ for dir in "google-chrome" "chromium" "vivaldi"; do
+ assertFileExists "home-files/.config/$dir/NativeMessagingHosts/com.github.browserpass.native.json"
+ assertFileExists "home-files/.config/$dir/policies/managed/com.github.browserpass.native.json"
+ done
+
+ assertFileExists "home-files/.mozilla/native-messaging-hosts/com.github.browserpass.native.json"
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/browserpass/default.nix b/home-manager/tests/modules/programs/browserpass/default.nix
new file mode 100644
index 00000000000..fa40ddcab31
--- /dev/null
+++ b/home-manager/tests/modules/programs/browserpass/default.nix
@@ -0,0 +1 @@
+{ browserpass = ./browserpass.nix; }
diff --git a/home-manager/tests/modules/programs/firefox/default.nix b/home-manager/tests/modules/programs/firefox/default.nix
new file mode 100644
index 00000000000..6612a9ac978
--- /dev/null
+++ b/home-manager/tests/modules/programs/firefox/default.nix
@@ -0,0 +1,4 @@
+{
+ firefox-profile-settings = ./profile-settings.nix;
+ firefox-state-version-19_09 = ./state-version-19_09.nix;
+}
diff --git a/home-manager/tests/modules/programs/firefox/profile-settings-expected-user.js b/home-manager/tests/modules/programs/firefox/profile-settings-expected-user.js
new file mode 100644
index 00000000000..0edd47b9101
--- /dev/null
+++ b/home-manager/tests/modules/programs/firefox/profile-settings-expected-user.js
@@ -0,0 +1,6 @@
+// Generated by Home Manager.
+
+user_pref("general.smoothScroll", false);
+
+
+
diff --git a/home-manager/tests/modules/programs/firefox/profile-settings.nix b/home-manager/tests/modules/programs/firefox/profile-settings.nix
new file mode 100644
index 00000000000..8c5fb4ec1fc
--- /dev/null
+++ b/home-manager/tests/modules/programs/firefox/profile-settings.nix
@@ -0,0 +1,36 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.firefox = {
+ enable = true;
+ profiles.test.settings = { "general.smoothScroll" = false; };
+ };
+
+ nixpkgs.overlays = [
+ (self: super: {
+ firefox-unwrapped = pkgs.runCommand "firefox-0" {
+ meta.description = "I pretend to be Firefox";
+ preferLocalBuild = true;
+ allowSubstitutes = false;
+ } ''
+ mkdir -p "$out/bin"
+ touch "$out/bin/firefox"
+ chmod 755 "$out/bin/firefox"
+ '';
+ })
+ ];
+
+ nmt.script = ''
+ assertFileRegex \
+ home-path/bin/firefox \
+ MOZ_APP_LAUNCHER
+
+ assertFileContent \
+ home-files/.mozilla/firefox/test/user.js \
+ ${./profile-settings-expected-user.js}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/firefox/state-version-19_09.nix b/home-manager/tests/modules/programs/firefox/state-version-19_09.nix
new file mode 100644
index 00000000000..27dc867ad29
--- /dev/null
+++ b/home-manager/tests/modules/programs/firefox/state-version-19_09.nix
@@ -0,0 +1,31 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ home.stateVersion = "19.09";
+
+ programs.firefox.enable = true;
+
+ nixpkgs.overlays = [
+ (self: super: {
+ firefox-unwrapped = pkgs.runCommand "firefox-0" {
+ meta.description = "I pretend to be Firefox";
+ preferLocalBuild = true;
+ allowSubstitutes = false;
+ } ''
+ mkdir -p "$out/bin"
+ touch "$out/bin/firefox"
+ chmod 755 "$out/bin/firefox"
+ '';
+ })
+ ];
+
+ nmt.script = ''
+ assertFileRegex \
+ home-path/bin/firefox \
+ MOZ_APP_LAUNCHER
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/getmail/default.nix b/home-manager/tests/modules/programs/getmail/default.nix
new file mode 100644
index 00000000000..cb789a90d64
--- /dev/null
+++ b/home-manager/tests/modules/programs/getmail/default.nix
@@ -0,0 +1 @@
+{ getmail = ./getmail.nix; }
diff --git a/home-manager/tests/modules/programs/getmail/getmail-expected.conf b/home-manager/tests/modules/programs/getmail/getmail-expected.conf
new file mode 100644
index 00000000000..90dc963e574
--- /dev/null
+++ b/home-manager/tests/modules/programs/getmail/getmail-expected.conf
@@ -0,0 +1,16 @@
+# Generated by Home-Manager.
+[retriever]
+type = SimpleIMAPSSLRetriever
+server = imap.example.com
+port = 993
+username = home.manager
+password_command = ('password-command')
+mailboxes = ( 'INBOX', 'Sent', 'Work' )
+
+[destination]
+type = MDA_external
+path = /bin/maildrop
+
+[options]
+delete = false
+read_all = true
diff --git a/home-manager/tests/modules/programs/getmail/getmail.nix b/home-manager/tests/modules/programs/getmail/getmail.nix
new file mode 100644
index 00000000000..fe10b98f981
--- /dev/null
+++ b/home-manager/tests/modules/programs/getmail/getmail.nix
@@ -0,0 +1,31 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ imports = [ ../../accounts/email-test-accounts.nix ];
+
+ config = {
+ home.username = "hm-user";
+ home.homeDirectory = "/home/hm-user";
+
+ accounts.email.accounts = {
+ "hm@example.com" = {
+ getmail = {
+ enable = true;
+ mailboxes = [ "INBOX" "Sent" "Work" ];
+ destinationCommand = "/bin/maildrop";
+ delete = false;
+ };
+ imap.port = 993;
+ };
+ };
+
+ nmt.script = ''
+ assertFileExists home-files/.getmail/getmailhm@example.com
+ assertFileContent home-files/.getmail/getmailhm@example.com ${
+ ./getmail-expected.conf
+ }
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/git/default.nix b/home-manager/tests/modules/programs/git/default.nix
new file mode 100644
index 00000000000..45aface8d26
--- /dev/null
+++ b/home-manager/tests/modules/programs/git/default.nix
@@ -0,0 +1,5 @@
+{
+ git-with-email = ./git-with-email.nix;
+ git-with-most-options = ./git.nix;
+ git-with-str-extra-config = ./git-with-str-extra-config.nix;
+}
diff --git a/home-manager/tests/modules/programs/git/git-expected.conf b/home-manager/tests/modules/programs/git/git-expected.conf
new file mode 100644
index 00000000000..d02ebf31649
--- /dev/null
+++ b/home-manager/tests/modules/programs/git/git-expected.conf
@@ -0,0 +1,42 @@
+[alias]
+a1=foo
+a2=baz
+
+[commit]
+gpgSign=true
+
+[extra]
+boolean=true
+integer=38
+multiple=1
+multiple=2
+name=value
+
+[extra "backcompat.with.dots"]
+previously=worked
+
+[extra "subsection"]
+value=test
+
+[filter "lfs"]
+clean=git-lfs clean -- %f
+process=git-lfs filter-process
+required=true
+smudge=git-lfs smudge -- %f
+
+[gpg]
+program=path-to-gpg
+
+[user]
+email=user@example.org
+name=John Doe
+signingKey=00112233445566778899AABBCCDDEEFF
+
+[include]
+path=~/path/to/config.inc
+
+[includeIf "gitdir:~/src/dir"]
+path=~/path/to/conditional.inc
+
+[includeIf "gitdir:~/src/dir"]
+path=@git_include_path@
diff --git a/home-manager/tests/modules/programs/git/git-with-email-expected.conf b/home-manager/tests/modules/programs/git/git-with-email-expected.conf
new file mode 100644
index 00000000000..01c1eec5823
--- /dev/null
+++ b/home-manager/tests/modules/programs/git/git-with-email-expected.conf
@@ -0,0 +1,15 @@
+[sendemail "hm-account"]
+from=hm@example.org
+smtpEncryption=tls
+smtpServer=smtp.example.org
+smtpUser=home.manager.jr
+
+[sendemail "hm@example.com"]
+from=hm@example.com
+smtpEncryption=tls
+smtpServer=smtp.example.com
+smtpUser=home.manager
+
+[user]
+email=hm@example.com
+name=H. M. Test
diff --git a/home-manager/tests/modules/programs/git/git-with-email.nix b/home-manager/tests/modules/programs/git/git-with-email.nix
new file mode 100644
index 00000000000..ca577eef4d3
--- /dev/null
+++ b/home-manager/tests/modules/programs/git/git-with-email.nix
@@ -0,0 +1,36 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ imports = [ ../../accounts/email-test-accounts.nix ];
+
+ config = {
+ programs.git = {
+ enable = true;
+ package = pkgs.gitMinimal;
+ userEmail = "hm@example.com";
+ userName = "H. M. Test";
+ };
+
+ nmt.script = ''
+ function assertGitConfig() {
+ local value
+ value=$(${pkgs.git}/bin/git config \
+ --file $TESTED/home-files/.config/git/config \
+ --get $1)
+ if [[ $value != $2 ]]; then
+ fail "Expected option '$1' to have value '$2' but it was '$value'"
+ fi
+ }
+
+ assertFileExists home-files/.config/git/config
+ assertFileContent home-files/.config/git/config ${
+ ./git-with-email-expected.conf
+ }
+
+ assertGitConfig "sendemail.hm@example.com.from" "hm@example.com"
+ assertGitConfig "sendemail.hm-account.from" "hm@example.org"
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/git/git-with-str-extra-config-expected.conf b/home-manager/tests/modules/programs/git/git-with-str-extra-config-expected.conf
new file mode 100644
index 00000000000..957438de13a
--- /dev/null
+++ b/home-manager/tests/modules/programs/git/git-with-str-extra-config-expected.conf
@@ -0,0 +1,5 @@
+This can be anything.
+
+[user]
+email=user@example.org
+name=John Doe
diff --git a/home-manager/tests/modules/programs/git/git-with-str-extra-config.nix b/home-manager/tests/modules/programs/git/git-with-str-extra-config.nix
new file mode 100644
index 00000000000..3dbc497a5ea
--- /dev/null
+++ b/home-manager/tests/modules/programs/git/git-with-str-extra-config.nix
@@ -0,0 +1,23 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.git = {
+ enable = true;
+ package = pkgs.gitMinimal;
+ extraConfig = ''
+ This can be anything.
+ '';
+ userEmail = "user@example.org";
+ userName = "John Doe";
+ };
+
+ nmt.script = ''
+ assertFileExists home-files/.config/git/config
+ assertFileContent home-files/.config/git/config \
+ ${./git-with-str-extra-config-expected.conf}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/git/git.nix b/home-manager/tests/modules/programs/git/git.nix
new file mode 100644
index 00000000000..7c0bf52de55
--- /dev/null
+++ b/home-manager/tests/modules/programs/git/git.nix
@@ -0,0 +1,77 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ gitInclude = {
+ user = {
+ name = "John Doe";
+ email = "user@example.org";
+ };
+ };
+
+ substituteExpected = path:
+ pkgs.substituteAll {
+ src = path;
+
+ git_include_path =
+ pkgs.writeText "contents" (generators.toINI { } gitInclude);
+ };
+
+in {
+ config = {
+ programs.git = mkMerge [
+ {
+ enable = true;
+ package = pkgs.gitMinimal;
+ aliases = {
+ a1 = "foo";
+ a2 = "bar";
+ };
+ extraConfig = {
+ extra = {
+ name = "value";
+ multiple = [ 1 ];
+ };
+ };
+ ignores = [ "*~" "*.swp" ];
+ includes = [
+ { path = "~/path/to/config.inc"; }
+ {
+ path = "~/path/to/conditional.inc";
+ condition = "gitdir:~/src/dir";
+ }
+ {
+ condition = "gitdir:~/src/dir";
+ contents = gitInclude;
+ }
+ ];
+ signing = {
+ gpgPath = "path-to-gpg";
+ key = "00112233445566778899AABBCCDDEEFF";
+ signByDefault = true;
+ };
+ userEmail = "user@example.org";
+ userName = "John Doe";
+ lfs.enable = true;
+ }
+
+ {
+ aliases.a2 = mkForce "baz";
+ extraConfig."extra \"backcompat.with.dots\"".previously = "worked";
+ extraConfig.extra.boolean = true;
+ extraConfig.extra.integer = 38;
+ extraConfig.extra.multiple = [ 2 ];
+ extraConfig.extra.subsection.value = "test";
+ }
+ ];
+
+ nmt.script = ''
+ assertFileExists home-files/.config/git/config
+ assertFileContent home-files/.config/git/config ${
+ substituteExpected ./git-expected.conf
+ }
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/gpg/default.nix b/home-manager/tests/modules/programs/gpg/default.nix
new file mode 100644
index 00000000000..7fed2cdcc69
--- /dev/null
+++ b/home-manager/tests/modules/programs/gpg/default.nix
@@ -0,0 +1 @@
+{ gpg-override-defaults = ./override-defaults.nix; }
diff --git a/home-manager/tests/modules/programs/gpg/override-defaults-expected.conf b/home-manager/tests/modules/programs/gpg/override-defaults-expected.conf
new file mode 100644
index 00000000000..3198183f723
--- /dev/null
+++ b/home-manager/tests/modules/programs/gpg/override-defaults-expected.conf
@@ -0,0 +1,19 @@
+cert-digest-algo SHA512
+charset utf-8
+default-preference-list SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed
+fixed-list-mode
+keyid-format 0xlong
+list-options show-uid-validity
+
+no-emit-version
+no-symkey-cache
+personal-cipher-preferences AES256 AES192 AES
+personal-compress-preferences ZLIB BZIP2 ZIP Uncompressed
+personal-digest-preferences SHA512 SHA384 SHA256
+require-cross-certification
+s2k-cipher-algo AES128
+s2k-digest-algo SHA512
+throw-keyids
+use-agent
+verify-options show-uid-validity
+with-fingerprint \ No newline at end of file
diff --git a/home-manager/tests/modules/programs/gpg/override-defaults.nix b/home-manager/tests/modules/programs/gpg/override-defaults.nix
new file mode 100644
index 00000000000..850334dc589
--- /dev/null
+++ b/home-manager/tests/modules/programs/gpg/override-defaults.nix
@@ -0,0 +1,22 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.gpg = {
+ enable = true;
+
+ settings = {
+ no-comments = false;
+ s2k-cipher-algo = "AES128";
+ throw-keyids = true;
+ };
+ };
+
+ nmt.script = ''
+ assertFileExists home-files/.gnupg/gpg.conf
+ assertFileContent home-files/.gnupg/gpg.conf ${./override-defaults-expected.conf}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/mbsync/default.nix b/home-manager/tests/modules/programs/mbsync/default.nix
new file mode 100644
index 00000000000..9c369fa5018
--- /dev/null
+++ b/home-manager/tests/modules/programs/mbsync/default.nix
@@ -0,0 +1 @@
+{ mbsync = ./mbsync.nix; }
diff --git a/home-manager/tests/modules/programs/mbsync/mbsync-expected.conf b/home-manager/tests/modules/programs/mbsync/mbsync-expected.conf
new file mode 100644
index 00000000000..f1ca79fe738
--- /dev/null
+++ b/home-manager/tests/modules/programs/mbsync/mbsync-expected.conf
@@ -0,0 +1,55 @@
+# Generated by Home Manager.
+
+IMAPAccount hm-account
+CertificateFile /etc/ssl/certs/ca-certificates.crt
+Host imap.example.org
+PassCmd "password-command 2"
+SSLType IMAPS
+User home.manager.jr
+
+IMAPStore hm-account-remote
+Account hm-account
+
+MaildirStore hm-account-local
+Inbox /home/hm-user/Mail/hm-account/Inbox
+Path /home/hm-user/Mail/hm-account/
+SubFolders Verbatim
+
+Channel hm-account
+Create None
+Expunge None
+Master :hm-account-remote:
+Patterns *
+Remove None
+Slave :hm-account-local:
+SyncState *
+
+
+IMAPAccount hm@example.com
+CertificateFile /etc/ssl/certs/ca-certificates.crt
+Host imap.example.com
+PassCmd password-command
+SSLType IMAPS
+User home.manager
+
+IMAPStore hm@example.com-remote
+Account hm@example.com
+
+MaildirStore hm@example.com-local
+Inbox /home/hm-user/Mail/hm@example.com/Inbox
+Path /home/hm-user/Mail/hm@example.com/
+SubFolders Verbatim
+
+Channel hm@example.com
+Create None
+Expunge None
+Master :hm@example.com-remote:
+Patterns *
+Remove None
+Slave :hm@example.com-local:
+SyncState *
+
+
+Group inboxes
+Channel hm-account:Inbox
+Channel hm@example.com:Inbox1,Inbox2
diff --git a/home-manager/tests/modules/programs/mbsync/mbsync.nix b/home-manager/tests/modules/programs/mbsync/mbsync.nix
new file mode 100644
index 00000000000..03a54c178f5
--- /dev/null
+++ b/home-manager/tests/modules/programs/mbsync/mbsync.nix
@@ -0,0 +1,31 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ imports = [ ../../accounts/email-test-accounts.nix ];
+
+ config = {
+ home.username = "hm-user";
+ home.homeDirectory = "/home/hm-user";
+
+ programs.mbsync = {
+ enable = true;
+ groups.inboxes = {
+ "hm@example.com" = [ "Inbox1" "Inbox2" ];
+ hm-account = [ "Inbox" ];
+ };
+ };
+
+ accounts.email.accounts = {
+ "hm@example.com".mbsync = { enable = true; };
+
+ hm-account.mbsync = { enable = true; };
+ };
+
+ nmt.script = ''
+ assertFileExists home-files/.mbsyncrc
+ assertFileContent home-files/.mbsyncrc ${./mbsync-expected.conf}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/neomutt/default.nix b/home-manager/tests/modules/programs/neomutt/default.nix
new file mode 100644
index 00000000000..289f2705efa
--- /dev/null
+++ b/home-manager/tests/modules/programs/neomutt/default.nix
@@ -0,0 +1 @@
+{ neomutt-simple = ./neomutt.nix; }
diff --git a/home-manager/tests/modules/programs/neomutt/hm-example.com-expected b/home-manager/tests/modules/programs/neomutt/hm-example.com-expected
new file mode 100644
index 00000000000..430509c36bd
--- /dev/null
+++ b/home-manager/tests/modules/programs/neomutt/hm-example.com-expected
@@ -0,0 +1,37 @@
+# Generated by Home Manager.
+set ssl_force_tls = yes
+set certificate_file=/etc/ssl/certs/ca-certificates.crt
+
+# GPG section
+set crypt_use_gpgme = yes
+set crypt_autosign = no
+set pgp_use_gpg_agent = yes
+set mbox_type = Maildir
+set sort = "threads"
+
+# MTA section
+set smtp_pass='`password-command`'
+set smtp_url='smtps://home.manager@smtp.example.com'
+
+
+
+
+
+# MRA section
+set folder='/home/hm-user/Mail/hm@example.com'
+set from='hm@example.com'
+set postponed='+Drafts'
+set realname='H. M. Test'
+set record='+Sent'
+set spoolfile='+Inbox'
+set trash='+Trash'
+color status cyan default
+
+
+
+# Extra configuration
+color status cyan default
+
+# notmuch section
+set nm_default_uri = "notmuch:///home/hm-user/Mail"
+virtual-mailboxes "My INBOX" "notmuch://?query=tag:inbox"
diff --git a/home-manager/tests/modules/programs/neomutt/neomutt-expected.conf b/home-manager/tests/modules/programs/neomutt/neomutt-expected.conf
new file mode 100644
index 00000000000..7711aa5a652
--- /dev/null
+++ b/home-manager/tests/modules/programs/neomutt/neomutt-expected.conf
@@ -0,0 +1,27 @@
+# Generated by Home Manager.
+set header_cache = "/home/hm-user/.cache/neomutt/headers/"
+set message_cachedir = "/home/hm-user/.cache/neomutt/messages/"
+set editor = "$EDITOR"
+set implicit_autoview = yes
+
+alternative_order text/enriched text/plain text
+
+set delete = yes
+
+# Binds
+
+
+# Macros
+
+
+
+
+# Extra configuration
+
+
+
+# register account hm@example.com
+mailboxes "/home/hm-user/Mail/hm@example.com/Inbox"
+folder-hook /home/hm-user/Mail/hm@example.com/ " \
+ source /home/hm-user/.config/neomutt/hm@example.com "
+source /home/hm-user/.config/neomutt/hm@example.com \ No newline at end of file
diff --git a/home-manager/tests/modules/programs/neomutt/neomutt.nix b/home-manager/tests/modules/programs/neomutt/neomutt.nix
new file mode 100644
index 00000000000..91cb9dca249
--- /dev/null
+++ b/home-manager/tests/modules/programs/neomutt/neomutt.nix
@@ -0,0 +1,47 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ imports = [ ../../accounts/email-test-accounts.nix ];
+
+ config = {
+ home.username = "hm-user";
+ home.homeDirectory = "/home/hm-user";
+ xdg.configHome = mkForce "/home/hm-user/.config";
+ xdg.cacheHome = mkForce "/home/hm-user/.cache";
+
+ accounts.email.accounts = {
+ "hm@example.com" = {
+ primary = true;
+ notmuch.enable = true;
+ neomutt = {
+ enable = true;
+ extraConfig = ''
+ color status cyan default
+ '';
+ };
+ imap.port = 993;
+ };
+ };
+
+ programs.neomutt = {
+ enable = true;
+ vimKeys = false;
+ };
+
+ nixpkgs.overlays =
+ [ (self: super: { neomutt = pkgs.writeScriptBin "dummy-neomutt" ""; }) ];
+
+ nmt.script = ''
+ assertFileExists home-files/.config/neomutt/neomuttrc
+ assertFileExists home-files/.config/neomutt/hm@example.com
+ assertFileContent home-files/.config/neomutt/neomuttrc ${
+ ./neomutt-expected.conf
+ }
+ assertFileContent home-files/.config/neomutt/hm@example.com ${
+ ./hm-example.com-expected
+ }
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/newsboat/default.nix b/home-manager/tests/modules/programs/newsboat/default.nix
new file mode 100644
index 00000000000..27f523a629c
--- /dev/null
+++ b/home-manager/tests/modules/programs/newsboat/default.nix
@@ -0,0 +1 @@
+{ newsboat-basics = ./newsboat-basics.nix; }
diff --git a/home-manager/tests/modules/programs/newsboat/newsboat-basics-urls.txt b/home-manager/tests/modules/programs/newsboat/newsboat-basics-urls.txt
new file mode 100644
index 00000000000..7f084961345
--- /dev/null
+++ b/home-manager/tests/modules/programs/newsboat/newsboat-basics-urls.txt
@@ -0,0 +1,3 @@
+http://example.org/feed.xml "tag1" "tag2" "~Cool feed"
+http://example.org/feed2.xml
+"query:foo:rssurl =~ \"example.com\""
diff --git a/home-manager/tests/modules/programs/newsboat/newsboat-basics.nix b/home-manager/tests/modules/programs/newsboat/newsboat-basics.nix
new file mode 100644
index 00000000000..e6eb4151776
--- /dev/null
+++ b/home-manager/tests/modules/programs/newsboat/newsboat-basics.nix
@@ -0,0 +1,33 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.newsboat = {
+ enable = true;
+
+ urls = [
+ {
+ url = "http://example.org/feed.xml";
+ tags = [ "tag1" "tag2" ];
+ title = "Cool feed";
+ }
+
+ { url = "http://example.org/feed2.xml"; }
+ ];
+
+ queries = { "foo" = ''rssurl =~ "example.com"''; };
+ };
+
+ nixpkgs.overlays = [
+ (self: super: { newsboat = pkgs.writeScriptBin "dummy-newsboat" ""; })
+ ];
+
+ nmt.script = ''
+ assertFileContent \
+ home-files/.newsboat/urls \
+ ${./newsboat-basics-urls.txt}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/readline/default.nix b/home-manager/tests/modules/programs/readline/default.nix
new file mode 100644
index 00000000000..c95745d19cd
--- /dev/null
+++ b/home-manager/tests/modules/programs/readline/default.nix
@@ -0,0 +1 @@
+{ readline-using-all-options = ./using-all-options.nix; }
diff --git a/home-manager/tests/modules/programs/readline/using-all-options.nix b/home-manager/tests/modules/programs/readline/using-all-options.nix
new file mode 100644
index 00000000000..ab851020c2e
--- /dev/null
+++ b/home-manager/tests/modules/programs/readline/using-all-options.nix
@@ -0,0 +1,31 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.readline = {
+ enable = true;
+
+ bindings = { "\\C-h" = "backward-kill-word"; };
+
+ variables = {
+ bell-style = "audible";
+ completion-map-case = true;
+ completion-prefix-display-length = 2;
+ };
+
+ extraConfig = ''
+ $if mode=emacs
+ "\e[1~": beginning-of-line
+ $endif
+ '';
+ };
+
+ nmt.script = ''
+ assertFileContent \
+ home-files/.inputrc \
+ ${./using-all-options.txt}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/readline/using-all-options.txt b/home-manager/tests/modules/programs/readline/using-all-options.txt
new file mode 100644
index 00000000000..6b4aef51e69
--- /dev/null
+++ b/home-manager/tests/modules/programs/readline/using-all-options.txt
@@ -0,0 +1,11 @@
+# Generated by Home Manager.
+
+$include /etc/inputrc
+set bell-style audible
+set completion-map-case on
+set completion-prefix-display-length 2
+"\C-h": backward-kill-word
+$if mode=emacs
+"\e[1~": beginning-of-line
+$endif
+
diff --git a/home-manager/tests/modules/programs/rofi/assert-on-both-theme-and-colors-expected.json b/home-manager/tests/modules/programs/rofi/assert-on-both-theme-and-colors-expected.json
new file mode 100644
index 00000000000..808288f4193
--- /dev/null
+++ b/home-manager/tests/modules/programs/rofi/assert-on-both-theme-and-colors-expected.json
@@ -0,0 +1 @@
+["Cannot use the rofi options 'theme' and 'colors' simultaneously.\n"] \ No newline at end of file
diff --git a/home-manager/tests/modules/programs/rofi/assert-on-both-theme-and-colors.nix b/home-manager/tests/modules/programs/rofi/assert-on-both-theme-and-colors.nix
new file mode 100644
index 00000000000..0f9cfc39a6c
--- /dev/null
+++ b/home-manager/tests/modules/programs/rofi/assert-on-both-theme-and-colors.nix
@@ -0,0 +1,29 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.rofi = {
+ enable = true;
+ theme = "foo";
+ colors = {
+ window = {
+ background = "background";
+ border = "border";
+ separator = "separator";
+ };
+ rows = { };
+ };
+ };
+
+ home.file.result.text = builtins.toJSON
+ (map (a: a.message) (filter (a: !a.assertion) config.assertions));
+
+ nmt.script = ''
+ assertFileContent \
+ home-files/result \
+ ${./assert-on-both-theme-and-colors-expected.json}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/rofi/default.nix b/home-manager/tests/modules/programs/rofi/default.nix
new file mode 100644
index 00000000000..c18c3b0ed6a
--- /dev/null
+++ b/home-manager/tests/modules/programs/rofi/default.nix
@@ -0,0 +1,3 @@
+{
+ rofi-assert-on-both-theme-and-colors = ./assert-on-both-theme-and-colors.nix;
+}
diff --git a/home-manager/tests/modules/programs/ssh/default-config-expected.conf b/home-manager/tests/modules/programs/ssh/default-config-expected.conf
new file mode 100644
index 00000000000..55748ea6c82
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/default-config-expected.conf
@@ -0,0 +1,15 @@
+
+
+
+
+Host *
+ ForwardAgent no
+ Compression no
+ ServerAliveInterval 0
+ HashKnownHosts no
+ UserKnownHostsFile ~/.ssh/known_hosts
+ ControlMaster no
+ ControlPath ~/.ssh/master-%r@%n:%p
+ ControlPersist no
+
+
diff --git a/home-manager/tests/modules/programs/ssh/default-config.nix b/home-manager/tests/modules/programs/ssh/default-config.nix
new file mode 100644
index 00000000000..6d7e5508a2f
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/default-config.nix
@@ -0,0 +1,18 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.ssh = { enable = true; };
+
+ home.file.assertions.text = builtins.toJSON
+ (map (a: a.message) (filter (a: !a.assertion) config.assertions));
+
+ nmt.script = ''
+ assertFileExists home-files/.ssh/config
+ assertFileContent home-files/.ssh/config ${./default-config-expected.conf}
+ assertFileContent home-files/assertions ${./no-assertions.json}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/ssh/default.nix b/home-manager/tests/modules/programs/ssh/default.nix
new file mode 100644
index 00000000000..507eef0bdb8
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/default.nix
@@ -0,0 +1,17 @@
+{
+ ssh-defaults = ./default-config.nix;
+ ssh-match-blocks = ./match-blocks-attrs.nix;
+
+ ssh-forwards-dynamic-valid-bind-no-asserts =
+ ./forwards-dynamic-valid-bind-no-asserts.nix;
+ ssh-forwards-dynamic-bind-path-with-port-asserts =
+ ./forwards-dynamic-bind-path-with-port-asserts.nix;
+ ssh-forwards-local-bind-path-with-port-asserts =
+ ./forwards-local-bind-path-with-port-asserts.nix;
+ ssh-forwards-local-host-path-with-port-asserts =
+ ./forwards-local-host-path-with-port-asserts.nix;
+ ssh-forwards-remote-bind-path-with-port-asserts =
+ ./forwards-remote-bind-path-with-port-asserts.nix;
+ ssh-forwards-remote-host-path-with-port-asserts =
+ ./forwards-remote-host-path-with-port-asserts.nix;
+}
diff --git a/home-manager/tests/modules/programs/ssh/forwards-dynamic-bind-path-with-port-asserts.nix b/home-manager/tests/modules/programs/ssh/forwards-dynamic-bind-path-with-port-asserts.nix
new file mode 100644
index 00000000000..cf2efe5a5a5
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/forwards-dynamic-bind-path-with-port-asserts.nix
@@ -0,0 +1,29 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.ssh = {
+ enable = true;
+ matchBlocks = {
+ dynamicBindPathWithPort = {
+ dynamicForwards = [{
+ # Error:
+ address = "/run/user/1000/gnupg/S.gpg-agent.extra";
+ port = 3000;
+ }];
+ };
+ };
+ };
+
+ home.file.result.text = builtins.toJSON
+ (map (a: a.message) (filter (a: !a.assertion) config.assertions));
+
+ nmt.script = ''
+ assertFileContent home-files/result ${
+ ./forwards-paths-with-ports-error.json
+ }
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts-expected.conf b/home-manager/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts-expected.conf
new file mode 100644
index 00000000000..5213d282c28
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts-expected.conf
@@ -0,0 +1,19 @@
+
+
+Host dynamicBindAddressWithPort
+ DynamicForward [127.0.0.1]:3000
+
+Host dynamicBindPathNoPort
+ DynamicForward /run/user/1000/gnupg/S.gpg-agent.extra
+
+Host *
+ ForwardAgent no
+ Compression no
+ ServerAliveInterval 0
+ HashKnownHosts no
+ UserKnownHostsFile ~/.ssh/known_hosts
+ ControlMaster no
+ ControlPath ~/.ssh/master-%r@%n:%p
+ ControlPersist no
+
+
diff --git a/home-manager/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts.nix b/home-manager/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts.nix
new file mode 100644
index 00000000000..d0c3a732256
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/forwards-dynamic-valid-bind-no-asserts.nix
@@ -0,0 +1,38 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.ssh = {
+ enable = true;
+ matchBlocks = {
+ dynamicBindPathNoPort = {
+ dynamicForwards = [{
+ # OK:
+ address = "/run/user/1000/gnupg/S.gpg-agent.extra";
+ }];
+ };
+
+ dynamicBindAddressWithPort = {
+ dynamicForwards = [{
+ # OK:
+ address = "127.0.0.1";
+ port = 3000;
+ }];
+ };
+ };
+ };
+
+ home.file.result.text = builtins.toJSON
+ (map (a: a.message) (filter (a: !a.assertion) config.assertions));
+
+ nmt.script = ''
+ assertFileExists home-files/.ssh/config
+ assertFileContent \
+ home-files/.ssh/config \
+ ${./forwards-dynamic-valid-bind-no-asserts-expected.conf}
+ assertFileContent home-files/result ${./no-assertions.json}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/ssh/forwards-local-bind-path-with-port-asserts.nix b/home-manager/tests/modules/programs/ssh/forwards-local-bind-path-with-port-asserts.nix
new file mode 100644
index 00000000000..f9d8e2daf85
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/forwards-local-bind-path-with-port-asserts.nix
@@ -0,0 +1,33 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.ssh = {
+ enable = true;
+ matchBlocks = {
+ localBindPathWithPort = {
+ localForwards = [{
+ # OK:
+ host.address = "127.0.0.1";
+ host.port = 3000;
+
+ # Error:
+ bind.address = "/run/user/1000/gnupg/S.gpg-agent.extra";
+ bind.port = 3000;
+ }];
+ };
+ };
+ };
+
+ home.file.result.text = builtins.toJSON
+ (map (a: a.message) (filter (a: !a.assertion) config.assertions));
+
+ nmt.script = ''
+ assertFileContent home-files/result ${
+ ./forwards-paths-with-ports-error.json
+ }
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/ssh/forwards-local-host-path-with-port-asserts.nix b/home-manager/tests/modules/programs/ssh/forwards-local-host-path-with-port-asserts.nix
new file mode 100644
index 00000000000..02a7e5b168d
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/forwards-local-host-path-with-port-asserts.nix
@@ -0,0 +1,33 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.ssh = {
+ enable = true;
+ matchBlocks = {
+ localHostPathWithPort = {
+ localForwards = [{
+ # OK:
+ bind.address = "127.0.0.1";
+ bind.port = 3000;
+
+ # Error:
+ host.address = "/run/user/1000/gnupg/S.gpg-agent.extra";
+ host.port = 3000;
+ }];
+ };
+ };
+ };
+
+ home.file.result.text = builtins.toJSON
+ (map (a: a.message) (filter (a: !a.assertion) config.assertions));
+
+ nmt.script = ''
+ assertFileContent home-files/result ${
+ ./forwards-paths-with-ports-error.json
+ }
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/ssh/forwards-paths-with-ports-error.json b/home-manager/tests/modules/programs/ssh/forwards-paths-with-ports-error.json
new file mode 100644
index 00000000000..e7e3a374ecc
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/forwards-paths-with-ports-error.json
@@ -0,0 +1 @@
+["Forwarded paths cannot have ports."] \ No newline at end of file
diff --git a/home-manager/tests/modules/programs/ssh/forwards-remote-bind-path-with-port-asserts.nix b/home-manager/tests/modules/programs/ssh/forwards-remote-bind-path-with-port-asserts.nix
new file mode 100644
index 00000000000..61ce9ae0385
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/forwards-remote-bind-path-with-port-asserts.nix
@@ -0,0 +1,33 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.ssh = {
+ enable = true;
+ matchBlocks = {
+ remoteBindPathWithPort = {
+ remoteForwards = [{
+ # OK:
+ host.address = "127.0.0.1";
+ host.port = 3000;
+
+ # Error:
+ bind.address = "/run/user/1000/gnupg/S.gpg-agent.extra";
+ bind.port = 3000;
+ }];
+ };
+ };
+ };
+
+ home.file.result.text = builtins.toJSON
+ (map (a: a.message) (filter (a: !a.assertion) config.assertions));
+
+ nmt.script = ''
+ assertFileContent home-files/result ${
+ ./forwards-paths-with-ports-error.json
+ }
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/ssh/forwards-remote-host-path-with-port-asserts.nix b/home-manager/tests/modules/programs/ssh/forwards-remote-host-path-with-port-asserts.nix
new file mode 100644
index 00000000000..71bdbcb70fd
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/forwards-remote-host-path-with-port-asserts.nix
@@ -0,0 +1,33 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.ssh = {
+ enable = true;
+ matchBlocks = {
+ remoteHostPathWithPort = {
+ remoteForwards = [{
+ # OK:
+ bind.address = "127.0.0.1";
+ bind.port = 3000;
+
+ # Error:
+ host.address = "/run/user/1000/gnupg/S.gpg-agent.extra";
+ host.port = 3000;
+ }];
+ };
+ };
+ };
+
+ home.file.result.text = builtins.toJSON
+ (map (a: a.message) (filter (a: !a.assertion) config.assertions));
+
+ nmt.script = ''
+ assertFileContent home-files/result ${
+ ./forwards-paths-with-ports-error.json
+ }
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/ssh/match-blocks-attrs-expected.conf b/home-manager/tests/modules/programs/ssh/match-blocks-attrs-expected.conf
new file mode 100644
index 00000000000..f0d768375f0
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/match-blocks-attrs-expected.conf
@@ -0,0 +1,29 @@
+
+
+Host * !github.com
+ Port 516
+ IdentityFile file1
+ IdentityFile file2
+
+Host abc
+ ProxyJump jump-host
+
+Host xyz
+ ServerAliveInterval 60
+ IdentityFile file
+ LocalForward [localhost]:8080 [10.0.0.1]:80
+ RemoteForward [localhost]:8081 [10.0.0.2]:80
+ RemoteForward /run/user/1000/gnupg/S.gpg-agent.extra /run/user/1000/gnupg/S.gpg-agent
+ DynamicForward [localhost]:2839
+
+Host *
+ ForwardAgent no
+ Compression no
+ ServerAliveInterval 0
+ HashKnownHosts no
+ UserKnownHostsFile ~/.ssh/known_hosts
+ ControlMaster no
+ ControlPath ~/.ssh/master-%r@%n:%p
+ ControlPersist no
+
+
diff --git a/home-manager/tests/modules/programs/ssh/match-blocks-attrs.nix b/home-manager/tests/modules/programs/ssh/match-blocks-attrs.nix
new file mode 100644
index 00000000000..a84a703e89d
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/match-blocks-attrs.nix
@@ -0,0 +1,55 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.ssh = {
+ enable = true;
+ matchBlocks = {
+ abc = {
+ identityFile = null;
+ proxyJump = "jump-host";
+ };
+
+ xyz = {
+ identityFile = "file";
+ serverAliveInterval = 60;
+ localForwards = [{
+ bind.port = 8080;
+ host.address = "10.0.0.1";
+ host.port = 80;
+ }];
+ remoteForwards = [
+ {
+ bind.port = 8081;
+ host.address = "10.0.0.2";
+ host.port = 80;
+ }
+ {
+ bind.address = "/run/user/1000/gnupg/S.gpg-agent.extra";
+ host.address = "/run/user/1000/gnupg/S.gpg-agent";
+ }
+ ];
+ dynamicForwards = [{ port = 2839; }];
+ };
+
+ "* !github.com" = {
+ identityFile = [ "file1" "file2" ];
+ port = 516;
+ };
+ };
+ };
+
+ home.file.assertions.text = builtins.toJSON
+ (map (a: a.message) (filter (a: !a.assertion) config.assertions));
+
+ nmt.script = ''
+ assertFileExists home-files/.ssh/config
+ assertFileContent \
+ home-files/.ssh/config \
+ ${./match-blocks-attrs-expected.conf}
+ assertFileContent home-files/assertions ${./no-assertions.json}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/ssh/no-assertions.json b/home-manager/tests/modules/programs/ssh/no-assertions.json
new file mode 100644
index 00000000000..0637a088a01
--- /dev/null
+++ b/home-manager/tests/modules/programs/ssh/no-assertions.json
@@ -0,0 +1 @@
+[] \ No newline at end of file
diff --git a/home-manager/tests/modules/programs/texlive/default.nix b/home-manager/tests/modules/programs/texlive/default.nix
new file mode 100644
index 00000000000..23bfe2daf0a
--- /dev/null
+++ b/home-manager/tests/modules/programs/texlive/default.nix
@@ -0,0 +1 @@
+{ texlive-minimal = ./texlive-minimal.nix; }
diff --git a/home-manager/tests/modules/programs/texlive/texlive-minimal.nix b/home-manager/tests/modules/programs/texlive/texlive-minimal.nix
new file mode 100644
index 00000000000..df143dbc660
--- /dev/null
+++ b/home-manager/tests/modules/programs/texlive/texlive-minimal.nix
@@ -0,0 +1,13 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.texlive.enable = true;
+
+ nmt.script = ''
+ assertFileExists home-path/bin/tex
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/tmux/default.nix b/home-manager/tests/modules/programs/tmux/default.nix
new file mode 100644
index 00000000000..d4501c60981
--- /dev/null
+++ b/home-manager/tests/modules/programs/tmux/default.nix
@@ -0,0 +1,7 @@
+{
+ tmux-emacs-with-plugins = ./emacs-with-plugins.nix;
+ tmux-not-enabled = ./not-enabled.nix;
+ tmux-vi-all-true = ./vi-all-true.nix;
+ tmux-secure-socket-enabled = ./secure-socket-enabled.nix;
+ tmux-disable-confirmation-prompt = ./disable-confirmation-prompt.nix;
+}
diff --git a/home-manager/tests/modules/programs/tmux/disable-confirmation-prompt.conf b/home-manager/tests/modules/programs/tmux/disable-confirmation-prompt.conf
new file mode 100644
index 00000000000..b599e603e4a
--- /dev/null
+++ b/home-manager/tests/modules/programs/tmux/disable-confirmation-prompt.conf
@@ -0,0 +1,31 @@
+# ============================================= #
+# Start with defaults from the Sensible plugin #
+# --------------------------------------------- #
+run-shell @sensible_rtp@
+# ============================================= #
+
+set -g default-terminal "screen"
+set -g base-index 0
+setw -g pane-base-index 0
+
+
+
+
+
+set -g status-keys emacs
+set -g mode-keys emacs
+
+
+
+
+
+bind-key & kill-window
+bind-key x kill-pane
+
+
+setw -g aggressive-resize off
+setw -g clock-mode-style 12
+set -s escape-time 500
+set -g history-limit 2000
+
+
diff --git a/home-manager/tests/modules/programs/tmux/disable-confirmation-prompt.nix b/home-manager/tests/modules/programs/tmux/disable-confirmation-prompt.nix
new file mode 100644
index 00000000000..e3d13a4b1b2
--- /dev/null
+++ b/home-manager/tests/modules/programs/tmux/disable-confirmation-prompt.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.tmux = {
+ enable = true;
+ disableConfirmationPrompt = true;
+ };
+
+ nixpkgs.overlays = [
+ (self: super: {
+ tmuxPlugins = super.tmuxPlugins // {
+ sensible = super.tmuxPlugins.sensible // {
+ rtp = "@sensible_rtp@";
+ };
+ };
+ })
+ ];
+
+ nmt.script = ''
+ assertFileExists home-files/.tmux.conf
+ assertFileContent home-files/.tmux.conf \
+ ${./disable-confirmation-prompt.conf}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/tmux/emacs-with-plugins.conf b/home-manager/tests/modules/programs/tmux/emacs-with-plugins.conf
new file mode 100644
index 00000000000..66b10183750
--- /dev/null
+++ b/home-manager/tests/modules/programs/tmux/emacs-with-plugins.conf
@@ -0,0 +1,54 @@
+# ============================================= #
+# Start with defaults from the Sensible plugin #
+# --------------------------------------------- #
+run-shell @tmuxplugin_sensible_rtp@
+# ============================================= #
+
+set -g default-terminal "screen"
+set -g base-index 0
+setw -g pane-base-index 0
+
+new-session
+
+bind v split-window -h
+bind s split-window -v
+
+
+set -g status-keys emacs
+set -g mode-keys emacs
+
+
+
+
+
+
+
+setw -g aggressive-resize on
+setw -g clock-mode-style 24
+set -s escape-time 500
+set -g history-limit 2000
+
+
+
+# ============================================= #
+# Load plugins with Home Manager #
+# --------------------------------------------- #
+
+# tmuxplugin-logging
+# ---------------------
+
+run-shell @tmuxplugin_logging_rtp@
+
+
+# tmuxplugin-prefix-highlight
+# ---------------------
+
+run-shell @tmuxplugin_prefix_highlight_rtp@
+
+
+# tmuxplugin-fzf-tmux-url
+# ---------------------
+
+run-shell @tmuxplugin_fzf_tmux_url_rtp@
+
+# ============================================= #
diff --git a/home-manager/tests/modules/programs/tmux/emacs-with-plugins.nix b/home-manager/tests/modules/programs/tmux/emacs-with-plugins.nix
new file mode 100644
index 00000000000..f9bccaa2ce4
--- /dev/null
+++ b/home-manager/tests/modules/programs/tmux/emacs-with-plugins.nix
@@ -0,0 +1,49 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.tmux = {
+ aggressiveResize = true;
+ clock24 = true;
+ enable = true;
+ keyMode = "emacs";
+ newSession = true;
+ reverseSplit = true;
+
+ plugins = with pkgs.tmuxPlugins; [
+ logging
+ prefix-highlight
+ fzf-tmux-url
+ ];
+ };
+
+ nixpkgs.overlays = [
+ (self: super: {
+ tmuxPlugins = super.tmuxPlugins // {
+ fzf-tmux-url = super.tmuxPlugins.fzf-tmux-url // {
+ rtp = "@tmuxplugin_fzf_tmux_url_rtp@";
+ };
+
+ logging = super.tmuxPlugins.logging // {
+ rtp = "@tmuxplugin_logging_rtp@";
+ };
+
+ prefix-highlight = super.tmuxPlugins.prefix-highlight // {
+ rtp = "@tmuxplugin_prefix_highlight_rtp@";
+ };
+
+ sensible = super.tmuxPlugins.sensible // {
+ rtp = "@tmuxplugin_sensible_rtp@";
+ };
+ };
+ })
+ ];
+
+ nmt.script = ''
+ assertFileExists home-files/.tmux.conf
+ assertFileContent home-files/.tmux.conf ${./emacs-with-plugins.conf}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/tmux/hm-session-vars.sh b/home-manager/tests/modules/programs/tmux/hm-session-vars.sh
new file mode 100644
index 00000000000..40d9c24b50d
--- /dev/null
+++ b/home-manager/tests/modules/programs/tmux/hm-session-vars.sh
@@ -0,0 +1,5 @@
+# Only source this once.
+if [ -n "$__HM_SESS_VARS_SOURCED" ]; then return; fi
+export __HM_SESS_VARS_SOURCED=1
+
+export TMUX_TMPDIR="${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}"
diff --git a/home-manager/tests/modules/programs/tmux/not-enabled.nix b/home-manager/tests/modules/programs/tmux/not-enabled.nix
new file mode 100644
index 00000000000..b7c675a83a2
--- /dev/null
+++ b/home-manager/tests/modules/programs/tmux/not-enabled.nix
@@ -0,0 +1,13 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.tmux = { enable = false; };
+
+ nmt.script = ''
+ assertPathNotExists home-files/.tmux.conf
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/tmux/secure-socket-enabled.nix b/home-manager/tests/modules/programs/tmux/secure-socket-enabled.nix
new file mode 100644
index 00000000000..34e9129c5a4
--- /dev/null
+++ b/home-manager/tests/modules/programs/tmux/secure-socket-enabled.nix
@@ -0,0 +1,17 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.tmux = {
+ enable = true;
+ secureSocket = true;
+ };
+
+ nmt.script = ''
+ assertFileExists home-path/etc/profile.d/hm-session-vars.sh
+ assertFileContent home-path/etc/profile.d/hm-session-vars.sh ${./hm-session-vars.sh}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/tmux/vi-all-true.conf b/home-manager/tests/modules/programs/tmux/vi-all-true.conf
new file mode 100644
index 00000000000..08e37e19b97
--- /dev/null
+++ b/home-manager/tests/modules/programs/tmux/vi-all-true.conf
@@ -0,0 +1,31 @@
+# ============================================= #
+# Start with defaults from the Sensible plugin #
+# --------------------------------------------- #
+run-shell @sensible_rtp@
+# ============================================= #
+
+set -g default-terminal "screen"
+set -g base-index 0
+setw -g pane-base-index 0
+
+new-session
+
+bind v split-window -h
+bind s split-window -v
+
+
+set -g status-keys vi
+set -g mode-keys vi
+
+
+
+
+
+
+
+setw -g aggressive-resize on
+setw -g clock-mode-style 24
+set -s escape-time 500
+set -g history-limit 2000
+
+
diff --git a/home-manager/tests/modules/programs/tmux/vi-all-true.nix b/home-manager/tests/modules/programs/tmux/vi-all-true.nix
new file mode 100644
index 00000000000..bce032fd654
--- /dev/null
+++ b/home-manager/tests/modules/programs/tmux/vi-all-true.nix
@@ -0,0 +1,29 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.tmux = {
+ aggressiveResize = true;
+ clock24 = true;
+ enable = true;
+ keyMode = "vi";
+ newSession = true;
+ reverseSplit = true;
+ };
+
+ nixpkgs.overlays = [
+ (self: super: {
+ tmuxPlugins = super.tmuxPlugins // {
+ sensible = super.tmuxPlugins.sensible // { rtp = "@sensible_rtp@"; };
+ };
+ })
+ ];
+
+ nmt.script = ''
+ assertFileExists home-files/.tmux.conf
+ assertFileContent home-files/.tmux.conf ${./vi-all-true.conf}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/zsh/default.nix b/home-manager/tests/modules/programs/zsh/default.nix
new file mode 100644
index 00000000000..37339598e35
--- /dev/null
+++ b/home-manager/tests/modules/programs/zsh/default.nix
@@ -0,0 +1,7 @@
+{
+ zsh-session-variables = ./session-variables.nix;
+ zsh-history-path-new-default = ./history-path-new-default.nix;
+ zsh-history-path-new-custom = ./history-path-new-custom.nix;
+ zsh-history-path-old-default = ./history-path-old-default.nix;
+ zsh-history-path-old-custom = ./history-path-old-custom.nix;
+}
diff --git a/home-manager/tests/modules/programs/zsh/history-path-new-custom.nix b/home-manager/tests/modules/programs/zsh/history-path-new-custom.nix
new file mode 100644
index 00000000000..0c052d6949e
--- /dev/null
+++ b/home-manager/tests/modules/programs/zsh/history-path-new-custom.nix
@@ -0,0 +1,20 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ home.stateVersion = "20.03";
+ programs.zsh = {
+ enable = true;
+ history.path = "$HOME/some/directory/zsh_history";
+ };
+
+ nixpkgs.overlays =
+ [ (self: super: { zsh = pkgs.writeScriptBin "dummy-zsh" ""; }) ];
+
+ nmt.script = ''
+ assertFileRegex home-files/.zshrc '^HISTFILE="$HOME/some/directory/zsh_history"$'
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/zsh/history-path-new-default.nix b/home-manager/tests/modules/programs/zsh/history-path-new-default.nix
new file mode 100644
index 00000000000..6d1f58a29dc
--- /dev/null
+++ b/home-manager/tests/modules/programs/zsh/history-path-new-default.nix
@@ -0,0 +1,17 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ home.stateVersion = "20.03";
+ programs.zsh.enable = true;
+
+ nixpkgs.overlays =
+ [ (self: super: { zsh = pkgs.writeScriptBin "dummy-zsh" ""; }) ];
+
+ nmt.script = ''
+ assertFileRegex home-files/.zshrc '^HISTFILE="$HOME/.zsh_history"$'
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/zsh/history-path-old-custom.nix b/home-manager/tests/modules/programs/zsh/history-path-old-custom.nix
new file mode 100644
index 00000000000..f5b178b5e97
--- /dev/null
+++ b/home-manager/tests/modules/programs/zsh/history-path-old-custom.nix
@@ -0,0 +1,20 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ home.stateVersion = "19.09";
+ programs.zsh = {
+ enable = true;
+ history.path = "some/directory/zsh_history";
+ };
+
+ nixpkgs.overlays =
+ [ (self: super: { zsh = pkgs.writeScriptBin "dummy-zsh" ""; }) ];
+
+ nmt.script = ''
+ assertFileRegex home-files/.zshrc '^HISTFILE="$HOME/some/directory/zsh_history"$'
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/zsh/history-path-old-default.nix b/home-manager/tests/modules/programs/zsh/history-path-old-default.nix
new file mode 100644
index 00000000000..d880d966454
--- /dev/null
+++ b/home-manager/tests/modules/programs/zsh/history-path-old-default.nix
@@ -0,0 +1,17 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ home.stateVersion = "19.03";
+ programs.zsh.enable = true;
+
+ nixpkgs.overlays =
+ [ (self: super: { zsh = pkgs.writeScriptBin "dummy-zsh" ""; }) ];
+
+ nmt.script = ''
+ assertFileRegex home-files/.zshrc '^HISTFILE="$HOME/.zsh_history"$'
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/programs/zsh/session-variables.nix b/home-manager/tests/modules/programs/zsh/session-variables.nix
new file mode 100644
index 00000000000..ca903619d68
--- /dev/null
+++ b/home-manager/tests/modules/programs/zsh/session-variables.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.zsh = {
+ enable = true;
+
+ sessionVariables = {
+ V1 = "v1";
+ V2 = "v2-${config.programs.zsh.sessionVariables.V1}";
+ };
+ };
+
+ nixpkgs.overlays = [
+ (self: super: {
+ zsh = pkgs.writeScriptBin "dummy-zsh" "";
+ })
+ ];
+
+ nmt.script = ''
+ assertFileExists home-files/.zshrc
+ assertFileRegex home-files/.zshrc 'export V1="v1"'
+ assertFileRegex home-files/.zshrc 'export V2="v2-v1"'
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/services/sxhkd/configuration.nix b/home-manager/tests/modules/services/sxhkd/configuration.nix
new file mode 100644
index 00000000000..992c4b18a94
--- /dev/null
+++ b/home-manager/tests/modules/services/sxhkd/configuration.nix
@@ -0,0 +1,30 @@
+{ config, ... }: {
+ config = {
+ services.sxhkd = {
+ enable = true;
+
+ keybindings = {
+ "super + a" = "run command a";
+ "super + b" = null;
+ "super + Shift + b" = "run command b";
+ };
+
+ extraConfig = ''
+ super + c
+ call command c
+
+ # comment
+ super + d
+ call command d
+ '';
+ };
+
+ nmt.script = ''
+ local sxhkdrc=home-files/.config/sxhkd/sxhkdrc
+
+ assertFileExists $sxhkdrc
+
+ assertFileContent $sxhkdrc ${./sxhkdrc}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/services/sxhkd/default.nix b/home-manager/tests/modules/services/sxhkd/default.nix
new file mode 100644
index 00000000000..ec25252cee0
--- /dev/null
+++ b/home-manager/tests/modules/services/sxhkd/default.nix
@@ -0,0 +1,4 @@
+{
+ sxhkd-configuration = ./configuration.nix;
+ sxhkd-service = ./service.nix;
+}
diff --git a/home-manager/tests/modules/services/sxhkd/service.nix b/home-manager/tests/modules/services/sxhkd/service.nix
new file mode 100644
index 00000000000..46ce259a718
--- /dev/null
+++ b/home-manager/tests/modules/services/sxhkd/service.nix
@@ -0,0 +1,20 @@
+{ config, ... }:
+{
+ config = {
+ services.sxhkd = {
+ enable = true;
+ extraPath = "/home/the-user/bin:/extra/path/bin";
+ };
+
+ nmt.script = ''
+ local serviceFile=home-files/.config/systemd/user/sxhkd.service
+
+ assertFileExists $serviceFile
+
+ assertFileRegex $serviceFile 'ExecStart=.*/bin/sxhkd'
+
+ assertFileRegex $serviceFile \
+ 'Environment=PATH=.*\.nix-profile/bin:/home/the-user/bin:/extra/path/bin'
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/services/sxhkd/sxhkdrc b/home-manager/tests/modules/services/sxhkd/sxhkdrc
new file mode 100644
index 00000000000..c8883464b29
--- /dev/null
+++ b/home-manager/tests/modules/services/sxhkd/sxhkdrc
@@ -0,0 +1,13 @@
+super + Shift + b
+ run command b
+
+super + a
+ run command a
+
+
+super + c
+ call command c
+
+# comment
+super + d
+ call command d
diff --git a/home-manager/tests/modules/services/window-managers/i3/default.nix b/home-manager/tests/modules/services/window-managers/i3/default.nix
new file mode 100644
index 00000000000..e239d6c07f1
--- /dev/null
+++ b/home-manager/tests/modules/services/window-managers/i3/default.nix
@@ -0,0 +1 @@
+{ i3-keybindings = ./i3-keybindings.nix; }
diff --git a/home-manager/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf b/home-manager/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf
new file mode 100644
index 00000000000..1e385e8c734
--- /dev/null
+++ b/home-manager/tests/modules/services/window-managers/i3/i3-keybindings-expected.conf
@@ -0,0 +1,106 @@
+font pango:monospace 8
+floating_modifier Mod1
+new_window normal 2
+new_float normal 2
+hide_edge_borders none
+force_focus_wrapping no
+focus_follows_mouse yes
+focus_on_window_activation smart
+mouse_warping output
+workspace_layout default
+workspace_auto_back_and_forth no
+
+client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577
+client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a
+client.unfocused #333333 #222222 #888888 #292d2e #222222
+client.urgent #2f343a #900000 #ffffff #900000 #900000
+client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c
+client.background #ffffff
+
+bindsym Mod1+0 workspace number 10
+bindsym Mod1+1 workspace number 1
+bindsym Mod1+2 workspace number 2
+bindsym Mod1+3 workspace number 3
+bindsym Mod1+4 workspace number 4
+bindsym Mod1+5 workspace number 5
+bindsym Mod1+6 workspace number 6
+bindsym Mod1+7 workspace number 7
+bindsym Mod1+8 workspace number 8
+bindsym Mod1+9 workspace number 9
+bindsym Mod1+Down focus down
+bindsym Mod1+Invented invented-key-command
+bindsym Mod1+Left overridden-command
+bindsym Mod1+Return exec i3-sensible-terminal
+
+bindsym Mod1+Shift+0 move container to workspace number 10
+bindsym Mod1+Shift+1 move container to workspace number 1
+bindsym Mod1+Shift+2 move container to workspace number 2
+bindsym Mod1+Shift+3 move container to workspace number 3
+bindsym Mod1+Shift+4 move container to workspace number 4
+bindsym Mod1+Shift+5 move container to workspace number 5
+bindsym Mod1+Shift+6 move container to workspace number 6
+bindsym Mod1+Shift+7 move container to workspace number 7
+bindsym Mod1+Shift+8 move container to workspace number 8
+bindsym Mod1+Shift+9 move container to workspace number 9
+bindsym Mod1+Shift+Down move down
+bindsym Mod1+Shift+Left move left
+bindsym Mod1+Shift+Right move right
+bindsym Mod1+Shift+Up move up
+bindsym Mod1+Shift+c reload
+bindsym Mod1+Shift+e exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit'
+bindsym Mod1+Shift+minus move scratchpad
+bindsym Mod1+Shift+q kill
+bindsym Mod1+Shift+r restart
+bindsym Mod1+Shift+space floating toggle
+bindsym Mod1+Up focus up
+bindsym Mod1+a focus parent
+bindsym Mod1+d exec @dmenu@/bin/dmenu_run
+bindsym Mod1+e layout toggle split
+bindsym Mod1+f fullscreen toggle
+bindsym Mod1+h split h
+bindsym Mod1+minus scratchpad show
+bindsym Mod1+r mode resize
+bindsym Mod1+s layout stacking
+bindsym Mod1+space focus mode_toggle
+bindsym Mod1+v split v
+bindsym Mod1+w layout tabbed
+
+mode "resize" {
+bindsym Down resize grow height 10 px or 10 ppt
+bindsym Escape mode default
+bindsym Left resize shrink width 10 px or 10 ppt
+bindsym Return mode default
+bindsym Right resize grow width 10 px or 10 ppt
+bindsym Up resize shrink height 10 px or 10 ppt
+}
+
+
+bar {
+
+ font pango:monospace 8
+ mode dock
+ hidden_state hide
+ position bottom
+ status_command @i3status@/bin/i3status
+ i3bar_command @i3@/bin/i3bar
+ workspace_buttons yes
+ strip_workspace_numbers no
+ tray_output primary
+ colors {
+ background #000000
+ statusline #ffffff
+ separator #666666
+ focused_workspace #4c7899 #285577 #ffffff
+ active_workspace #333333 #5f676a #ffffff
+ inactive_workspace #333333 #222222 #888888
+ urgent_workspace #2f343a #900000 #ffffff
+ binding_mode #2f343a #900000 #ffffff
+ }
+
+}
+
+
+
+
+
+
diff --git a/home-manager/tests/modules/services/window-managers/i3/i3-keybindings.nix b/home-manager/tests/modules/services/window-managers/i3/i3-keybindings.nix
new file mode 100644
index 00000000000..4f8515e61ff
--- /dev/null
+++ b/home-manager/tests/modules/services/window-managers/i3/i3-keybindings.nix
@@ -0,0 +1,35 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+ config = {
+ xsession.windowManager.i3 = {
+ enable = true;
+
+ config.keybindings =
+ let modifier = config.xsession.windowManager.i3.config.modifier;
+ in lib.mkOptionDefault {
+ "${modifier}+Left" = "overridden-command";
+ "${modifier}+Right" = null;
+ "${modifier}+Invented" = "invented-key-command";
+ };
+ };
+
+ nixpkgs.overlays = [
+ (self: super: {
+ dmenu = super.dmenu // { outPath = "@dmenu@"; };
+
+ i3 = super.i3 // { outPath = "@i3@"; };
+
+ i3status = super.i3status // { outPath = "@i3status@"; };
+ })
+ ];
+
+ nmt.script = ''
+ assertFileExists home-files/.config/i3/config
+ assertFileContent home-files/.config/i3/config \
+ ${./i3-keybindings-expected.conf}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/systemd/default.nix b/home-manager/tests/modules/systemd/default.nix
new file mode 100644
index 00000000000..c1779ac59fb
--- /dev/null
+++ b/home-manager/tests/modules/systemd/default.nix
@@ -0,0 +1,5 @@
+{
+ systemd-services = ./services.nix;
+ systemd-session-variables = ./session-variables.nix;
+ systemd-timers = ./timers.nix;
+}
diff --git a/home-manager/tests/modules/systemd/services-expected.conf b/home-manager/tests/modules/systemd/services-expected.conf
new file mode 100644
index 00000000000..34b9618d6d3
--- /dev/null
+++ b/home-manager/tests/modules/systemd/services-expected.conf
@@ -0,0 +1,5 @@
+[Service]
+ExecStart=/some/exec/start/command --with-arguments "%i"
+
+[Unit]
+Description=A basic test service
diff --git a/home-manager/tests/modules/systemd/services.nix b/home-manager/tests/modules/systemd/services.nix
new file mode 100644
index 00000000000..f1f7a42bb1a
--- /dev/null
+++ b/home-manager/tests/modules/systemd/services.nix
@@ -0,0 +1,23 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ systemd.user.services."test-service@" = {
+ Unit = {
+ Description = "A basic test service";
+ };
+
+ Service = {
+ ExecStart = ''/some/exec/start/command --with-arguments "%i"'';
+ };
+ };
+
+ nmt.script = ''
+ local serviceFile=home-files/.config/systemd/user/test-service@.service
+ assertFileExists $serviceFile
+ assertFileContent $serviceFile ${./services-expected.conf}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/systemd/session-variables-expected.conf b/home-manager/tests/modules/systemd/session-variables-expected.conf
new file mode 100644
index 00000000000..5b6e80bc32b
--- /dev/null
+++ b/home-manager/tests/modules/systemd/session-variables-expected.conf
@@ -0,0 +1,2 @@
+V_int=1
+V_str=2
diff --git a/home-manager/tests/modules/systemd/session-variables.nix b/home-manager/tests/modules/systemd/session-variables.nix
new file mode 100644
index 00000000000..7cfb4a6c7c3
--- /dev/null
+++ b/home-manager/tests/modules/systemd/session-variables.nix
@@ -0,0 +1,18 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ systemd.user.sessionVariables = {
+ V_int = 1;
+ V_str = "2";
+ };
+
+ nmt.script = ''
+ local envFile=home-files/.config/environment.d/10-home-manager.conf
+ assertFileExists $envFile
+ assertFileContent $envFile ${./session-variables-expected.conf}
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/systemd/timers-expected.conf b/home-manager/tests/modules/systemd/timers-expected.conf
new file mode 100644
index 00000000000..b19f044cc0b
--- /dev/null
+++ b/home-manager/tests/modules/systemd/timers-expected.conf
@@ -0,0 +1,8 @@
+[Install]
+WantedBy=timers.target
+
+[Timer]
+OnUnitActiveSec=1h 30m
+
+[Unit]
+Description=A basic test timer
diff --git a/home-manager/tests/modules/systemd/timers.nix b/home-manager/tests/modules/systemd/timers.nix
new file mode 100644
index 00000000000..eaa43f17695
--- /dev/null
+++ b/home-manager/tests/modules/systemd/timers.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ systemd.user.timers.test-timer = {
+ Unit = { Description = "A basic test timer"; };
+
+ Timer = { OnUnitActiveSec = "1h 30m"; };
+
+ Install = { WantedBy = [ "timers.target" ]; };
+ };
+
+ nmt.script = ''
+ local unitDir=home-files/.config/systemd/user
+ local timerFile=$unitDir/test-timer.timer
+
+ assertFileExists $timerFile
+ assertFileContent $timerFile ${./timers-expected.conf}
+
+ assertFileExists $unitDir/timers.target.wants/test-timer.timer
+ '';
+ };
+}
diff --git a/home-manager/tests/modules/xresources/default.nix b/home-manager/tests/modules/xresources/default.nix
new file mode 100644
index 00000000000..afd15fbd300
--- /dev/null
+++ b/home-manager/tests/modules/xresources/default.nix
@@ -0,0 +1 @@
+{ xresources = ./xresources.nix; }
diff --git a/home-manager/tests/modules/xresources/xresources-expected.conf b/home-manager/tests/modules/xresources/xresources-expected.conf
new file mode 100644
index 00000000000..20b47e5080b
--- /dev/null
+++ b/home-manager/tests/modules/xresources/xresources-expected.conf
@@ -0,0 +1,5 @@
+Test*boolean1: true
+Test*boolean2: false
+Test*int: 10
+Test*list: list-str, true, false, 10
+Test*string: test-string
diff --git a/home-manager/tests/modules/xresources/xresources.nix b/home-manager/tests/modules/xresources/xresources.nix
new file mode 100644
index 00000000000..f73e326f31e
--- /dev/null
+++ b/home-manager/tests/modules/xresources/xresources.nix
@@ -0,0 +1,22 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+ config = {
+ xresources = {
+ properties = {
+ "Test*string" = "test-string";
+ "Test*boolean1" = true;
+ "Test*boolean2" = false;
+ "Test*int" = 10;
+ "Test*list" = [ "list-str" true false 10 ];
+ };
+ };
+
+ nmt.script = ''
+ assertFileExists home-files/.Xresources
+ assertFileContent home-files/.Xresources ${./xresources-expected.conf}
+ '';
+ };
+}