mass changes

This commit is contained in:
Joshua 2024-01-29 19:08:06 +01:00
parent b61e5c0552
commit 5db74ebcb6
23 changed files with 356 additions and 358 deletions

2
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,2 @@
{
}

View file

@ -1,14 +1,15 @@
const { defineConfig } = require("cypress"); const { defineConfig } = require("cypress");
const { functions } = require("./src/utils");
module.exports = defineConfig({ module.exports = defineConfig({
snapshot: { snapshot: {
// snapshotPath: "cypress/snapshots/", // snapshotPath: "cypress/snapshots/",
SNAPSHOT_UPDATE: true // SNAPSHOT_UPDATE: true,
useFolders: true,
}, },
e2e: { e2e: {
setupNodeEvents(on, config) { setupNodeEvents(on, config) {
functions.tasks(on, config); // implement node event listeners here
}, },
}, },
}); });

View file

@ -1,75 +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: { SNAPSHOT_UPDATE: true } }
cy.wrap({ , () => {
"foo": "bar", it("works with objects", () => {
"Fizzy Drink": "Pop" cy.wrap({
}).snapshot( "foo": "bar",
// "Filename", { "Fizzy Drink": "Pop"
// snapshotPath: "asdasd" }).snapshot();
// } });
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/fixtures/snapshots",
snapshotName: "Strings",
});
});
it(
"works with arrays",
{
env: {
SNAPSHOT_UPDATE: true,
},
},
() => {
cy.wrap([1, 2, 3, 4]).snapshot({
snapshotPath: "cypress/fixtures/snapshots",
snapshotName: "Arrays",
});
}
); );
// cypress/fixtures/@datashard-snapshot/simple-types/works-with-objects/asdjskadhasj.json
}); });
context("complex types"
// it("works with numbers", () => { // , { env: { SNAPSHOT_UPDATE: true } }
// cy.wrap(42).snapshot({ , () => {
// snapshotPath: "cypress/fixtures/snapshots", it('works with more "complicated" Objects', () => {
// snapshotName: "Numbers", cy.wrap({
// }); "status": 200,
// }); "response": {
"array": [0, 1, 2, "Three"],
// it("works with strings", () => { "object": {
// cy.wrap("foo-bar").snapshot({ "with": "more details"
// snapshotPath: "cypress/fixtures/snapshots", }
// snapshotName: "Strings", }
// }); }
// }); ).snapshot()
})
// it( it("works based on fixtures", () => {
// "works with arrays", cy
// { .wrap({
// env: { "jsonapi": {
// SNAPSHOT_UPDATE: true, "version": "2.0"
// }, },
// }, "included": [
// () => { {
// cy.wrap([1, 2, 3, 4]).snapshot({ "type": "users",
// snapshotPath: "cypress/fixtures/snapshots", "id": "2",
// snapshotName: "Arrays", "attributes": {
// }); "name": "Test"
// } }
// ); }
// it('works with more "complicated" Objects', () => { ]
// cy.fixture("Complex").snapshot({ })
// snapshotPath: 'cypress/fixtures/snapshots', .snapshot();
// 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",
// });
// });
});
}); });

View file

@ -1,4 +0,0 @@
{
"foo": "bar",
"Fizzy Drink": "Soda"
}

View file

@ -1,4 +0,0 @@
{
"foo": "bar",
"Fizzy Drink": "Pop"
}

View file

@ -0,0 +1,14 @@
{
"jsonapi": {
"version": "2.0"
},
"included": [
{
"type": "users",
"id": "2",
"attributes": {
"name": "Test"
}
}
]
}

View file

@ -0,0 +1,14 @@
{
"jsonapi": {
"version": "2.0"
},
"included": [
{
"type": "users",
"id": "2",
"attributes": {
"name": "Test"
}
}
]
}

View file

@ -1,9 +1,14 @@
{ {
"status": 200, "status": 200,
"response": { "response": {
"array": [0, 1, 2, "Three"], "array": [
0,
1,
2,
"Three"
],
"object": { "object": {
"with": "more details" "with": "more details"
} }
} }
} }

View file

