Skip to content

Please Add The Ability To Define Custom Test Trigger Patterns #6457

@klondikemarlen

Description

@klondikemarlen

Clear and concise description of the problem

As a developer using Vitest I want the ability to have an .html or .txt file trigger the re-run of a specific test file so that I can have an easier time testing mailers and email templates.

I'd like to see an option similar to what Ruby's Guard has.
In Guard it would look something like this:

guard :minitest, cli: '--force' do
  # Watch for changes in .ts, .html, or .txt files in mailers or templates directories
  watch(%r{^src/(mailers|templates)/(.*)\.(ts|html|txt)$}) do |m|
    "api/tests/mailers/#{m[2]}.test.ts"
  end
end

This would cause changes to:

  • api/src/templates/workflow-steps/next-step-mailer.html
  • api/src/templates/workflow-steps/next-step-mailer.txt
  • api/src/mailers/workflow-steps/next-step-mailer.ts
    to all trigger the test api/tests/mailers/workflow-steps/next-step-mailer.test.ts to run.

Suggested solution

Given that the JS equivalent might be something like

const chokidar = require('chokidar');
const { exec } = require('child_process');

// Watch for changes in .ts, .html, or .txt files in mailers or templates directories
chokidar.watch('src/{mailers,templates}/**/*.{ts,html,txt}')
  .on('change', (path) => {
    const match = path.match(/^src\/(mailers|templates)\/(.*)\.(ts|html|txt)$/);
    if (match) {
      const testFile = `api/tests/mailers/${match[2]}.test.ts`;
      console.log(`Detected change in: ${path}. Running ${testFile}`);
      exec(`npx vitest run ${testFile}`, (err, stdout, stderr) => {
        if (err) {
          console.error(`Error: ${stderr}`);
          return;
        }
        console.log(stdout);
      });
    }
  });

It would probably be possible to make a vitest config option test.watch.triggerPatterns with an interface like:

import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    watch: {
      triggerPatterns: [{
        pattern: /^src\/(mailers|templates)\/(.*)\.(ts|html|txt)$/,
        testToRun: (match) => {
          return `api/tests/mailers/${match[2]}.test.ts`
        },
      }],
    },
  },
});

Alternative

Option 1

Use https://vitest.dev/config/#forcereruntriggers

import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    forceRerunTriggers: [
      "**/*.(html|txt)", // Rerun tests when data files change
    ],
  },
});

While I'm happy that this option exists; I don't love it, because it forces all the tests to re-run, not just the relevant one.

Option 2

Use direct import at top of test file
e.g.

// in api/tests/mailers/workflow-steps/next-step-mailer.test.ts
import "@/templates/workflow-steps/next-step-mailer.html?raw"
import "@/templates/workflow-steps/next-step-mailer.txt?raw"

I can't decide if I like this option more or less than the previous option.
On one hand, its efficient, and pretty straight forward.
On the other hand its not a global configuration, so I'm effectively leaking config into individual files.
Also its likely that future developers will have no idea what this does without an explanatory comment.

Additional context

Guard docs at https://github.com/guard/guard/wiki/Custom-matchers-in-watches#using-custom-matchers-in-watches
Guard DSL source https://github.com/guard/guard/blob/7ccce79c46a6e9d1acaca989bc1a2b72d3806221/lib/guard/dsl.rb#L209
Guard Watcher implementation source https://github.com/guard/guard/blob/7ccce79c46a6e9d1acaca989bc1a2b72d3806221/lib/guard/watcher.rb#L13

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Has plan

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions