-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Snapshot location #1489
Snapshot location #1489
Conversation
…hot location through sourcemaps. As discussed in avajs#1459
- throw on invalid sourcemap - remove extra snapshot-location cli option
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR @impaler! I'm excited about seeing both the source map resolution land, as well as having a configurable snapshot directory.
lib/cli.js
Outdated
@@ -144,6 +144,7 @@ exports.run = () => { | |||
timeout: conf.timeout, | |||
concurrency: conf.concurrency ? parseInt(conf.concurrency, 10) : 0, | |||
updateSnapshots: conf.updateSnapshots, | |||
snapshotLocation: conf.snapshotLocation, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps resolve the absolute path here: conf.snapshotLocation ? path.resolve(projectDir, conf.snapshotLocation) : null
. This would even enable absolute paths, and remove complexity in the snapshot manager code.
Total bikeshed, but how do you feel about snapshotDir
? Seems snappier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure no preference here from me projectDir, I think I saw Dir used somewhere else :)
lib/runner.js
Outdated
@@ -187,7 +188,8 @@ class Runner extends EventEmitter { | |||
projectDir: this.projectDir, | |||
relFile: path.relative(this.projectDir, this.file), | |||
testDir: path.dirname(this.file), | |||
updating: this.updateSnapshots | |||
updating: this.updateSnapshots, | |||
location: this.snapshotLocation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this.snapshotLocation
is either null
or an absolute path, this could be renamed from location
to fixedLocation
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I like it.
lib/snapshot-manager.js
Outdated
const testDir = determineSourceMappedDir(options); | ||
if (options.location) { | ||
// "snapshotLocation" in ava package.json config, snapshots derive a location | ||
// relative from the source testDir not the preset "__snapshots__" folder names |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When options.location
becomes options.fixedLocation
this comment becomes unnecessary since it's clear what is expected of the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I guess the comment highlighted some of the ambiguitiy, please checkout the latest revision.
lib/snapshot-manager.js
Outdated
// "snapshotLocation" in ava package.json config, snapshots derive a location | ||
// relative from the source testDir not the preset "__snapshots__" folder names | ||
const resolvedLocation = path.resolve(options.projectDir, options.location); | ||
const relativeTestLocation = options.testDir.replace(options.projectDir, ''); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this refer to testDir
, rather than options.testDir
?
Also, you should be able to use path.relative(projectDir, testDir)
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, please checkout the latest revision.
lib/snapshot-manager.js
Outdated
@@ -365,8 +386,31 @@ function determineSnapshotDir(projectDir, testDir) { | |||
return testDir; | |||
} | |||
|
|||
function determineSourceMappedDir(options) { | |||
const sourceMapFilePath = path.join(options.testDir, `${options.name}.map`); | |||
const sourceMapContent = tryReadSourceMap(sourceMapFilePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use https://www.npmjs.com/package/convert-source-map, like in nyc: https://github.com/istanbuljs/nyc/blob/fb3ab927796963379edfddd4d2385002fa236f65/lib/source-maps.js#L16
This will support inline source maps as well as source map references. It does presume that these references are in the source file, but I think that's a fair assumption.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed thanks a bunch I am new to that library very cool. Seems to work well with the inline version in my testing https://github.com/impaler/ava-snapshot-location/tree/master/inline-sourcemaps
readme.md
Outdated
|
||
Snapshots fixtures will be then saved in a directory structure that reflects the test sourcecode. | ||
|
||
If you are transpiling the tests with sourcemaps, ava will derive the test location from the `*.js.map` files, see more in the [TypeScript](docs/recipes/typescript.md) recipe. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are running AVA against precompiled test files, AVA will try and use source maps to determine the location of the original files. Snapshots will be stored next to these files, following the same rules as if AVA had executed the original files directly. This is great if you're writing your tests in TypeScript (see our TypeScript recipe).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
test('another feature test', t => { | ||
t.snapshot(new Map()); | ||
}); | ||
//# sourceMappingURL=test.js.map |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you make sure these files have a newline at the end of them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that just for constency? in this case everything under ...build/*
is directly from the typescript compiler, I usually hesitate to edit compiled files for style only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough.
test/cli.js
Outdated
'src/test/snapshots', | ||
'src/feature/__tests__/__snapshots__' | ||
]; | ||
const removeExists = relFilePath => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't remove anything though?
You should remove these files at least prior to running the test, otherwise on local setups you won't be able to tell if the code has broken if they're persisted from previous runs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this is wrong, I have updated this be a little more dry 12f1ff8#diff-583d616f4b01bf1fa153e71c0cef7de7R704. If there are more integration tests on projects like this I can think of some better ways to do it, like maybe the project should be first duplicated to a /tmp location and so on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not too concerned about how DRY this is. The other test looks good, just need to take that same approach here.
@@ -0,0 +1,10 @@ | |||
{ | |||
"scripts": { | |||
"build": "tsc" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this assume tsc
is installed globally? I know we have a dev dependency on it but running build
inside this directory won't pick it up. This should either refer to the top-level node_modules/.bin/tsc
or use npx tsc
.
(Also, going by the GitHub output here, the indentation seems off in this file and tsconfig.json
.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it does, I don't think there will be any need to run build here for the tests anyway. So I fixed the indentation and removed "scripts".
docs/recipes/typescript.md
Outdated
|
||
## Snapshots | ||
|
||
Ava derives the base location for the snapshot fixtures relative to the typescript as if it were standard javascript tests. It determines this from the associated `*.js.map` sourcemap files. Enabling sourcemaps with the typescript compiler can be done in either the [tsconfig](http://www.typescriptlang.org/docs/handbook/tsconfig-json.html) `tsconfig.json#compilerOptions#sourceMap=true` or in the `tsc` cli option `--sourceMap`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than this paragraph, update the sample tsconfig.json
to enable source maps. Honestly it should always be enabled, since it helps AVA show correct stack traces and code snippets when assertions fail.
Thanks for the great review @novemberborn :) I won't claim that we have complete integration test coverage on this snapshot feature, but it has the main aspects. Otherwise as I said in a comment I think we would need some more utilities to duplicate project folders and run all scenarios like I am testing in https://github.com/impaler/ava-snapshot-location. Based on what I can see on appveyor the ci issues seem unrelated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very cool, I think this is almost there!
Based on what I can see on appveyor the ci issues seem unrelated.
Yea. I'm rerunning it just in case.
I won't claim that we have complete integration test coverage on this snapshot feature, but it has the main aspects. Otherwise as I said in a comment I think we would need some more utilities to duplicate project folders and run all scenarios like I am testing in impaler/ava-snapshot-location.
I won't say no to a PR that achieves that, but it doesn't need to hold up landing this one. All new lines are covered so that's 💯 https://codecov.io/gh/avajs/ava/pull/1489/diff
lib/snapshot-manager.js
Outdated
const relativeTestLocation = options.testDir.replace(options.projectDir, ''); | ||
return path.join(resolvedLocation, relativeTestLocation); | ||
if (options.fixedLocation) { | ||
const relativeTestLocation = testDir.replace(options.projectDir, ''); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use path.relative(options.projectDir, testDir)
.
lib/snapshot-manager.js
Outdated
} | ||
return path.dirname(path.resolve(options.testDir, testFileSource)); | ||
} | ||
const sourceMapContent = tryRead(options.relFile).toString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tryRead()
returns null
if the file doesn't exist. You'll have to read it into a variable and bail out of if it's null
.
Perhaps this function should return null
if no source-mapped directory could be determined. Then determineSnapshotDir()
can do testDir = determineSourceMappedDir(options) || options.testDir
.
test/cli.js
Outdated
}) | ||
.reduce((a, b) => a.concat(b), []); | ||
const removeExistingSnapshotFixtureFiles = filePath => { | ||
return fs.existsSync(filePath) && fs.unlinkSync(filePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is still room for the file to be deleted right in between existsSync
and unlinkSync
. Would be better to do https://github.com/impaler/ava/blob/12f1ff8d73e0ae47c109eed9737470c9d421fa8e/test/cli.js#L568:L574, even if it's more verbose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure that will also throw any fs issues, I updated the pull request :)
test/cli.js
Outdated
'src/test/snapshots', | ||
'src/feature/__tests__/__snapshots__' | ||
]; | ||
const removeExists = relFilePath => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not too concerned about how DRY this is. The other test looks good, just need to take that same approach here.
"src/**/*test.js" | ||
], | ||
"snapshotDir": "snapshot-fixtures" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick alert: the indentation in this file is inconsistent. It's just a fixture, but once seen I can't not comment 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
test('another feature test', t => { | ||
t.snapshot(new Map()); | ||
}); | ||
//# sourceMappingURL=test.js.map |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough.
…ck. Rename local var prefix from snapshot to snap for "snappyness".
The windoze build still seems intermittent and unrelated, since the same error is happening in other branches it seems out of scope. Let me know if the github squash commits isn't enough, Cheers :) |
Set to null, since the location behavior is verified through CLI tests.
* Pass the absolute test file path into the snapshot manager * Read the test file using the absolute path (otherwise the read would be relative to the process' working directory) * Pass test directory when reading from map file source * Correctly resolve source file from the test directory * Remove incorrect '../' source root default value * Rename variables for better clarity * Remove ternaries
@impaler this is great! I've pushed some minor fixes, and some larger fixes to Could you give those a spin with your project? Will merge this if it's all good. |
Thanks @novemberborn, yes everything is working as I expected with your changes :) And looks like appveyor is now working, know if it was it related to changes here? |
Thanks @impaler! |
* Allow users to configure the snapshot location * Resolve the location through source-maps, in case the tests were precompiled into a build directory, e.g. via TypeScript
* Allow users to configure the snapshot location * Resolve the location through source-maps, in case the tests were precompiled into a build directory, e.g. via TypeScript
@novemberborn As discussed in #1459 the proposal to support custom snapshot locations and sourcemaps is:
Although there are some the test fixtures added for integration tests, I created an example project to more easily test the implementation.
https://github.com/impaler/ava-snapshot-location