dceky 1.0.0-beta.6 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/.eslintrc.js +93 -0
  2. package/README.md +41 -0
  3. package/cypress/e2e/profile-test.cy.ts +10 -0
  4. package/cypress/fixtures/example.json +5 -0
  5. package/cypress/support/commands.ts +37 -0
  6. package/cypress/support/e2e.ts +17 -0
  7. package/cypress.config.ts +9 -0
  8. package/docs/GlobalsAndProfiles.md +23 -0
  9. package/lib/setup/addToGitIgnore.d.ts +6 -0
  10. package/lib/setup/addToGitIgnore.js +47 -0
  11. package/lib/setup/addToGitIgnore.js.map +1 -0
  12. package/lib/setup/checkRequiredFiles.d.ts +6 -0
  13. package/lib/setup/checkRequiredFiles.js +59 -0
  14. package/lib/setup/checkRequiredFiles.js.map +1 -0
  15. package/lib/setup/genCommandImportFile.d.ts +7 -0
  16. package/lib/setup/genCommandImportFile.js +67 -0
  17. package/lib/setup/genCommandImportFile.js.map +1 -0
  18. package/lib/setup/genDynamicConfigFile.d.ts +5 -0
  19. package/lib/setup/genDynamicConfigFile.js +29 -0
  20. package/lib/setup/genDynamicConfigFile.js.map +1 -0
  21. package/lib/setup/helpers/getRootPath.d.ts +7 -0
  22. package/lib/setup/helpers/getRootPath.js +17 -0
  23. package/lib/setup/helpers/getRootPath.js.map +1 -0
  24. package/lib/setup/index.d.ts +1 -0
  25. package/lib/setup/index.js +16 -0
  26. package/lib/setup/index.js.map +1 -0
  27. package/lib/setup/setupCypressDependencies.d.ts +6 -0
  28. package/lib/setup/setupCypressDependencies.js +40 -0
  29. package/lib/setup/setupCypressDependencies.js.map +1 -0
  30. package/lib/src/commands/assertDoesNotHaveClass.d.ts +20 -0
  31. package/lib/src/commands/assertDoesNotHaveClass.js +17 -0
  32. package/lib/src/commands/assertDoesNotHaveClass.js.map +1 -0
  33. package/lib/src/commands/assertHasClass.d.ts +20 -0
  34. package/lib/src/commands/assertHasClass.js +17 -0
  35. package/lib/src/commands/assertHasClass.js.map +1 -0
  36. package/lib/src/commands/assertNumElements.d.ts +19 -0
  37. package/lib/src/commands/assertNumElements.js +17 -0
  38. package/lib/src/commands/assertNumElements.js.map +1 -0
  39. package/lib/src/commands/extractDataFromClass.d.ts +18 -0
  40. package/lib/src/commands/extractDataFromClass.js +25 -0
  41. package/lib/src/commands/extractDataFromClass.js.map +1 -0
  42. package/lib/src/commands/extractDataFromClassByContents.d.ts +19 -0
  43. package/lib/src/commands/extractDataFromClassByContents.js +26 -0
  44. package/lib/src/commands/extractDataFromClassByContents.js.map +1 -0
  45. package/lib/src/commands/getJSON.d.ts +16 -0
  46. package/lib/src/commands/getJSON.js +21 -0
  47. package/lib/src/commands/getJSON.js.map +1 -0
  48. package/lib/src/commands/getNumElements.d.ts +15 -0
  49. package/lib/src/commands/getNumElements.js +19 -0
  50. package/lib/src/commands/getNumElements.js.map +1 -0
  51. package/lib/src/commands/handleHarvardKey.d.ts +15 -0
  52. package/lib/src/commands/handleHarvardKey.js +53 -0
  53. package/lib/src/commands/handleHarvardKey.js.map +1 -0
  54. package/lib/src/commands/launchAs.d.ts +25 -0
  55. package/lib/src/commands/launchAs.js +66 -0
  56. package/lib/src/commands/launchAs.js.map +1 -0
  57. package/lib/src/commands/launchLTIUsingToken.d.ts +21 -0
  58. package/lib/src/commands/launchLTIUsingToken.js +68 -0
  59. package/lib/src/commands/launchLTIUsingToken.js.map +1 -0
  60. package/lib/src/commands/navigateToHref.d.ts +15 -0
  61. package/lib/src/commands/navigateToHref.js +35 -0
  62. package/lib/src/commands/navigateToHref.js.map +1 -0
  63. package/lib/src/commands/runScript.d.ts +15 -0
  64. package/lib/src/commands/runScript.js +20 -0
  65. package/lib/src/commands/runScript.js.map +1 -0
  66. package/lib/src/commands/typeInto.d.ts +24 -0
  67. package/lib/src/commands/typeInto.js +41 -0
  68. package/lib/src/commands/typeInto.js.map +1 -0
  69. package/lib/src/commands/visitCanvasGETEndpoint.d.ts +20 -0
  70. package/lib/src/commands/visitCanvasGETEndpoint.js +26 -0
  71. package/lib/src/commands/visitCanvasGETEndpoint.js.map +1 -0
  72. package/lib/src/commands/waitForElementVisible.d.ts +16 -0
  73. package/lib/src/commands/waitForElementVisible.js +19 -0
  74. package/lib/src/commands/waitForElementVisible.js.map +1 -0
  75. package/lib/src/genConfiguration/helpers/getRootPath.d.ts +7 -0
  76. package/lib/src/genConfiguration/helpers/getRootPath.js +17 -0
  77. package/lib/src/genConfiguration/helpers/getRootPath.js.map +1 -0
  78. package/lib/src/genConfiguration/helpers/resolveDependents.d.ts +13 -0
  79. package/lib/src/genConfiguration/helpers/resolveDependents.js +50 -0
  80. package/lib/src/genConfiguration/helpers/resolveDependents.js.map +1 -0
  81. package/lib/src/genConfiguration/helpers/splitEnv.d.ts +10 -0
  82. package/lib/src/genConfiguration/helpers/splitEnv.js +27 -0
  83. package/lib/src/genConfiguration/helpers/splitEnv.js.map +1 -0
  84. package/{src/genConfiguration.ts → lib/src/genConfiguration/index.d.ts} +3 -6
  85. package/lib/src/genConfiguration/index.js +89 -0
  86. package/lib/src/genConfiguration/index.js.map +1 -0
  87. package/lib/src/genConfiguration/types/DependentValue.d.ts +11 -0
  88. package/lib/src/genConfiguration/types/DependentValue.js +3 -0
  89. package/lib/src/genConfiguration/types/DependentValue.js.map +1 -0
  90. package/lib/src/genConfiguration/types/GlobalsOrProfile.d.ts +9 -0
  91. package/lib/src/genConfiguration/types/GlobalsOrProfile.js +3 -0
  92. package/lib/src/genConfiguration/types/GlobalsOrProfile.js.map +1 -0
  93. package/lib/src/genConfiguration/types/SplitEnv.d.ts +13 -0
  94. package/lib/src/genConfiguration/types/SplitEnv.js +3 -0
  95. package/lib/src/genConfiguration/types/SplitEnv.js.map +1 -0
  96. package/lib/{index.d.ts → src/index.d.ts} +1 -1
  97. package/lib/{index.js → src/index.js} +6 -3
  98. package/lib/src/index.js.map +1 -0
  99. package/lib/src/init.d.ts +6 -0
  100. package/lib/src/init.js +45 -0
  101. package/lib/src/init.js.map +1 -0
  102. package/lib/start/constants/AVAILABLE_BROWSERS.d.ts +9 -0
  103. package/lib/start/constants/AVAILABLE_BROWSERS.js +27 -0
  104. package/lib/start/constants/AVAILABLE_BROWSERS.js.map +1 -0
  105. package/lib/start/helpers/exec.d.ts +8 -0
  106. package/lib/start/helpers/exec.js +18 -0
  107. package/lib/start/helpers/exec.js.map +1 -0
  108. package/lib/start/helpers/extractArgValue.d.ts +10 -0
  109. package/lib/start/helpers/extractArgValue.js +39 -0
  110. package/lib/start/helpers/extractArgValue.js.map +1 -0
  111. package/lib/start/helpers/findProfilesByNames.d.ts +16 -0
  112. package/lib/start/helpers/findProfilesByNames.js +35 -0
  113. package/lib/start/helpers/findProfilesByNames.js.map +1 -0
  114. package/lib/start/helpers/getRootPath.d.ts +7 -0
  115. package/lib/start/helpers/getRootPath.js +17 -0
  116. package/lib/start/helpers/getRootPath.js.map +1 -0
  117. package/lib/start/helpers/parseCommaSeparated.d.ts +8 -0
  118. package/lib/start/helpers/parseCommaSeparated.js +23 -0
  119. package/lib/start/helpers/parseCommaSeparated.js.map +1 -0
  120. package/lib/start/helpers/print.d.ts +38 -0
  121. package/lib/start/helpers/print.js +145 -0
  122. package/lib/start/helpers/print.js.map +1 -0
  123. package/lib/start/helpers/prompt.d.ts +8 -0
  124. package/lib/start/helpers/prompt.js +25 -0
  125. package/lib/start/helpers/prompt.js.map +1 -0
  126. package/lib/start/helpers/showChooser.d.ts +21 -0
  127. package/lib/start/helpers/showChooser.js +116 -0
  128. package/lib/start/helpers/showChooser.js.map +1 -0
  129. package/lib/start/helpers/validateBrowsers.d.ts +8 -0
  130. package/lib/start/helpers/validateBrowsers.js +36 -0
  131. package/lib/start/helpers/validateBrowsers.js.map +1 -0
  132. package/lib/start/index.d.ts +7 -0
  133. package/lib/start/index.js +140 -0
  134. package/lib/start/index.js.map +1 -0
  135. package/lib/start/types/ChooserOption.d.ts +10 -0
  136. package/lib/start/types/ChooserOption.js +3 -0
  137. package/lib/start/types/ChooserOption.js.map +1 -0
  138. package/package.json +28 -8
  139. package/setup/addToGitIgnore.ts +48 -0
  140. package/setup/checkRequiredFiles.ts +63 -0
  141. package/setup/genCommandImportFile.ts +76 -0
  142. package/setup/genDynamicConfigFile.ts +29 -0
  143. package/setup/helpers/getRootPath.ts +13 -0
  144. package/setup/index.ts +11 -0
  145. package/setup/setupCypressDependencies.ts +38 -0
  146. package/src/commands/assertDoesNotHaveClass.ts +51 -0
  147. package/src/commands/assertHasClass.ts +51 -0
  148. package/src/commands/assertNumElements.ts +50 -0
  149. package/src/commands/extractDataFromClass.ts +52 -0
  150. package/src/commands/extractDataFromClassByContents.ts +55 -0
  151. package/src/commands/getJSON.ts +45 -0
  152. package/src/commands/getNumElements.ts +45 -0
  153. package/src/commands/handleHarvardKey.ts +91 -0
  154. package/src/commands/launchAs.ts +120 -0
  155. package/src/commands/launchLTIUsingToken.ts +115 -0
  156. package/src/commands/navigateToHref.ts +60 -0
  157. package/src/commands/runScript.ts +44 -0
  158. package/src/commands/typeInto.ts +88 -0
  159. package/src/commands/visitCanvasGETEndpoint.ts +61 -0
  160. package/src/commands/waitForElementVisible.ts +49 -0
  161. package/src/genConfiguration/helpers/getRootPath.ts +13 -0
  162. package/src/genConfiguration/helpers/resolveDependents.ts +46 -0
  163. package/src/genConfiguration/helpers/splitEnv.ts +30 -0
  164. package/src/genConfiguration/index.ts +95 -0
  165. package/src/genConfiguration/types/DependentValue.ts +14 -0
  166. package/src/genConfiguration/types/GlobalsOrProfile.ts +12 -0
  167. package/src/genConfiguration/types/SplitEnv.ts +18 -0
  168. package/src/index.ts +7 -4
  169. package/src/init.ts +36 -17
  170. package/start/constants/AVAILABLE_BROWSERS.ts +28 -0
  171. package/start/helpers/exec.ts +17 -0
  172. package/start/helpers/extractArgValue.ts +42 -0
  173. package/start/helpers/findProfilesByNames.ts +39 -0
  174. package/start/helpers/getRootPath.ts +13 -0
  175. package/start/helpers/parseCommaSeparated.ts +23 -0
  176. package/start/helpers/print.ts +155 -0
  177. package/start/helpers/prompt.ts +23 -0
  178. package/start/helpers/showChooser.ts +140 -0
  179. package/start/helpers/validateBrowsers.ts +35 -0
  180. package/start/index.ts +164 -0
  181. package/start/types/ChooserOption.ts +11 -0
  182. package/tsconfig.json +3 -4
  183. package/.eslintrc.json +0 -58
  184. package/lib/genConfiguration.d.ts +0 -8
  185. package/lib/genConfiguration.js +0 -13
  186. package/lib/genConfiguration.js.map +0 -1
  187. package/lib/index.js.map +0 -1
  188. package/lib/init.d.ts +0 -13
  189. package/lib/init.js +0 -10
  190. package/lib/init.js.map +0 -1
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ /* eslint-disable no-console */
7
+ var AVAILABLE_BROWSERS_1 = __importDefault(require("../constants/AVAILABLE_BROWSERS"));
8
+ /**
9
+ * Validate browsers (supports multiple)
10
+ * @author Yuen Ler Chow
11
+ * @param browserNames array of browser names to validate
12
+ * @returns array of valid browser names (lowercased)
13
+ */
14
+ var validateBrowsers = function (browserNames) {
15
+ var valid = [];
16
+ var invalid = [];
17
+ // Convert all browser names to lowercase for comparison
18
+ var lowercaseBrowserNames = browserNames.map(function (browser) { return browser.toLowerCase(); });
19
+ // Validate each browser
20
+ lowercaseBrowserNames.forEach(function (browser) {
21
+ if (AVAILABLE_BROWSERS_1.default.some(function (b) { return b.name.toLowerCase() === browser.toLowerCase(); })) {
22
+ valid.push(browser);
23
+ }
24
+ else {
25
+ invalid.push(browser);
26
+ }
27
+ });
28
+ // If there are invalid browsers, log error and exit
29
+ if (invalid.length > 0) {
30
+ console.error("Browser(s) invalid: ".concat(invalid.join(', '), ". Available browsers: ").concat(AVAILABLE_BROWSERS_1.default.join(', ')));
31
+ process.exit(1);
32
+ }
33
+ return valid;
34
+ };
35
+ exports.default = validateBrowsers;
36
+ //# sourceMappingURL=validateBrowsers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateBrowsers.js","sourceRoot":"","sources":["../../../start/helpers/validateBrowsers.ts"],"names":[],"mappings":";;;;;AAAA,+BAA+B;AAC/B,uFAAiE;AAEjE;;;;;GAKG;AACH,IAAM,gBAAgB,GAAG,UAAC,YAAsB;IAC9C,IAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,wDAAwD;IACxD,IAAM,qBAAqB,GAAG,YAAY,CAAC,GAAG,CAAC,UAAC,OAAO,IAAO,OAAO,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/F,wBAAwB;IACxB,qBAAqB,CAAC,OAAO,CAAC,UAAC,OAAO;QACpC,IAAI,4BAAkB,CAAC,IAAI,CAAC,UAAC,CAAC,IAAO,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/F,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,oDAAoD;IACpD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,8BAAuB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,mCAAyB,4BAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAE,CAAC,CAAC;QACjH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,kBAAe,gBAAgB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Checks arguments and environment variables (for PROFILE, BROWSER, and HEADLESS),
3
+ * asks user for missing selections, and launches Cypress
4
+ * @author Gardenia Liu
5
+ * @author Yuen Ler Chow
6
+ */
7
+ export {};
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ /* eslint-disable no-console */
3
+ /**
4
+ * Checks arguments and environment variables (for PROFILE, BROWSER, and HEADLESS),
5
+ * asks user for missing selections, and launches Cypress
6
+ * @author Gardenia Liu
7
+ * @author Yuen Ler Chow
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ // Import libs
14
+ var fs_1 = __importDefault(require("fs"));
15
+ var path_1 = __importDefault(require("path"));
16
+ // Import helpers
17
+ var showChooser_1 = __importDefault(require("./helpers/showChooser"));
18
+ var parseCommaSeparated_1 = __importDefault(require("./helpers/parseCommaSeparated"));
19
+ var findProfilesByNames_1 = __importDefault(require("./helpers/findProfilesByNames"));
20
+ var validateBrowsers_1 = __importDefault(require("./helpers/validateBrowsers"));
21
+ var extractArgValue_1 = __importDefault(require("./helpers/extractArgValue"));
22
+ var getRootPath_1 = __importDefault(require("./helpers/getRootPath"));
23
+ // Import constants
24
+ var AVAILABLE_BROWSERS_1 = __importDefault(require("./constants/AVAILABLE_BROWSERS"));
25
+ // Get the project directory
26
+ var pwd = (0, getRootPath_1.default)();
27
+ // Find available profiles under /cypress/profiles
28
+ var profilesDir = path_1.default.join(pwd, 'cypress/profiles');
29
+ if (!fs_1.default.existsSync(profilesDir)) {
30
+ console.warn("[cypress.config] Could not load profile '".concat(profilesDir, "'"));
31
+ process.exit(1);
32
+ }
33
+ // Find all files matching the pattern: {ProfileName}.Profile.ts
34
+ var profileFiles = (fs_1.default
35
+ .readdirSync(profilesDir)
36
+ .filter(function (f) {
37
+ return f.endsWith('.Profile.ts');
38
+ }));
39
+ // Get profile names by removing '.Profile.ts'
40
+ var profiles = profileFiles.map(function (file) {
41
+ var profileName = file.replace('.Profile.ts', '');
42
+ return { file: file, profileName: profileName };
43
+ });
44
+ // Exit if no profiles found
45
+ if (profiles.length === 0) {
46
+ console.error("No profiles found in '".concat(profilesDir, "'"));
47
+ process.exit(1);
48
+ }
49
+ // Parse CLI arguments
50
+ var args = process.argv.slice(2);
51
+ // Get selections from environment variables or CLI arguments
52
+ var selectedProfiles = [];
53
+ var selectedBrowsers = [];
54
+ var isHeadless = false;
55
+ // Check for PROFILE (env var or CLI arg)
56
+ var envProfileRaw = process.env.PROFILE;
57
+ var argProfileRaw = (0, extractArgValue_1.default)(args, '--profile');
58
+ var profileRaw = envProfileRaw || argProfileRaw;
59
+ if (profileRaw) {
60
+ var profileNames = (0, parseCommaSeparated_1.default)(profileRaw);
61
+ selectedProfiles = (0, findProfilesByNames_1.default)(profileNames, profiles);
62
+ }
63
+ // Check for BROWSER (env var or CLI arg)
64
+ var envBrowserRaw = process.env.BROWSER;
65
+ var argBrowserRaw = (0, extractArgValue_1.default)(args, '--browser');
66
+ var browserRaw = envBrowserRaw || argBrowserRaw;
67
+ if (browserRaw) {
68
+ var browserNames = (0, parseCommaSeparated_1.default)(browserRaw);
69
+ selectedBrowsers = (0, validateBrowsers_1.default)(browserNames);
70
+ }
71
+ // Check for HEADLESS (env var or CLI flag)
72
+ var envHeadlessRaw = process.env.HEADLESS;
73
+ var headlessFlagValue = (0, extractArgValue_1.default)(args, '--headless');
74
+ var hasHeadlessFlag = headlessFlagValue !== undefined;
75
+ isHeadless = !!(envHeadlessRaw && envHeadlessRaw.toLowerCase() !== 'false') || hasHeadlessFlag;
76
+ // If headless wasn't specified, ask the user to choose
77
+ if (!envHeadlessRaw && !hasHeadlessFlag) {
78
+ var choices = (0, showChooser_1.default)({
79
+ question: 'Run in headless mode?',
80
+ options: [
81
+ { tag: '1', description: 'Yes (headless)' },
82
+ { tag: '2', description: 'No (interactive)' },
83
+ ],
84
+ title: 'Select mode',
85
+ allowMulti: false,
86
+ });
87
+ isHeadless = choices[0].tag === '1';
88
+ }
89
+ // If running headless and no browsers were selected, ask the user to choose
90
+ if (isHeadless && selectedBrowsers.length === 0) {
91
+ var options = AVAILABLE_BROWSERS_1.default.map(function (_a) {
92
+ var tag = _a.tag, name = _a.name;
93
+ return {
94
+ tag: tag,
95
+ description: name,
96
+ };
97
+ });
98
+ var choices = (0, showChooser_1.default)({
99
+ question: 'Choose browser(s) (commas for multiple: C,F)',
100
+ options: options,
101
+ title: 'Select browser(s)',
102
+ allowMulti: true,
103
+ });
104
+ selectedBrowsers = (choices
105
+ .map(function (choice) {
106
+ return AVAILABLE_BROWSERS_1.default[choice.index];
107
+ })
108
+ .map(function (_a) {
109
+ var name = _a.name;
110
+ return name;
111
+ }));
112
+ }
113
+ // If no profiles were selected, ask the user to choose
114
+ // - In headless mode, allow selecting multiple profiles
115
+ // - In visible mode, only allow selecting a single profile
116
+ // In the case where their environment selected more than one profile, but they are not headless, make them re-choose
117
+ if (selectedProfiles.length === 0
118
+ || (!isHeadless && selectedProfiles.length > 1)) {
119
+ var options = profiles.map(function (p, idx) {
120
+ return {
121
+ tag: String(idx + 1),
122
+ description: p.profileName,
123
+ };
124
+ });
125
+ var choices = (0, showChooser_1.default)({
126
+ question: (isHeadless
127
+ ? 'Choose profile(s) (commas for multiple: 1,2):'
128
+ : 'Choose profile:'),
129
+ options: options,
130
+ title: "Choose profile".concat(isHeadless ? 's' : ''),
131
+ allowMulti: isHeadless,
132
+ });
133
+ selectedProfiles = choices.map(function (choice) { return profiles[choice.index]; });
134
+ }
135
+ // Execute commands for each combination of profile and browser (not yet implemented)
136
+ console.log('Starting Cypress with the following configuration:');
137
+ console.log("Profiles: ".concat(selectedProfiles.map(function (p) { return p.profileName; }).join(', ')));
138
+ console.log("Browsers: ".concat(selectedBrowsers.join(', ')));
139
+ console.log("Headless: ".concat(isHeadless));
140
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../start/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * An option that can be put into a chooser
3
+ * @author Gabe Abrams
4
+ */
5
+ type ChooserOption = {
6
+ description: string;
7
+ tag?: string;
8
+ index?: number;
9
+ };
10
+ export default ChooserOption;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ChooserOption.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChooserOption.js","sourceRoot":"","sources":["../../../start/types/ChooserOption.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "dceky",
3
- "version": "1.0.0-beta.6",
3
+ "version": "1.0.3",
4
4
  "description": "Cypress toolkit for Harvard DCE",