@ -1 +0,0 @@
{"foo":"bar","Fizzy Drink":"Soda"}

View file

@ -1,4 +0,0 @@
{
"foo": "bar",
"Fizzy Drink": "Soda"
}

View file

@ -1,2 +1,2 @@
// register .snapshot() command // register .snapshot() command
require('../..').register() require('../../src/index').register()

View file

@ -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,
}; };

View file

@ -1,13 +1,13 @@
const lazy = require("lazy-ass"); const lazy = require("lazy-ass");
const is = require("check-more-types"); const is = require("check-more-types");
const snapshot = require("../snapshots/snapshot"); const snapshot = require("./snapshot");
module.exports = () => { module.exports = () => {
lazy(is.fn(global.before), "Missing global before function"); lazy(is.fn(global.before), "Missing global before function");
lazy(is.fn(global.after), "Missing global after function"); lazy(is.fn(global.after), "Missing global after function");
lazy(is.object(global.Cypress), "Missing Cypress object"); lazy(is.object(global.Cypress), "Missing Cypress object");
Cypress.Commands.add("snapshot", { prevSubject: "optional" }, snapshot); Cypress.Commands.add("snapshot", { prevSubject: "optional" }, snapshot);
return snapshot; return snapshot;
}; };

View file

@ -1,97 +1,112 @@
const serializeDomElement = require("../serializers/serializeDomElement"); const serializeDomElement = require("./utils/serializers/serializeDomElement");
const serializeToHTML = require("../serializers/serializeToHTML"); const serializeToHTML = require("./utils/serializers/serializeToHTML");
const compareValues = require("./compareValues"); const compareValues = require("./utils/compareValues");
const path = require("path"); const path = require("path");
const identity = (x) => x; const identity = (x) => x;
const pickSerializer = (asJson, value) => { const pickSerializer = (asJson, value) => {
if (Cypress.dom.isJquery(value)) { if (Cypress.dom.isJquery(value)) {
return asJson ? serializeDomElement : serializeToHTML; return asJson ? serializeDomElement : serializeToHTML;
} }
return identity; return identity;
}; };
const store_snapshot = (props = { value, name, raiser }) => { const store_snapshot = (props = { value, name, raiser }) => {
if (!Cypress.env().SNAPSHOT_UPDATE) { if (Cypress.env().SNAPSHOT_UPDATE || Cypress.config('snapshot').SNAPSHOT_UPDATE) {
cy.fixture(props.name).then(content => props.raiser({ value: props.value, expected: content })) cy.log(props.name)
} else { console.log(props.name)
cy.writeFile(`${props.name}.json`, JSON.stringify(props.value.null, 2)) cy.writeFile(`${props.name}.json`, JSON.stringify(props.value, null, 2))
} } else {
// TODO: Figure out how to replace the fixture folder name if people move it
const fixtureName = props.name.replace("cypress/fixtures", "")
// cy.fixture(props.name) cy.fixture(fixtureName).then(content => props.raiser({ value: props.value, expected: content }))
// .then(exist => { }
// cy.log('fixture 2') };
// if (exist && !Cypress.env().SNAPSHOT_UPDATE) {
// cy.log(`fixture exists and doesn't update`) const set_snapshot = ({ snapshotName, serialized, value }) => {
// props.raiser({ value: props.value, expected: exist, type: "fixture" }); let devToolsLog = { $el: serialized };
// } else { if (Cypress.dom.isJquery(value)) {
// cy.log(`fixture exists and updates`) devToolsLog.$el = value;
// cy.writeFile(expectedPath, JSON.stringify(props.value, null, 2)); }
// }
// }) const options = {
}; name: "snapshot",
message: snapshotName,
const set_snapshot = ({ snapshotName, serialized, value }) => { consoleProps: () => devToolsLog,
let devToolsLog = { $el: serialized }; };
if (Cypress.dom.isJquery(value)) {
devToolsLog.$el = value; if (value) options.$el = value;
}
const raiser = ({ value, expected }) => {
const options = { const result = compareValues({ expected, value });
name: "snapshot", if (!Cypress.env().SNAPSHOT_UPDATE && !result.success) {
message: snapshotName, devToolsLog = {
consoleProps: () => devToolsLog, ...devToolsLog,
}; message: result,
expected,
if (value) options.$el = value; value,
};
const raiser = ({ value, expected }) => {
const result = compareValues({ expected, value }); throw new Error(
if (!Cypress.env().SNAPSHOT_UPDATE && !result.success) { `Snapshot Difference found.\nPlease Update the Snapshot\n
devToolsLog = {
...devToolsLog,
message: result, ${JSON.stringify(result.result.replaceAll(/[╺┿╳]/g, ""), null, 2)}`
expected, );
value, }
}; };
Cypress.log(options);
throw new Error(
`Snapshot Difference found.\nPlease Update the Snapshot\n store_snapshot({
value,
name: snapshotName,
${JSON.stringify(result.result.replaceAll(/[╺┿╳]/g, ""), null, 2)}` raiser,
); });
} };
};
Cypress.log(options); function replaceCharacters(str, asFolder, sep) {
if (asFolder) {
store_snapshot({ if (!sep) throw new Error("Separator not Passed.")
value, return str
name: snapshotName, .replace(/ /gi, '-')
raiser, .replace(/\//gi, "-")
}); .replaceAll('"', '')
}; .replaceAll(sep, '/')
} else {
const get_snapshot_name = (asFolder, stepName) => { return str
const names = Cypress.currentTest.titlePath; .replaceAll(' ', '-')
const sep = ">>datashard.work<<" .replaceAll('/', '-')
if (stepName) names.push(stepName) .replaceAll('"', '')
}
if (asFolder) return names.join(sep).replace(/ /gi, "-").replace(/\//gi, "-").replaceAll(sep, '/') }
else return names.join('__').replaceAll(" ", "-").replaceAll("/", "-")
}; const get_snapshot_name = (asFolder, stepName) => {
const names = Cypress.currentTest.titlePath;
module.exports = (value, stepName, options = { json: true, asFolder: false }) => { const sep = ">>datashard.work<<"
if (typeof value !== "object" || Array.isArray(value))
value = { data: value };
const serializer = pickSerializer(options.json, value); if (stepName && typeof stepName !== 'object') {
const serialized = serializer(value); names.push(stepName)
set_snapshot({ }
snapshotName: path.join(
options.snapshotPath || Cypress.config('snapshot').snapshotPath || 'snapshots',
`/${get_snapshot_name(options.asFolder, stepName)}`), if (asFolder) return replaceCharacters(names.join(sep), true, sep)
serialized, else return replaceCharacters(names.join('__'), false)
value, };
});
}; 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: path.join(
options.snapshotPath || Cypress.config('snapshot').snapshotPath || 'cypress/fixtures/snapshots',
`/${get_snapshot_name(options.asFolder, stepName)}`),
serialized,
value,
});
};

