1{ pkgs, ... }:
2
3let
4 mkConfig = name: keys: ''
5 import XMonad
6 import XMonad.Operations (restart)
7 import XMonad.Util.EZConfig
8 import XMonad.Util.SessionStart
9 import Control.Monad (when)
10 import Text.Printf (printf)
11 import System.Posix.Process (executeFile)
12 import System.Info (arch,os)
13 import System.Environment (getArgs)
14 import System.FilePath ((</>))
15
16 main = do
17 dirs <- getDirectories
18 launch (def { startupHook = startup } `additionalKeysP` myKeys) dirs
19
20 startup = isSessionStart >>= \sessInit ->
21 spawn "touch /tmp/${name}"
22 >> if sessInit then setSessionStarted else spawn "xterm"
23
24 myKeys = [${builtins.concatStringsSep ", " keys}]
25
26 compiledConfig = printf "xmonad-%s-%s" arch os
27
28 compileRestart resume = do
29 dirs <- asks directories
30
31 whenX (recompile dirs True) $
32 when resume writeStateToFile
33 *> catchIO
34 ( do
35 args <- getArgs
36 executeFile (cacheDir dirs </> compiledConfig) False args Nothing
37 )
38 '';
39
40 oldKeys = [
41 ''("M-C-x", spawn "xterm")''
42 ''("M-q", restart "xmonad" True)''
43 ''("M-C-q", compileRestart True)''
44 ''("M-C-t", spawn "touch /tmp/somefile")'' # create somefile
45 ];
46
47 newKeys = [
48 ''("M-C-x", spawn "xterm")''
49 ''("M-q", restart "xmonad" True)''
50 ''("M-C-q", compileRestart True)''
51 ''("M-C-r", spawn "rm /tmp/somefile")'' # delete somefile
52 ];
53
54 newConfig = pkgs.writeText "xmonad.hs" (mkConfig "newXMonad" newKeys);
55in
56{
57 name = "xmonad";
58 meta = with pkgs.lib.maintainers; {
59 maintainers = [
60 nequissimus
61 ivanbrennan
62 ];
63 };
64
65 nodes.machine =
66 { pkgs, ... }:
67 {
68 imports = [
69 ./common/x11.nix
70 ./common/user-account.nix
71 ];
72 test-support.displayManager.auto.user = "alice";
73 services.displayManager.defaultSession = "none+xmonad";
74 services.xserver.windowManager.xmonad = {
75 enable = true;
76 enableConfiguredRecompile = true;
77 enableContribAndExtras = true;
78 extraPackages = with pkgs.haskellPackages; haskellPackages: [ xmobar ];
79 config = mkConfig "oldXMonad" oldKeys;
80 };
81 };
82
83 testScript =
84 { nodes, ... }:
85 let
86 user = nodes.machine.users.users.alice;
87 in
88 ''
89 machine.wait_for_x()
90 machine.wait_for_file("${user.home}/.Xauthority")
91 machine.succeed("xauth merge ${user.home}/.Xauthority")
92 machine.send_key("alt-ctrl-x")
93 machine.wait_for_window("${user.name}.*machine")
94 machine.sleep(1)
95 machine.screenshot("terminal1")
96 machine.succeed("rm /tmp/oldXMonad")
97 machine.send_key("alt-q")
98 machine.wait_for_file("/tmp/oldXMonad")
99 machine.wait_for_window("${user.name}.*machine")
100 machine.sleep(1)
101 machine.screenshot("terminal2")
102
103 # /tmp/somefile should not exist yet
104 machine.fail("stat /tmp/somefile")
105
106 # original config has a keybinding that creates somefile
107 machine.send_key("alt-ctrl-t")
108 machine.wait_for_file("/tmp/somefile")
109
110 # set up the new config
111 machine.succeed("mkdir -p ${user.home}/.xmonad")
112 machine.copy_from_host("${newConfig}", "${user.home}/.config/xmonad/xmonad.hs")
113
114 # recompile xmonad using the new config
115 machine.send_key("alt-ctrl-q")
116 machine.wait_for_file("/tmp/newXMonad")
117
118 # new config has a keybinding that deletes somefile
119 machine.send_key("alt-ctrl-r")
120 machine.wait_until_fails("stat /tmp/somefile", timeout=30)
121
122 # restart with the old config, and confirm the old keybinding is back
123 machine.succeed("rm /tmp/oldXMonad")
124 machine.send_key("alt-q")
125 machine.wait_for_file("/tmp/oldXMonad")
126 machine.send_key("alt-ctrl-t")
127 machine.wait_for_file("/tmp/somefile")
128 '';
129}