5
- "main": "./lib/index.js",
6
- "types": "./lib/index.d.ts",
5
+ "main": "./lib/src/index.js",
6
+ "types": "./lib/src/index.d.ts",
7
7
  "scripts": {
8
- "build": "tsc --project ./tsconfig.json"
8
+ "build": "tsc --project ./tsconfig.json",
9
+ "ky:start": "npx tsx ./start/index.ts",
10
+ "ky:setup": "npx tsx ./setup/index.ts",
11
+ "ky:dev": "npm run ky:setup && npm run ky:start"
9
12
  },
10
13
  "repository": {
11
14
  "type": "git",
@@ -22,11 +25,28 @@
22
25
  "url": "https://github.com/harvard-edtech/dceky/issues"
23
26
  },
24
27
  "homepage": "https://github.com/harvard-edtech/dceky#readme",
25
- "peerDependencies": {
26
- "cypress": "x.x.x"
28
+ "dependencies": {
29
+ "child_process": "^1.0.2",
30
+ "clear": "^0.1.0",
31
+ "deepmerge": "4.3.1",
32
+ "prompt-sync": "^4.2.0",
33
+ "@types/prompt-sync": "^4.2.3",
34
+ "@types/clear": "^0.1.4",
35
+ "@types/node": "^22.7.0"
27
36
  },
28
37
  "devDependencies": {
29
- "@types/node": "^22.7.0",
30
- "typescript": "^5.9.3"
38
+ "typescript": "^5.9.3",
39
+ "@types/deepmerge": "2.1.0",
40
+ "@types/node": "^24.6.1",
41
+ "cross-env": "^10.1.0",
42
+ "eslint": "^8.42.0",
43
+ "eslint-config-airbnb": "^19.0.4",
44
+ "eslint-config-airbnb-typescript": "^17.1.0",
45
+ "eslint-plugin-import": "^2.32.0",
46
+ "eslint-plugin-jsx-a11y": "^6.10.2",
47
+ "eslint-plugin-react": "^7.37.5"
48
+ },
49
+ "peerDependencies": {
50
+ "cypress": "^x.x.x"
31
51
  }
32
52
  }
