@jahia/cypress 3.17.6 → 3.17.8
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/dist/support/provisioning/index.d.ts +1 -0
- package/dist/support/provisioning/index.js +1 -0
- package/dist/support/provisioning/uninstallBundle.d.ts +9 -0
- package/dist/support/provisioning/uninstallBundle.js +12 -0
- package/dist/utils/GraphQLHelper.d.ts +1 -0
- package/dist/utils/GraphQLHelper.js +142 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/fixtures/graphql/introspection.graphql +53 -0
- package/package.json +1 -1
- package/src/support/provisioning/index.ts +1 -0
- package/src/support/provisioning/uninstallBundle.ts +20 -0
- package/src/utils/GraphQLHelper.ts +152 -0
- package/src/utils/index.ts +1 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
declare global {
|
|
3
|
+
namespace Cypress {
|
|
4
|
+
interface Chainable<Subject> {
|
|
5
|
+
uninstallBundle(bundleSymbolicName: string): Chainable<Cypress.Response<any>>;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export declare const uninstallBundle: (bundleSymbolicName: string) => void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-namespace */
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.uninstallBundle = void 0;
|
|
5
|
+
/// <reference types="cypress" />
|
|
6
|
+
var uninstallBundle = function (bundleSymbolicName) {
|
|
7
|
+
cy.runProvisioningScript({
|
|
8
|
+
fileContent: '- uninstallBundle: "' + bundleSymbolicName + '"\n',
|
|
9
|
+
type: 'application/yaml'
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
exports.uninstallBundle = uninstallBundle;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getDescriptions: (rootNode: string) => Cypress.Chainable;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint max-depth: ["error", 5] */
|
|
3
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
|
|
4
|
+
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
|
|
5
|
+
to[j] = from[i];
|
|
6
|
+
return to;
|
|
7
|
+
};
|
|
8
|
+
exports.__esModule = true;
|
|
9
|
+
exports.getDescriptions = void 0;
|
|
10
|
+
// This returns a flat list of all children fields and args for a given GraphQL node
|
|
11
|
+
// This list can then be used in Cypress tests to look for missing descriptions
|
|
12
|
+
var getDescriptions = function (rootNode) {
|
|
13
|
+
cy.log('Starting analysis from GraphQL node: ' + rootNode);
|
|
14
|
+
return execIntrospection(rootNode, [], []).then(function (descriptions) {
|
|
15
|
+
return descriptions;
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
exports.getDescriptions = getDescriptions;
|
|
19
|
+
var execIntrospection = function (typeName, descriptions, nodePath) {
|
|
20
|
+
return cy.apollo({
|
|
21
|
+
variables: {
|
|
22
|
+
typeName: typeName
|
|
23
|
+
},
|
|
24
|
+
queryFile: 'graphql/introspection.graphql'
|
|
25
|
+
}).then(function (response) {
|
|
26
|
+
var _a;
|
|
27
|
+
var responseDataType = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.__type;
|
|
28
|
+
if (responseDataType === null || responseDataType === undefined || responseDataType.kind === 'UNION') {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (responseDataType) {
|
|
32
|
+
// This array will be populated with types identified in the introspection query
|
|
33
|
+
// These will then be further introspected to get their children fields and args
|
|
34
|
+
var fetchSubTypes_1 = [];
|
|
35
|
+
descriptions.push({
|
|
36
|
+
name: responseDataType.name,
|
|
37
|
+
description: responseDataType.description,
|
|
38
|
+
schemaType: '__Type',
|
|
39
|
+
schemaNode: responseDataType,
|
|
40
|
+
nodePath: nodePath
|
|
41
|
+
});
|
|
42
|
+
// The following exploration of the object follows precisely the Graphql Introspection
|
|
43
|
+
// spec available at https://github.com/graphql/graphql-spec/blob/main/spec/Section%204%20--%20Introspection.md
|
|
44
|
+
if (responseDataType.fields) {
|
|
45
|
+
for (var _i = 0, _b = responseDataType.fields; _i < _b.length; _i++) {
|
|
46
|
+
var graphqlField = _b[_i];
|
|
47
|
+
var fieldPath = __spreadArray(__spreadArray([], nodePath), [responseDataType.name, graphqlField.name]);
|
|
48
|
+
descriptions.push({
|
|
49
|
+
name: graphqlField.name,
|
|
50
|
+
description: graphqlField.description,
|
|
51
|
+
schemaType: '__Field',
|
|
52
|
+
schemaNode: graphqlField,
|
|
53
|
+
nodePath: fieldPath
|
|
54
|
+
});
|
|
55
|
+
fetchSubTypes_1.push({ typeName: graphqlField.type.name, atPath: fieldPath });
|
|
56
|
+
if (graphqlField.args) {
|
|
57
|
+
for (var _c = 0, _d = graphqlField.args; _c < _d.length; _c++) {
|
|
58
|
+
var graphQLInputValue = _d[_c];
|
|
59
|
+
var inputValuePath = __spreadArray(__spreadArray([], fieldPath), [graphQLInputValue.name]);
|
|
60
|
+
descriptions.push({
|
|
61
|
+
name: graphQLInputValue.name,
|
|
62
|
+
description: graphQLInputValue.description,
|
|
63
|
+
schemaType: '__InputValue',
|
|
64
|
+
schemaNode: graphQLInputValue,
|
|
65
|
+
nodePath: inputValuePath
|
|
66
|
+
});
|
|
67
|
+
fetchSubTypes_1.push({ typeName: graphQLInputValue.type.name, atPath: inputValuePath });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (responseDataType.interfaces) {
|
|
73
|
+
for (var _e = 0, _f = responseDataType.interfaces; _e < _f.length; _e++) {
|
|
74
|
+
var graphQLInterfaceType = _f[_e];
|
|
75
|
+
var fieldPath = __spreadArray(__spreadArray([], nodePath), [responseDataType.name, graphQLInterfaceType.name]);
|
|
76
|
+
descriptions.push({
|
|
77
|
+
name: graphQLInterfaceType.name,
|
|
78
|
+
description: graphQLInterfaceType.description,
|
|
79
|
+
schemaType: '__Type',
|
|
80
|
+
schemaNode: graphQLInterfaceType,
|
|
81
|
+
nodePath: fieldPath
|
|
82
|
+
});
|
|
83
|
+
fetchSubTypes_1.push({ typeName: graphQLInterfaceType.name, atPath: fieldPath });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (responseDataType.possibleTypes) {
|
|
87
|
+
for (var _g = 0, _h = responseDataType.possibleTypes; _g < _h.length; _g++) {
|
|
88
|
+
var graphQLType = _h[_g];
|
|
89
|
+
var fieldPath = __spreadArray(__spreadArray([], nodePath), [responseDataType.name, graphQLType.name]);
|
|
90
|
+
descriptions.push({
|
|
91
|
+
name: graphQLType.name,
|
|
92
|
+
description: graphQLType.description,
|
|
93
|
+
schemaType: '__Type',
|
|
94
|
+
schemaNode: graphQLType,
|
|
95
|
+
nodePath: fieldPath
|
|
96
|
+
});
|
|
97
|
+
fetchSubTypes_1.push({ typeName: graphQLType.name, atPath: fieldPath });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (responseDataType.enumValues) {
|
|
101
|
+
for (var _j = 0, _k = responseDataType.enumValues; _j < _k.length; _j++) {
|
|
102
|
+
var graphQLEnumValue = _k[_j];
|
|
103
|
+
var enumPath = __spreadArray(__spreadArray([], nodePath), [responseDataType.name, graphQLEnumValue.name]);
|
|
104
|
+
descriptions.push({
|
|
105
|
+
name: graphQLEnumValue.name,
|
|
106
|
+
description: graphQLEnumValue.description,
|
|
107
|
+
schemaType: '__EnumValue',
|
|
108
|
+
schemaNode: graphQLEnumValue,
|
|
109
|
+
nodePath: enumPath
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (responseDataType.inputFields) {
|
|
114
|
+
for (var _l = 0, _m = responseDataType.inputFields; _l < _m.length; _l++) {
|
|
115
|
+
var graphQLInputValue = _m[_l];
|
|
116
|
+
var inputValuePath = __spreadArray(__spreadArray([], nodePath), [responseDataType.name, graphQLInputValue.name]);
|
|
117
|
+
descriptions.push({
|
|
118
|
+
name: graphQLInputValue.name,
|
|
119
|
+
description: graphQLInputValue.description,
|
|
120
|
+
schemaType: '__InputValue',
|
|
121
|
+
schemaNode: graphQLInputValue,
|
|
122
|
+
nodePath: inputValuePath
|
|
123
|
+
});
|
|
124
|
+
fetchSubTypes_1.push({ typeName: graphQLInputValue.type.name, atPath: inputValuePath });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (responseDataType.ofType) {
|
|
128
|
+
fetchSubTypes_1.push({ typeName: responseDataType.ofType.name, atPath: nodePath });
|
|
129
|
+
}
|
|
130
|
+
var uniqueSubTypes = fetchSubTypes_1
|
|
131
|
+
// Filter out duplicate types to ensure we don't introspect the same type multiple times
|
|
132
|
+
.filter(function (obj, index) { return fetchSubTypes_1.findIndex(function (item) { return item.typeName === obj.typeName; }) === index; })
|
|
133
|
+
// Filter out types that have a name of null (e.g. List of non-null types)
|
|
134
|
+
.filter(function (subtype) { return subtype.typeName !== null; })
|
|
135
|
+
// Remove types that might have already been introspected
|
|
136
|
+
.filter(function (subtype) { return descriptions.find(function (d) { return d.schemaType === '__Type' && d.name === subtype.typeName; }) === undefined; });
|
|
137
|
+
return Cypress.Promise.each(uniqueSubTypes, function (subType) {
|
|
138
|
+
return execIntrospection(subType.typeName, descriptions, __spreadArray(__spreadArray([], subType.atPath), [subType.typeName]));
|
|
139
|
+
}).then(function () { return descriptions; }); // Return descriptions after all recursive calls have completed
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
};
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -17,3 +17,4 @@ __exportStar(require("./UsersHelper"), exports);
|
|
|
17
17
|
__exportStar(require("./VanityUrlHelper"), exports);
|
|
18
18
|
__exportStar(require("./ClusterHelper"), exports);
|
|
19
19
|
__exportStar(require("./JahiaPlatformHelper"), exports);
|
|
20
|
+
__exportStar(require("./GraphQLHelper"), exports);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
query IntrospectionQuery($typeName: String!) {
|
|
2
|
+
__type(name: $typeName) {
|
|
3
|
+
kind
|
|
4
|
+
name
|
|
5
|
+
description
|
|
6
|
+
fields(includeDeprecated: true) {
|
|
7
|
+
name
|
|
8
|
+
description
|
|
9
|
+
deprecationReason
|
|
10
|
+
isDeprecated
|
|
11
|
+
args {
|
|
12
|
+
name
|
|
13
|
+
description
|
|
14
|
+
type {
|
|
15
|
+
kind
|
|
16
|
+
name
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
type {
|
|
20
|
+
kind
|
|
21
|
+
name
|
|
22
|
+
description
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
interfaces {
|
|
26
|
+
name
|
|
27
|
+
description
|
|
28
|
+
}
|
|
29
|
+
possibleTypes {
|
|
30
|
+
name
|
|
31
|
+
description
|
|
32
|
+
}
|
|
33
|
+
enumValues(includeDeprecated: true) {
|
|
34
|
+
name
|
|
35
|
+
description
|
|
36
|
+
deprecationReason
|
|
37
|
+
isDeprecated
|
|
38
|
+
}
|
|
39
|
+
inputFields {
|
|
40
|
+
name
|
|
41
|
+
description
|
|
42
|
+
type {
|
|
43
|
+
kind
|
|
44
|
+
name
|
|
45
|
+
description
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
ofType {
|
|
49
|
+
name
|
|
50
|
+
description
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-namespace */
|
|
2
|
+
|
|
3
|
+
// Load type definitions that come with Cypress module
|
|
4
|
+
/// <reference types="cypress" />
|
|
5
|
+
|
|
6
|
+
declare global {
|
|
7
|
+
namespace Cypress {
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9
|
+
interface Chainable<Subject> {
|
|
10
|
+
uninstallBundle(bundleSymbolicName: string): Chainable<Cypress.Response<any>>
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const uninstallBundle = function (bundleSymbolicName: string): void {
|
|
16
|
+
cy.runProvisioningScript({
|
|
17
|
+
fileContent: '- uninstallBundle: "' + bundleSymbolicName + '"\n',
|
|
18
|
+
type: 'application/yaml'
|
|
19
|
+
});
|
|
20
|
+
};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/* eslint max-depth: ["error", 5] */
|
|
2
|
+
|
|
3
|
+
interface GraphQLField {
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface GraphQLDescription {
|
|
8
|
+
name: string; // Name of the element in the schema
|
|
9
|
+
description: string; // Description of the element in the schema
|
|
10
|
+
schemaType: string; // Type of the element in the schema according to the GraphQL spec
|
|
11
|
+
schemaNode: GraphQLField; // The actual node fetched from the schema
|
|
12
|
+
nodePath: string[] // The path to the node in the schema
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// This returns a flat list of all children fields and args for a given GraphQL node
|
|
16
|
+
// This list can then be used in Cypress tests to look for missing descriptions
|
|
17
|
+
export const getDescriptions = (rootNode: string): Cypress.Chainable => {
|
|
18
|
+
cy.log('Starting analysis from GraphQL node: ' + rootNode);
|
|
19
|
+
return execIntrospection(rootNode, [], []).then(descriptions => {
|
|
20
|
+
return descriptions;
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const execIntrospection = (typeName: string, descriptions: GraphQLDescription[], nodePath): Cypress.Chainable => {
|
|
25
|
+
return cy.apollo({
|
|
26
|
+
variables: {
|
|
27
|
+
typeName: typeName
|
|
28
|
+
},
|
|
29
|
+
queryFile: 'graphql/introspection.graphql'
|
|
30
|
+
}).then(response => {
|
|
31
|
+
const responseDataType = response?.data?.__type;
|
|
32
|
+
if (responseDataType === null || responseDataType === undefined || responseDataType.kind === 'UNION') {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (responseDataType) {
|
|
37
|
+
// This array will be populated with types identified in the introspection query
|
|
38
|
+
// These will then be further introspected to get their children fields and args
|
|
39
|
+
const fetchSubTypes: {typeName: string, atPath: string[]}[] = [];
|
|
40
|
+
|
|
41
|
+
descriptions.push({
|
|
42
|
+
name: responseDataType.name,
|
|
43
|
+
description: responseDataType.description,
|
|
44
|
+
schemaType: '__Type',
|
|
45
|
+
schemaNode: responseDataType,
|
|
46
|
+
nodePath
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// The following exploration of the object follows precisely the Graphql Introspection
|
|
50
|
+
// spec available at https://github.com/graphql/graphql-spec/blob/main/spec/Section%204%20--%20Introspection.md
|
|
51
|
+
if (responseDataType.fields) {
|
|
52
|
+
for (const graphqlField of responseDataType.fields) {
|
|
53
|
+
const fieldPath = [...nodePath, responseDataType.name, graphqlField.name];
|
|
54
|
+
descriptions.push({
|
|
55
|
+
name: graphqlField.name,
|
|
56
|
+
description: graphqlField.description,
|
|
57
|
+
schemaType: '__Field',
|
|
58
|
+
schemaNode: graphqlField,
|
|
59
|
+
nodePath: fieldPath
|
|
60
|
+
});
|
|
61
|
+
fetchSubTypes.push({typeName: graphqlField.type.name, atPath: fieldPath});
|
|
62
|
+
|
|
63
|
+
if (graphqlField.args) {
|
|
64
|
+
for (const graphQLInputValue of graphqlField.args) {
|
|
65
|
+
const inputValuePath = [...fieldPath, graphQLInputValue.name];
|
|
66
|
+
descriptions.push({
|
|
67
|
+
name: graphQLInputValue.name,
|
|
68
|
+
description: graphQLInputValue.description,
|
|
69
|
+
schemaType: '__InputValue',
|
|
70
|
+
schemaNode: graphQLInputValue,
|
|
71
|
+
nodePath: inputValuePath
|
|
72
|
+
});
|
|
73
|
+
fetchSubTypes.push({typeName: graphQLInputValue.type.name, atPath: inputValuePath});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (responseDataType.interfaces) {
|
|
80
|
+
for (const graphQLInterfaceType of responseDataType.interfaces) {
|
|
81
|
+
const fieldPath = [...nodePath, responseDataType.name, graphQLInterfaceType.name];
|
|
82
|
+
descriptions.push({
|
|
83
|
+
name: graphQLInterfaceType.name,
|
|
84
|
+
description: graphQLInterfaceType.description,
|
|
85
|
+
schemaType: '__Type',
|
|
86
|
+
schemaNode: graphQLInterfaceType,
|
|
87
|
+
nodePath: fieldPath
|
|
88
|
+
});
|
|
89
|
+
fetchSubTypes.push({typeName: graphQLInterfaceType.name, atPath: fieldPath});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (responseDataType.possibleTypes) {
|
|
94
|
+
for (const graphQLType of responseDataType.possibleTypes) {
|
|
95
|
+
const fieldPath = [...nodePath, responseDataType.name, graphQLType.name];
|
|
96
|
+
descriptions.push({
|
|
97
|
+
name: graphQLType.name,
|
|
98
|
+
description: graphQLType.description,
|
|
99
|
+
schemaType: '__Type',
|
|
100
|
+
schemaNode: graphQLType,
|
|
101
|
+
nodePath: fieldPath
|
|
102
|
+
});
|
|
103
|
+
fetchSubTypes.push({typeName: graphQLType.name, atPath: fieldPath});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (responseDataType.enumValues) {
|
|
108
|
+
for (const graphQLEnumValue of responseDataType.enumValues) {
|
|
109
|
+
const enumPath = [...nodePath, responseDataType.name, graphQLEnumValue.name];
|
|
110
|
+
descriptions.push({
|
|
111
|
+
name: graphQLEnumValue.name,
|
|
112
|
+
description: graphQLEnumValue.description,
|
|
113
|
+
schemaType: '__EnumValue',
|
|
114
|
+
schemaNode: graphQLEnumValue,
|
|
115
|
+
nodePath: enumPath
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (responseDataType.inputFields) {
|
|
121
|
+
for (const graphQLInputValue of responseDataType.inputFields) {
|
|
122
|
+
const inputValuePath = [...nodePath, responseDataType.name, graphQLInputValue.name];
|
|
123
|
+
descriptions.push({
|
|
124
|
+
name: graphQLInputValue.name,
|
|
125
|
+
description: graphQLInputValue.description,
|
|
126
|
+
schemaType: '__InputValue',
|
|
127
|
+
schemaNode: graphQLInputValue,
|
|
128
|
+
nodePath: inputValuePath
|
|
129
|
+
});
|
|
130
|
+
fetchSubTypes.push({typeName: graphQLInputValue.type.name, atPath: inputValuePath});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (responseDataType.ofType) {
|
|
135
|
+
fetchSubTypes.push({typeName: responseDataType.ofType.name, atPath: nodePath});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const uniqueSubTypes = fetchSubTypes
|
|
139
|
+
// Filter out duplicate types to ensure we don't introspect the same type multiple times
|
|
140
|
+
.filter((obj, index) => fetchSubTypes.findIndex(item => item.typeName === obj.typeName) === index)
|
|
141
|
+
// Filter out types that have a name of null (e.g. List of non-null types)
|
|
142
|
+
.filter(subtype => subtype.typeName !== null)
|
|
143
|
+
// Remove types that might have already been introspected
|
|
144
|
+
.filter(subtype => descriptions.find(d => d.schemaType === '__Type' && d.name === subtype.typeName) === undefined);
|
|
145
|
+
|
|
146
|
+
return Cypress.Promise.each(uniqueSubTypes, subType => {
|
|
147
|
+
return execIntrospection(subType.typeName, descriptions, [...subType.atPath, subType.typeName]);
|
|
148
|
+
}).then(() => descriptions); // Return descriptions after all recursive calls have completed
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
|
package/src/utils/index.ts
CHANGED