Running tests on folders within folders from package.json - unit-testing

I have an app with the test command set as follows in package.json:
"test": "mocha --require babel-core/register --watch-extensions js **/*.test.js",
Unfortunately my apps folder structure goes deeper than that command allows me to. It looks something like this:
app
└── someFolder
└── subFolder
└── subSubFolder
└── fileNeedsToBeTest.js
└── fileNeedsToBeTest.test.js
└── anotherFolder
└── anotherFileNeedsToBeTest.js
└── anotherFileNeedsToBeTest.test.js
The problem is as the test command stands I can only test what is in anotherFolder but I also need the files in someFolder/subFolder/subSubFolder to be tested. I didn't want to specify exact paths because I have multiple instances of this occurring across the app.
How could I fix my test command to be able to find *.test.js files no matter how deep they might be in the folders?

Your glob pattern **/*.test.js should be wrapped in double quotes ("..."), however, because it's specified in JSON they'll need to be escaped with a backslash, i.e. \"...\".
Your test command should be changed to the following:
"test": "mocha --require babel-core/register --watch-extensions js \"**/*.test.js\"",
This will find all files ending with .test.js in the root of your project directory many levels deep.
Tip: I'm assuming that you're app folder exists in the root of your project, at the same level as your package.json and node_modules directory. If that's the scenario, then the glob pattern **/*.test.js will potentially find any files ending with .test.js from the node_modules directory - which will result in those test's being run too. To prevent that you can negate the node_modules directory in your glob pattern as shown in the following:
"test": "mocha --require babel-core/register --watch-extensions js \"{,!(node_modules)/**/}*.test.js\""
EDIT:
In response to the following comment:
...where does {,!(node_modules)/**/}*.test.js part of the command come from? What syntax is that?
Mocha utilizes node-glob as one of it's dependencies. The syntax for that part of the command is defined by node-glob (...which is analogous to the syntax Bash uses for globbing/pathname expansion).
A reference for this syntax can be found in Glob Primer section of the node-glob documentation.
Explanation of the specific pattern used for this scenario:
Let's breakdown the pertinent parts of that pattern...
(A) Braced section
│
┌─────────┴──────────┐
{,!(node_modules)/**/}*.test.js
│└──────┬──────┘└─┬┘ │└───┬───┘
│ │ │ │ │
│ │ │ │ (F) filename extension
│ │ │ │
│ │ │ (E) Single Globstar
│ │ │
│ │ (D) Double Globstar
│ │
│ (C) Negation section
│
(B) Comma-delimited
(A) Braced section: The docs describe it as:
Before parsing the path part patterns, braced sections are expanded into a set. Braced sections start with { and end with }, with any number of comma-delimited sections within. Braced sections may contain slash characters, so a{/b/c,bcd} would expand into a/b/c and abcd.
(B) Comma-delimited
The braced section begins with a comma-delimiter because the next Negation section, (the part beginning with !), must come after another pattern - it can't be at the beginning. Here the initial pattern before the comma-delimiter has not been provided; in this scenario it simply implies the project directory (or perhaps more specifically the same/current directory where package.json is stored). We could actually change the pattern to either of the following and we would get the same results.
{/,!(node_modules)/**/}*.test.js
^
{./,!(node_modules)/**/}*.test.js
^^
Note, either / or ./ were added to the pattern respectively before the comma-delimiter. It's the same as how we may define paths to assets in html, javascript, etc.
(C) Negation section
The ! means "don't match this" or "ignore this". The docs describe it as:
!(pattern|pattern|pattern) Matches anything that does not match any of the patterns provided.
In our scenario it's used to ignore the node_modules folder.
(D) Double globstar
The /**/ part matches any number of characters including /. Perhaps more simply it means scan all files and sub-folders, however many levels deep.
(E) Single Globstar
Match all all characters of a filename if/when they end with the filename extension provided (F).
(F) filename extension
Match all files ending with the .test.js filename extension.

Related

Using rename to change prefix of files recursively in Ubuntu, (regex not working)

