const serializeDomElement = require("../serializers/serializeDomElement"); const serializeToHTML = require("../serializers/serializeToHTML"); const compareValues = require("./compareValues"); const { initStore } = require("snap-shot-store"); const path = require("path"); const identity = (x) => x; const pickSerializer = (asJson, value) => { if (Cypress.dom.isJquery(value)) { return asJson ? serializeDomElement : serializeToHTML; } return identity; }; const newStore = (name) => { return initStore(name); }; const store_snapshot = (store, 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)); } }); }; const set_snapshot = ( store, { snapshotName, snapshotPath, serialized, value } ) => { if (!store) return; 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.value) { result.orElse((json) => { devToolsLog = { ...devToolsLog, message: json.message, expected, value, }; throw new Error( `Snapshot Difference found.\nPlease Update the Snapshot\n\n${json.message.replaceAll(' ', ' ')}` ); }); } }; Cypress.log(options); store_snapshot(store, { 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); const store = newStore(serialized || {}); set_snapshot(store, { snapshotName: get_snapshot_name( Cypress.currentTest, options.snapshotName || step ), snapshotPath: options.snapshotPath, serialized, value, }); };