anc95 / inquirer-file-tree-selection

inquirer prompt for select a file or dir by file tree
49 stars 26 forks source link

Validation does not work when filter is used #29

Closed atjn closed 3 years ago

atjn commented 3 years ago

I use the validate function to make sure the user cannot select the root folder:

  validate: async answer => Boolean(answer !== process.cwd())

I also use the filter function to get a relative path as output:

  filter: answer => path.relative(process.cwd(), answer)

When I add the filter function, the validate function seems to stop working. The root path is still a red color, but if I press enter, I am allowed to select it as my answer. This seems to only happen when the filter function returns a different answer than the original answer. If it outputs the same as its input, everything still works fine.

Steps to reproduce

Create a new test project with the following code:

import inquirer from "inquirer";
import fileTree from "inquirer-file-tree-selection-prompt";
const prompt = inquirer.createPromptModule();
prompt.registerPrompt("file-tree", fileTree);

await prompt([
    {
        name: "test",
        type: "file-tree",
        message: `This is a test.`,
        validate: async path => Boolean(path !== process.cwd()),
        filter: answer => answer,
    }
]);

Run this example and notice that you cannot select the root folder, as is expected. (you can also try to remove the filter function and see that that also works as expected)

Now change the filter function to this:

  filter: answer => "different output answer",

Run the example again and notice that you can now select the root folder, even though you weren't supposed to be able to do that.

anc95 commented 3 years ago

I read the code of the Base Prompt Class, it's handleSubmitEvents Implements the validate before submit.

const validation = submit.pipe(
  flatMap((value) => {
    this.startSpinner(value, this.opt.filteringText);
    return asyncFilter(value, self.answers).then(
      (filteredValue) => {
        this.startSpinner(filteredValue, this.opt.validatingText);
        return validate(filteredValue, self.answers).then(
          (isValid) => ({ isValid, value: filteredValue }),
          (err) => ({ isValid: err, value: filteredValue })
        );
      },
      (err) => ({ isValid: err })
    );
  }),
  share()
);

It was passed the filtered value to validation function. but I used the originValue to make validation to decide if print a red word. This difference makes it impossible to use validate and filter at the same time.

I will work on to always pass the filteredValue to validation as Inquirejs does. is it okay for you?

anc95 commented 3 years ago

I just published 1.0.8 version. you can try this. If there is still some trouble with this plugin, very welcome to feedback here~