How to configure jest snapshot locations - javascript

I'd like for my jest snapshots to be created as a sibling to my test file
I current have my snapshots being put in the default __snapshots__ folder.
Current:
What I would like to achieve:
I found this post on github: https://github.com/facebook/jest/issues/1650
In the thread someone says the following should work but I haven't had any luck (even with changing the regex and other changes):
module.exports = {
testPathForConsistencyCheck: 'some/example.test.js',
resolveSnapshotPath: (testPath, snapshotExtension) =>
testPath.replace(/\.test\.([tj]sx?)/, `${snapshotExtension}.$1`),
resolveTestPath: (snapshotFilePath, snapshotExtension) =>
snapshotFilePath.replace(snapshotExtension, '.test'),
}

In package.json (or if you use jest.config.js) you need to add the path for the snapshotResolver file:
"jest": {
"snapshotResolver": "./snapshotResolver.js"
}
snapshotResolver.js is a file with code that you found in a Github issue.
In my case this file was located at the root of the project (near node_modules folder)

These solutions are more complicated that is needed for what you are trying to do.
As per pointed out in https://github.com/facebook/jest/issues/1650
Solution
Create a file: I used - 'jest/snapshotResolver.js'
module.exports = {
resolveSnapshotPath: (testPath, snapshotExtension) =>
testPath + snapshotExtension,
resolveTestPath: (snapshotFilePath, snapshotExtension) =>
snapshotFilePath.replace(snapshotExtension, ''),
testPathForConsistencyCheck: 'some.test.js',
};
in your jest config set that file to the resolver
snapshotResolver: './jest/snapshotResolve.js',
or if your jest config in package.json:
"snapshotResolver": "./jest/snapshotResolve.js",
Explanation
In short these two functions mirror each other, one takes the test file path and returns the snapshot path, the other takes the snapshot path and returns the test file path. The third is a file path example for validation.
Clearer code To help clarify what is going on
One thing to keep in mind is that the path is the full path not the relative path.
/**
*
* #param testPath Path of the test file being test3ed
* #param snapshotExtension The extension for snapshots (.snap usually)
*/
const resolveSnapshotPath = (testPath, snapshotExtension) => {
const snapshotFilePath = testPath + snapshotExtension; //(i.e. some.test.js + '.snap')
return snapshotFilePath;
}
/**
*
* #param snapshotFilePath The filename of the snapshot (i.e. some.test.js.snap)
* #param snapshotExtension The extension for snapshots (.snap)
*/
const resolveTestPath = (snapshotFilePath, snapshotExtension) => {
const testPath = snapshotFilePath.replace(snapshotExtension, '').replace('__snapshots__/', ''); //Remove the .snap
return testPath;
}
/* Used to validate resolveTestPath(resolveSnapshotPath( {this} )) */
const testPathForConsistencyCheck = 'some.test.js';
module.exports = {
resolveSnapshotPath, resolveTestPath, testPathForConsistencyCheck
};

Also, in addition to the path to the snapshotResolver as suggested in the Vasyl Nahuliak's answer, to achieve having the snapshot and the test files looking like this:
file.test.js
file.test.js.snap
your snapshotResolver should look like this:
module.exports = {
testPathForConsistencyCheck: 'some/example.test.js',
resolveSnapshotPath: (testPath, snapshotExtension) =>
testPath.replace(/\.test\.([tj]sx?)/, `.test.$1${snapshotExtension}`),
resolveTestPath: (snapshotFilePath, snapshotExtension) =>
snapshotFilePath.replace(snapshotExtension, ''),
};

Related

unzipping the file using cypress

