@jahia/cypress 8.0.0 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +65 -0
  3. package/dist/injections/bash-data.d.ts +1 -0
  4. package/dist/injections/bash-data.js +57 -0
  5. package/dist/injections/chars-data.d.ts +1 -0
  6. package/dist/injections/chars-data.js +25 -0
  7. package/dist/injections/htmlentities-data.d.ts +1 -0
  8. package/dist/injections/htmlentities-data.js +22 -0
  9. package/dist/injections/numbers-data.d.ts +1 -0
  10. package/dist/injections/numbers-data.js +66 -0
  11. package/dist/injections/sql-data.d.ts +1 -0
  12. package/dist/injections/sql-data.js +82 -0
  13. package/dist/injections/xss-data.d.ts +1 -0
  14. package/dist/injections/xss-data.js +740 -0
  15. package/dist/support/apollo/apollo.d.ts +2 -0
  16. package/dist/support/apollo/apollo.js +77 -15
  17. package/dist/support/browserHelper.d.ts +10 -0
  18. package/dist/support/browserHelper.js +167 -0
  19. package/dist/support/index.d.ts +3 -0
  20. package/dist/support/index.js +3 -0
  21. package/dist/support/jfaker.d.ts +60 -0
  22. package/dist/support/jfaker.js +241 -0
  23. package/dist/support/modSince.d.ts +52 -0
  24. package/dist/support/modSince.js +180 -0
  25. package/dist/support/provisioning/executeGroovy.js +41 -2
  26. package/dist/support/provisioning/runProvisioningScript.d.ts +1 -1
  27. package/dist/support/provisioning/runProvisioningScript.js +84 -7
  28. package/dist/support/registerSupport.js +34 -0
  29. package/docs/browser-helper.md +158 -0
  30. package/docs/jfaker.md +450 -0
  31. package/package.json +3 -1
  32. package/src/injections/bash-data.ts +54 -0
  33. package/src/injections/chars-data.ts +22 -0
  34. package/src/injections/htmlentities-data.ts +19 -0
  35. package/src/injections/numbers-data.ts +63 -0
  36. package/src/injections/sql-data.ts +79 -0
  37. package/src/injections/xss-data.ts +737 -0
  38. package/src/support/apollo/apollo.ts +74 -11
  39. package/src/support/browserHelper.ts +186 -0
  40. package/src/support/index.ts +3 -0
  41. package/src/support/jfaker.ts +245 -0
  42. package/src/support/modSince.ts +222 -0
  43. package/src/support/provisioning/executeGroovy.md +7 -1
  44. package/src/support/provisioning/executeGroovy.ts +46 -2
  45. package/src/support/provisioning/runProvisioningScript.ts +89 -12
  46. package/src/support/registerSupport.ts +29 -0
  47. package/tests/cypress/e2e/jfaker.spec.ts +411 -0
  48. package/tests/cypress/e2e/modSince.spec.ts +306 -0
  49. package/tests/cypress.config.ts +23 -0
  50. package/tests/package.json +41 -0
  51. package/tests/reporter-config.json +13 -0
  52. package/tests/yarn.lock +8578 -0
  53. package/tsconfig.json +3 -0
