dream2nix icon indicating copy to clipboard operation
dream2nix copied to clipboard

[help] node project - run tests?

Open hermann-p opened this issue 3 years ago • 3 comments
trafficstars

My node (TypeScript) project builds just fine with a minimal dream2nix-config from the examples (and I'm amazed at how easy and clutter-free it is compared to other node nixification tools!).
Now I'd like to run the flake from a git workflow using nixbuild/nix-quick-install-action@v14. The project has a common pattern for node apps:

"scripts": {
  "build": "tsc",
  "test": "jest"
  }

The build script gets called successfully from commandline and from the git-workflow

name: Test
on: [pull_request, push]

jobs:
  test-and-build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: nixbuild/nix-quick-install-action@v14
        with:
          nix_conf: experimental-features = nix-command flakes
      - name: build packages
        run: nix build '.#default'

Now I'd also like to run the task test, so I can use the workflow's exit state as complete sanity check, but I can't find a way to do so.

  • When modifying my build command to npm run test; tsc or adding a postbuild command, the test will fail because it can't find any test files (test files are in the ./src/ folder and identified by a xxx.test.ts substring).
  • When adding an "app" to flakes that runs the jest executable from the result, it will fail due to missing dependencies, namely ts-jest not found.

I think the latter might be fixable by moving all node dev-dependencies to runtime dependencies, but this would negatively impact the distributed package's size and dependency graph.

Is there some misconception I have about the working of dream2nix? How should I go about, fixing this?

The repository in question

hermann-p avatar Aug 01 '22 08:08 hermann-p

I tried running this with:

{
  inputs = {
    dream2nix.url = "github:nix-community/dream2nix";
    nixpkgs.url = "github:nixos/nixpkgs";
    nixpkgs.follows = "nixpkgs";
  };

  outputs = { self, dream2nix, nixpkgs }@inp:
    (dream2nix.lib.makeFlakeOutputs {
      systems = [ "x86_64-linux" ];
      config.projectRoot = ./.;
      source = ./.;
      packageOverrides = {
        grud-devtools = {
          "build-test" = {
            buildScript = ''
              # Run build
              npm run build

              # Run tests
              npm run test -- --verbose --debug
            '';
          };
        };
      };
    }) // {
      apps.x86_64-linux.checks = {
        type = "app";
        program =
          "${self.packages.x86_64-linux.default}/lib/node_modules/grud-devtools/node_modules/jest/bin/jest.js";
      };
    };
}

I get:

> [email protected] test /nix/store/d9l2lcshhh60z8md5rxvnrfzda03l8wb-grud-devtools-0.1.0/lib/node_modules/grud-devtools
> jest "--verbose" "--debug"