I need to unzip the file using 'unzipping' whereas I am using the below code to do the same but it is partially unzipping but it is throwing an Invalid path error (as path contains special character *).please help me to fix it
let path = 'cypress/downloads/'
let file = '910-00001.1-20220419-1843.zip'
describe('example unzip', () => {
it(' test', () => {
cy.task('unzipping', { path, file })
})
//task code (Added it into plugins --> index.js)
const unzipping = require('./unzipping')
module.exports = (on, config) => {
on('task', {
'unzipping': unzipping.unzip,
})
}
// ./unzipping file (created a file named unzipping.js inside plugin folder)
const decompress = require('decompress');
const unzip = ({ path, file }) => decompress(path + file, path + 'unzip/' + file.replace('.zip', ''))
module.exports = {
    unzip,
}
So, I tried all your code you gave above, and it worked perfectly.
The only thing I can think if is the contents of the zip is the problem. In my test I made a simple zip with two text files 1.txt and 2.txt, then running the test, found them in the folder /cypress/downloads/unzip/910-00001.1-20220419-1843.
I suggest you do the same with a dummy zip, if the code works then look at the contents of 910-00001.1-20220419-1843.zip.

how to get discord.js to pick a random image from file

I'm in another pickle I've realized over the past week that my images are not loading due to the fact the links have expired so I wanna find out how to go about using a file directory in the code.
Here's what I've tried:
});
client.on('message', message => {
if (message.content.startsWith('L!hug')) {
var fs = require('fs');
var files = fs.readdirSync('C:\Users\nevbw\Desktop\games\FBIBot\images\hugs')
/* now files is an Array of the name of the files in the folder and you can pick a random name inside of that array */
let chosenFile = files[Math.floor(Math.random() * files.length)]
}
});
and
});
client.on('message', message => {
if (message.content.startsWith('L!hug')) {
const path = 'C:\Users\nevbw\Desktop\games\FBIBot\images\hugs';
const fs = require('fs');
fs.readdirSync(path).forEach(file => {
ranfile = Math.floor(Math.random() * file.length);
message.channel.sendFile(ranfile);
})
}
});
found out through searching and searching but found a answer the modified it to this, i hope people use this in future reference!
const num = (Math.floor(Math.random()* 5)+1).toString(); message.channel.send({files: [`./slap/slap${num}.gif`]})
Using fs.readdirSync('./images/') instead of fs.readFileSync('./images/') works easier, but then you will have to create the folder inside of VSC and put the images in the folder, you can also drag and drop the images into the solution and use:
var files = fs.readdirSync(`./images/`).filter(file => file.endsWith('.png'))
so that when it looks for an image, it doesn't select anything else. hope it helps for some people.
Happy to help.
You're using FS the wrong way. This Is What It Should Look Like :D Also Here Is Some Documentation on It ( https://nodejs.org/dist/latest-v13.x/docs/api/fs.html ).
-- Code --
Also Just As A Tip! I See You Are Using Full Directories, That's Quite Innificeng (E.g if You Change Your Username, Drive ID, etc.) so in fs provided the image is in the same folder you can just do ./(ImageName), or if it is in the same folder but under another say /FBIBot/Images you can do ./Images/(ImageName). ^^
--
What The Error Was: (I Unfortunately Cannot Test it But I Am Like 99% Sure).
You Were Using fs.readdirSync(path).forEach(file => { When You Were Meant To Be Using fs.readfilesync(path).forEach(file => {.
-- First Code --
});
client.on('message', message => {
if (message.content.startsWith('L!hug')) {
var fs = require('fs');
var files = fs.readfileSync('C:\Users\nevbw\Desktop\games\FBIBot\images\hugs')
/* now files is an Array of the name of the files in the folder and you can pick a random name inside of that array */
let chosenFile = files[Math.floor(Math.random() * files.length)]
}
});
-- Second Code --
});
client.on('message', message => {
if (message.content.startsWith('L!hug')) {
var fs = require('fs');
var files = fs.readFileSync('C:\Users\nevbw\Desktop\games\FBIBot\images\hugs')
/* now files is an Array of the name of the files in the folder and you can pick a random name inside of that array */
let chosenFile = files[Math.floor(Math.random() * files.length)]
}
});
^^

Rename webpack/gatsby chunkmapping strings