@@ -0,0 +1,52 @@
1
+ /** Cypress environment variable key used to store the current Jahia version. */
2
+ export declare const JAHIA_VERSION_ENV_VAR = "CYPRESS_JAHIA_VERSION";
3
+ declare global {
4
+ namespace Mocha {
5
+ interface TestFunction {
6
+ since(requiredVersion: string, title: string, fn?: Func): Test;
7
+ since(requiredVersion: string, title: string, config: Cypress.TestConfigOverrides, fn?: Func): Test;
8
+ }
9
+ interface ExclusiveTestFunction {
10
+ since(requiredVersion: string, title: string, fn?: Func): Test;
11
+ since(requiredVersion: string, title: string, config: Cypress.TestConfigOverrides, fn?: Func): Test;
12
+ }
13
+ interface PendingTestFunction {
14
+ since(requiredVersion: string, title: string, fn?: Func): Test;
15
+ since(requiredVersion: string, title: string, config: Cypress.TestConfigOverrides, fn?: Func): Test;
16
+ }
17
+ interface SuiteFunction {
18
+ since(requiredVersion: string, title: string, fn: (this: Suite) => void): Suite;
19
+ }
20
+ interface ExclusiveSuiteFunction {
21
+ since(requiredVersion: string, title: string, fn: (this: Suite) => void): Suite;
22
+ }
23
+ interface PendingSuiteFunction {
24
+ since(requiredVersion: string, title: string, fn: (this: Suite) => void): Suite;
25
+ }
26
+ }
27
+ }
28
+ /**
29
+ * Fetches the Jahia version from the GraphQL API, strips the `-SNAPSHOT` suffix,
30
+ * and caches the result in `Cypress.env(JAHIA_VERSION_ENV_VAR)`.
31
+ */
32
+ export declare const initializeVersionSupport: () => Cypress.Chainable<any>;
33
+ /**
34
+ * Attaches `.since()` to `it`, `it.only`, `it.skip`, `describe`, `describe.only`,
35
+ * and `describe.skip`. Safe to call multiple times — subsequent calls are no-ops.
36
+ */
37
+ export declare const registerVersionSupport: () => void;
38
+ /**
39
+ * Enables version-gated testing for the Cypress suite.
40
+ * Registers `it.since`, `describe.since` (and their `.only`/`.skip` variants),
41
+ * then fetches the running Jahia version in a root `before()` hook.
42
+ *
43
+ * @example
44
+ * it.since('8.2.0', 'works on 8.2+', () => { ... });
45
+ * describe.since('8.2.0', 'suite for 8.2+', () => { ... });
46
+ */
47
+ declare function enable(): void;
48
+ /** Public API for Jahia version-gated testing. */
49
+ export declare const modSince: {
50
+ enable: typeof enable;
51
+ };
52
+ export {};
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.modSince = exports.registerVersionSupport = exports.initializeVersionSupport = exports.JAHIA_VERSION_ENV_VAR = void 0;
4
+ var compare_versions_1 = require("compare-versions");
5
+ // Intentionally keep explicit path to avoid edge case errors in runtime
6
+ var JahiaPlatformHelper_1 = require("../utils/JahiaPlatformHelper");
7
+ /** Cypress environment variable key used to store the current Jahia version. */
8
+ exports.JAHIA_VERSION_ENV_VAR = 'CYPRESS_JAHIA_VERSION';
9
+ // ─── Internal helpers ────────────────────────────────────────────────────────
10
+ /**
11
+ * Returns `true` when `current` satisfies `>= required`.
12
+ * Treats missing, empty, or unparseable versions as unsupported.
13
+ * @param current - The running Jahia version read from `Cypress.env`.
14
+ * @param required - Minimum version the test or suite needs.
15
+ */
16
+ var isSupported = function (current, required) {
17
+ if (!(current === null || current === void 0 ? void 0 : current.trim())) {
18
+ return false;
19
+ }
20
+ try {
21
+ return (0, compare_versions_1.compare)(String(current), required, '>=');
22
+ }
23
+ catch (_a) {
24
+ return false;
25
+ }
26
+ };
27
+ /**
28
+ * Validates `since(...)` arguments and throws a descriptive error on misuse.
29
+ * Detects the common mistake of swapping `requiredVersion` and `title`.
30
+ * @param version - Version string passed as the first argument.
31
+ * @param title - Title string passed as the second argument.
32
+ * @param scope - Label used in the error message (e.g. `"it.since"`).
33
+ */
34
+ var assertArgs = function (version, title, scope) {
35
+ if (!(0, compare_versions_1.validate)(version)) {
36
+ var hint = (0, compare_versions_1.validate)(title) ? ' (arguments appear swapped)' : '';
37
+ throw new Error("[".concat(scope, "] Invalid version: \"").concat(version, "\"").concat(hint, "."));
38
+ }
39
+ };
40
+ /**
41
+ * Builds a human-readable message explaining why a test or suite was skipped.
42
+ * @param scope - Label for the helper (e.g. `"it.since"` or `"describe.since"`).
43
+ * @param title - Original test or suite title.
44
+ * @param required - Minimum version the test or suite needs.
45
+ * @param current - The running Jahia version; `undefined` when not yet fetched.
46
+ */
47
+ var skipReason = function (scope, title, required, current) {
48
+ return current ?
49
+ "[".concat(scope, "] Skipping \"").concat(title, "\" \u2014 ").concat(exports.JAHIA_VERSION_ENV_VAR, "=\"").concat(current, "\" < required ").concat(required, ".") :
50
+ "[".concat(scope, "] Skipping \"").concat(title, "\" \u2014 ").concat(exports.JAHIA_VERSION_ENV_VAR, " is not set. Required: ").concat(required, ".");
51
+ };
52
+ // ─── Public API ───────────────────────────────────────────────────────────────
53
+ /**
54
+ * Fetches the Jahia version from the GraphQL API, strips the `-SNAPSHOT` suffix,
55
+ * and caches the result in `Cypress.env(JAHIA_VERSION_ENV_VAR)`.
56
+ */
57
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
+ var initializeVersionSupport = function () {
59
+ return (0, JahiaPlatformHelper_1.getJahiaVersion)().then(function (jahiaVersion) {
60
+ var version = jahiaVersion.release.replace('-SNAPSHOT', '');
61
+ Cypress.env(exports.JAHIA_VERSION_ENV_VAR, version);
62
+ return version;
63
+ });
64
+ };
65
+ exports.initializeVersionSupport = initializeVersionSupport;
66
+ /**
67
+ * Attaches `.since()` to `it`, `it.only`, `it.skip`, `describe`, `describe.only`,
68
+ * and `describe.skip`. Safe to call multiple times — subsequent calls are no-ops.
69
+ */
70
+ var registerVersionSupport = function () {
71
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
+ var mochaIt = globalThis.it;
73
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
74
+ var mochaDescribe = globalThis.describe;
75
+ if (!mochaIt) {
76
+ throw new Error('Unable to register version support because Mocha `it` is not available.');
77
+ }
78
+ if (!mochaDescribe) {
79
+ throw new Error('Unable to register version support because Mocha `describe` is not available.');
80
+ }
81
+ var _loop_1 = function (target) {
82
+ if (typeof target.since === 'function') {
83
+ return "continue";
84
+ }
85
+ var isSkip = target === mochaIt.skip;
86
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
87
+ target.since = function (version, title, configOrFn, maybeFn) {
88
+ assertArgs(version, title, 'it.since');
89
+ if (isSkip) {
90
+ // It.skip.since: always skip unconditionally, preserve the title
91
+ return typeof configOrFn === 'function' || configOrFn === undefined ?
92
+ target(title, configOrFn) :
93
+ target(title, configOrFn, maybeFn);
94
+ }
95
+ var userFn = typeof configOrFn === 'function' ? configOrFn : maybeFn;
96
+ var wrappedFn = function () {
97
+ var current = Cypress.env(exports.JAHIA_VERSION_ENV_VAR);
98
+ if (!isSupported(current, version)) {
99
+ console.warn(skipReason('it.since', title, version, current));
100
+ this.skip();
101
+ }
102
+ else if (typeof userFn === 'function') {
103
+ return userFn.call(this);
104
+ }
105
+ };
106
+ return typeof configOrFn === 'object' && configOrFn !== null ?
107
+ target(title, configOrFn, wrappedFn) :
108
+ target(title, wrappedFn);
109
+ };
110
+ };
111
+ // Attach .since() to it / it.only / it.skip
112
+ for (var _i = 0, _a = [mochaIt, mochaIt.only, mochaIt.skip]; _i < _a.length; _i++) {
113
+ var target = _a[_i];
114
+ _loop_1(target);
115
+ }
116
+ var _loop_2 = function (target) {
117
+ if (typeof target.since === 'function') {
118
+ return "continue";
119
+ }
120
+ var isSkip = target === mochaDescribe.skip;
121
+ target.since = function (version, title, fn) {
122
+ assertArgs(version, title, 'describe.since');
123
+ if (isSkip) {
124
+ // Describe.skip.since: always skip unconditionally, preserve the title
125
+ return target(title, fn);
126
+ }
127
+ return target(title, function () {
128
+ // Suite-level runtime check runs after the global before() has fetched the version
129
+ before(function () {
130
+ var current = Cypress.env(exports.JAHIA_VERSION_ENV_VAR);
131
+ if (!isSupported(current, version)) {
132
+ console.warn(skipReason('describe.since', title, version, current));
133
+ this.skip();
134
+ }
135
+ });
136
+ fn.call(this);
137
+ });
138
+ };
139
+ };
140
+ // Attach .since() to describe / describe.only / describe.skip
141
+ for (var _b = 0, _c = [mochaDescribe, mochaDescribe.only, mochaDescribe.skip]; _b < _c.length; _b++) {
142
+ var target = _c[_b];
143
+ _loop_2(target);
144
+ }
145
+ // Compatibility shim: redirect accidental it.skip(version, title, fn) → it.skip.since(...)
146
+ var origItSkip = mochaIt.skip;
147
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
148
+ mochaIt.skip = Object.assign(function (title, configOrTitle, maybeFn) {
149
+ if ((0, compare_versions_1.validate)(title) && typeof configOrTitle === 'string' && typeof maybeFn === 'function') {
150
+ return origItSkip.since(title, configOrTitle, maybeFn);
151
+ }
152
+ return typeof configOrTitle === 'function' || configOrTitle === undefined ?
153
+ origItSkip(title, configOrTitle) :
154
+ origItSkip(title, configOrTitle, maybeFn);
155
+ }, { since: origItSkip.since });
156
+ var origDescribeSkip = mochaDescribe.skip;
157
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
158
+ mochaDescribe.skip = Object.assign(function (title, fnOrTitle, maybeFn) {
159
+ if ((0, compare_versions_1.validate)(title) && typeof fnOrTitle === 'string' && typeof maybeFn === 'function') {
160
+ return origDescribeSkip.since(title, fnOrTitle, maybeFn);
161
+ }
162
+ return origDescribeSkip(title, fnOrTitle);
163
+ }, { since: origDescribeSkip.since });
164
+ };
165
+ exports.registerVersionSupport = registerVersionSupport;
166
+ /**
167
+ * Enables version-gated testing for the Cypress suite.
168
+ * Registers `it.since`, `describe.since` (and their `.only`/`.skip` variants),
169
+ * then fetches the running Jahia version in a root `before()` hook.
170
+ *
171
+ * @example
172
+ * it.since('8.2.0', 'works on 8.2+', () => { ... });
173
+ * describe.since('8.2.0', 'suite for 8.2+', () => { ... });
174
+ */
175
+ function enable() {
176
+ (0, exports.registerVersionSupport)();
177
+ before(function () { return (0, exports.initializeVersionSupport)(); });
178
+ }
179
+ /** Public API for Jahia version-gated testing. */
180
+ exports.modSince = { enable: enable };
@@ -10,6 +10,36 @@ var serverDefaults = {
10
10
  };