View file

@ -1,115 +1,115 @@
const isNestedData = (expected, value) => { const isNestedData = (expected, value) => {
return ( return (
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) { } else if (expected == undefined) {
result = `| "➖╺ ${JSON.stringify(expected)?.replaceAll('"', "'")}|${value?.replaceAll('"', "'")}",`; result = `| "➖╺ ${JSON.stringify(expected)?.replaceAll('"', "'")}|${value?.replaceAll('"', "'")}",`;
} else if (value == undefined) { } else if (value == undefined) {
result = `| "➕┿ ${JSON.stringify(expected)?.replaceAll('"', "'")}|${value?.replaceAll('"', "'")}",`; result = `| "➕┿ ${JSON.stringify(expected)?.replaceAll('"', "'")}|${value?.replaceAll('"', "'")}",`;
} else { } else {
result = `| ⭕ "⭕╳ ${JSON.stringify(expected)?.replaceAll('"', "'")}|${value?.replaceAll('"', "'")}",`; result = `| ⭕ "⭕╳ ${JSON.stringify(expected)?.replaceAll('"', "'")}|${value?.replaceAll('"', "'")}",`;
} }
return result; return result;
}; };
/** /**
* *
* @param {string} text * @param {string} text
* @returns {string} * @returns {string}
*/ */
function parseTextToJSON(text) { function parseTextToJSON(text) {
const lines = const lines =
// JSON.stringify( // JSON.stringify(
text text
.replace(/\| [✅➖➕⭕]/g, "").trim() .replace(/\| [✅➖➕⭕]/g, "").trim()
.replace(/(.*?),\s*(\}|])/g, "$1$2") .replace(/(.*?),\s*(\}|])/g, "$1$2")
// ) // )
return lines; return lines;
// return JSON.stringify(lines, null, 2); // return JSON.stringify(lines, null, 2);
} }
function containsDiffChars(str) { function containsDiffChars(str) {
const emojis = ["╺", "┿", ""]; const emojis = ["╺", "┿", ""];
return emojis.some(emoji => str.includes(emoji)); return emojis.some(emoji => str.includes(emoji));
} }
const compare = (expected, value) => { const compare = (expected, value) => {
if(value === undefined){ if(value === undefined){
throw new Error("Please provide Data to compare against.") throw new Error("Please provide Data to compare against.")
} }
let compareResult = ""; let compareResult = "";
if (isNestedData(expected, value)) { if (isNestedData(expected, value)) {
if (Array.isArray(expected)) { if (Array.isArray(expected)) {
compareResult += `[`; compareResult += `[`;
let dataX, dataY; let dataX, dataY;
if (expected.length >= value.length) { if (expected.length >= value.length) {
dataX = expected; dataX = expected;
dataY = value; dataY = value;
} else { } else {
dataX = value; dataX = value;
dataY = expected; dataY = expected;
} }
dataX.forEach(function (item, index) { dataX.forEach(function (item, index) {
const resultset = compare(item, dataY[index]); const resultset = compare(item, dataY[index]);
compareResult += resultset.result; compareResult += resultset.result;
}); });
compareResult += `],`; compareResult += `],`;
} else { } else {
let dataX, dataY; let dataX, dataY;
compareResult += `{`; compareResult += `{`;
if (Object.keys(expected).length >= Object.keys(value).length) { if (Object.keys(expected).length >= Object.keys(value).length) {
dataX = expected; dataX = expected;
dataY = value; dataY = value;
} else { } else {
dataX = value; dataX = value;
dataY = expected; dataY = expected;
} }
Object.keys(dataX).forEach((key) => { Object.keys(dataX).forEach((key) => {
const resultset = compare(dataX[key], dataY[key]); const resultset = compare(dataX[key], dataY[key]);
compareResult += `"${key}": ${resultset.result}`; compareResult += `"${key}": ${resultset.result}`;
}); });
compareResult += `},`; compareResult += `},`;
} }
} else { } else {
compareResult = checkDataState(expected, value); compareResult = checkDataState(expected, value);
} }
let result = parseTextToJSON(compareResult).replace(/(},)$/g, `}`); let result = parseTextToJSON(compareResult).replace(/(},)$/g, `}`);
console.log("compareResult",compareResult) console.log("compareResult",compareResult)
console.log("result", result.replace(/(},)$/g, `}`)) console.log("result", result.replace(/(},)$/g, `}`))
// let result = compareResult; // let result = compareResult;
try { try {
return { return {
success: !containsDiffChars(result), success: !containsDiffChars(result),
result, result,
}; };
} catch (error) { } catch (error) {
return { success: false, result }; return { success: false, result };
} }
}; };
/** /**
* *
* @param {{ * @param {{
* expected: { [k:string]: any}, * expected: { [k:string]: any},
* value: {[k:string]:any} * value: {[k:string]:any}
* }} values * }} values
*/ */
module.exports = function compareValues(values) { module.exports = function compareValues(values) {
return compare(values.expected, values.value); return compare(values.expected, values.value);
}; };

View file

@ -1,5 +0,0 @@
const readFileMaybe = require("../tasks/readFileMaybe");
module.exports = (on, config) => {
on("task", { readFileMaybe });
};

View file

@ -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,
},
};

View file

@ -1,9 +0,0 @@
const fs = require("fs");
module.exports = (filename) => {
if (fs.existsSync(filename)) {
return fs.readFileSync(filename, "utf8");
}
return false;
};