{
  "configs": [
    {
      "automock": false,
      "cache": true,
      "cacheDirectory": "/build/jest_rs",
      "clearMocks": false,
      "coveragePathIgnorePatterns": [
        "/node_modules/"
      ],
      "cwd": "/nix/store/d9l2lcshhh60z8md5rxvnrfzda03l8wb-grud-devtools-0.1.0/lib/node_modules/grud-devtools",
      "detectLeaks": false,
      "detectOpenHandles": false,
      "errorOnDeprecated": false,
      "extensionsToTreatAsEsm": [],
      "fakeTimers": {
        "enableGlobally": false
      },
      "forceCoverageMatch": [],
      "globals": {},
      "haste": {
        "computeSha1": false,
        "enableSymlinks": false,
        "forceNodeFilesystemAPI": true,
        "throwOnModuleCollision": false
      },
      "id": "4957166a42cdd73dc20763cac55fc75a",
      "injectGlobals": true,
      "moduleDirectories": [
        "node_modules"
      ],
      "moduleFileExtensions": [
        "js",
        "mjs",
        "cjs",
        "jsx",
        "ts",
        "tsx",
        "json",
        "node"
      ],
      "moduleNameMapper": [],
      "modulePathIgnorePatterns": [],
      "prettierPath": "prettier",
      "resetMocks": false,
      "resetModules": false,
      "restoreMocks": false,
      "rootDir": "/nix/store/d9l2lcshhh60z8md5rxvnrfzda03l8wb-grud-devtools-0.1.0/lib/node_modules/grud-devtools",
      "roots": [
        "/nix/store/d9l2lcshhh60z8md5rxvnrfzda03l8wb-grud-devtools-0.1.0/lib/node_modules/grud-devtools"
      ],
      "runner": "/nix/store/vpcbv8a0y2gn4mc7dyfksmcqkflqr3rn-jest-runner-28.1.3/lib/node_modules/jest-runner/build/index.js",
      "sandboxInjectedGlobals": [],
      "setupFiles": [],
      "setupFilesAfterEnv": [],
      "skipFilter": false,
      "slowTestThreshold": 5,
      "snapshotSerializers": [],
      "testEnvironment": "/nix/store/7va0n0pc033g4lm3yyj9ycnjg2xcv12i-jest-environment-node-28.1.3/lib/node_modules/jest-environment-node/build/index.js",
      "testEnvironmentOptions": {},
      "testLocationInResults": false,
      "testMatch": [
        "**/__tests__/**/*.[jt]s?(x)",
        "**/?(*.)+(spec|test).[tj]s?(x)"
      ],
      "testPathIgnorePatterns": [
        "/node_modules/"
      ],
      "testRegex": [],
      "testRunner": "/nix/store/z91jbznsf1an8nxvdmjpg90qv62k85cz-jest-circus-28.1.3/lib/node_modules/jest-circus/runner.js",
      "transform": [
        [
          "^.+\\.tsx?$",
          "/nix/store/qxx63ziqjngaz1x2p07kvgwjy42mgm0h-ts-jest-28.0.5/lib/node_modules/ts-jest/dist/index.js",
          {}
        ]
      ],
      "transformIgnorePatterns": [
        "/node_modules/",
        "\\.pnp\\.[^\\/]+$"
      ],
      "watchPathIgnorePatterns": []
    }
  ],
  "globalConfig": {
    "bail": 0,
    "changedFilesWithAncestor": false,
    "ci": false,
    "collectCoverage": false,
    "collectCoverageFrom": [],
    "coverageDirectory": "/nix/store/d9l2lcshhh60z8md5rxvnrfzda03l8wb-grud-devtools-0.1.0/lib/node_modules/grud-devtools/coverage",
    "coverageProvider": "babel",
    "coverageReporters": [
      "json",
      "text",
      "lcov",
      "clover"
    ],
    "detectLeaks": false,
    "detectOpenHandles": false,
    "errorOnDeprecated": false,
    "expand": false,
    "findRelatedTests": false,
    "forceExit": false,
    "json": false,
    "lastCommit": false,
    "listTests": false,
    "logHeapUsage": false,
    "maxConcurrency": 5,
    "maxWorkers": 7,
    "noStackTrace": false,
    "nonFlagArgs": [],
    "notify": false,
    "notifyMode": "failure-change",
    "onlyChanged": false,
    "onlyFailures": false,
    "passWithNoTests": false,
    "projects": [],
    "rootDir": "/nix/store/d9l2lcshhh60z8md5rxvnrfzda03l8wb-grud-devtools-0.1.0/lib/node_modules/grud-devtools",
    "runTestsByPath": false,
    "skipFilter": false,
    "testFailureExitCode": 1,
    "testPathPattern": "",
    "testSequencer": "/nix/store/77r6n71lgax69ryhnq1xwm9hgj02gics-__at__jest__slash__test-sequencer-28.1.3/lib/node_modules/@jest/test-sequencer/build/index.js",
    "updateSnapshot": "new",
    "useStderr": false,
    "verbose": true,
    "watch": false,
    "watchAll": false,
    "watchman": true
  },
  "version": "28.1.3"
}

Which looks quite right, so I am really not sure why jest cannot locate the test files.

tinybeachthor avatar Aug 10 '22 20:08 tinybeachthor

I have played with this a while, and completely forgot to respond here. I'm sorry for that. From my observation, the problem seems to be that jest excludes directories that have a node_modules somewhere in their path. Since the dream2nix builder buidls directly in $out/lib/node_modules/$packageName, all test directories will get excluded by default.

We should find out how jest can be configured to not ignore that directory and maybe add a community override that patches it to have that option set by default.

Alternatively we could change the builder to not build inside $out/lib/node_modules. It should probably build inside /build anyways and then move the files after the build is finished

DavHau avatar Aug 13 '22 10:08 DavHau

@DavHau Making jest un-ignore the node_modules package seems to be a good idea. It should be enough to set the testPathIgnorePattern to not ignore our node_module, and there's a number of places where this could be done:

  • In package.json, in a top level entry: {..."jest": {"testPathIgnorePattern": ["regex", "regex",...] }, ... }
  • When calling the files from CLI with --testPathIgnorePattern='regex'
  • In the jest config file the project chose to use

To un-ignore only the node_modules directory of our own package, its subdirectory should be prefixed with an exclamation mark, as seen here.

I have no knowledge of dream2nix' internals, but I don't know if changing the build [directory] will fix the problem transparently. To my understanding, it would only guarantee a successful test run if the test command gets called during the build phase. If it is used as a second call, as in my example where it will allow git to determine if the build or the test did fail, the files would already be copied to the out-path and we'd be back at jest ignoring the files.

Edit: The second call will possibly never work as long as all packages required for the test run are only used as dev dependencies. A pure nix-build will only have deps, not dev-deps. Considering this, the change to the build path might be an idea requiring less fragile changes.

hermann-p avatar Aug 16 '22 06:08 hermann-p

This should be fixed by https://github.com/nix-community/dream2nix/pull/337

DavHau avatar Nov 09 '22 19:11 DavHau