I am using rename available in ubuntu:
$ rename --version
/usr/bin/rename using File::Rename version 0.20
This is what my directory looks like:
$ tree .
.
├── awp-3
├── bar
│   └── wp-2
└── wp-foo
└── wp-1
My goal is that I want to rename all files and folders with the prefix wp- to static-
This is what I ran:
$ shopt -s globstar
$ rename -n 's/wp-/static-/' **
rename(awp-3, astatic-3)
rename(bar/wp-2, bar/static-2)
rename(wp-foo, static-foo)
rename(wp-foo/wp-1, static-foo/wp-1)
This is almost what I want. The file awp-3 should not have been renamed.
So I did this instead:
$ rename -n 's/^wp-/static-/' **
rename(wp-foo, static-foo)
rename(wp-foo/wp-1, static-foo/wp-1)
For some reason, this didn't change the filename of wp-1 or wp-2.
How can i use rename to change wp-2, wp-foo and wp-1 to static-*?
The ^ anchor only matches beginning of line. I'm guessing you want
rename -n 's%(^|/)wp-%$1static-%' **
Another way to tighten this up is to say wp must only occur adjacent to a word boundary.
rename -n 's/\bwp-/static-/' **
Renaming files recursively using rename is problematic: you have to make sure that you rename the inner files/subdirectories first before renaming the parent directories. Simply adding the /g modifier to rename all the levels (e.g. s!(^|/)wp-!$1static-!g to rename(wp-foo/wp-1, static-foo/static-1) won't work.
It's better to use a tool that supports recursive operation, such as perlmv. I suggest a perl-based tool because rename is also a perl-based tool and they work similarly. Unfortunately there's not yet a Debian/Ubuntu package for perlmv, so you'll need to install it via a CPAN client (e.g. cpanm -n App::perlmv). Once you have perlmv:
% perlmv -R -de 's/^wp-/static-/' *
The result:
% tree .
.
├── awp-3
├── bar
│   └── static-2
└── static-foo
└── static-1
Notes:
you don't have to use ** with perlmv, just *.
-R is for recursive.
dry-run mode in perlmv is -d not -n. Once you see that perlmv will do what you want, you can omit the -d or replace it with -v (verbose).
you need to add -e before specifying perl code.

How can I skip deleting folders except a specified folder for a web deploy (msdeploy) sync?

Suppose I have a destination folder structure that looks like this:
D:\DEPLOY\DEST
│ 0.txt
│
├───a
│ a.txt
│
└───b
├───b1
│ │ b1.txt
│ │
│ ├───b1a
│ │ b1a.txt
│ │
│ └───b1b
│ b1b.txt
│
└───b2
b2.txt
I also have a source folder structure that looks like this:
D:\DEPLOY\SOURCE
└───b
└───b1
└───b1a
b1a-new.txt
I would like to synchronize the source to the destination, but only below the \b\\b1\b1a path. To do that, when running MSDeploy, I add a skip rule matching all dirPaths not containing this path:
msdeploy -verb:sync
-source:contentPath=D:\deploy\source
-dest:contentPath=D:\deploy\dest
-skip:skipAction=delete,objectName=dirPath,absolutePath='(?!\\b\\b1\\b1a)'
-whatif
resulting in:
Info: Deleting file (D:\deploy\dest\0.txt).
Info: Deleting file (D:\deploy\dest\b\b1\b1.txt).
Info: Adding file (D:\deploy\dest\b\b1\b1a\b1a-new.txt).
Info: Deleting file (D:\deploy\dest\b\b1\b1a\b1a.txt).
Total changes: 4 (1 added, 3 deleted, 0 updated, 0 parameters changed, 0 bytes copied)
To my surprise, this does more than expected. MSDeploy also deletes the files 0.txt and b1.txt, which are under a dirPath that I expect to be skipped based on the regex. I tried various permutations of the absolutePath regex, but to no avail.
What should I be doing instead? Or is this beyond the possibilities of msdeploy?
Note: this example is simplified. In reality my source is package, not a contentPath. That is why the obvious answer of syncing at the b\b1\b1a-level would not apply.
You've specified that you don't want it to delete directories outside that folder, but your skip rule says nothing about files. Just remove ,objectName=dirPath from your skip directive and it will skip deletes on any provider.
As an aside, skip rules are actually quite nuanced in their behavior. I have a blog post that digs into it which might help: Demystifying MSDeploy skip rules

explain gitignore pattern matching

I have the following directory tree:
> #pwd is the repo
> tree -a
.
├── .git
│   |.....
├── .gitignore
├── README.md
├── f1.html
├── f2.html ... and some more html
├── images
│   └── river.jpg
>
I also have the following in my .gitignore:
> cat .gitignore
*
!*.html
!images/*.*
>
I would like all files in the images directory to be included in the repo. But that is not happening. I got it to work using the following in gitignore:
*
!*.html
!images*
!*.jp*g
What is happening here? Is there a foolproof way to test gitignore. I checked the documentation. Here is the point it don't understand (this is under pattern format heading):
Otherwise, Git treats the pattern as a shell glob suitable for
consumption by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the
pattern will not match a / in the pathname. For example,
"Documentation/*.html" matches "Documentation/git.html" but not
"Documentation/ppc/ppc.html" or "tools/perf/Documentation/perf.html".
Firstly the tricky part in your question is the first line in the .gitignore file:
* // Says exclude each and every file in the repository,
// unless I specify with ! pattern explicitly to consider it
First we will consider the first version of your .gitignore.
* exclude every file in the repository.
!*.html allow all html files.
!images/*.* consider all types of file in images folder.
To include all JPG/JPEG you could have simply added !*.jp*g at 3rd line, which would have made git to consider all jpg and jpeg irrespective of any folder where that file is. But you specifically wanted only from images folder and not only jpg, any type of file in the images folder. Let's read some documentation related to it and in 3rd section we will go to solution part.
Git ignore pattern regarding the folder consideration:
Pattern ending only with slash: If a pattern ends with <dir-name>/ then git will ignore the files contained in that directory and all other sub-directories. As example given in the docs
foo/ will match a directory foo and paths underneath it, but will not
match a regular file or a symbolic link foo
but also note, if any pattern matches a file in the excluded directory, git doesn’t consider it.
Pattern does not have slash: If you are specifying the dir name in the ignore list which does not end with a slash, git will consider it as just a pattern, which can match any file having that pathname.
If the pattern does not contain a slash /, Git treats it as a shell
glob pattern and checks for a match against the pathname relative to
the location
Pattern with slash and special character (*/?) : If the pattern ends like the 1st example you gave, images/*.* It works as specified in the documentation
Example: "Documentation/*.html" matches "Documentation/git.html" but not
"Documentation/ppc/ppc.html" or "tools/perf/Documentation/perf.html".
Solution
Considering 3rd point git should consider all the files in the images directory for !images/*.* pattern. But it is not doing that because the documentation says one more important point
Git doesn’t list excluded directories
Because of the first line * the "images" directory itself is ignored. So first we should tell the git to consider images directory and later additional lines explicitly to say consider the other types (if needed).
*
!*.html
!images/ // <- consider images folder
!images/*.*
Note : the last line considers all types of files only from images directory not from any of its sub-directories. (3rd point in section 2)

hgignore glob ** not matching correctly

I have tried the following hgignore files however both times folders expected to be ignored are listed when runnign the hg status command
syntax: glob
Somefolder/**
However Somefolder is still listed when I then run hg status
So I then tired this version (which should ignore EVERYTHING)
syntax: glob
**
However same result from running the hg status command.
Well, then, I'm not sure what's wrong with your environment, because what you did should work. It works on mine:
santa#samoyed:/tmp/MockProject$ tree .
.
└── Somefolder
└── Subfolder
└── ph.txt
2 directories, 1 file
santa#samoyed:/tmp/MockProject$ cat .hgignore
syntax: glob
Somefolder/**
santa#samoyed:/tmp/MockProject$ hg status
? .hgignore
santa#samoyed:/tmp/MockProject$

Using "depends" in webassets bundles

I'm using webassets in my Flask application using Flask-Assets and I'm having trouble with the depends option when creating bundles.
In my case I'm bundling LESS files from the following directory structure:
/static
\_ /css
\_ /bootstrap
| \_ bootstrap.less // This file #imports variables.less and custom.less
| \_ variables.less
\_ custom.less
My bundle looks like this:
css = Bundle(
"css/bootstrap/bootstrap.less",
filters="less, cssmin",
output="dist/base.css",
depends="**/*.less"
)
With these settings, the LESS files are rebuilt whenever a change is made to either bootstrap.less or custom.less but NOT variables.less.
From what I understand, the expression used for the depends option is a glob instruction and using the one above should simply go through all directories recursively and pick up any LESS files. However, it never seems to pick up on any changes made to variables.less.
In my attempts to fix this, I've tried the following options for depends:
"*.less" - Doesn't pick up anything (as it's searching in the root of the project directory, I believe, where there are no LESS files anyway)
"**/*.less, myproject/static/css/bootstrap/variables.less" - Doesn't pick up on any changes in any file at all.
"**/*.less, myproject/static/css/bootstrap/variables.less" - Same as the one above.
"myproject/static/css/bootstrap/variables.less" - Strangely enough, this picks up on changes made to both variables.less AND any other LESS files (such as custom.less).
In essence, the last item is the "solution" for my problem but I have no idea why it works the way it does, so it doesn't sit well with me. Can anyone provide an explanation or a nudge in the right direction here?
Thanks!
The problem here is that recursive glob ** is not supported in glob module (yet; see issue 13968).
Here's how I have set this up in one of my projects (not sure if that would suit your needs):
less/
├── bootstrap/
│  ├── bootstrap.less
│   ├── variables.less
│   └── ...
└── style.less # #import "bootstrap/bootstrap.less";
Bundle configuration:
css = Bundle(
"less/style.less",
filters="less, cssmin",
output="css/all.css",
depends="less/bootstrap/*.less"
)
I fixed this by installing the glob2 module. My depends='**/*.scss' then started working as I expected, watching for changes in nested directories as well as the top level.