11
11
  var executeGroovy = function (scriptFile, replacements, jahiaServer) {
12
12
  if (jahiaServer === void 0) { jahiaServer = serverDefaults; }
13
+ var result;
14
+ var duration;
15
+ var scriptContent;
16
+ var startTime = Date.now();
17
+ var replacementsLabel = replacements && Object.keys(replacements).length > 0 ?
18
+ " \u2014 ".concat(JSON.stringify(replacements)) :
19
+ '';
20
+ var logger = Cypress.log({
21
+ autoEnd: false,
22
+ name: 'executeGroovy',
23
+ displayName: 'groovy',
24
+ message: "".concat(scriptFile).concat(replacementsLabel),
25
+ consoleProps: function () { return ({
26
+ Script: scriptFile,
27
+ 'Script Content': scriptContent !== null && scriptContent !== void 0 ? scriptContent : '(loading...)',
28
+ Replacements: replacements !== null && replacements !== void 0 ? replacements : {},
29
+ Server: jahiaServer.url,
30
+ Duration: duration === undefined ? 'pending' : "".concat(duration, "ms"),
31
+ Result: result
32
+ }); }
33
+ });
34
+ cy.fixture(scriptFile, 'utf-8').then(function (content) {
35
+ var processed = content;
36
+ if (replacements) {
37
+ Object.keys(replacements).forEach(function (k) {
38
+ processed = processed.replaceAll(k, replacements[k]);
39
+ });
40
+ }
41
+ scriptContent = processed;
42
+ });
13
43
  cy.runProvisioningScript({
14
44
  script: {
15
45
  fileContent: '- executeScript: "' + scriptFile + '"',
@@ -21,7 +51,16 @@ var executeGroovy = function (scriptFile, replacements, jahiaServer) {
21
51
  type: 'text/plain',
22
52
  encoding: 'utf-8'
23
53
  }],
24
- jahiaServer: jahiaServer
25
- }).then(function (r) { return r[0]; });
54
+ jahiaServer: jahiaServer,
55
+ options: { log: false }
56
+ }).then(function (r) {
57
+ result = r === null || r === void 0 ? void 0 : r[0];
58
+ duration = Date.now() - startTime;
59
+ var hasFailed = typeof result === 'string' && result.includes('.failed');
60
+ var prefix = hasFailed ? '❌ ' : '✅ ';
61
+ logger.set('message', "".concat(prefix).concat(scriptFile).concat(replacementsLabel));
62
+ logger === null || logger === void 0 ? void 0 : logger.end();
63
+ return result;
64
+ });
26
65
  };
