loki icon indicating copy to clipboard operation
loki copied to clipboard

ENOENT error encountered while using fileNameFormatter feature

Open Geloloboy opened this issue 5 years ago • 9 comments

DESCRIPTION: The following error is encountered when running into an image with valid difference from baseline: Loki Filename Error

STEPS TO REPLICATE: Set the following attribute in loki.config.js: fileNameFormatter: ({ configurationName, kind, story }) = ${configurationName}/${kind}_${story}.toLowerCase()

EXPECTED RESULT: An image is different error is encountered Difference is shown on the difference folder

ACTUAL RESULT: ENOENT error is encountered No image gets saved on the difference folder

NOTE: Haven't tested on a flat file structure since our storybook instance have folders set up in them

Geloloboy avatar Apr 02 '20 22:04 Geloloboy

Haven't tested on a flat file structure

It works for flat structure, so there's definitely a bug related to missing directories when creating diff. +1 cause this currently makes using fileNameFormatter impossible for most usages.

jalooc avatar Apr 05 '20 13:04 jalooc

After a short research I think I found it:

Loki uses looksSame.createDiff passing the diff option to looks-same in the form of the path to the file. looks-same in turn, after some processing saves the file using fs.createWriteStream(), passing that path as a parameter. Now, fs.createWriteStream() fails when the directory the path is pointing to doesn't exist - and that's the problem.

The reason why saving reference and current images works in Loki is because Loki saves them itself using fsExtra.outputFile() which creates any missing directories.

That's a tough one then - seems like the best option would be to ask looks-same to use the same saving method as Loki (it makes sense for them from the usability point of view). If it doesn't work out, I guess the only option is for Loki to create that dir manually before executing looksSame.createDiff(). Which option should we take @oblador ?

jalooc avatar Apr 05 '20 14:04 jalooc

+1

opened an issue to 'looks-same', feel free to elaborate there, +1 or comment

alonseg avatar Apr 23 '20 04:04 alonseg

@alonseg A link wouldn't hurt 😉

jalooc avatar Apr 23 '20 07:04 jalooc

@jalooc sure, I just thought you can see here my mention :)

https://github.com/gemini-testing/looks-same/issues/68

alonseg avatar Apr 23 '20 07:04 alonseg

Ran into this problem recently while using fileNameFormatter to place references near the component:

fileNameFormatter({configurationName, kind, story}) {
    return `components/${kind}/__references__/${configurationName}/${story.toLowerCase()}`;
}

looks-same definitely has a flaw, but when switching diffing engine to gm the same error occurs: gm compare: Unable to open file (...) [No such file or directory].

Maybe Loki should create path to the difference image before calling differ and then just remove it if there is no any difference? BTW, gm differ already removes (https://github.com/oblador/loki/blob/master/packages/diff-graphics-magick/src/create-graphics-magick-differ.js#L21).

kirilldronkin avatar Apr 29 '20 15:04 kirilldronkin

@kirilldronkin in the looks-same case I don't think we even need the removal part, we can create the path only if it is not the same. see here: looksSame.createDiff

I can create the PR but I'd like to hear @oblador opinion first to know if he'll approve it

alonseg avatar Apr 30 '20 06:04 alonseg

I think a better approach would be to write the diff to a temp dir and then move it if there is a diff. Otherwise we'd end up with a bunch of empty directories.

oblador avatar Jul 24 '20 07:07 oblador

For anyone stumbling on this, here's a workound using patch-package

  • Add these two patches to <root>/patches

@loki+diff-graphics-magick+0.25.0.patch

index 8a32d31..f5cc93f 100644
--- a/node_modules/@loki/diff-graphics-magick/src/create-graphics-magick-differ.js
+++ b/node_modules/@loki/diff-graphics-magick/src/create-graphics-magick-differ.js
@@ -4,6 +4,7 @@ const gm = require('gm');
 function createGraphicsMagickDiffer(config) {
   return function getImageDiff(path1, path2, diffPath, tolerance) {
     const instanceConfig = { tolerance: tolerance / 100, ...config };
+    fs.ensureFileSync(diffPath);
     return new Promise((resolve, reject) => {
       gm.compare(
         path1,

@loki+diff-looks-same+0.25.1.patch

index 033a2e6..3d29fde 100644
--- a/node_modules/@loki/diff-looks-same/src/create-looks-same-differ.js
+++ b/node_modules/@loki/diff-looks-same/src/create-looks-same-differ.js
@@ -4,6 +4,7 @@ const looksSame = require('looks-same');
 function createLooksSameDiffer(config) {
   return function getImageDiff(path1, path2, diffPath, tolerance) {
     const instanceConfig = { tolerance, ...config };
+    fs.ensureFileSync(diffPath);
     return new Promise(async (resolve, reject) => {
       const [reference, current] = (await Promise.all([
         fs.readFile(path1),

  • Make sure you have "postinstall": "patch-package" in the scripts of your package.json

This will automatically patch the scripts for diffing with the two engines to add a fs.ensureFileSync, therefore creating the necessary directories/files before the actual diff. This might result in a bunch of empty directories, but that isn't much of a concern for me (especially since this is simply a workaround to make it work)

SebDuf avatar Sep 27 '20 19:09 SebDuf