mirror of
https://github.com/datashard/snapshot.git
synced 2024-12-04 18:57:36 +00:00
Compare commits
20 commits
e2ef9784e4
...
9351d344a7
Author | SHA1 | Date | |
---|---|---|---|
|
9351d344a7 | ||
|
e4f9cbc5cf | ||
|
71fe145047 | ||
|
a12634c9a3 | ||
|
8add20790e | ||
|
dc1290ec04 | ||
|
b4f841d878 | ||
|
930662045c | ||
|
d45d7479f0 | ||
|
bc6ffad697 | ||
|
4b96c41056 | ||
|
f51bcae462 | ||
|
b1ce5f2fdf | ||
|
5f861d4949 | ||
|
960e699075 | ||
|
cb39e029c3 | ||
|
7c6f997bc0 | ||
|
9a41366c82 | ||
|
5db74ebcb6 | ||
|
b61e5c0552 |
35 changed files with 570 additions and 1172 deletions
BIN
.github/assets/Correct.png
vendored
Normal file
BIN
.github/assets/Correct.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 9 KiB |
BIN
.github/assets/Error.png
vendored
Normal file
BIN
.github/assets/Error.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
.github/assets/config.png
vendored
BIN
.github/assets/config.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 76 KiB |
|
@ -1,3 +1,5 @@
|
||||||
cypress/
|
cypress/
|
||||||
cypress.config.js
|
cypress.config.js
|
||||||
.github/workflows/
|
.github/workflows/
|
||||||
|
.vscode/
|
||||||
|
renovate.json
|
22
LICENSE
Normal file
22
LICENSE
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
Copyright (c) 2023-2024 Joshua data@shard.wtf
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use,
|
||||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
183
README.md
183
README.md
|
@ -1,55 +1,56 @@
|
||||||
# @datashard/snapshot
|
# @datashard/snapshot
|
||||||
|
|
||||||
> Adds value / object / DOM element snapshot testing support to Cypress test runner
|
> Adds JSON Snapshot comparison to Cypress
|
||||||
|
|
||||||
<details>
|
## ⚠️ Breaking Changes ⚠️
|
||||||
<summary>Changes between <code>@datashard/snapshot</code> and <code>@cypress/snapshot</code></summary>
|
|
||||||
<br>
|
|
||||||
They're mostly the same, as this is a fork of the Latter, though it's not a drop-in replacement.
|
|
||||||
|
|
||||||
Unlike `@cypress/snapshot`, this saves snapshots in their own files with a sensible default and strives to have ongoing Support for future Cypress Versions
|
- With V3, the `readFileMaybe` task has been removed, we now rely on `cy.fixture` internally.
|
||||||
|
- the previous `SNAPSHOT_UPDATE` Environment/Config Variable has been changed to `updateSnapshots`
|
||||||
|
|
||||||
</details>
|
> [!DANGER]
|
||||||
|
This means that previous tests will likely be broken, *please make sure that your tests pass before updating to the latest version of this Plugin*.
|
||||||
|
|
||||||
<!-- [![NPM][npm-icon] ][npm-url] -->
|
This current release will be released as `3.0.0-beta`, should Bugs be found by me or my Employer, I will open Issues/PRs to fix those, should anyone else find Bugs/Edgecases, etc. please open an Issue.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
Requires [Node](https://nodejs.org/en/) version 10 or above.
|
Requires Node 16 or above
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm install --save-dev @datashard/snapshot
|
npm i --save-dev @datashard/snapshot
|
||||||
```
|
```
|
||||||
|
|
||||||
## Import
|
## Import
|
||||||
|
|
||||||
After installing, you need to add this snippet within your Cypress Support File (default: `cypress/support/e2e.{js,ts}`)
|
After Installing, you'll need to add the following import into your Commands/Support File
|
||||||
|
|
||||||
|
> by default this will be `cypress/support/e2e.js`
|
||||||
|
|
||||||
```js
|
```js
|
||||||
require("@datashard/snapshot").register();
|
require('@datashard/snapshot').regsiter()
|
||||||
```
|
```
|
||||||
|
|
||||||
This registers a new command to create new snapshot or compare value to old snapshot
|
This will register a new Command `.snapshot()`, to create and compare JSON Snapshots.
|
||||||
|
|
||||||
and add the following to your `cypress.config.{js,ts}`
|
## Config
|
||||||
|
|
||||||
|
You can pass `updateSnapshots` and `useFolders` as options in the `cypress.config.js` file
|
||||||
|
|
||||||
|
![Example Settings for the Module](./.github/assets/config.png)
|
||||||
|
Alternatively, you can also add `snapshotUpdate` as an Environment Variable to update your snapshots.
|
||||||
|
|
||||||
|
Simply pass `--env updateSnapshots=true` when running Cypress.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
If properly added, usage of this plugin is rather simple, just add `.snapshot()` to cypress functions that return valid JSON. (i.e. `cy.wrap`)
|
||||||
|
|
||||||
|
When properly added, you can chain `.snapshot()` off of `cy` functions like `cy.wrap`, just make sure they return valid JSON.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
```js
|
```js
|
||||||
e2e: {
|
describe("my test", () => {
|
||||||
setupNodeEvents(on, config) {
|
|
||||||
require("@datashard/snapshot").tasks(on, config)
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Note** \
|
|
||||||
> \
|
|
||||||
> `@datashard/snapshot` **requires** the `readFileMaybe` plugin to be included, which can be easily done using the code above
|
|
||||||
|
|
||||||
# Usage
|
|
||||||
|
|
||||||
Currently, if you want to take more than one snapshot, you need to pass a Step Name to prevent overwrites / test failures
|
|
||||||
|
|
||||||
```js
|
|
||||||
describe("my tests", () => {
|
|
||||||
it("works", () => {
|
it("works", () => {
|
||||||
cy.log("first snapshot");
|
cy.log("first snapshot");
|
||||||
cy.wrap({ foo: 42 }).snapshot("foo");
|
cy.wrap({ foo: 42 }).snapshot("foo");
|
||||||
|
@ -59,113 +60,33 @@ describe("my tests", () => {
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
In the above case, you can find the stored snapshot in their own files, mentioned above them
|
This Plugin will then save your snapshots as
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// useFolders: false
|
||||||
|
cypress/fixtures/my-test__works__foo.json
|
||||||
|
cypress/fixtures/my-test__works__bar.json
|
||||||
|
|
||||||
|
// useFolders: true
|
||||||
|
cypress/fixtures/my-test/works/foo.json
|
||||||
|
cypress/fixtures/my-test/works/bar.json
|
||||||
|
|
||||||
|
// {fixtureFolder}/<Context>-<Describe>-<It>-<Name?>.json
|
||||||
|
// {fixtureFolder}/<Context>/<Describe>/<It>/<Name?>.json
|
||||||
|
|
||||||
```jsonc
|
|
||||||
// cypress/snapshots/my-tests-works-foo.json
|
|
||||||
{ "foo": 42 }
|
|
||||||
// cypress/snapshots/my-tests-works-bar.json
|
|
||||||
{ "bar": 101 }
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If you change the site values, the saved snapshot will no longer match, throwing an error
|
Snapshots will generally be saved using this the Convention mentioned in the Comment of the above Codeblock, which is provided by the named Cypress Test Steps.
|
||||||
|
|
||||||
(picture taken from `cypress/snapshots/Arrays.json`)
|
Passing a name to the Snapshot function is required, but not checked, if you want to take multiple snapshots in the same block.
|
||||||
![Snapshot mismatch](.github/assets/updated-mismatch.png)
|
|
||||||
|
|
||||||
Click on the `SNAPSHOT` step in the Command Log to see expected and current value printed in the DevTools.
|
If you have two or more Snapshots in the same Block, the next one ***WILL*** always overwrite the previous one while updating, causing the First Snapshot in the Block to Fail.
|
||||||
|
While running your Tests, if a value changed, it will, of course, no longer match the snapshot and throw an Error.
|
||||||
|
|
||||||
### Options
|
Which will look like this:
|
||||||
|
|
||||||
You can control snapshot comparison and behavior through a few options.
|
![](./.github/assets/Error.png)
|
||||||
|
|
||||||
```js
|
When the Test succeeds, it will instead log a Success in the Log and let you know where the File has been saved to, relative to the Fixture Snapshot Folder
|
||||||
cy.get(...).snapshot({
|
|
||||||
snapshotName: 'Snapshot Name', // Overwrite the generated Snapshot name
|
|
||||||
snapshotPath: 'cypress/not_snapshots', // Overwrite where the Snapshot should be stored
|
|
||||||
json: false // convert DOM elements into JSON
|
|
||||||
}) // when storing in the snapshot file
|
|
||||||
|
|
||||||
// will save as
|
![](./.github/assets/Correct.png)
|
||||||
// cypress/not_snapshots/Snapshot-Name.json
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also pass a "Step Name" to the Function
|
|
||||||
|
|
||||||
```js
|
|
||||||
cy.get(...).snapshot("Intercepted API Request")
|
|
||||||
// will save as
|
|
||||||
// cypress/snapshots/<context>-<describe>-<it>-Intercepted-API-Request.json
|
|
||||||
// to prevent duplications
|
|
||||||
```
|
|
||||||
|
|
||||||
or both
|
|
||||||
|
|
||||||
```js
|
|
||||||
cy.get(...).snapshot("Intercepted API Request", {
|
|
||||||
snapshotPath: "cypress/snapshots/api",
|
|
||||||
snapshotName: "first_intercept"
|
|
||||||
})
|
|
||||||
|
|
||||||
// will save as
|
|
||||||
// cypress/snapshots/api/first_intercept.json
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
This module provides some configuration options:
|
|
||||||
|
|
||||||
#### snapshot.snapshotPath
|
|
||||||
|
|
||||||
Sets the default Path for saving Snapshots (default: `cypress/snapshots`)
|
|
||||||
|
|
||||||
![Config Screenshot](./.github/assets/config.png)
|
|
||||||
|
|
||||||
#### `ENV` CYPRESS_UPDATE_SNAPSHOTS
|
|
||||||
|
|
||||||
Lets you pass a Env Variable to update failing Tests with the new Data
|
|
||||||
|
|
||||||
#
|
|
||||||
|
|
||||||
### Small print
|
|
||||||
|
|
||||||
Authors:
|
|
||||||
|
|
||||||
- Joshua <[data@shard.wtf](mailto:data@shard.wtf)>
|
|
||||||
- Gleb Bahmutov <gleb@cypress.io>
|
|
||||||
|
|
||||||
<br>
|
|
||||||
License: MIT - do anything with the code, but don't blame us if it does not work.
|
|
||||||
|
|
||||||
Support: If you find any problems with this module [open an issue](https://github.com/datashard/snapshot/issues) on Github
|
|
||||||
|
|
||||||
## MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2017-2022 Cypress.io <hello@cypress.io> & Joshua <data@shard.wtf>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
|
||||||
obtaining a copy of this software and associated documentation
|
|
||||||
files (the "Software"), to deal in the Software without
|
|
||||||
restriction, including without limitation the rights to use,
|
|
||||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following
|
|
||||||
conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
[npm-icon]: https://nodei.co/npm/@datashard/snapshot.svg?downloads=true
|
|
||||||
[npm-url]: https://npmjs.org/package/@datashard/snapshot
|
|
||||||
[semantic-url]: https://github.com/semantic-release/semantic-release
|
|
||||||
[renovate-badge]: https://img.shields.io/badge/renovate-app-blue.svg
|
|
||||||
[renovate-app]: https://renovateapp.com/
|
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
const { defineConfig } = require("cypress");
|
const { defineConfig } = require("cypress");
|
||||||
const { functions } = require("./src/utils");
|
|
||||||
|
|
||||||
module.exports = defineConfig({
|
module.exports = defineConfig({
|
||||||
|
// fixturesFolder: "cypress/fixtures",
|
||||||
snapshot: {
|
snapshot: {
|
||||||
snapshotPath: "cypress/snapshots/",
|
// updateSnapshots: true,
|
||||||
|
useFolders: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
e2e: {
|
e2e: {
|
||||||
setupNodeEvents(on, config) {
|
setupNodeEvents(on, config) {
|
||||||
functions.tasks(on, config);
|
// implement node event listeners here
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
|
@ -1,47 +1,78 @@
|
||||||
/* eslint-env mocha */
|
/* eslint-env mocha */
|
||||||
/* global cy */
|
/* global cy */
|
||||||
describe("@datashard/snapshot", () => {
|
describe("datashard/snapshot", () => {
|
||||||
context("simple types", () => {
|
context("simple types"
|
||||||
it("works with objects", () => {
|
// , { env: { updateSnapshots: true } }
|
||||||
cy.fixture("File2").snapshot({
|
, () => {
|
||||||
snapshotPath: "cypress/snapshots",
|
it("works with objects", () => {
|
||||||
snapshotName: "Objects",
|
cy.wrap({
|
||||||
|
"foo": "bar",
|
||||||
|
"Fizzy Drink": "Pop"
|
||||||
|
}).snapshot();
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it("works with numbers", () => {
|
it("works with numbers", () => {
|
||||||
cy.wrap(42).snapshot({
|
cy.wrap(42).snapshot({
|
||||||
snapshotPath: "cypress/snapshots",
|
snapshotPath: "cypress/fixtures/snapshots",
|
||||||
snapshotName: "Numbers",
|
snapshotName: "Numbers",
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("works with strings", () => {
|
|
||||||
cy.wrap("foo-bar").snapshot({
|
|
||||||
snapshotPath: "cypress/snapshots",
|
|
||||||
snapshotName: "Strings",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it(
|
|
||||||
"works with arrays",
|
|
||||||
{
|
|
||||||
env: {
|
|
||||||
SNAPSHOT_UPDATE: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
cy.wrap([1, 2, 3, 4]).snapshot({
|
|
||||||
snapshotPath: "cypress/snapshots",
|
|
||||||
snapshotName: "Arrays",
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
);
|
|
||||||
it('works with more "complicated" Objects', () => {
|
it("works with strings", () => {
|
||||||
cy.fixture("Complex").snapshot({
|
cy.wrap("foo-bar").snapshot({
|
||||||
snapshotPath: 'cypress/snapshots',
|
snapshotPath: "cypress/fixtures/snapshots",
|
||||||
snapshotName: "Complex"
|
snapshotName: "Strings",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it(
|
||||||
|
"works with arrays",
|
||||||
|
{
|
||||||
|
env: {
|
||||||
|
updateSnapshots: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
cy.wrap([1, 2, 3, 4]).snapshot({
|
||||||
|
snapshotPath: "cypress/fixtures/snapshots",
|
||||||
|
snapshotName: "Arrays",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
});
|
||||||
|
context("complex types"
|
||||||
|
// , { env: { SNAPSHOT_UPDATE: true } }
|
||||||
|
, () => {
|
||||||
|
it('works with more "complicated" Objects', () => {
|
||||||
|
cy.wrap({
|
||||||
|
"status": 200,
|
||||||
|
"response": {
|
||||||
|
"array": [0, 1, 2, "4"],
|
||||||
|
"object": {
|
||||||
|
"with": "more details"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thisisnew": "wtf"
|
||||||
|
}).snapshot()
|
||||||
})
|
})
|
||||||
|
it("works based on fixtures", () => {
|
||||||
|
cy
|
||||||
|
.wrap({
|
||||||
|
"jsonapi": {
|
||||||
|
"version": "2.0"
|
||||||
|
},
|
||||||
|
"included": [
|
||||||
|
{
|
||||||
|
"type": "users",
|
||||||
|
"id": "2",
|
||||||
|
"attributes": {
|
||||||
|
"name": "Test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.snapshot();
|
||||||
|
});
|
||||||
})
|
})
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,25 +3,21 @@
|
||||||
describe("Random Describe", () => {
|
describe("Random Describe", () => {
|
||||||
context("Random Context", () => {
|
context("Random Context", () => {
|
||||||
it("Random It", () => {
|
it("Random It", () => {
|
||||||
cy.fixture("File").snapshot("Fixture File", {
|
cy.wrap(42).snapshot("Numbers");
|
||||||
snapshotName: "Random Fixture File"
|
cy.wrap("foo-bar").snapshot("Strings");
|
||||||
});
|
cy.wrap([1, 2, 3]).snapshot("Arrays");
|
||||||
// cy.fixture("File2").snapshot("Fixture File",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// it("works with numbers", () => {
|
// it("works with numbers", () => {
|
||||||
// console.log(cy.wrap(42))
|
// console.log(cy.wrap(42))
|
||||||
// cy.wrap(42).snapshot();
|
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// it("works with strings", () => {
|
// it("works with strings", () => {
|
||||||
// console.log(cy.wrap("foo-bar"))
|
// console.log(cy.wrap("foo-bar"))
|
||||||
// cy.wrap("foo-bar").snapshot();
|
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// it("works with arrays", () => {
|
// it("works with arrays", () => {
|
||||||
// console.log(cy.wrap([1, 2, 3]))
|
// console.log(cy.wrap([1, 2, 3]))
|
||||||
// cy.wrap([1, 2, 3]).snapshot();
|
|
||||||
// });
|
// });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"foo": "bar",
|
|
||||||
"Fizzy Drink": "Soda"
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"foo": "bar",
|
|
||||||
"Fizzy Drink": "Pop"
|
|
||||||
}
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"jsonapi": {
|
||||||
|
"version": "2.0"
|
||||||
|
},
|
||||||
|
"included": [
|
||||||
|
{
|
||||||
|
"type": "users",
|
||||||
|
"id": "2",
|
||||||
|
"attributes": {
|
||||||
|
"name": "Test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -5,10 +5,11 @@
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
"Three"
|
"4"
|
||||||
],
|
],
|
||||||
"object": {
|
"object": {
|
||||||
"with": "more details"
|
"with": "more details"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"thisisnew": "wtf"
|
||||||
}
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"data": 42
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"data": "foo-bar"
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"status": 200,
|
|
||||||
"response": {
|
|
||||||
"array": [0, 1, 2, "Three"],
|
|
||||||
"object": {
|
|
||||||
"with": "more details"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
{"foo":"bar","Fizzy Drink":"Soda"}
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"foo": "bar",
|
|
||||||
"Fizzy Drink": "Soda"
|
|
||||||
}
|
|
|
@ -1,2 +1,4 @@
|
||||||
// register .snapshot() command
|
// register .snapshot() command
|
||||||
require('../..').register()
|
|
||||||
|
|
||||||
|
require('../../src/index').register()
|
||||||
|
|
730
package-lock.json
generated
730
package-lock.json
generated
File diff suppressed because it is too large
Load diff
14
package.json
14
package.json
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "@datashard/snapshot",
|
"name": "@datashard/snapshot",
|
||||||
"description": "Adds value / object / DOM element snapshot testing support to Cypress test runner",
|
"description": "Adds JSON Snapshot testing support to Cypress",
|
||||||
"version": "2.3.2",
|
"version": "3.0.0-beta",
|
||||||
"author": "Joshua <data@shard.wtf>, Gleb Bahmutov <gleb@cypress.io>",
|
"author": "Joshua <data@shard.wtf>",
|
||||||
"bugs": "https://github.com/datashard/snapshot/issues",
|
"bugs": "https://github.com/datashard/snapshot/issues",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
|
@ -13,13 +13,13 @@
|
||||||
"src/*/**",
|
"src/*/**",
|
||||||
"!src/*-spec.js"
|
"!src/*-spec.js"
|
||||||
],
|
],
|
||||||
"homepage": "https://github.com/datashard/snapshot#readme",
|
"homepage": "https://shard.wtf/snapshot",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cypress",
|
"cypress",
|
||||||
"cypress-io",
|
"cypress-io",
|
||||||
"plugin",
|
"plugin",
|
||||||
"snapshot",
|
"snapshot",
|
||||||
"testing"
|
"testing", "json"
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
|
@ -33,11 +33,11 @@
|
||||||
"unused-deps": "dependency-check --unused --no-dev . --entry src/index.js",
|
"unused-deps": "dependency-check --unused --no-dev . --entry src/index.js",
|
||||||
"semantic-release": "semantic-release",
|
"semantic-release": "semantic-release",
|
||||||
"cypress:open": "cypress open",
|
"cypress:open": "cypress open",
|
||||||
"cypress:update": "cypress run --env SNAPSHOT_UPDATE=true",
|
"cypress:update": "cypress run --env updateSnapshots=true",
|
||||||
"cypress:run": "cypress run"
|
"cypress:run": "cypress run"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cypress": "10.6.0",
|
"cypress": "12.13.0",
|
||||||
"debug": "3.2.7",
|
"debug": "3.2.7",
|
||||||
"dependency-check": "2.10.1"
|
"dependency-check": "2.10.1"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// global cy, Cypress
|
// global cy, Cypress
|
||||||
const { functions } = require("./utils/index");
|
const register = require("./register");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
register: functions.register,
|
register
|
||||||
tasks: functions.tasks,
|
|
||||||
};
|
};
|
||||||
|
|
119
src/register.js
Normal file
119
src/register.js
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
const lazy = require("lazy-ass");
|
||||||
|
const is = require("check-more-types");
|
||||||
|
const snapshot = require("./snapshot");
|
||||||
|
|
||||||
|
const baseStyles = [
|
||||||
|
{
|
||||||
|
name: 'info',
|
||||||
|
color: '#cbd5e1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'success',
|
||||||
|
color: '#10b981',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'warning',
|
||||||
|
color: '#fbbf24',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'error',
|
||||||
|
color: '#dc2626',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to convert hex colors to rgb
|
||||||
|
* @param {string} hex - hex color
|
||||||
|
* @returns {string}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // returns "255 255 255"
|
||||||
|
* hex2rgb("#ffffff")
|
||||||
|
*/
|
||||||
|
function hex2rgb(hex) {
|
||||||
|
const r = parseInt(hex.slice(1, 3), 16)
|
||||||
|
const g = parseInt(hex.slice(3, 5), 16)
|
||||||
|
const b = parseInt(hex.slice(5, 7), 16)
|
||||||
|
|
||||||
|
return `${r} ${g} ${b}`
|
||||||
|
}
|
||||||
|
|
||||||
|
baseStyles.forEach((style) => {
|
||||||
|
createCustomLog(style.name, style.color)
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a custom log
|
||||||
|
* @param {string} name - Name of the custom log
|
||||||
|
* @param {string} baseColor - Base color of the custom log in hex format
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // Create a custom log with name "misc" and base color "#9333ea"
|
||||||
|
* createCustomLog("misc", "#9333ea")
|
||||||
|
*/
|
||||||
|
function createCustomLog(name, baseColor) {
|
||||||
|
if (!name || !baseColor) {
|
||||||
|
throw new Error('Missing parameters')
|
||||||
|
}
|
||||||
|
|
||||||
|
const logStyle = document.createElement('style')
|
||||||
|
|
||||||
|
logStyle.textContent = `
|
||||||
|
.command.command-name-log-${name} span.command-method {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
min-width: 10px;
|
||||||
|
border-radius: 0.125rem;
|
||||||
|
border-width: 1px;
|
||||||
|
padding-left: 0.375rem;
|
||||||
|
padding-right: 0.375rem;
|
||||||
|
padding-top: 0.125rem;
|
||||||
|
padding-bottom: 0.125rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
border-color: rgb(${hex2rgb(baseColor)} / 1);
|
||||||
|
background-color: rgb(${hex2rgb(baseColor)} / 0.2);
|
||||||
|
color: rgb(${hex2rgb(baseColor)} / 1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.command.command-name-log-${name} span.command-message{
|
||||||
|
color: rgb(${hex2rgb(baseColor)} / 1);
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.command.command-name-log-${name} span.command-message strong,
|
||||||
|
.command.command-name-log-${name} span.command-message em {
|
||||||
|
color: rgb(${hex2rgb(baseColor)} / 1);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
Cypress.$(window.top.document.head).append(logStyle)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print a message with a formatted style
|
||||||
|
* @param {Object} log - The message to be printed.
|
||||||
|
* @param {string} log.title - The title of the message.
|
||||||
|
* @param {string} log.message - The content of the message.
|
||||||
|
* @param {('info' | 'warning' | 'error' | 'success')} log.type - The type of the message.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // Print a message with a formatted style e.g. success
|
||||||
|
* cy.print({ title: 'foo', message: 'bar', type: 'success' })
|
||||||
|
*/
|
||||||
|
function cyPrint({ title, message, type }) {
|
||||||
|
Cypress.log({
|
||||||
|
name: `log-${type}`,
|
||||||
|
displayName: `${title}`,
|
||||||
|
message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = () => {
|
||||||
|
lazy(is.fn(global.before), "Missing global before function");
|
||||||
|
lazy(is.fn(global.after), "Missing global after function");
|
||||||
|
lazy(is.object(global.Cypress), "Missing Cypress object");
|
||||||
|
|
||||||
|
Cypress.Commands.add("snapshot", { prevSubject: "optional" }, snapshot);
|
||||||
|
Cypress.Commands.add('SNAPSHOT_prettyprint', cyPrint)
|
||||||
|
|
||||||
|
};
|
118
src/snapshot.js
Normal file
118
src/snapshot.js
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
const serializeDomElement = require("./utils/serializers/serializeDomElement");
|
||||||
|
const serializeToHTML = require("./utils/serializers/serializeToHTML");
|
||||||
|
const compareValues = require("./utils/compareValues");
|
||||||
|
const path = require("path");
|
||||||
|
const identity = (x) => x;
|
||||||
|
|
||||||
|
const pickSerializer = (asJson, value) => {
|
||||||
|
if (Cypress.dom.isJquery(value)) {
|
||||||
|
return asJson ? serializeDomElement : serializeToHTML;
|
||||||
|
}
|
||||||
|
return identity;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} text
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const parseTextToJSON = (text) => text.replace(/\| [✅➖➕⭕]/g, "").trim().replace(/(.*?),\s*(\}|])/g, "$1$2").replace(/},(?!")$/g, "}").replaceAll(/[╺┿╳]/g, "")
|
||||||
|
|
||||||
|
const store_snapshot = ({ value, name, raiser } = { value, name, raiser }) => {
|
||||||
|
if (Cypress.env().updateSnapshots || Cypress.config('snapshot').updateSnapshots) {
|
||||||
|
cy.SNAPSHOT_prettyprint({ title: "INFO", type: "info", message: "Saving Snapshot" })
|
||||||
|
cy.writeFile(path.join(Cypress.config().fixturesFolder, `${name}.json`), JSON.stringify(value, null, 2))
|
||||||
|
} else {
|
||||||
|
cy.fixture(name).then(expected => raiser({ value, expected }))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const set_snapshot = ({ snapshotName, serialized, value }) => {
|
||||||
|
let devToolsLog = { $el: serialized };
|
||||||
|
if (Cypress.dom.isJquery(value)) {
|
||||||
|
devToolsLog.$el = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
let options = {
|
||||||
|
name: "snapshot",
|
||||||
|
message: snapshotName,
|
||||||
|
consoleProps: () => { return devToolsLog },
|
||||||
|
...(value && { $el: value })
|
||||||
|
};
|
||||||
|
|
||||||
|
const raiser = ({ value, expected }) => {
|
||||||
|
const result = compareValues({ expected, value });
|
||||||
|
if ((!Cypress.env().updateSnapshots || !Cypress.config('snapshot').updateSnapshots) && !result.success) {
|
||||||
|
devToolsLog = () => {
|
||||||
|
return { expected, value }
|
||||||
|
};
|
||||||
|
|
||||||
|
const error = (inError) => `
|
||||||
|
Snapshot Difference found.\nPlease Update the Snapshot ${inError ? `\n${JSON.stringify(JSON.parse(parseTextToJSON(result.result)), null, 3).replaceAll(' ', " ")}` : ""}`
|
||||||
|
|
||||||
|
Cypress.log({ message: error(true) })
|
||||||
|
|
||||||
|
throw new Error(error());
|
||||||
|
} else {
|
||||||
|
cy.SNAPSHOT_prettyprint({
|
||||||
|
title: "SUCCESS",
|
||||||
|
message: snapshotName,
|
||||||
|
type: "success"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
store_snapshot({
|
||||||
|
value,
|
||||||
|
name: snapshotName,
|
||||||
|
raiser,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function replaceCharacters(str, asFolder, sep) {
|
||||||
|
if (asFolder) {
|
||||||
|
if (!sep) throw new Error("Separator not Passed.")
|
||||||
|
return str
|
||||||
|
.replace(/ /gi, '-')
|
||||||
|
.replace(/\//gi, "-")
|
||||||
|
.replaceAll('"', '')
|
||||||
|
.replaceAll(sep, '/')
|
||||||
|
} else {
|
||||||
|
return str
|
||||||
|
.replaceAll(' ', '-')
|
||||||
|
.replaceAll('/', '-')
|
||||||
|
.replaceAll('"', '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const get_snapshot_name = (asFolder, stepName) => {
|
||||||
|
const names = Cypress.currentTest.titlePath;
|
||||||
|
const sep = ">>datashard.work<<"
|
||||||
|
|
||||||
|
|
||||||
|
if (stepName && typeof stepName !== 'object') {
|
||||||
|
names.push(stepName)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (asFolder) return replaceCharacters(names.join(sep), true, sep)
|
||||||
|
else return replaceCharacters(names.join('__'), false)
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = (value, stepName, options = { json: true }) => {
|
||||||
|
if (typeof stepName === 'object') options = { ...options, ...stepName }
|
||||||
|
if (typeof value !== "object" || Array.isArray(value))
|
||||||
|
value = { data: value };
|
||||||
|
const serializer = pickSerializer(options.json, value);
|
||||||
|
const serialized = serializer(value);
|
||||||
|
options.asFolder = Cypress.config('snapshot').useFolders || false
|
||||||
|
|
||||||
|
set_snapshot({
|
||||||
|
snapshotName: `/${get_snapshot_name(options.asFolder, stepName)}`,
|
||||||
|
serialized,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
};
|
|
@ -1,51 +1,21 @@
|
||||||
// const { expect: chaiExpect } = require("chai");
|
|
||||||
|
|
||||||
const isNestedData = (expected, value) => {
|
const containsDiffChars = str => ["╺", "┿", "╳"].some(emoji => str.includes(emoji));
|
||||||
return (
|
const isNestedData = (expected, value) => expected && value && typeof expected == 'object' && typeof value == 'object';
|
||||||
expected && value && typeof expected == `object` && typeof value == `object`
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkDataState = (expected, value) => {
|
const checkDataState = (expected, value) => {
|
||||||
let result;
|
let result;
|
||||||
|
|
||||||
if (expected === value) {
|
if (expected === value) {
|
||||||
result = `| ✅ "${value}",`;
|
result = `| ✅ "${value}",`;
|
||||||
} else if (expected == undefined) {
|
|
||||||
result = `| ➖ "➖╺ ${expected}|${value}",`;
|
|
||||||
} else if (value == undefined) {
|
|
||||||
result = `| ➕ "➕┿ ${expected}|${value}",`;
|
|
||||||
} else {
|
} else {
|
||||||
result = `| ⭕ "⭕╳ ${expected}|${value}",`;
|
result = `| ⭕ "⭕╳ ${JSON.stringify(expected)?.replaceAll('"', "'")} | ${value?.replaceAll('"', "'")}",`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {string} text
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
|
|
||||||
function parseTextToJSON(text) {
|
|
||||||
const lines =
|
|
||||||
text
|
|
||||||
.replace(/\| [✅➖➕⭕]/g, "").trim()
|
|
||||||
.replace(/(.*?),\s*(\}|])/g, "$1$2");
|
|
||||||
return lines;
|
|
||||||
// return JSON.stringify(lines, null, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
function containsDiffChars(str) {
|
|
||||||
const emojis = ["╺", "┿", "╳"];
|
|
||||||
return emojis.some(emoji => str.includes(emoji));
|
|
||||||
}
|
|
||||||
|
|
||||||
const compare = (expected, value) => {
|
const compare = (expected, value) => {
|
||||||
let compareResult = "";
|
let compareResult = "";
|
||||||
let compareSuccess = true;
|
|
||||||
|
|
||||||
if (isNestedData(expected, value)) {
|
if (isNestedData(expected, value)) {
|
||||||
if (Array.isArray(expected)) {
|
if (Array.isArray(expected)) {
|
||||||
|
@ -62,7 +32,6 @@ const compare = (expected, value) => {
|
||||||
|
|
||||||
dataX.forEach(function (item, index) {
|
dataX.forEach(function (item, index) {
|
||||||
const resultset = compare(item, dataY[index]);
|
const resultset = compare(item, dataY[index]);
|
||||||
compareSuccess = resultset.success;
|
|
||||||
compareResult += resultset.result;
|
compareResult += resultset.result;
|
||||||
});
|
});
|
||||||
compareResult += `],`;
|
compareResult += `],`;
|
||||||
|
@ -79,26 +48,21 @@ const compare = (expected, value) => {
|
||||||
|
|
||||||
Object.keys(dataX).forEach((key) => {
|
Object.keys(dataX).forEach((key) => {
|
||||||
const resultset = compare(dataX[key], dataY[key]);
|
const resultset = compare(dataX[key], dataY[key]);
|
||||||
|
|
||||||
compareSuccess = resultset.success;
|
|
||||||
compareResult += `"${key}": ${resultset.result}`;
|
compareResult += `"${key}": ${resultset.result}`;
|
||||||
});
|
});
|
||||||
compareResult += `}`;
|
compareResult += `},`;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
compareSuccess = false;
|
|
||||||
compareResult = checkDataState(expected, value);
|
compareResult = checkDataState(expected, value);
|
||||||
}
|
}
|
||||||
let result = parseTextToJSON(compareResult);
|
|
||||||
// let result = compareResult;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
success: !containsDiffChars(result),
|
success: !containsDiffChars(compareResult),
|
||||||
result,
|
result: compareResult,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { success: false, result };
|
return { success: false, result: compareResult };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
const readFileMaybe = require("../tasks/readFileMaybe");
|
|
||||||
|
|
||||||
module.exports = (on, config) => {
|
|
||||||
on("task", { readFileMaybe });
|
|
||||||
};
|
|
|
@ -1,13 +0,0 @@
|
||||||
const lazy = require("lazy-ass");
|
|
||||||
const is = require("check-more-types");
|
|
||||||
const snapshot = require("../snapshots/snapshot");
|
|
||||||
|
|
||||||
module.exports = () => {
|
|
||||||
lazy(is.fn(global.before), "Missing global before function");
|
|
||||||
lazy(is.fn(global.after), "Missing global after function");
|
|
||||||
lazy(is.object(global.Cypress), "Missing Cypress object");
|
|
||||||
|
|
||||||
Cypress.Commands.add("snapshot", { prevSubject: true }, snapshot);
|
|
||||||
|
|
||||||
return snapshot;
|
|
||||||
};
|
|
|
@ -1,28 +0,0 @@
|
||||||
const serializeToHTML = require("./serializers/serializeToHTML");
|
|
||||||
const serializeDomElement = require("./serializers/serializeDomElement");
|
|
||||||
const compareValues = require("./snapshots/compareValues");
|
|
||||||
const readFileMaybe = require("./tasks/readFileMaybe");
|
|
||||||
const identity = (x) => x;
|
|
||||||
const publicProps = (name) => !name.startsWith("__");
|
|
||||||
const countSnapshots = (snapshots) =>
|
|
||||||
Object.keys(snapshots).filter(publicProps).length;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
serializers: {
|
|
||||||
serializeDomElement,
|
|
||||||
serializeToHTML,
|
|
||||||
identity,
|
|
||||||
countSnapshots,
|
|
||||||
},
|
|
||||||
snapshots: {
|
|
||||||
compareValues,
|
|
||||||
},
|
|
||||||
|
|
||||||
functions: {
|
|
||||||
register: require("./functions/register"),
|
|
||||||
tasks: require("./functions/addTasks"),
|
|
||||||
},
|
|
||||||
tasks: {
|
|
||||||
readFileMaybe,
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,111 +0,0 @@
|
||||||
const serializeDomElement = require("../serializers/serializeDomElement");
|
|
||||||
const serializeToHTML = require("../serializers/serializeToHTML");
|
|
||||||
const compareValues = require("./compareValues");
|
|
||||||
const path = require("path");
|
|
||||||
const identity = (x) => x;
|
|
||||||
|
|
||||||
const pickSerializer = (asJson, value) => {
|
|
||||||
if (Cypress.dom.isJquery(value)) {
|
|
||||||
return asJson ? serializeDomElement : serializeToHTML;
|
|
||||||
}
|
|
||||||
return identity;
|
|
||||||
};
|
|
||||||
|
|
||||||
const store_snapshot = (props = { value, name, path, raiser }) => {
|
|
||||||
const expectedPath = path.join(
|
|
||||||
props.path ||
|
|
||||||
Cypress.config("snapshot").snapshotPath ||
|
|
||||||
"cypress/snapshots",
|
|
||||||
`${props.name.join("_").replace(/ /gi, "-").replace(/\//gi, "-")}.json`
|
|
||||||
);
|
|
||||||
cy.task("readFileMaybe", expectedPath).then((exist) => {
|
|
||||||
if (exist && !Cypress.env().SNAPSHOT_UPDATE) {
|
|
||||||
props.raiser({ value: props.value, expected: JSON.parse(exist) });
|
|
||||||
} else {
|
|
||||||
cy.writeFile(expectedPath, JSON.stringify(props.value, null, 2));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const set_snapshot = (
|
|
||||||
{ snapshotName, snapshotPath, serialized, value }
|
|
||||||
) => {
|
|
||||||
let devToolsLog = { $el: serialized };
|
|
||||||
|
|
||||||
if (Cypress.dom.isJquery(value)) {
|
|
||||||
devToolsLog.$el = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
name: "snapshot",
|
|
||||||
message: Cypress._.last(snapshotName),
|
|
||||||
consoleProps: () => devToolsLog,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (value) options.$el = value;
|
|
||||||
|
|
||||||
const raiser = ({ value, expected }) => {
|
|
||||||
const result = compareValues({ expected, value });
|
|
||||||
|
|
||||||
if (!Cypress.env().SNAPSHOT_UPDATE && !result.success) {
|
|
||||||
devToolsLog = {
|
|
||||||
...devToolsLog,
|
|
||||||
message: result,
|
|
||||||
expected,
|
|
||||||
value,
|
|
||||||
};
|
|
||||||
|
|
||||||
// ╺
|
|
||||||
// ┿
|
|
||||||
// ╳
|
|
||||||
|
|
||||||
throw new Error(
|
|
||||||
`Snapshot Difference found.\nPlease Update the Snapshot\n\n${JSON.stringify(
|
|
||||||
JSON.parse(result.result),
|
|
||||||
null,
|
|
||||||
2
|
|
||||||
)
|
|
||||||
.replaceAll(" ", " ")
|
|
||||||
.replaceAll(/[╺┿╳]/g, "")}`
|
|
||||||
// `Snapshot Difference found.\nPlease Update the Snapshot\n\n${result.result}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Cypress.log(options);
|
|
||||||
|
|
||||||
store_snapshot({
|
|
||||||
value,
|
|
||||||
name: snapshotName,
|
|
||||||
path: snapshotPath,
|
|
||||||
raiser,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const get_snapshot_name = (test, custom_name) => {
|
|
||||||
const names = test.titlePath;
|
|
||||||
|
|
||||||
const index = custom_name;
|
|
||||||
names.push(String(index));
|
|
||||||
|
|
||||||
if (custom_name) return [custom_name];
|
|
||||||
return names;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = (value, step, options) => {
|
|
||||||
if (typeof step === "object") options = step;
|
|
||||||
if (typeof value !== "object" || Array.isArray(value))
|
|
||||||
value = { data: value };
|
|
||||||
|
|
||||||
const serializer = pickSerializer(options.json, value);
|
|
||||||
const serialized = serializer(value);
|
|
||||||
|
|
||||||
set_snapshot({
|
|
||||||
snapshotName: get_snapshot_name(
|
|
||||||
Cypress.currentTest,
|
|
||||||
options.snapshotName || step
|
|
||||||
),
|
|
||||||
snapshotPath: options.snapshotPath,
|
|
||||||
serialized,
|
|
||||||
value,
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,9 +0,0 @@
|
||||||
const fs = require("fs");
|
|
||||||
|
|
||||||
module.exports = (filename) => {
|
|
||||||
if (fs.existsSync(filename)) {
|
|
||||||
return fs.readFileSync(filename, "utf8");
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
Loading…
Reference in a new issue