packages feed

nix-lang-0.1.0.0: test/Edit.hs

{-# LANGUAGE QuasiQuotes #-}

module Edit where

import Nix.Lang.Edit
import Nix.Lang.ExactPrint
import Nix.Lang.QQ.Parsed (nixParsedQQ)
import qualified Nix.Lang.Types.Ps as Ps
import Nix.Lang.Utils
import Test.Tasty
import Test.Tasty.HUnit

tests :: TestTree
tests =
  testGroup
    "edit"
    [ testCase "editExpr supports nested selector updates" editExprNestedSelectorUpdate,
      testCase "editExpr repairs root replacements" editExprRootReplacement,
      testCase "editExpr preserves unrelated let binding layout" editExprPreservesUnrelatedLetLayout,
      testCase "editExpr repairs shape-changing replacement locally" editExprShapeChangingReplacement,
      testCase "editExpr repairs list element replacement" editExprListElementReplacement,
      testCase "editExpr supports binding lookup by key" editExprBindingLookupByKey,
      testCase "editExpr supports binding lookup by path" editExprBindingLookupByPath,
      testCase "editExpr supports let binding insertion" editExprLetBindingInsertion,
      testCase "editExpr supports set binding insertion" editExprSetBindingInsertion,
      testCase "editExpr supports inherit binding insertion" editExprInheritBindingInsertion,
      testCase "editBinding supports inherit scope updates" editBindingInheritScopeUpdate,
      testCase "editBinding supports inherit key updates" editBindingInheritKeyUpdate,
      testCase "editBinding supports inherit key insertion" editBindingInheritKeyInsertion
    ]

editExprNestedSelectorUpdate :: Assertion
editExprNestedSelectorUpdate = do
  let expr =
        [nixParsedQQ|
          let
            f = {a, b}: a + b;
          in
            f { a = 1; b = 2; }
        |] ::
          Ps.LExpr
  case editExpr (letBody // appArgument // bindingAt 0 // bindingValue) (setIntLiteral 233) expr of
    Right x -> renderExactText (unLoc x) @?= "let\n  f = {a, b}: a + b;\nin\n  f { a = 233; b = 2; }"
    Left err -> fail $ show err

editExprPreservesUnrelatedLetLayout :: Assertion
editExprPreservesUnrelatedLetLayout = do
  let expr =
        [nixParsedQQ|
          let
            f = {a, b}: a + b;
            g = [
              1
              2
            ];
          in
            f { a = 1; b = 2; }
        |] ::
          Ps.LExpr
  case editExpr (letBody // appArgument // bindingAt 0 // bindingValue) (setIntLiteral 233) expr of
    Right x ->
      renderExactText (unLoc x)
        @?= "let\n  f = {a, b}: a + b;\n  g = [\n    1\n    2\n  ];\nin\n  f { a = 233; b = 2; }"
    Left err -> fail $ show err

editExprRootReplacement :: Assertion
editExprRootReplacement = do
  let expr =
        [nixParsedQQ|
          {
            a = 1;
            b = [
              2
              3
            ];
          }
        |] ::
          Ps.LExpr
      replacement =
        [nixParsedQQ|
          {
            a = 2;
            b = [
              3
              4
            ];
          }
        |] ::
          Ps.LExpr
  case editExpr root (replace replacement) expr of
    Right x ->
      renderExactText (unLoc x)
        @?= "{\n  a = 2;\n  b = [\n    3\n    4\n  ];\n}"
    Left err -> fail $ show err

editExprShapeChangingReplacement :: Assertion
editExprShapeChangingReplacement = do
  let expr =
        [nixParsedQQ|
          let
            value = 1;
          in
            [ value 2 ]
        |] ::
          Ps.LExpr
      replacement =
        [nixParsedQQ|
          value 20
        |] ::
          Ps.LExpr
  case editExpr (letBody // listElement 0) (replace replacement) expr of
    Right x ->
      renderExactText (unLoc x)
        @?= "let\n  value = 1;\nin\n  [\n    value 20\n    2\n            ]"
    Left err -> fail $ show err

editExprListElementReplacement :: Assertion
editExprListElementReplacement = do
  let expr =
        [nixParsedQQ|
          [
            1
            2
            3
          ]
        |] ::
          Ps.LExpr
  case editExpr (listElement 1) (setIntLiteral 200) expr of
    Right x ->
      renderExactText (unLoc x)
        @?= "[\n  1\n  200\n  3\n]"
    Left err -> fail $ show err

editExprBindingLookupByKey :: Assertion
editExprBindingLookupByKey = do
  let expr =
        [nixParsedQQ|
          {
            a = 1;
            b = 2;
          }
        |] ::
          Ps.LExpr
  case editExpr (bindingByKey "b" // bindingValue) (setIntLiteral 20) expr of
    Right x ->
      renderExactText (unLoc x)
        @?= "{\n  a = 1;\n  b = 20;\n}"
    Left err -> fail $ show err

editExprBindingLookupByPath :: Assertion
editExprBindingLookupByPath = do
  let expr =
        [nixParsedQQ|
          {
            services.nginx.enable = false;
          }
        |] ::
          Ps.LExpr
  case editExpr (bindingByPath ["services", "nginx", "enable"] // bindingValue) (replaceExprText "true") expr of
    Right x ->
      renderExactText (unLoc x)
        @?= "{\n  services.nginx.enable = true;\n}"
    Left err -> fail $ show err

editExprLetBindingInsertion :: Assertion
editExprLetBindingInsertion = do
  let expr =
        [nixParsedQQ|
          let
            a = 1;
          in
            a
        |] ::
          Ps.LExpr
  case editExpr root (insertBindingText (InsertBindingAt 1) "b = 2;") expr of
    Right x ->
      renderExactText (unLoc x)
        @?= "let\n  a = 1;\n  b = 2;\nin\n  a"
    Left err -> fail $ show err

editExprSetBindingInsertion :: Assertion
editExprSetBindingInsertion = do
  let expr =
        [nixParsedQQ|
          {
            a = 1;
            c = 3;
          }
        |] ::
          Ps.LExpr
  case editExpr root (insertBindingText (InsertBindingAt 1) "b = 2;") expr of
    Right x ->
      renderExactText (unLoc x)
        @?= "{\n  a = 1;\n  b = 2;\n  c = 3;\n}"
    Left err -> fail $ show err

editExprInheritBindingInsertion :: Assertion
editExprInheritBindingInsertion = do
  let expr =
        [nixParsedQQ|
          {
            a = 1;
          }
        |] ::
          Ps.LExpr
  case editExpr root (insertBindingText (InsertBindingAt 0) "inherit (pkgs) lib;") expr of
    Right x ->
      renderExactText (unLoc x)
        @?= "{\n  inherit (pkgs) lib;\n  a = 1;\n}"
    Left err -> fail $ show err

editBindingInheritScopeUpdate :: Assertion
editBindingInheritScopeUpdate = do
  let expr =
        [nixParsedQQ|
          {
            inherit (pkgs) lib;
          }
        |] ::
          Ps.LExpr
  case editExpr (bindingByKey "lib" // inheritScope) (replaceExprText "scope") expr of
    Right x -> renderExactText (unLoc x) @?= "{\n  inherit (scope) lib;\n}"
    Left err -> fail $ show err

editBindingInheritKeyUpdate :: Assertion
editBindingInheritKeyUpdate = do
  let expr =
        [nixParsedQQ|
          {
            inherit (pkgs) old other;
          }
        |] ::
          Ps.LExpr
  case editExpr (bindingByKey "old" // inheritKey "old") (replaceAttrKeyText "new") expr of
    Right x -> renderExactText (unLoc x) @?= "{\n  inherit (pkgs) new other;\n}"
    Left err -> fail $ show err

editBindingInheritKeyInsertion :: Assertion
editBindingInheritKeyInsertion = do
  let expr =
        [nixParsedQQ|
          {
            inherit (pkgs) a c;
          }
        |] ::
          Ps.LExpr
  case editExpr (bindingByKey "a") (insertInheritKeyTextAt 1 "b") expr of
    Right x -> renderExactText (unLoc x) @?= "{\n  inherit (pkgs) a b c;\n}"
    Left err -> fail $ show err