dceky 1.0.23 → 1.0.25
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/lib/src/commands/getCredentialValue.d.ts +18 -0
- package/lib/{commands/assertHasClass.js → src/commands/getCredentialValue.js} +8 -6
- package/lib/src/commands/getCredentialValue.js.map +1 -0
- package/lib/src/commands/getCredentialValues.d.ts +18 -0
- package/lib/{commands/getTitle.js → src/commands/getCredentialValues.js} +5 -9
- package/lib/src/commands/getCredentialValues.js.map +1 -0
- package/lib/src/commands/getProfileValue.d.ts +15 -0
- package/lib/{commands/getId.js → src/commands/getProfileValue.js} +5 -10
- package/lib/src/commands/getProfileValue.js.map +1 -0
- package/lib/src/commands/handleHarvardKey.js +36 -33
- package/lib/src/commands/handleHarvardKey.js.map +1 -1
- package/lib/src/commands/index.js +6 -0
- package/lib/src/commands/index.js.map +1 -1
- package/lib/src/commands/launchAs.js +70 -68
- package/lib/src/commands/launchAs.js.map +1 -1
- package/lib/src/commands/logIntoPorta.js +46 -43
- package/lib/src/commands/logIntoPorta.js.map +1 -1
- package/lib/src/genConfiguration/index.js +7 -4
- package/lib/src/genConfiguration/index.js.map +1 -1
- package/package.json +2 -2
- package/src/commands/getCredentialValue.ts +45 -0
- package/src/commands/getCredentialValues.ts +43 -0
- package/src/commands/getProfileValue.ts +40 -0
- package/src/commands/handleHarvardKey.ts +41 -38
- package/src/commands/index.ts +6 -0
- package/src/commands/launchAs.ts +90 -88
- package/src/commands/logIntoPorta.ts +61 -57
- package/src/genConfiguration/index.ts +11 -4
- package/cypress/e2e/profile-test.cy.ts +0 -10
- package/cypress/fixtures/example.json +0 -5
- package/cypress/support/commands.ts +0 -37
- package/cypress/support/e2e.ts +0 -17
- package/lib/commands/assertDoesNotHaveClass.d.ts +0 -18
- package/lib/commands/assertDoesNotHaveClass.js +0 -17
- package/lib/commands/assertDoesNotHaveClass.js.map +0 -1
- package/lib/commands/assertHasClass.d.ts +0 -18
- package/lib/commands/assertHasClass.js.map +0 -1
- package/lib/commands/assertNumElements.d.ts +0 -18
- package/lib/commands/assertNumElements.js +0 -17
- package/lib/commands/assertNumElements.js.map +0 -1
- package/lib/commands/clickWithRetry.d.ts +0 -19
- package/lib/commands/clickWithRetry.js +0 -29
- package/lib/commands/clickWithRetry.js.map +0 -1
- package/lib/commands/genTextOfLength.d.ts +0 -20
- package/lib/commands/genTextOfLength.js +0 -20
- package/lib/commands/genTextOfLength.js.map +0 -1
- package/lib/commands/getAttribute.d.ts +0 -20
- package/lib/commands/getAttribute.js +0 -22
- package/lib/commands/getAttribute.js.map +0 -1
- package/lib/commands/getClassName.d.ts +0 -15
- package/lib/commands/getClassName.js +0 -21
- package/lib/commands/getClassName.js.map +0 -1
- package/lib/commands/getCurrentDateInfo.d.ts +0 -21
- package/lib/commands/getCurrentDateInfo.js +0 -25
- package/lib/commands/getCurrentDateInfo.js.map +0 -1
- package/lib/commands/getId.d.ts +0 -15
- package/lib/commands/getId.js.map +0 -1
- package/lib/commands/getNumElements.d.ts +0 -14
- package/lib/commands/getNumElements.js +0 -19
- package/lib/commands/getNumElements.js.map +0 -1
- package/lib/commands/getSpecialChars.d.ts +0 -14
- package/lib/commands/getSpecialChars.js +0 -16
- package/lib/commands/getSpecialChars.js.map +0 -1
- package/lib/commands/getTitle.d.ts +0 -13
- package/lib/commands/getTitle.js.map +0 -1
- package/lib/commands/handleHarvardKey.d.ts +0 -18
- package/lib/commands/handleHarvardKey.js +0 -56
- package/lib/commands/handleHarvardKey.js.map +0 -1
- package/lib/commands/handleHarvardKey2.d.ts +0 -14
- package/lib/commands/handleHarvardKey2.js +0 -88
- package/lib/commands/handleHarvardKey2.js.map +0 -1
- package/lib/commands/launchAs.d.ts +0 -20
- package/lib/commands/launchAs.js +0 -60
- package/lib/commands/launchAs.js.map +0 -1
- package/lib/commands/launchLTIUsingToken.d.ts +0 -19
- package/lib/commands/launchLTIUsingToken.js +0 -74
- package/lib/commands/launchLTIUsingToken.js.map +0 -1
- package/lib/commands/listSelectLabels.d.ts +0 -15
- package/lib/commands/listSelectLabels.js +0 -24
- package/lib/commands/listSelectLabels.js.map +0 -1
- package/lib/commands/listSelectValues.d.ts +0 -15
- package/lib/commands/listSelectValues.js +0 -26
- package/lib/commands/listSelectValues.js.map +0 -1
- package/lib/commands/navigateToHref.d.ts +0 -19
- package/lib/commands/navigateToHref.js +0 -23
- package/lib/commands/navigateToHref.js.map +0 -1
- package/lib/commands/padWithZeros.d.ts +0 -20
- package/lib/commands/padWithZeros.js +0 -24
- package/lib/commands/padWithZeros.js.map +0 -1
- package/lib/commands/runScript.d.ts +0 -16
- package/lib/commands/runScript.js +0 -25
- package/lib/commands/runScript.js.map +0 -1
- package/lib/commands/typeInto.d.ts +0 -20
- package/lib/commands/typeInto.js +0 -28
- package/lib/commands/typeInto.js.map +0 -1
- package/lib/commands/uniquify.d.ts +0 -15
- package/lib/commands/uniquify.js +0 -25
- package/lib/commands/uniquify.js.map +0 -1
- package/lib/commands/visitCanvasEndpoint.d.ts +0 -27
- package/lib/commands/visitCanvasEndpoint.js +0 -35
- package/lib/commands/visitCanvasEndpoint.js.map +0 -1
- package/lib/commands/visitCanvasGETEndpoint.d.ts +0 -20
- package/lib/commands/visitCanvasGETEndpoint.js +0 -26
- package/lib/commands/visitCanvasGETEndpoint.js.map +0 -1
- package/lib/commands/waitForAtLeastOneElementPresent.d.ts +0 -23
- package/lib/commands/waitForAtLeastOneElementPresent.js +0 -27
- package/lib/commands/waitForAtLeastOneElementPresent.js.map +0 -1
- package/lib/commands/waitForElementVisible.d.ts +0 -14
- package/lib/commands/waitForElementVisible.js +0 -20
- package/lib/commands/waitForElementVisible.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/init.d.ts +0 -6
- package/lib/init.js +0 -69
- package/lib/init.js.map +0 -1
- package/lib/postinstall/helpers/exec.d.ts +0 -8
- package/lib/postinstall/helpers/exec.js +0 -18
- package/lib/postinstall/helpers/exec.js.map +0 -1
- package/lib/setup/checkRequiredFiles.d.ts +0 -6
- package/lib/setup/checkRequiredFiles.js +0 -60
- package/lib/setup/checkRequiredFiles.js.map +0 -1
- package/lib/setup/genEmptyGlobalFile.d.ts +0 -7
- package/lib/setup/genEmptyGlobalFile.js +0 -41
- package/lib/setup/genEmptyGlobalFile.js.map +0 -1
- package/lib/src/commands/launchLTIUsingToken.d.ts +0 -21
- package/lib/src/commands/launchLTIUsingToken.js +0 -76
- package/lib/src/commands/launchLTIUsingToken.js.map +0 -1
- package/lib/src/commands/visitCanvasGETEndpoint.d.ts +0 -20
- package/lib/src/commands/visitCanvasGETEndpoint.js +0 -26
- package/lib/src/commands/visitCanvasGETEndpoint.js.map +0 -1
- package/lib/src/init.d.ts +0 -6
- package/lib/src/init.js +0 -71
- package/lib/src/init.js.map +0 -1
- package/lib/src/node.d.ts +0 -2
- package/lib/src/node.js +0 -10
- package/lib/src/node.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/genConfiguration/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+BAA+B;AAC/B,mCAAmC;AACnC,8CAA8C;AAC9C,8CAAwB;AAExB,iBAAiB;AACjB,mCAAuC;AAEvC,4BAA4B;AAC5B,wDAAkC;AAElC,iBAAiB;AACjB,gEAA0C;AAC1C,kFAA4D;AAC5D,sEAAgD;AAMhD,8BAA8B;AAC9B,IAAM,GAAG,GAAG,IAAA,qBAAW,GAAE,CAAC;AAE1B;;;;;GAKG;AACH,IAAM,gBAAgB,GAAG;;IACvB,eAAe;IACf,IAAM,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;IACxD,IAAM,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;IAE1D,gCAAgC;IAChC,IAAM,iBAAiB,GAAqB,OAAO,CAAC,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC;IAC3G,IAAM,eAAe,GAAqB,OAAO,CAAC,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC;IACvG,IAAM,YAAY,GAAqB,OAAO,CAAC,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC;IAEjG,iDAAiD;IACjD,IAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC;IAC3D,IAAM,kBAAkB,GAAG,SAAS,CAAC;IAErC,uCAAuC;IACvC,IAAI,cAAc,GAAqB,EAAE,CAAC;IAC1C,IAAI,CAAC;QACH,8DAA8D;QAC9D,IAAM,GAAG,GAAG,OAAO,CAAC,cAAI,CAAC,IAAI,CAAC,aAAa,EAAE,WAAI,WAAW,aAAU,CAAC,CAAC,CAAC;QACzE,cAAc,GAAG,CAAC,MAAA,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,mCAAI,GAAG,mCAAI,EAAE,CAAqB,CAAC;IACnE,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,mDAA4C,WAAW,cAAW,EAAE,CAAC,CAAC,CAAC;QACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,qCAAqC;IACrC,IAAI,qBAAqB,GAAqB,EAAE,CAAC;IACjD,IAAI,CAAC;QACH,8DAA8D;QAC9D,IAAM,GAAG,GAAG,OAAO,CAAC,cAAI,CAAC,IAAI,CAAC,aAAa,EAAE,WAAI,kBAAkB,aAAU,CAAC,CAAC,CAAC;QAChF,qBAAqB,GAAG,CAAC,MAAA,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,mCAAI,GAAG,mCAAI,EAAE,CAAqB,CAAC;IAC1E,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,mDAA4C,kBAAkB,cAAW,EAAE,CAAC,CAAC,CAAC;QAC3F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,gDAAgD;IAChD,IAAM,OAAO,GAAuB;QAClC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/genConfiguration/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dceky",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.25",
|
|
4
4
|
"description": "Cypress toolkit for Harvard DCE",
|
|
5
5
|
"main": "./lib/src/index.js",
|
|
6
6
|
"types": "./lib/src/index.d.ts",
|
|
@@ -52,6 +52,6 @@
|
|
|
52
52
|
"typescript": "^5.9.3"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"cypress": "^
|
|
55
|
+
"cypress": "^15.11.0"
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
/*----------------------------------------*/
|
|
4
|
+
/* ---------------- Type ---------------- */
|
|
5
|
+
/*----------------------------------------*/
|
|
6
|
+
|
|
7
|
+
declare global {
|
|
8
|
+
namespace Cypress {
|
|
9
|
+
interface Chainable {
|
|
10
|
+
/**
|
|
11
|
+
* Alias for cy.env for retrieving a single environment variable
|
|
12
|
+
* Obtains a credential value from the Cypress env depending on
|
|
13
|
+
* the provided key.
|
|
14
|
+
* @author Allison Zhang
|
|
15
|
+
* @param key the key of the environment variable to retrieve
|
|
16
|
+
* @return The value of the specified environment variable
|
|
17
|
+
* the corresponding environment variable values from global credentials
|
|
18
|
+
*/
|
|
19
|
+
getCredentialValue(
|
|
20
|
+
key: string,
|
|
21
|
+
): Chainable<any>;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/*----------------------------------------*/
|
|
27
|
+
/* --------------- Command -------------- */
|
|
28
|
+
/*----------------------------------------*/
|
|
29
|
+
|
|
30
|
+
const getCredentialValue = () => {
|
|
31
|
+
Cypress.Commands.add(
|
|
32
|
+
'getCredentialValue',
|
|
33
|
+
(key) => {
|
|
34
|
+
return cy.env([key]).then(({ [key]: value }) => {
|
|
35
|
+
return cy.wrap(value);
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/*----------------------------------------*/
|
|
42
|
+
/* --------------- Export --------------- */
|
|
43
|
+
/*----------------------------------------*/
|
|
44
|
+
|
|
45
|
+
export default getCredentialValue;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
/*----------------------------------------*/
|
|
4
|
+
/* ---------------- Type ---------------- */
|
|
5
|
+
/*----------------------------------------*/
|
|
6
|
+
|
|
7
|
+
declare global {
|
|
8
|
+
namespace Cypress {
|
|
9
|
+
interface Chainable {
|
|
10
|
+
/**
|
|
11
|
+
* Alias for cy.env for retrieving multiple environment variables at once
|
|
12
|
+
* Obtains multiple credential values from the Cypress env depending on
|
|
13
|
+
* the provided keys.
|
|
14
|
+
* @author Allison Zhang
|
|
15
|
+
* @param keys the keys of the environment variables to retrieve
|
|
16
|
+
* @return Object where keys are the provided keys and the values are
|
|
17
|
+
* the corresponding environment variable values from global credentials
|
|
18
|
+
*/
|
|
19
|
+
getCredentialValues(
|
|
20
|
+
keys: string[],
|
|
21
|
+
): Chainable<Record<string, any>>;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/*----------------------------------------*/
|
|
27
|
+
/* --------------- Command -------------- */
|
|
28
|
+
/*----------------------------------------*/
|
|
29
|
+
|
|
30
|
+
const getCredentialValues = () => {
|
|
31
|
+
Cypress.Commands.add(
|
|
32
|
+
'getCredentialValues',
|
|
33
|
+
(keys) => {
|
|
34
|
+
return cy.env(keys);
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/*----------------------------------------*/
|
|
40
|
+
/* --------------- Export --------------- */
|
|
41
|
+
/*----------------------------------------*/
|
|
42
|
+
|
|
43
|
+
export default getCredentialValues;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
/*----------------------------------------*/
|
|
4
|
+
/* ---------------- Type ---------------- */
|
|
5
|
+
/*----------------------------------------*/
|
|
6
|
+
|
|
7
|
+
declare global {
|
|
8
|
+
namespace Cypress {
|
|
9
|
+
interface Chainable {
|
|
10
|
+
/**
|
|
11
|
+
* Alias for Cypress.expose
|
|
12
|
+
* @author Allison Zhang
|
|
13
|
+
* @param key the key of the environment variable to retrieve
|
|
14
|
+
* @return Environment variable from the exposed environment
|
|
15
|
+
*/
|
|
16
|
+
getProfileValue(
|
|
17
|
+
key: string,
|
|
18
|
+
): ObjectLike;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/*----------------------------------------*/
|
|
24
|
+
/* --------------- Command -------------- */
|
|
25
|
+
/*----------------------------------------*/
|
|
26
|
+
|
|
27
|
+
const getProfileValue = () => {
|
|
28
|
+
Cypress.Commands.add(
|
|
29
|
+
'getProfileValue',
|
|
30
|
+
(key) => {
|
|
31
|
+
return Cypress.expose(key);
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/*----------------------------------------*/
|
|
37
|
+
/* --------------- Export --------------- */
|
|
38
|
+
/*----------------------------------------*/
|
|
39
|
+
|
|
40
|
+
export default getProfileValue;
|
|
@@ -32,52 +32,55 @@ const handleHarvardKey = () => {
|
|
|
32
32
|
) => {
|
|
33
33
|
cy.log('🔓 Handling HarvardKey authentication via UI');
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
// Get user credentials from environment variables
|
|
36
|
+
cy.env([name]).then((environment) => {
|
|
37
|
+
const userInfo = environment[name];
|
|
38
|
+
if (!userInfo) {
|
|
39
|
+
throw new Error(`Could not find ${name} in environment variables`);
|
|
40
|
+
}
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
// Destructure the user info object
|
|
43
|
+
const { username, password } = userInfo;
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Cypress.require('dceky');
|
|
46
|
-
// To go the login screen
|
|
47
|
-
// Clicking the button doesn't work for some reason, so we access the href attribute instead
|
|
48
|
-
return cy.navigateToHref('#idp_1001962798_button');
|
|
49
|
-
}).then((fullUrl: string) => {
|
|
50
|
-
// Navigate to the Harvard login page using originWithKaixa
|
|
51
|
-
cy.origin('https://harvard.idp.cirrusidentity.com', {
|
|
52
|
-
args: { username, password, fullUrl },
|
|
53
|
-
}, (args) => {
|
|
45
|
+
// Get the Harvard login URL using originWithKaixa with auto-initialized functions
|
|
46
|
+
cy.origin('https://apps.cirrusidentity.com', () => {
|
|
54
47
|
Cypress.require('dceky');
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
48
|
+
// To go the login screen
|
|
49
|
+
// Clicking the button doesn't work for some reason, so we access the href attribute instead
|
|
50
|
+
return cy.navigateToHref('#idp_1001962798_button');
|
|
51
|
+
}).then((fullUrl: string) => {
|
|
52
|
+
// Navigate to the Harvard login page using originWithKaixa
|
|
53
|
+
cy.origin('https://harvard.idp.cirrusidentity.com', {
|
|
54
|
+
args: { username, password, fullUrl },
|
|
55
|
+
}, (args) => {
|
|
56
|
+
Cypress.require('dceky');
|
|
57
|
+
const {
|
|
58
|
+
username: harvardUsername,
|
|
59
|
+
password: harvardPassword,
|
|
60
|
+
fullUrl: harvardLoginUrl,
|
|
61
|
+
} = args;
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
cy.on('uncaught:exception', (e: Error) => {
|
|
64
|
+
// Ignore known HarvardKey errors
|
|
65
|
+
if (!e.message.includes('ready is not defined')) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
});
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
// Visit the Harvard login page
|
|
72
|
+
cy.visit(harvardLoginUrl);
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
// Wait for and fill in the login form
|
|
75
|
+
cy.waitForElementVisible('#username');
|
|
76
|
+
cy.waitForElementVisible('#password');
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
cy.typeInto({ item: '#username', text: harvardUsername });
|
|
79
|
+
cy.typeInto({ item: '#password', text: harvardPassword });
|
|
78
80
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
// Submit the form
|
|
82
|
+
cy.get('input[type="submit"], button[type="submit"], .btn-primary').click();
|
|
83
|
+
});
|
|
81
84
|
});
|
|
82
85
|
});
|
|
83
86
|
},
|
package/src/commands/index.ts
CHANGED
|
@@ -29,6 +29,9 @@ import uniquify from './uniquify';
|
|
|
29
29
|
import visitCanvasEndpoint from './visitCanvasEndpoint';
|
|
30
30
|
import waitForAtLeastOneElementPresent from './waitForAtLeastOneElementPresent';
|
|
31
31
|
import waitForElementVisible from './waitForElementVisible';
|
|
32
|
+
import getProfileValue from './getProfileValue';
|
|
33
|
+
import getCredentialValue from './getCredentialValue';
|
|
34
|
+
import getCredentialValues from './getCredentialValues';
|
|
32
35
|
|
|
33
36
|
/**
|
|
34
37
|
* Initialize custom commands
|
|
@@ -66,6 +69,9 @@ const commands = () => {
|
|
|
66
69
|
visitCanvasEndpoint();
|
|
67
70
|
waitForAtLeastOneElementPresent();
|
|
68
71
|
waitForElementVisible();
|
|
72
|
+
getProfileValue();
|
|
73
|
+
getCredentialValue();
|
|
74
|
+
getCredentialValues();
|
|
69
75
|
};
|
|
70
76
|
|
|
71
77
|
export default commands;
|
package/src/commands/launchAs.ts
CHANGED
|
@@ -58,7 +58,7 @@ const launchAs = () => {
|
|
|
58
58
|
|
|
59
59
|
// Get courseId from environment variables if not provided
|
|
60
60
|
if (!courseId) {
|
|
61
|
-
const envCourseId = Cypress.
|
|
61
|
+
const envCourseId = Cypress.expose('courseId');
|
|
62
62
|
if (!envCourseId) {
|
|
63
63
|
throw new Error('Could not find courseId in environment variables');
|
|
64
64
|
}
|
|
@@ -66,102 +66,104 @@ const launchAs = () => {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
// Get appName from environment variables if not provided
|
|
69
|
-
appName = appName || Cypress.
|
|
69
|
+
appName = appName || Cypress.expose('appName');
|
|
70
70
|
if (!appName) {
|
|
71
71
|
throw new Error('Could not find appName in environment variables');
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
// Get user accessToken from environment variables
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
// List external tools in the course
|
|
85
|
-
return (
|
|
86
|
-
cy
|
|
87
|
-
.request({
|
|
88
|
-
method: 'GET',
|
|
89
|
-
url: `https://canvas.harvard.edu/api/v1/courses/${courseId}/external_tools`,
|
|
90
|
-
body: {
|
|
91
|
-
per_page: 200,
|
|
92
|
-
access_token: accessToken,
|
|
93
|
-
},
|
|
94
|
-
})
|
|
95
|
-
.then((response) => {
|
|
96
|
-
// Extract tools from the body
|
|
97
|
-
const externalTools = response.body;
|
|
98
|
-
|
|
99
|
-
// Find the external tool of interest
|
|
100
|
-
const matchingTool = externalTools.find((externalTool: any) => {
|
|
101
|
-
// Skip non-nav items
|
|
102
|
-
if (
|
|
103
|
-
// No nav
|
|
104
|
-
!externalTool.course_navigation
|
|
105
|
-
// No nav information
|
|
106
|
-
|| typeof externalTool.course_navigation !== 'object'
|
|
107
|
-
) {
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
75
|
+
cy.env([name]).then((environment) => {
|
|
76
|
+
const userInfo = environment[name];
|
|
77
|
+
if (!userInfo) {
|
|
78
|
+
throw new Error(`Could not find ${name} in environment variables`);
|
|
79
|
+
}
|
|
80
|
+
const { accessToken } = userInfo;
|
|
81
|
+
if (!accessToken) {
|
|
82
|
+
throw new Error(`Could not find accessToken for ${name} in environment variables`);
|
|
83
|
+
}
|
|
110
84
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
85
|
+
// List external tools in the course
|
|
86
|
+
return (
|
|
87
|
+
cy
|
|
88
|
+
.request({
|
|
89
|
+
method: 'GET',
|
|
90
|
+
url: `https://canvas.harvard.edu/api/v1/courses/${courseId}/external_tools`,
|
|
91
|
+
body: {
|
|
92
|
+
per_page: 200,
|
|
93
|
+
access_token: accessToken,
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
.then((response) => {
|
|
97
|
+
// Extract tools from the body
|
|
98
|
+
const externalTools = response.body;
|
|
99
|
+
|
|
100
|
+
// Find the external tool of interest
|
|
101
|
+
const matchingTool = externalTools.find((externalTool: any) => {
|
|
102
|
+
// Skip non-nav items
|
|
103
|
+
if (
|
|
104
|
+
// No nav
|
|
105
|
+
!externalTool.course_navigation
|
|
106
|
+
// No nav information
|
|
107
|
+
|| typeof externalTool.course_navigation !== 'object'
|
|
108
|
+
) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Skip non-labeled items
|
|
113
|
+
if (!externalTool.course_navigation.text) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Skip if the app name does not match the expected name
|
|
118
|
+
const thisAppName = (
|
|
119
|
+
externalTool
|
|
120
|
+
.course_navigation
|
|
121
|
+
.text
|
|
122
|
+
.trim()
|
|
123
|
+
.toLowerCase()
|
|
124
|
+
);
|
|
125
|
+
return thisAppName === appName.trim().toLowerCase();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Make sure we found the app
|
|
129
|
+
if (!matchingTool) {
|
|
130
|
+
throw new Error(`Could not find any apps named "${appName}" in course ${courseId}`);
|
|
114
131
|
}
|
|
115
132
|
|
|
116
|
-
//
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
133
|
+
// Get the toolId for the matching tool
|
|
134
|
+
const toolId = matchingTool?.id || 0;
|
|
135
|
+
return cy.wrap(toolId);
|
|
136
|
+
})
|
|
137
|
+
.then((toolId) => {
|
|
138
|
+
// Request sessionless launch URL
|
|
139
|
+
return (
|
|
140
|
+
cy
|
|
141
|
+
.request({
|
|
142
|
+
method: 'GET',
|
|
143
|
+
url: `https://canvas.harvard.edu/api/v1/courses/${courseId}/external_tools/sessionless_launch?id=${toolId}`,
|
|
144
|
+
body: {
|
|
145
|
+
per_page: 200,
|
|
146
|
+
access_token: accessToken,
|
|
147
|
+
},
|
|
148
|
+
})
|
|
149
|
+
.its('body')
|
|
123
150
|
);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
.request({
|
|
141
|
-
method: 'GET',
|
|
142
|
-
url: `https://canvas.harvard.edu/api/v1/courses/${courseId}/external_tools/sessionless_launch?id=${toolId}`,
|
|
143
|
-
body: {
|
|
144
|
-
per_page: 200,
|
|
145
|
-
access_token: accessToken,
|
|
146
|
-
},
|
|
147
|
-
})
|
|
148
|
-
.its('body')
|
|
149
|
-
);
|
|
150
|
-
})
|
|
151
|
-
.then((sessionlessLaunchInfo) => {
|
|
152
|
-
cy.on('uncaught:exception', (e: Error) => {
|
|
153
|
-
// Ignore known LTI launch errors
|
|
154
|
-
if (!e.message.includes('postMessage')) {
|
|
155
|
-
return true;
|
|
156
|
-
}
|
|
157
|
-
return false;
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
// Launch via the sessionless launch URL
|
|
161
|
-
const launchURL = sessionlessLaunchInfo.url;
|
|
162
|
-
cy.visit(launchURL);
|
|
163
|
-
})
|
|
164
|
-
);
|
|
151
|
+
})
|
|
152
|
+
.then((sessionlessLaunchInfo) => {
|
|
153
|
+
cy.on('uncaught:exception', (e: Error) => {
|
|
154
|
+
// Ignore known LTI launch errors
|
|
155
|
+
if (!e.message.includes('postMessage')) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
return false;
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Launch via the sessionless launch URL
|
|
162
|
+
const launchURL = sessionlessLaunchInfo.url;
|
|
163
|
+
cy.visit(launchURL);
|
|
164
|
+
})
|
|
165
|
+
);
|
|
166
|
+
});
|
|
165
167
|
},
|
|
166
168
|
);
|
|
167
169
|
};
|
|
@@ -73,84 +73,88 @@ const logIntoPorta = () => {
|
|
|
73
73
|
) => {
|
|
74
74
|
cy.log('🔓 Handling HarvardKey authentication via API');
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// Request 1: GET Cirrus Identity discovery page
|
|
90
|
-
cy.request({
|
|
91
|
-
url: LOGIN_PAGE,
|
|
92
|
-
followRedirect: true,
|
|
93
|
-
failOnStatusCode: false,
|
|
94
|
-
headers: htmlHeaders,
|
|
95
|
-
}).then((discoveryRes) => {
|
|
96
|
-
// Parse discovery page for HarvardKey IdP button href
|
|
97
|
-
const btnMatch = discoveryRes.body.match(
|
|
98
|
-
new RegExp(`href=["']([^"']+)["'][^>]*id=["']${HARVARDKEY_IDP_BUTTON_ID}["']`),
|
|
99
|
-
);
|
|
100
|
-
if (!btnMatch) {
|
|
101
|
-
throw new Error('Could not find HarvardKey IdP button link on discovery page');
|
|
76
|
+
// Get user credentials from environment variables
|
|
77
|
+
cy.env([name]).then((environment) => {
|
|
78
|
+
const userInfo = environment[name];
|
|
79
|
+
|
|
80
|
+
if (!userInfo) {
|
|
81
|
+
throw new Error(`Could not find ${name} in environment variables`);
|
|
82
|
+
}
|
|
83
|
+
const { username, password } = userInfo;
|
|
84
|
+
|
|
85
|
+
// Check if username and password are set
|
|
86
|
+
if (!username || !password) {
|
|
87
|
+
throw new Error(`Credential "${name}" is missing username and/or password`);
|
|
102
88
|
}
|
|
103
89
|
|
|
104
|
-
const
|
|
90
|
+
const htmlHeaders = { accept: 'text/html' };
|
|
105
91
|
|
|
106
|
-
// Request
|
|
92
|
+
// Request 1: GET Cirrus Identity discovery page
|
|
107
93
|
cy.request({
|
|
108
|
-
url:
|
|
94
|
+
url: LOGIN_PAGE,
|
|
109
95
|
followRedirect: true,
|
|
110
96
|
failOnStatusCode: false,
|
|
111
97
|
headers: htmlHeaders,
|
|
112
|
-
}).then((
|
|
113
|
-
// Parse
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
throw new Error('Could not find login form action on HarvardKey page');
|
|
98
|
+
}).then((discoveryRes) => {
|
|
99
|
+
// Parse discovery page for HarvardKey IdP button href
|
|
100
|
+
const btnMatch = discoveryRes.body.match(
|
|
101
|
+
new RegExp(`href=["']([^"']+)["'][^>]*id=["']${HARVARDKEY_IDP_BUTTON_ID}["']`),
|
|
102
|
+
);
|
|
103
|
+
if (!btnMatch) {
|
|
104
|
+
throw new Error('Could not find HarvardKey IdP button link on discovery page');
|
|
120
105
|
}
|
|
121
106
|
|
|
122
|
-
|
|
107
|
+
const idpUrl = `${IDP_BASE_URL}${btnMatch[1]}`;
|
|
108
|
+
|
|
109
|
+
// Request 2: GET HarvardKey IdP login page
|
|
123
110
|
cy.request({
|
|
124
|
-
|
|
125
|
-
url: loginFormUrl,
|
|
126
|
-
form: true,
|
|
111
|
+
url: idpUrl,
|
|
127
112
|
followRedirect: true,
|
|
128
113
|
failOnStatusCode: false,
|
|
129
114
|
headers: htmlHeaders,
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
username,
|
|
133
|
-
password,
|
|
134
|
-
},
|
|
135
|
-
}).then((authRes) => {
|
|
136
|
-
// Parse SAML form from login response
|
|
115
|
+
}).then((loginPageRes) => {
|
|
116
|
+
// Parse login form action and hidden fields
|
|
137
117
|
const {
|
|
138
|
-
action:
|
|
139
|
-
fields:
|
|
140
|
-
} = getFormData(
|
|
141
|
-
if (!
|
|
142
|
-
throw new Error('Could not find
|
|
118
|
+
action: loginFormUrl,
|
|
119
|
+
fields: loginHiddenFields,
|
|
120
|
+
} = getFormData(loginPageRes.body);
|
|
121
|
+
if (!loginFormUrl) {
|
|
122
|
+
throw new Error('Could not find login form action on HarvardKey page');
|
|
143
123
|
}
|
|
144
124
|
|
|
145
|
-
// Request
|
|
146
|
-
|
|
125
|
+
// Request 3: POST credentials to HarvardKey login form
|
|
126
|
+
cy.request({
|
|
147
127
|
method: 'POST',
|
|
148
|
-
url:
|
|
128
|
+
url: loginFormUrl,
|
|
149
129
|
form: true,
|
|
150
130
|
followRedirect: true,
|
|
151
131
|
failOnStatusCode: false,
|
|
152
132
|
headers: htmlHeaders,
|
|
153
|
-
body:
|
|
133
|
+
body: {
|
|
134
|
+
...loginHiddenFields,
|
|
135
|
+
username,
|
|
136
|
+
password,
|
|
137
|
+
},
|
|
138
|
+
}).then((authRes) => {
|
|
139
|
+
// Parse SAML form from login response
|
|
140
|
+
const {
|
|
141
|
+
action: samlFormUrl,
|
|
142
|
+
fields: samlHiddenFields,
|
|
143
|
+
} = getFormData(authRes.body, 'form[action*="saml2-acs"]');
|
|
144
|
+
if (!samlFormUrl) {
|
|
145
|
+
throw new Error('Could not find SAML form in login response');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Request 4: POST SAML assertion to ACS
|
|
149
|
+
return cy.request({
|
|
150
|
+
method: 'POST',
|
|
151
|
+
url: samlFormUrl,
|
|
152
|
+
form: true,
|
|
153
|
+
followRedirect: true,
|
|
154
|
+
failOnStatusCode: false,
|
|
155
|
+
headers: htmlHeaders,
|
|
156
|
+
body: samlHiddenFields,
|
|
157
|
+
});
|
|
154
158
|
});
|
|
155
159
|
});
|
|
156
160
|
});
|
|
@@ -65,7 +65,6 @@ const genConfiguration = () => {
|
|
|
65
65
|
|
|
66
66
|
// NOTE: Order matters (later overrides earlier)
|
|
67
67
|
const sources: GlobalsOrProfile[] = [
|
|
68
|
-
GlobalCredentials,
|
|
69
68
|
GlobalResources,
|
|
70
69
|
GlobalValues,
|
|
71
70
|
profileModules,
|
|
@@ -92,13 +91,20 @@ const genConfiguration = () => {
|
|
|
92
91
|
const dependents: GlobalsOrProfile = resolveDependents(dependentValues, basics);
|
|
93
92
|
|
|
94
93
|
// Add basics, depends, and profileName into the final env
|
|
95
|
-
const
|
|
94
|
+
const exposed: GlobalsOrProfile = {
|
|
96
95
|
...basics,
|
|
97
96
|
...dependents,
|
|
98
97
|
profileName,
|
|
99
98
|
};
|
|
100
99
|
|
|
101
|
-
|
|
100
|
+
// Add all global values and credentials into the final env
|
|
101
|
+
// Does not support dependent values in GlobalCredentials, TODO: Fix
|
|
102
|
+
const securedEnv = {
|
|
103
|
+
...GlobalCredentials,
|
|
104
|
+
...exposed,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
let baseUrl = exposed.baseURL;
|
|
102
108
|
if (!baseUrl?.startsWith('http')) {
|
|
103
109
|
baseUrl = `https://${baseUrl}`;
|
|
104
110
|
}
|
|
@@ -109,7 +115,8 @@ const genConfiguration = () => {
|
|
|
109
115
|
experimentalWebKitSupport: true,
|
|
110
116
|
experimentalOriginDependencies: true,
|
|
111
117
|
baseUrl,
|
|
112
|
-
|
|
118
|
+
expose: exposed,
|
|
119
|
+
env: securedEnv,
|
|
113
120
|
},
|
|
114
121
|
});
|
|
115
122
|
};
|