27
66
  exports.executeGroovy = executeGroovy;
@@ -29,4 +29,4 @@ export type JahiaServer = {
29
29
  username: string;
30
30
  password: string;
31
31
  };
32
- export declare const runProvisioningScript: ({ script, files, jahiaServer, options, requestOptions }: RunProvisioningScriptParams) => void;
32
+ export declare const runProvisioningScript: (paramsOrScript: RunProvisioningScriptParams | FormFile | StringDictionary[], ...rest: any[]) => void;
@@ -52,10 +52,71 @@ var serverDefaults = {
52
52
  password: Cypress.env('SUPER_USER_PASSWORD')
53
53
  };
54
54
  function isFormFile(script) {
55
- return Boolean(script.fileContent || script.fileName);
55
+ return Boolean((script === null || script === void 0 ? void 0 : script.fileContent) || (script === null || script === void 0 ? void 0 : script.fileName));
56
56
  }
57
- var runProvisioningScript = function (_a) {
58
- var script = _a.script, files = _a.files, _b = _a.jahiaServer, jahiaServer = _b === void 0 ? serverDefaults : _b, _c = _a.options, options = _c === void 0 ? { log: true } : _c, _d = _a.requestOptions, requestOptions = _d === void 0 ? {} : _d;
57
+ function getScriptSummary(script) {
58
+ if (isFormFile(script)) {
59
+ if (script.fileName) {
60
+ return script.fileName;
61
+ }
62
+ if (script.fileContent) {
63
+ // Parse first operation and its value from YAML list: "- operationName: value"
64
+ var yamlMatch = script.fileContent.match(/^\s*-\s+(\w+)\s*:\s*"?([^"\n]+)"?/m);
65
+ if (yamlMatch) {
66
+ return "".concat(yamlMatch[1], ": ").concat(yamlMatch[2].trim());
67
+ }
68
+ // Parse first operation name from JSON array: [{"operationName": ...}]
69
+ try {
70
+ var parsed = JSON.parse(script.fileContent);
71
+ if (Array.isArray(parsed) && parsed.length > 0) {
72
+ var ops_1 = parsed.map(function (op) { var _a; return (_a = Object.keys(op)[0]) !== null && _a !== void 0 ? _a : 'unknown'; });
73
+ return ops_1.length === 1 ? ops_1[0] : "[".concat(ops_1.join(', '), "]");
74
+ }
75
+ }
76
+ catch (_a) {
77
+ // Not valid JSON, fall through
78
+ }
79
+ }
80
+ return 'inline script';
81
+ }
82
+ if (!script || script.length === 0) {
83
+ return 'empty script';
84
+ }
85
+ var ops = script.map(function (op) { var _a; return (_a = Object.keys(op)[0]) !== null && _a !== void 0 ? _a : 'unknown'; });
86
+ return ops.length === 1 ? ops[0] : "[".concat(ops.join(', '), "]");
87
+ }
88
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
89
+ var runProvisioningScript = function (paramsOrScript) {
90
+ var _a, _b, _c, _d, _e;
91
+ var rest = [];
92
+ for (var _i = 1; _i < arguments.length; _i++) {
93
+ rest[_i - 1] = arguments[_i];
94
+ }
95
+ // Backward-compatible: support old positional signature
96
+ // runProvisioningScript(script, files, jahiaServer, options, timeout)
97
+ var script;
98
+ var files;
99
+ var jahiaServer;
100
+ var options;
101
+ var requestOptions;
102
+ var isLegacyCall = Array.isArray(paramsOrScript) ||
103
+ paramsOrScript.fileContent !== undefined ||
104
+ paramsOrScript.fileName !== undefined;
105
+ if (isLegacyCall) {
106
+ script = paramsOrScript;
107
+ files = rest[0];
108
+ jahiaServer = (_a = rest[1]) !== null && _a !== void 0 ? _a : serverDefaults;
109
+ options = (_b = rest[2]) !== null && _b !== void 0 ? _b : { log: true };
110
+ requestOptions = {};
111
+ }
112
+ else {
113
+ var params = paramsOrScript;
114
+ script = params.script;
115
+ files = params.files;
116
+ jahiaServer = (_c = params.jahiaServer) !== null && _c !== void 0 ? _c : serverDefaults;
117
+ options = (_d = params.options) !== null && _d !== void 0 ? _d : { log: true };
118
+ requestOptions = (_e = params.requestOptions) !== null && _e !== void 0 ? _e : {};
119
+ }
59
120
  var formData = new FormData();
60
121
  if (isFormFile(script)) {
61
122
  append(script, formData, 'script');
@@ -76,18 +137,28 @@ var runProvisioningScript = function (_a) {
76
137
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
138
  var result;
78
139
  var logger;
140
+ var scriptSummary = getScriptSummary(script);
141
+ var replacementsFromFiles = files === null || files === void 0 ? void 0 : files.filter(function (f) { return f.replacements && Object.keys(f.replacements).length > 0; }).map(function (f) { return "".concat(f.fileName, ": ").concat(JSON.stringify(f.replacements)); });
79
142
  if (options.log) {
80
143
  logger = Cypress.log({
81
144
  autoEnd: false,
82
145
  name: 'runProvisioningScript',
83
146
  displayName: 'provScript',
84
- message: "Run ".concat(isFormFile(script) && script.fileName ? script.fileName : 'inline script', " towards server: ").concat(jahiaServer.url),
147
+ message: "".concat(scriptSummary, " @ ").concat(jahiaServer.url),
85
148
  consoleProps: function () {
149
+ var _a;
86
150
  return {
87
151
  Script: script,
88
- Files: files,
89
- Response: response,
90
- Yielded: result
152
+ Operations: isFormFile(script) ?
153
+ undefined :
154
+ script === null || script === void 0 ? void 0 : script.map(function (op) { return "".concat(Object.keys(op)[0], ": ").concat(Object.values(op)[0]); }),
155
+ Files: (_a = files === null || files === void 0 ? void 0 : files.map(function (f) { var _a; return (_a = f.fileName) !== null && _a !== void 0 ? _a : 'inline file'; })) !== null && _a !== void 0 ? _a : [],
156
+ Replacements: (replacementsFromFiles === null || replacementsFromFiles === void 0 ? void 0 : replacementsFromFiles.length) > 0 ? replacementsFromFiles : undefined,
157
+ Server: jahiaServer.url,
158
+ 'HTTP Status': response ? "".concat(response.status, " ").concat(response.statusText) : 'pending',
159
+ Duration: response ? "".concat(response.duration, "ms") : 'pending',
160
+ Result: result,
161
+ Response: response
91
162
  };
92
163
  }
93
164
  });
@@ -113,6 +184,12 @@ var runProvisioningScript = function (_a) {
113
184
  result = res;
114
185
  }
115
186
  logger === null || logger === void 0 ? void 0 : logger.end();
187
+ if (logger) {
188
+ var hasFailed = res.status !== 200 ||
189
+ (Array.isArray(result) && result.some(function (r) { return typeof r === 'string' && r.includes('.failed'); })); // eslint-disable-line @typescript-eslint/no-explicit-any
190
+ var prefix = hasFailed ? '❌ ' : '✅ ';
191
+ logger.set('message', "".concat(prefix).concat(scriptSummary, " @ ").concat(jahiaServer.url));
192
+ }
116
193
  return result;
117
194
  });
118
195
  };
@@ -1,4 +1,15 @@
1
1
  "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
2
13
  Object.defineProperty(exports, "__esModule", { value: true });
3
14
  exports.registerSupport = void 0;
4
15
  var apollo_1 = require("./apollo");
@@ -8,6 +19,8 @@ var logout_1 = require("./logout");
8
19
  var fixture_1 = require("./fixture");
9
20
  var repeatUntil_1 = require("./repeatUntil");
10
21
  var testStep_1 = require("./testStep");
22
+ var jfaker_1 = require("./jfaker");
23
+ var modSince_1 = require("./modSince");
11
24
  var registerSupport = function () {
12
25
  Cypress.Commands.add('apolloClient', apollo_1.apolloClient);
13
26
  Cypress.Commands.add('apollo', { prevSubject: 'optional' }, apollo_1.apollo);
@@ -22,5 +35,26 @@ var registerSupport = function () {
22
35
  Cypress.Commands.add('repeatUntil', repeatUntil_1.repeatUntil);
23
36
  Cypress.Commands.overwrite('fixture', fixture_1.fixture);
24
37
  Cypress.Commands.add('step', testStep_1.step);
38
+ // Register it.since()/describe.since()
39
+ modSince_1.modSince.enable();
40
+ /**
41
+ * Override Cypress `type()` command to interpret special characters (e.g., {, }, etc.) either literally or as commands.
42
+ * The behavior is controlled by the `parseSpecialCharSequences` option, which can be set to `true`
43
+ * to enable command parsing or `false` to treat special characters as literal input.
44
+ *
45
+ * Since Cypress `clear()` command is an alias for `.type('{selectall}{del}')`,
46
+ * such case has to be handled to ensure that the special character sequences are properly interpreted when clearing the input.
47
+ * Also cover older Cypress versions which were using {backspace} was used instead of {del} .
48
+ */
49
+ Cypress.Commands.overwrite('type', function (originalFn, element, text, options) {
50
+ if (options === void 0) { options = {}; }
51
+ // Check if this is Cypress `.clear() call
52
+ var isCypressClearSequence = ['{selectall}{del}', '{selectall}{backspace}'].includes(text.toString());
53
+ // Do not override if this is `.clear()` call or data type is `faker`
54
+ var parseSpecialCharSequences = isCypressClearSequence || jfaker_1.jfaker.getDataType() === 'faker';
55
+ // Merge options with passed ones (if any)
56
+ var newOptions = __assign({ parseSpecialCharSequences: parseSpecialCharSequences }, options);
57
+ return originalFn(element, text, newOptions);
58
+ });
25
59
  };
26
60
  exports.registerSupport = registerSupport;
@@ -0,0 +1,158 @@
1
+ # Browser Helpers
2
+
3
+ ## Overview
4
+
5
+ The Browser Helpers module provides exported helper functions for debugging and managing browser storage (`cookies`, `localStorage`, `sessionStorage`) in Cypress tests.
6
+
7
+ Warning: These helpers log full storage/cookie values by design. Use carefully in automated runs to avoid leaking tokens, credentials, or session identifiers in logs.
8
+
9
+ ## Import and Usage Model
10
+
11
+ ```typescript
12
+ import {BrowserHelper} from '@jahia/cypress';
13
+
14
+ it('inspects browser state', () => {
15
+ cy.login();
16
+ BrowserHelper.logCookies();
17
+ BrowserHelper.logLocalStorage();
18
+ });
19
+ ```
20
+
21
+ ## Available Helpers
22
+
23
+ ### `BrowserHelper.logCookies()`
24
+
25
+ Logs all available cookies with metadata and values.
26
+
27
+ - Returns: `Cypress.Chainable<void>`
28
+ - Typical use: inspect authentication and security cookie attributes during debugging
29
+
30
+ ### `BrowserHelper.logCookie(cookieName)`
31
+
32
+ Logs one cookie by name in a detailed format.
33
+
34
+ - Parameters: `cookieName: string`
35
+ - Returns: `Cypress.Chainable<void>`
36
+
37
+ ### `BrowserHelper.clearSessionCookies()`
38
+
39
+ Clears only session cookies.
40
+
41
+ - Returns: `Cypress.Chainable<void>`
42
+
43
+ ### `BrowserHelper.clearPersistentCookies()`
44
+
45
+ Clears only persistent cookies.
46
+
47
+ - Returns: `Cypress.Chainable<void>`
48
+
49
+ ### `BrowserHelper.simulateClose()`
50
+
51
+ Simulates a browser close by clearing `sessionStorage` and session cookies only.
52
+
53
+ - Returns: `void`
54
+ - Clears: session cookies + all `sessionStorage`
55
+ - Keeps: persistent cookies + `localStorage`
56
+
57
+ ### `BrowserHelper.resetState()`
58
+
59
+ Resets browser client-side state by clearing all cookies and all storages.
60
+
61
+ - Returns: `void`
62
+ - Clears: all cookies + all `localStorage` + all `sessionStorage`
63
+
64
+ ### `BrowserHelper.logSessionStorage()`
65
+
66
+ Logs all `sessionStorage` entries grouped by origin.
67
+
68
+ - Returns: `Cypress.Chainable<void>`
69
+
70
+ ### `BrowserHelper.logLocalStorage()`
71
+
72
+ Logs all `localStorage` entries grouped by origin.
73
+
74
+ - Returns: `Cypress.Chainable<void>`
75
+
76
+ ## Integration Examples
77
+
78
+ ### Authentication Debugging
79
+
80
+ ```typescript
81
+ import {BrowserHelper} from '@jahia/cypress';
82
+
83
+ describe('Authentication Flow', () => {
84
+ it('keeps session after reload', () => {
85
+ cy.step('Login', () => {
86
+ cy.login('testuser@example.com', 'password');
87
+ BrowserHelper.logCookie('JSESSIONID');
88
+ cy.get('[data-testid="dashboard"]').should('be.visible');
89
+ });
90
+
91
+ cy.step('Reload page', () => {
92
+ cy.reload();
93
+ BrowserHelper.logCookie('JSESSIONID');
94
+ cy.get('[data-testid="dashboard"]').should('be.visible');
95
+ });
96
+ });
97
+ });
98
+ ```
99
+
100
+ ### Simulate Browser Close
101
+
102
+ ```typescript
103
+ import {BrowserHelper} from '@jahia/cypress';
104
+
105
+ it('validates behavior after browser close', () => {
106
+ cy.login();
107
+ BrowserHelper.logCookies();
108
+
109
+ // Simulate browser close (clears session cookies and session storage)
110
+ BrowserHelper.simulateClose();
111
+
112
+ // Visit the app again to see the effect of reset
113
+ cy.visit(url);
114
+
115
+ BrowserHelper.logCookies();
116
+ BrowserHelper.logSessionStorage();
117
+ });
118
+ ```
119
+
120
+ ### Simulate Browser Reset (clear all cookies and storages)
121
+
122
+ ```typescript
123
+ import {BrowserHelper} from '@jahia/cypress';
124
+
125
+ it('validates behavior after full browser reset', () => {
126
+ cy.login();
127
+ BrowserHelper.logCookies();
128
+
129
+ // Reset all browser state
130
+ BrowserHelper.resetState();
131
+
132
+ // Visit the app again to see the effect of reset
133
+ cy.visit(url);
134
+
135
+ BrowserHelper.logCookies();
136
+ BrowserHelper.logSessionStorage();
137
+ });
138
+ ```
139
+
140
+ ## Best Practices
141
+
142
+ 1. Use these helpers for interactive debugging, not as regular test assertions.
143
+ 2. Avoid running full storage/cookie logging in CI unless required.
144
+ 3. Prefer targeted checks (`logCookie`) over full dumps (`logCookies`) for sensitive environments.
145
+ 4. Use `resetState()` for hard test isolation, and `simulateClose()` for realistic session lifecycle checks.
146
+
147
+ ## API Reference
148
+
149
+ | Helper | Parameters | Returns | Description |
150
+ |--------|------------|---------|-------------|
151
+ | `BrowserHelper.logCookies()` | - | `Cypress.Chainable<void>` | Logs all cookies with full metadata |
152
+ | `BrowserHelper.logCookie(cookieName)` | `string` | `Cypress.Chainable<void>` | Logs one cookie by name |
153
+ | `BrowserHelper.clearSessionCookies()` | - | `Cypress.Chainable<void>` | Clears session cookies only |
154
+ | `BrowserHelper.clearPersistentCookies()` | - | `Cypress.Chainable<void>` | Clears persistent cookies only |
155
+ | `BrowserHelper.simulateClose()` | - | `void` | Clears session storage and session cookies |
156
+ | `BrowserHelper.resetState()` | - | `void` | Clears all storages and all cookies |
157
+ | `BrowserHelper.logSessionStorage()` | - | `Cypress.Chainable<void>` | Logs all session storage data |
158
+ | `BrowserHelper.logLocalStorage()` | - | `Cypress.Chainable<void>` | Logs all local storage data |