When building our production app in Gatsby, I see something like this:
window.___chunkMapping={
"app":[],
"component---src-templates-page-tsx":[],
"component---src-templates-pages-newsletter-tsx":[]
}
Is it possible to hash these paths instead of printing them out? We don‘t want to expose too much from what is happening in the back.
I tried setting these configs in webpack:
output: {
filename: `[chunkhash:2][contenthash:5].js`,
chunkFilename: `[chunkhash:2][contenthash:5].js`,
},
And it successfully hashes .js files but not the template paths.
I upvoted this question when I first saw it, I think it's definitely should be done in production build.
Unfortunately, componentChunkName (the template path in question) is generated by Gatsby in createPage & not handled by webpack.
The code that generates componentChunkName is over here: github
I tried to modify the code as follow:
const { kebabCase } = require(`lodash`)
const path = require(`path`)
+ const uuidv5 = require(`uuid/v5`)
const { store } = require(`../redux`)
const generateComponentChunkName = componentPath => {
const program = store.getState().program
let directory = `/`
if (program && program.directory) {
directory = program.directory
}
const name = path.relative(directory, componentPath)
- return `component---${kebabCase(name)}`
+ return process.env.NODE_ENV === `production`
+ ? `component---${uuidv5(name, uuidv5.URL)}`
+ : `component---${kebabCase(name)}`
}
exports.generateComponentChunkName = generateComponentChunkName
This successfully hides all the component names in production build:
app: Array [ "/app-e593b3d93932ed3a0363.js" ]
"component---11d478fe-6a55-579c-becf-625ab1e57cf4": Array [ "/component---11d478fe-6a55-579c-becf-625ab1e57cf4-76c90ae50035c52657a0.js" ]
"component---15c76861-b723-5e0a-823c-b6832aeeb0a0": Array [ "/component---15c76861-b723-5e0a-823c-b6832aeeb0a0-18eb457ba6c147e1b31b.js" ]
...
None of the local unit tests failed, my clicking-around-until-something-breaks test also hasn't yielded any errors. I might submit a PR later today to see if the maintainers have some insights on why this is not a good idea.
Edit: I opened an issue instead: github, you can subscribe to the issue to see how it resolves.

How can I automatically update my javascript file to import newly detected files?

