diff --git a/README.md b/README.md index 1b33e11..6803bde 100644 --- a/README.md +++ b/README.md @@ -62,9 +62,9 @@ describe("my tests", () => { In the above case, you can find the stored snapshot in their own files, mentioned above them ```jsonc -// cypress/snapshots/my-tests-works-foo.json +// cypress/fixtures/snapshots/my-tests-works-foo.json { "foo": 42 } -// cypress/snapshots/my-tests-works-bar.json +// cypress/fixtures/snapshots/my-tests-works-bar.json { "bar": 101 } ``` @@ -82,7 +82,7 @@ You can control snapshot comparison and behavior through a few options. ```js cy.get(...).snapshot({ snapshotName: 'Snapshot Name', // Overwrite the generated Snapshot name - snapshotPath: 'cypress/not_snapshots', // Overwrite where the Snapshot should be stored + snapshotPath: 'cypress/fixtures/not_snapshots', // Overwrite where the Snapshot should be stored json: false // convert DOM elements into JSON }) // when storing in the snapshot file diff --git a/cypress.config.js b/cypress.config.js index 7c57e27..890cf53 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -3,7 +3,8 @@ const { functions } = require("./src/utils"); module.exports = defineConfig({ snapshot: { - snapshotPath: "cypress/snapshots/", + // snapshotPath: "cypress/snapshots/", + SNAPSHOT_UPDATE: true }, e2e: { setupNodeEvents(on, config) { diff --git a/cypress/e2e/1.cy.js b/cypress/e2e/1.cy.js index d1dc177..c7f0a09 100644 --- a/cypress/e2e/1.cy.js +++ b/cypress/e2e/1.cy.js @@ -3,45 +3,73 @@ describe("@datashard/snapshot", () => { context("simple types", () => { it("works with objects", () => { - cy.fixture("File2").snapshot({ - snapshotPath: "cypress/snapshots", - snapshotName: "Objects", - }); + cy.wrap({ + "foo": "bar", + "Fizzy Drink": "Pop" + }).snapshot( + // "Filename", { + // snapshotPath: "asdasd" + // } + ); + + // cypress/fixtures/@datashard-snapshot/simple-types/works-with-objects/asdjskadhasj.json }); - it("works with numbers", () => { - cy.wrap(42).snapshot({ - snapshotPath: "cypress/snapshots", - snapshotName: "Numbers", - }); - }); + // it("works with numbers", () => { + // cy.wrap(42).snapshot({ + // snapshotPath: "cypress/fixtures/snapshots", + // snapshotName: "Numbers", + // }); + // }); - it("works with strings", () => { - cy.wrap("foo-bar").snapshot({ - snapshotPath: "cypress/snapshots", - snapshotName: "Strings", - }); - }); + // it("works with strings", () => { + // cy.wrap("foo-bar").snapshot({ + // snapshotPath: "cypress/fixtures/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', () => { - cy.fixture("Complex").snapshot({ - snapshotPath: 'cypress/snapshots', - snapshotName: "Complex" - }) - }) + // it( + // "works with arrays", + // { + // env: { + // SNAPSHOT_UPDATE: true, + // }, + // }, + // () => { + // cy.wrap([1, 2, 3, 4]).snapshot({ + // snapshotPath: "cypress/fixtures/snapshots", + // snapshotName: "Arrays", + // }); + // } + // ); + // it('works with more "complicated" Objects', () => { + // cy.fixture("Complex").snapshot({ + // snapshotPath: 'cypress/fixtures/snapshots', + // snapshotName: "Complex" + // }) + // }) + // it.only("works based on fixtures", () => { + // cy + // .wrap({ + // "jsonapi": { + // "version": "2.0" + // }, + // "included": [ + // { + // "type": "users", + // "id": "2", + // "attributes": { + // "name": "Test" + // } + // } + // ] + // }) + // .snapshot({ + // snapshotFixture: "generated", + // // snapshotPath: "cypress/fixtures/snapshots", + // // snapshotName: "generated", + // }); + // }); }); }); diff --git a/src/utils/functions/register.js b/src/utils/functions/register.js index 8ad3504..e1d8d0a 100644 --- a/src/utils/functions/register.js +++ b/src/utils/functions/register.js @@ -7,7 +7,7 @@ module.exports = () => { lazy(is.fn(global.after), "Missing global after function"); lazy(is.object(global.Cypress), "Missing Cypress object"); - Cypress.Commands.add("snapshot", { prevSubject: true }, snapshot); + Cypress.Commands.add("snapshot", { prevSubject: "optional" }, snapshot); return snapshot; }; diff --git a/src/utils/snapshots/compareValues.js b/src/utils/snapshots/compareValues.js index bd05fef..510ef71 100644 --- a/src/utils/snapshots/compareValues.js +++ b/src/utils/snapshots/compareValues.js @@ -1,5 +1,3 @@ -// const { expect: chaiExpect } = require("chai"); - const isNestedData = (expected, value) => { return ( expected && value && typeof expected == `object` && typeof value == `object` @@ -12,11 +10,11 @@ const checkDataState = (expected, value) => { if (expected === value) { result = `| ✅ "${value}",`; } else if (expected == undefined) { - result = `| ➖ "➖╺ ${expected}|${value}",`; + result = `| ➖ "➖╺ ${JSON.stringify(expected)?.replaceAll('"', "'")}|${value?.replaceAll('"', "'")}",`; } else if (value == undefined) { - result = `| ➕ "➕┿ ${expected}|${value}",`; + result = `| ➕ "➕┿ ${JSON.stringify(expected)?.replaceAll('"', "'")}|${value?.replaceAll('"', "'")}",`; } else { - result = `| ⭕ "⭕╳ ${expected}|${value}",`; + result = `| ⭕ "⭕╳ ${JSON.stringify(expected)?.replaceAll('"', "'")}|${value?.replaceAll('"', "'")}",`; } return result; @@ -31,9 +29,11 @@ const checkDataState = (expected, value) => { function parseTextToJSON(text) { const lines = - text - .replace(/\| [✅➖➕⭕]/g, "").trim() - .replace(/(.*?),\s*(\}|])/g, "$1$2"); + // JSON.stringify( + text + .replace(/\| [✅➖➕⭕]/g, "").trim() + .replace(/(.*?),\s*(\}|])/g, "$1$2") + // ) return lines; // return JSON.stringify(lines, null, 2); } @@ -44,8 +44,10 @@ function containsDiffChars(str) { } const compare = (expected, value) => { + if(value === undefined){ + throw new Error("Please provide Data to compare against.") + } let compareResult = ""; - let compareSuccess = true; if (isNestedData(expected, value)) { if (Array.isArray(expected)) { @@ -62,7 +64,6 @@ const compare = (expected, value) => { dataX.forEach(function (item, index) { const resultset = compare(item, dataY[index]); - compareSuccess = resultset.success; compareResult += resultset.result; }); compareResult += `],`; @@ -79,17 +80,16 @@ const compare = (expected, value) => { Object.keys(dataX).forEach((key) => { const resultset = compare(dataX[key], dataY[key]); - - compareSuccess = resultset.success; compareResult += `"${key}": ${resultset.result}`; }); - compareResult += `}`; + compareResult += `},`; } } else { - compareSuccess = false; compareResult = checkDataState(expected, value); } - let result = parseTextToJSON(compareResult); + let result = parseTextToJSON(compareResult).replace(/(},)$/g, `}`); + console.log("compareResult",compareResult) + console.log("result", result.replace(/(},)$/g, `}`)) // let result = compareResult; try { diff --git a/src/utils/snapshots/snapshot.js b/src/utils/snapshots/snapshot.js index 8f9f3b6..925a1dd 100644 --- a/src/utils/snapshots/snapshot.js +++ b/src/utils/snapshots/snapshot.js @@ -11,34 +11,36 @@ const pickSerializer = (asJson, value) => { 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 store_snapshot = (props = { value, name, raiser }) => { + if (!Cypress.env().SNAPSHOT_UPDATE) { + cy.fixture(props.name).then(content => props.raiser({ value: props.value, expected: content })) + } else { + cy.writeFile(`${props.name}.json`, JSON.stringify(props.value.null, 2)) + } + + + // cy.fixture(props.name) + // .then(exist => { + // cy.log('fixture 2') + // if (exist && !Cypress.env().SNAPSHOT_UPDATE) { + // cy.log(`fixture exists and doesn't update`) + // props.raiser({ value: props.value, expected: exist, type: "fixture" }); + // } else { + // cy.log(`fixture exists and updates`) + // cy.writeFile(expectedPath, JSON.stringify(props.value, null, 2)); + // } + // }) }; -const set_snapshot = ( - { snapshotName, snapshotPath, serialized, value } -) => { +const set_snapshot = ({ snapshotName, serialized, value }) => { let devToolsLog = { $el: serialized }; - if (Cypress.dom.isJquery(value)) { devToolsLog.$el = value; } const options = { name: "snapshot", - message: Cypress._.last(snapshotName), + message: snapshotName, consoleProps: () => devToolsLog, }; @@ -46,7 +48,6 @@ const set_snapshot = ( const raiser = ({ value, expected }) => { const result = compareValues({ expected, value }); - if (!Cypress.env().SNAPSHOT_UPDATE && !result.success) { devToolsLog = { ...devToolsLog, @@ -55,19 +56,11 @@ const set_snapshot = ( 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}` + `Snapshot Difference found.\nPlease Update the Snapshot\n + + + ${JSON.stringify(result.result.replaceAll(/[╺┿╳]/g, ""), null, 2)}` ); } }; @@ -76,35 +69,28 @@ const set_snapshot = ( store_snapshot({ value, name: snapshotName, - path: snapshotPath, raiser, }); }; -const get_snapshot_name = (test, custom_name) => { - const names = test.titlePath; +const get_snapshot_name = (asFolder, stepName) => { + const names = Cypress.currentTest.titlePath; + const sep = ">>datashard.work<<" + if (stepName) names.push(stepName) - const index = custom_name; - names.push(String(index)); - - if (custom_name) return [custom_name]; - return names; + if (asFolder) return names.join(sep).replace(/ /gi, "-").replace(/\//gi, "-").replaceAll(sep, '/') + else return names.join('__').replaceAll(" ", "-").replaceAll("/", "-") }; -module.exports = (value, step, options) => { - if (typeof step === "object") options = step; +module.exports = (value, stepName, options = { json: true, asFolder: false }) => { 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, + snapshotName: path.join( + options.snapshotPath || Cypress.config('snapshot').snapshotPath || 'snapshots', + `/${get_snapshot_name(options.asFolder, stepName)}`), serialized, value, });