@@ -0,0 +1,48 @@
1
+ /* eslint-disable no-console */
2
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
3
+ import path from 'path';
4
+ import getRootPath from './helpers/getRootPath';
5
+
6
+ /**
7
+ * Ensure gitignore includes the necessary entries for Cypress results
8
+ * @author Yuen Ler Chow
9
+ */
10
+ const addToGitIgnore = (): void => {
11
+ const root = getRootPath();
12
+
13
+ const gitignorePath = path.join(root, '.gitignore');
14
+
15
+ const entries = [
16
+ 'cypress-results/',
17
+ 'cypress/downloads',
18
+ 'cypress/screenshots',
19
+ 'cypress/videos',
20
+ ];
21
+
22
+ let gitignoreContent = '';
23
+ if (existsSync(gitignorePath)) {
24
+ gitignoreContent = readFileSync(gitignorePath, 'utf8');
25
+ }
26
+
27
+ // Check which entries are missing
28
+ const missingEntries = entries.filter((entry) => {
29
+ // Check if entry exists (with or without newline)
30
+ const regex = new RegExp(`^${entry.replace(/\//g, '\\/')}$`, 'm');
31
+ return !regex.test(gitignoreContent);
32
+ });
33
+
34
+ // Add missing entries
35
+ if (missingEntries.length > 0) {
36
+ if (gitignoreContent && !gitignoreContent.endsWith('\n')) {
37
+ gitignoreContent += '\n';
38
+ }
39
+ gitignoreContent += '\n# Cypress parallel test results (added by dceky)\n';
40
+ missingEntries.forEach((entry) => {
41
+ gitignoreContent += `${entry}\n`;
42
+ });
43
+ writeFileSync(gitignorePath, gitignoreContent, 'utf8');
44
+ console.log(`Added ${missingEntries.length} entries to .gitignore`);
45
+ }
46
+ };
47
+
48
+ export default addToGitIgnore;
@@ -0,0 +1,63 @@
1
+ /* eslint-disable no-console */
2
+ import { existsSync } from 'fs';
3
+ import path from 'path';
4
+ import getRootPath from './helpers/getRootPath';
5
+
6
+ /**
7
+ * Ensure required configuration files exist in the consumer repo
8
+ * @author Yuen Ler Chow
9
+ */
10
+ const checkRequiredFiles = (): void => {
11
+ const root = getRootPath();
12
+
13
+ const globalsPath = path.join(root, 'cypress/globals');
14
+ const profilesPath = path.join(root, 'cypress/profiles');
15
+
16
+ // Common file extensions to check
17
+ const extensions = ['.js', '.ts', '.json', '.mjs', '.cjs'];
18
+
19
+ // Required global files
20
+ const requiredGlobals = [
21
+ 'GlobalCredentials',
22
+ 'GlobalResources',
23
+ 'GlobalValues',
24
+ ];
25
+
26
+ // Determine profile file name (default is stage)
27
+ const profileName = process.env.CYPRESS_PROFILE || 'stage';
28
+ const requiredProfile = `${profileName}.Profile`;
29
+
30
+ // Check for missing files
31
+ const missingFiles: string[] = [];
32
+
33
+ // Check global files
34
+ requiredGlobals.forEach((file) => {
35
+ const filePath = path.join(globalsPath, file);
36
+ const found = extensions.some((ext) => {
37
+ return existsSync(`${filePath}${ext}`);
38
+ });
39
+ if (!found) {
40
+ missingFiles.push(`cypress/globals/${file}.ts`);
41
+ }
42
+ });
43
+
44
+ // Check profile file
45
+ const profileFilePath = path.join(profilesPath, requiredProfile);
46
+ const profileFound = extensions.some((ext) => {
47
+ return existsSync(`${profileFilePath}${ext}`);
48
+ });
49
+ if (!profileFound) {
50
+ missingFiles.push(`cypress/profiles/${requiredProfile}.ts`);
51
+ }
52
+
53
+ if (missingFiles.length > 0) {
54
+ console.error('\nMissing required configuration files in this project:');
55
+ missingFiles.forEach((file) => {
56
+ console.error(` - ${file}`);
57
+ });
58
+ console.error('\nPlease create these files before running setup.');
59
+ process.exit(1);
60
+ }
61
+ };
62
+
63
+ export default checkRequiredFiles;
@@ -0,0 +1,76 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import getRootPath from './helpers/getRootPath';
4
+
5
+ /**
6
+ * Generate an index.ts file that imports and runs all command files in cypress/commands
7
+ * This should be called from cypress.config.js
8
+ * @author Yuen Ler Chow
9
+ */
10
+ const genCommandImportFile = () => {
11
+ const root = getRootPath();
12
+
13
+ const cypressCommandsDir = path.join(root, 'cypress/commands');
14
+ const outputFile = path.join(cypressCommandsDir, 'index.ts');
15
+ const topOfFileComment = '// Auto-generated by dceky - do not edit manually';
16
+
17
+ // Check if the directory exists
18
+ if (!fs.existsSync(cypressCommandsDir)) {
19
+ // Create the directory
20
+ fs.mkdirSync(cypressCommandsDir, { recursive: true });
21
+ // Create an empty file so init doesn't fail
22
+ fs.writeFileSync(outputFile, `${topOfFileComment}\n`);
23
+ return outputFile;
24
+ }
25
+
26
+ // Get all files in the directory
27
+ const files = fs.readdirSync(cypressCommandsDir);
28
+ const commandFiles: string[] = [];
29
+
30
+ // Filter out non-JS/TS files and process each file
31
+ files.forEach((file) => {
32
+ // Skip non-JS/TS files (like .d.ts, .map, etc.)
33
+ if (!file.endsWith('.js') && !file.endsWith('.ts')) {
34
+ return;
35
+ }
36
+
37
+ // Skip index files
38
+ if (file === 'index.js' || file === 'index.ts') {
39
+ return;
40
+ }
41
+
42
+ // Determine the file's path
43
+ const filePath = path.join(cypressCommandsDir, file);
44
+
45
+ // Check if it's a file (not a directory)
46
+ const stats = fs.statSync(filePath);
47
+ if (!stats.isFile()) {
48
+ return;
49
+ }
50
+
51
+ // Store the file name
52
+ commandFiles.push(file);
53
+ });
54
+
55
+ // Generate require statements and function calls
56
+ const requires: string[] = [];
57
+ const calls: string[] = [];
58
+
59
+ commandFiles.forEach((file) => {
60
+ const requirePath = `./${file}`;
61
+ // Create a safe variable name (replace non-alphanumeric with underscore)
62
+ const importName = file.replace(/\.(js|ts)$/, '');
63
+ const varName = importName.replace(/[^a-zA-Z0-9]/g, '_');
64
+
65
+ requires.push(`const ${varName} = require('${requirePath}');`);
66
+ calls.push(`${varName}.default();`);
67
+ });
68
+
69
+ // Build the final content
70
+ const content = `${topOfFileComment}\n${requires.join('\n')}\n\n${calls.join('\n')}`;
71
+
72
+ // Write to the output file
73
+ fs.writeFileSync(outputFile, content, 'utf8');
74
+ };
75
+
76
+ export default genCommandImportFile;
@@ -0,0 +1,29 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import getRootPath from './helpers/getRootPath';
4
+
5
+ /**
6
+ * Generate the dynamic configuration file
7
+ */
8
+ const genDynamicConfigFile = (): string => {
9
+ const root = getRootPath();
10
+
11
+ const outputFile = path.join(root, 'cypress.config.ts');
12
+
13
+ // Create the dynamic configuration file
14
+ const dynamicConfigFile = [
15
+ '// Auto-generated by dceky - do not edit manually',
16
+ '',
17
+ 'import { genConfiguration } from \'dceky\';',
18
+ '',
19
+ 'export default genConfiguration();',
20
+ '',
21
+ ].join('\n');
22
+
23
+ // Write the configuration file directly
24
+ fs.writeFileSync(outputFile, dynamicConfigFile, 'utf8');
25
+
26
+ return outputFile;
27
+ };
28
+
29
+ export default genDynamicConfigFile;
@@ -0,0 +1,13 @@
1
+ import path from 'path';
2
+
3
+ /**
4
+ * Get the root path of the project
5
+ * @author Yuen Ler Chow
6
+ * @returns the root path of the project
7
+ */
8
+ const getRootPath = () => {
9
+ const root = path.join(__dirname, '../../../../');
10
+ return root;
11
+ };
12
+
13
+ export default getRootPath;
package/setup/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ import genCommandImportFile from './genCommandImportFile';
2
+ import genDynamicConfigFile from './genDynamicConfigFile';
3
+ import addToGitIgnore from './addToGitIgnore';
4
+ import setupCypressDependencies from './setupCypressDependencies';
5
+ import checkRequiredFiles from './checkRequiredFiles';
6
+
7
+ checkRequiredFiles();
8
+ genCommandImportFile();
9
+ genDynamicConfigFile();
10
+ addToGitIgnore();
11
+ setupCypressDependencies();
@@ -0,0 +1,38 @@
1
+ /* eslint-disable no-console */
2
+ import getRootPath from './helpers/getRootPath';
3
+
4
+ /**
5
+ * Ensure required packages exist in the consumer repo
6
+ * @author Yuen Ler Chow
7
+ */
8
+ const setupCypressDependencies = (): void => {
9
+ const root = getRootPath();
10
+
11
+ const requiredPkgs = [
12
+ 'cypress-parallel',
13
+ 'cypress-multi-reporters',
14
+ 'mochawesome',
15
+ 'mochawesome-merge',
16
+ 'mochawesome-report-generator',
17
+ ];
18
+
19
+ const missingPkgs = requiredPkgs.filter((pkg) => {
20
+ try {
21
+ // Resolve from the consumer project root
22
+ require.resolve(pkg, { paths: [root] });
23
+ return false;
24
+ } catch {
25
+ return true;
26
+ }
27
+ });
28
+
29
+ if (missingPkgs.length > 0) {
30
+ const installCmd = `npm i -D ${missingPkgs.join(' ')}`;
31
+ console.error(`\nMissing required devDependencies in this project: ${missingPkgs.join(', ')}`);
32
+ console.error('Run the following command, then try again:');
33
+ console.error(`\n${installCmd}\n`);
34
+ process.exit(1);
35
+ }
36
+ };
37
+
38
+ export default setupCypressDependencies;
@@ -0,0 +1,51 @@
1
+ /// <reference types="cypress" />
2
+
3
+ /*----------------------------------------*/
4
+ /* ---------------- Type ---------------- */
5
+ /*----------------------------------------*/
6
+
7
+ declare global {
8
+ namespace Cypress {
9
+ interface Chainable {
10
+ /**
11
+ * Assert that an element does not have a specific className
12
+ * @author Yuen Ler Chow
13
+ * @param opts object containing all arguments
14
+ * @param opts.item the css selector for finding the element
15
+ * @param opts.className the className to check for
16
+ * @return Cypress chainable containing the element that was checked
17
+ */
18
+ assertDoesNotHaveClass(
19
+ opts: {
20
+ item: string,
21
+ className: string,
22
+ },
23
+ ): Chainable<JQuery<HTMLElement>>;
24
+ }
25
+ }
26
+ }
27
+
28
+ /*----------------------------------------*/
29
+ /* --------------- Command -------------- */
30
+ /*----------------------------------------*/
31
+
32
+ const assertDoesNotHaveClass = () => {
33
+ Cypress.Commands.add(
34
+ 'assertDoesNotHaveClass',
35
+ (
36
+ opts: {
37
+ item: string,
38
+ className: string,
39
+ },
40
+ ) => {
41
+ cy.log(`Assert ${opts.item} does not have class ${opts.className}`);
42
+ return cy.get(opts.item).should('not.have.class', opts.className);
43
+ },
44
+ );
45
+ };
46
+
47
+ /*----------------------------------------*/
48
+ /* --------------- Export --------------- */
49
+ /*----------------------------------------*/
50
+
51
+ export default assertDoesNotHaveClass;
@@ -0,0 +1,51 @@
1
+ /// <reference types="cypress" />
2
+
3
+ /*----------------------------------------*/
4
+ /* ---------------- Type ---------------- */
5
+ /*----------------------------------------*/
6
+
7
+ declare global {
8
+ namespace Cypress {
9
+ interface Chainable {
10
+ /**
11
+ * Assert that an element has a specific className
12
+ * @author Yuen Ler Chow
13
+ * @param opts object containing all arguments
14
+ * @param opts.item the css selector for finding the element
15
+ * @param opts.className the className to check for
16
+ * @return Cypress chainable containing the element that was checked
17
+ */
18
+ assertHasClass(
19
+ opts: {
20
+ item: string,
21
+ className: string,
22
+ },
23
+ ): Chainable<JQuery<HTMLElement>>;
24
+ }
25
+ }
26
+ }
27
+
28
+ /*----------------------------------------*/
29
+ /* --------------- Command -------------- */
30
+ /*----------------------------------------*/
31
+
32
+ const assertHasClass = () => {
33
+ Cypress.Commands.add(
34
+ 'assertHasClass',
35
+ (
36
+ opts: {
37
+ item: string,
38
+ className: string,
39
+ },
40
+ ) => {
41
+ cy.log(`Assert ${opts.item} has class ${opts.className}`);
42
+ return cy.get(opts.item).should('have.class', opts.className);
43
+ },
44
+ );
45
+ };
46
+
47
+ /*----------------------------------------*/
48
+ /* --------------- Export --------------- */
49
+ /*----------------------------------------*/
50
+
51
+ export default assertHasClass;