I tagged watchman as it MIGHT be the solution I'm looking for, but I don't quite know how to use it in this way!
I have a directory
/imgs
/icons
/bird.png
/cat.png
/dog.png
/pig.png
and I have a file
/imgs/index.js
My index.js is responsible for importing all of the images and then exporting a single object for the rest of my project to use.
const bird = require('./icons/bird.png');
const cat = require('./icons/cat.png');
const dog = require('./icons/dog.png');
const pig = require('./icons/pig.png');
const Icons = { bird, cat, dog, pig };
export default Icons;
What I want to do is watch my imgs folder for new additions, and automatically update my index.js to import these new files and add them to my object. I need to import them with Common.js and export them with ES6.
Does anyone know a good solution to this problem?
A potential solution is to write a JavaScript script that generates your index.js like so:
'use strict';
const fs = require('fs');
const DIR = __dirname + '/imgs/icons';
const output = __dirname + '/imgs/index.js';
return fs.readdir(DIR, (err, files) => {
let result = '';
let references = [];
files.forEach(item => {
// assuming item has the format animal.png
let newReference = item.split('.')[0];
references.push(newReference);
result += `const ${newReference} = require('./icons/${item}');\n`;
});
result += `\nconst Icons = { ${references} };\n\nexport default Icons;`;
fs.writeFile(output, result, err => {
if (err) throw err;
console.log(output + ' updated');
});
});
Place that file (let's call it watcher.js for this purpose) in imgs's parent directory and make watchman run it whenever changes in your icons directory are detected:
watchman imgs/icons "node watcher.js"
Notice that if a new file gets put into the watched directory, the index.js-creating script will not re-run. Only if it gets altered again (even if just gets saved again with the same data), the index.js will reflect that change.
You can simply test that by running touch imgs/icons/crabigator.png twice and look at the watchman log and/or content of index.js.

How to resolve a path that includes an environment variable, in nodejs?

I would like to run an executable and its path contains an enviroment variable, for example if I would like to run chrome.exe I would like to write something like this
var spawn = require('child_process').spawn;
spawn('chrome',[], {cwd: '%LOCALAPPDATA%\\Google\\Chrome\\Application', env: process.env})
instead of
var spawn = require('child_process').spawn;
spawn('chrome',[], {cwd: 'C:\\Users\myuser\\AppData\\Local\\Google\\Chrome\\Application', env: process.env}).
Is there a package I can use in order to achieve this?
You can use a regex to replace your variable with the relevant property of process.env :
let str = '%LOCALAPPDATA%\\Google\\Chrome\\Application'
let replaced = str.replace(/%([^%]+)%/g, (_,n) => process.env[n])
I don't think a package is needed when it's a one-liner.
I realize that the question is asking for Windows environment variables, but I modified #Denys Séguret's answer to handle bash's ${MY_VAR} and $MY_VAR style formats as I thought it might be useful for others who came here.
Note: the two arguments are because there are two groupings based on the variations of the format.
str.replace(/\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/ig, (_, a, b) => process.env[a || b])
Adding a TypeScript friendly addition to the excellent answer by Denys Séguret:
let replaced = str.replace(/%([^%]+)%/g, (original, matched) => {
const r = Process.env[matched]
return r ? r : ''
})
Here is a generic helper function for this:
/**
* Replaces all environment variables with their actual value.
* Keeps intact non-environment variables using '%'
* #param {string} filePath The input file path with percents
* #return {string} The resolved file path
*/
function resolveWindowsEnvironmentVariables (filePath) {
if (!filePath || typeof(filePath) !== 'string') {
return '';
}
/**
* #param {string} withPercents '%USERNAME%'
* #param {string} withoutPercents 'USERNAME'
* #return {string}
*/
function replaceEnvironmentVariable (withPercents, withoutPercents) {
let found = process.env[withoutPercents];
// 'C:\Users\%USERNAME%\Desktop\%asdf%' => 'C:\Users\bob\Desktop\%asdf%'
return found || withPercents;
}
// 'C:\Users\%USERNAME%\Desktop\%PROCESSOR_ARCHITECTURE%' => 'C:\Users\bob\Desktop\AMD64'
filePath = filePath.replace(/%([^%]+)%/g, replaceEnvironmentVariable);
return filePath;
}
Can be called from anywhere
Does basic type checking first, you may want to change what is returned by default in the first if block
Functions are named in ways that explain what they do
Variables are named in ways that explain what they are
Comments added make it clear what outcomes can occur
Handles non-environment variables wrapped in percents, since the Windows file system allows for folders to be named %asdf%
JSDoc blocks for automated documentation, type checking, and auto-complete in certain editors
You may also want to use if (process.platform !== 'win32') {} depending on your need
These answers are crazy. Just can use path:
const folder = require('path').join(
process.env.LOCALAPPDATA,
'Google/Chrome/Application',
);
console.log(folder); // C:\Users\MyName\AppData\Local\Google\Chrome\Application
On Linux/MacOS, I spawn a process to resolve paths with env variables, is safe - let bash to do the work for you. Obviously less performant, but a lot more robust. Looks like this:
import * as cp from 'child_process';
// mapPaths takes an array of paths/strings with env vars, and expands each one
export const mapPaths = (searchRoots: Array<string>, cb: Function) => {
const mappedRoots = searchRoots.map(function (v) {
return `echo "${v}"`;
});
const k = cp.spawn('bash');
k.stdin.end(mappedRoots.join(';'));
const results: Array<string> = [];
k.stderr.pipe(process.stderr);
k.stdout.on('data', (d: string) => {
results.push(d);
});
k.once('error', (e) => {
log.error(e.stack || e);
cb(e);
});
k.once('exit', code => {
const pths = results.map((d) => {
return String(d || '').trim();
})
.filter(Boolean);
cb(code, pths);
});
};

Categories