dceky 1.0.0-beta.5 → 1.0.2
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/.eslintrc.js +93 -0
- package/README.md +41 -0
- package/cypress/e2e/profile-test.cy.ts +10 -0
- package/cypress/fixtures/example.json +5 -0
- package/cypress/support/commands.ts +37 -0
- package/cypress/support/e2e.ts +17 -0
- package/cypress.config.ts +9 -0
- package/docs/GlobalsAndProfiles.md +23 -0
- package/lib/setup/addToGitIgnore.d.ts +6 -0
- package/lib/setup/addToGitIgnore.js +46 -0
- package/lib/setup/addToGitIgnore.js.map +1 -0
- package/lib/setup/checkRequiredFiles.d.ts +6 -0
- package/lib/setup/checkRequiredFiles.js +58 -0
- package/lib/setup/checkRequiredFiles.js.map +1 -0
- package/lib/setup/genCommandImportFile.d.ts +7 -0
- package/lib/setup/genCommandImportFile.js +66 -0
- package/lib/setup/genCommandImportFile.js.map +1 -0
- package/lib/setup/genConfiguration/helpers/resolveDependents.d.ts +13 -0
- package/lib/setup/genConfiguration/helpers/resolveDependents.js +50 -0
- package/lib/setup/genConfiguration/helpers/resolveDependents.js.map +1 -0
- package/lib/setup/genConfiguration/helpers/splitEnv.d.ts +10 -0
- package/lib/setup/genConfiguration/helpers/splitEnv.js +27 -0
- package/lib/setup/genConfiguration/helpers/splitEnv.js.map +1 -0
- package/lib/setup/genConfiguration/index.d.ts +15 -0
- package/lib/setup/genConfiguration/index.js +86 -0
- package/lib/setup/genConfiguration/index.js.map +1 -0
- package/lib/setup/genConfiguration/types/DependentValue.d.ts +11 -0
- package/lib/setup/genConfiguration/types/DependentValue.js +3 -0
- package/lib/setup/genConfiguration/types/DependentValue.js.map +1 -0
- package/lib/setup/genConfiguration/types/GlobalsOrProfile.d.ts +9 -0
- package/lib/setup/genConfiguration/types/GlobalsOrProfile.js +3 -0
- package/lib/setup/genConfiguration/types/GlobalsOrProfile.js.map +1 -0
- package/lib/setup/genConfiguration/types/SplitEnv.d.ts +13 -0
- package/lib/setup/genConfiguration/types/SplitEnv.js +3 -0
- package/lib/setup/genConfiguration/types/SplitEnv.js.map +1 -0
- package/lib/setup/genConfigurationFile.d.ts +2 -0
- package/lib/setup/genConfigurationFile.js +63 -0
- package/lib/setup/genConfigurationFile.js.map +1 -0
- package/lib/setup/genDynamicConfigFile.d.ts +5 -0
- package/lib/setup/genDynamicConfigFile.js +28 -0
- package/lib/setup/genDynamicConfigFile.js.map +1 -0
- package/lib/setup/index.d.ts +1 -0
- package/lib/setup/index.js +16 -0
- package/lib/setup/index.js.map +1 -0
- package/lib/setup/setupCypressDependencies.d.ts +6 -0
- package/lib/setup/setupCypressDependencies.js +40 -0
- package/lib/setup/setupCypressDependencies.js.map +1 -0
- package/lib/src/commands/assertDoesNotHaveClass.d.ts +20 -0
- package/lib/src/commands/assertDoesNotHaveClass.js +17 -0
- package/lib/src/commands/assertDoesNotHaveClass.js.map +1 -0
- package/lib/src/commands/assertHasClass.d.ts +20 -0
- package/lib/src/commands/assertHasClass.js +17 -0
- package/lib/src/commands/assertHasClass.js.map +1 -0
- package/lib/src/commands/assertNumElements.d.ts +19 -0
- package/lib/src/commands/assertNumElements.js +17 -0
- package/lib/src/commands/assertNumElements.js.map +1 -0
- package/lib/src/commands/extractDataFromClass.d.ts +18 -0
- package/lib/src/commands/extractDataFromClass.js +25 -0
- package/lib/src/commands/extractDataFromClass.js.map +1 -0
- package/lib/src/commands/extractDataFromClassByContents.d.ts +19 -0
- package/lib/src/commands/extractDataFromClassByContents.js +26 -0
- package/lib/src/commands/extractDataFromClassByContents.js.map +1 -0
- package/lib/src/commands/getJSON.d.ts +16 -0
- package/lib/src/commands/getJSON.js +21 -0
- package/lib/src/commands/getJSON.js.map +1 -0
- package/lib/src/commands/getNumElements.d.ts +15 -0
- package/lib/src/commands/getNumElements.js +19 -0
- package/lib/src/commands/getNumElements.js.map +1 -0
- package/lib/src/commands/handleHarvardKey.d.ts +15 -0
- package/lib/src/commands/handleHarvardKey.js +53 -0
- package/lib/src/commands/handleHarvardKey.js.map +1 -0
- package/lib/src/commands/launchAs.d.ts +25 -0
- package/lib/src/commands/launchAs.js +66 -0
- package/lib/src/commands/launchAs.js.map +1 -0
- package/lib/src/commands/launchLTIUsingToken.d.ts +21 -0
- package/lib/src/commands/launchLTIUsingToken.js +68 -0
- package/lib/src/commands/launchLTIUsingToken.js.map +1 -0
- package/lib/src/commands/navigateToHref.d.ts +15 -0
- package/lib/src/commands/navigateToHref.js +35 -0
- package/lib/src/commands/navigateToHref.js.map +1 -0
- package/lib/src/commands/runScript.d.ts +15 -0
- package/lib/src/commands/runScript.js +20 -0
- package/lib/src/commands/runScript.js.map +1 -0
- package/lib/src/commands/typeInto.d.ts +24 -0
- package/lib/src/commands/typeInto.js +41 -0
- package/lib/src/commands/typeInto.js.map +1 -0
- package/lib/src/commands/visitCanvasGETEndpoint.d.ts +20 -0
- package/lib/src/commands/visitCanvasGETEndpoint.js +26 -0
- package/lib/src/commands/visitCanvasGETEndpoint.js.map +1 -0
- package/lib/src/commands/waitForElementVisible.d.ts +16 -0
- package/lib/src/commands/waitForElementVisible.js +19 -0
- package/lib/src/commands/waitForElementVisible.js.map +1 -0
- package/lib/src/genConfiguration/helpers/resolveDependents.d.ts +13 -0
- package/lib/src/genConfiguration/helpers/resolveDependents.js +50 -0
- package/lib/src/genConfiguration/helpers/resolveDependents.js.map +1 -0
- package/lib/src/genConfiguration/helpers/splitEnv.d.ts +10 -0
- package/lib/src/genConfiguration/helpers/splitEnv.js +27 -0
- package/lib/src/genConfiguration/helpers/splitEnv.js.map +1 -0
- package/{src/genConfiguration.ts → lib/src/genConfiguration/index.d.ts} +3 -6
- package/lib/src/genConfiguration/index.js +88 -0
- package/lib/src/genConfiguration/index.js.map +1 -0
- package/lib/src/genConfiguration/types/DependentValue.d.ts +11 -0
- package/lib/src/genConfiguration/types/DependentValue.js +3 -0
- package/lib/src/genConfiguration/types/DependentValue.js.map +1 -0
- package/lib/src/genConfiguration/types/GlobalsOrProfile.d.ts +9 -0
- package/lib/src/genConfiguration/types/GlobalsOrProfile.js +3 -0
- package/lib/src/genConfiguration/types/GlobalsOrProfile.js.map +1 -0
- package/lib/src/genConfiguration/types/SplitEnv.d.ts +13 -0
- package/lib/src/genConfiguration/types/SplitEnv.js +3 -0
- package/lib/src/genConfiguration/types/SplitEnv.js.map +1 -0
- package/lib/{index.d.ts → src/index.d.ts} +1 -1
- package/lib/{index.js → src/index.js} +6 -3
- package/lib/src/index.js.map +1 -0
- package/lib/src/init.d.ts +6 -0
- package/lib/src/init.js +45 -0
- package/lib/src/init.js.map +1 -0
- package/lib/start/constants/AVAILABLE_BROWSERS.d.ts +9 -0
- package/lib/start/constants/AVAILABLE_BROWSERS.js +27 -0
- package/lib/start/constants/AVAILABLE_BROWSERS.js.map +1 -0
- package/lib/start/helpers/exec.d.ts +8 -0
- package/lib/start/helpers/exec.js +18 -0
- package/lib/start/helpers/exec.js.map +1 -0
- package/lib/start/helpers/extractArgValue.d.ts +10 -0
- package/lib/start/helpers/extractArgValue.js +39 -0
- package/lib/start/helpers/extractArgValue.js.map +1 -0
- package/lib/start/helpers/findProfilesByNames.d.ts +16 -0
- package/lib/start/helpers/findProfilesByNames.js +35 -0
- package/lib/start/helpers/findProfilesByNames.js.map +1 -0
- package/lib/start/helpers/parseCommaSeparated.d.ts +8 -0
- package/lib/start/helpers/parseCommaSeparated.js +23 -0
- package/lib/start/helpers/parseCommaSeparated.js.map +1 -0
- package/lib/start/helpers/print.d.ts +38 -0
- package/lib/start/helpers/print.js +145 -0
- package/lib/start/helpers/print.js.map +1 -0
- package/lib/start/helpers/prompt.d.ts +8 -0
- package/lib/start/helpers/prompt.js +25 -0
- package/lib/start/helpers/prompt.js.map +1 -0
- package/lib/start/helpers/showChooser.d.ts +21 -0
- package/lib/start/helpers/showChooser.js +116 -0
- package/lib/start/helpers/showChooser.js.map +1 -0
- package/lib/start/helpers/validateBrowsers.d.ts +8 -0
- package/lib/start/helpers/validateBrowsers.js +36 -0
- package/lib/start/helpers/validateBrowsers.js.map +1 -0
- package/lib/start/index.d.ts +7 -0
- package/lib/start/index.js +139 -0
- package/lib/start/index.js.map +1 -0
- package/lib/start/types/ChooserOption.d.ts +10 -0
- package/lib/start/types/ChooserOption.js +3 -0
- package/lib/start/types/ChooserOption.js.map +1 -0
- package/package.json +28 -8
- package/setup/addToGitIgnore.ts +47 -0
- package/setup/checkRequiredFiles.ts +62 -0
- package/setup/genCommandImportFile.ts +75 -0
- package/setup/genDynamicConfigFile.ts +28 -0
- package/setup/index.ts +11 -0
- package/setup/setupCypressDependencies.ts +38 -0
- package/src/commands/assertDoesNotHaveClass.ts +51 -0
- package/src/commands/assertHasClass.ts +51 -0
- package/src/commands/assertNumElements.ts +50 -0
- package/src/commands/extractDataFromClass.ts +52 -0
- package/src/commands/extractDataFromClassByContents.ts +55 -0
- package/src/commands/getJSON.ts +45 -0
- package/src/commands/getNumElements.ts +45 -0
- package/src/commands/handleHarvardKey.ts +91 -0
- package/src/commands/launchAs.ts +120 -0
- package/src/commands/launchLTIUsingToken.ts +115 -0
- package/src/commands/navigateToHref.ts +60 -0
- package/src/commands/runScript.ts +44 -0
- package/src/commands/typeInto.ts +88 -0
- package/src/commands/visitCanvasGETEndpoint.ts +61 -0
- package/src/commands/waitForElementVisible.ts +49 -0
- package/src/genConfiguration/helpers/resolveDependents.ts +47 -0
- package/src/genConfiguration/helpers/splitEnv.ts +30 -0
- package/src/genConfiguration/index.ts +94 -0
- package/src/genConfiguration/types/DependentValue.ts +14 -0
- package/src/genConfiguration/types/GlobalsOrProfile.ts +12 -0
- package/src/genConfiguration/types/SplitEnv.ts +18 -0
- package/src/index.ts +7 -4
- package/src/init.ts +36 -27
- package/start/constants/AVAILABLE_BROWSERS.ts +28 -0
- package/start/helpers/exec.ts +17 -0
- package/start/helpers/extractArgValue.ts +42 -0
- package/start/helpers/findProfilesByNames.ts +39 -0
- package/start/helpers/parseCommaSeparated.ts +23 -0
- package/start/helpers/print.ts +155 -0
- package/start/helpers/prompt.ts +23 -0
- package/start/helpers/showChooser.ts +140 -0
- package/start/helpers/validateBrowsers.ts +35 -0
- package/start/index.ts +163 -0
- package/start/types/ChooserOption.ts +11 -0
- package/tsconfig.json +3 -4
- package/.eslintrc.json +0 -58
- package/lib/genConfiguration.d.ts +0 -8
- package/lib/genConfiguration.js +0 -13
- package/lib/genConfiguration.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/init.d.ts +0 -13
- package/lib/init.js +0 -19
- package/lib/init.js.map +0 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Ensure gitignore includes the necessary entries for Cypress results
|
|
7
|
+
* @author Yuen Ler Chow
|
|
8
|
+
*/
|
|
9
|
+
const addToGitIgnore = (): void => {
|
|
10
|
+
const root = path.join(__dirname, '../..');
|
|
11
|
+
|
|
12
|
+
const gitignorePath = path.join(root, '.gitignore');
|
|
13
|
+
|
|
14
|
+
const entries = [
|
|
15
|
+
'cypress-results/',
|
|
16
|
+
'cypress/downloads',
|
|
17
|
+
'cypress/screenshots',
|
|
18
|
+
'cypress/videos',
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
let gitignoreContent = '';
|
|
22
|
+
if (existsSync(gitignorePath)) {
|
|
23
|
+
gitignoreContent = readFileSync(gitignorePath, 'utf8');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Check which entries are missing
|
|
27
|
+
const missingEntries = entries.filter((entry) => {
|
|
28
|
+
// Check if entry exists (with or without newline)
|
|
29
|
+
const regex = new RegExp(`^${entry.replace(/\//g, '\\/')}$`, 'm');
|
|
30
|
+
return !regex.test(gitignoreContent);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Add missing entries
|
|
34
|
+
if (missingEntries.length > 0) {
|
|
35
|
+
if (gitignoreContent && !gitignoreContent.endsWith('\n')) {
|
|
36
|
+
gitignoreContent += '\n';
|
|
37
|
+
}
|
|
38
|
+
gitignoreContent += '\n# Cypress parallel test results (added by dceky)\n';
|
|
39
|
+
missingEntries.forEach((entry) => {
|
|
40
|
+
gitignoreContent += `${entry}\n`;
|
|
41
|
+
});
|
|
42
|
+
writeFileSync(gitignorePath, gitignoreContent, 'utf8');
|
|
43
|
+
console.log(`Added ${missingEntries.length} entries to .gitignore`);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default addToGitIgnore;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Ensure required configuration files exist in the consumer repo
|
|
7
|
+
* @author Yuen Ler Chow
|
|
8
|
+
*/
|
|
9
|
+
const checkRequiredFiles = (): void => {
|
|
10
|
+
const root = path.join(__dirname, '../..');
|
|
11
|
+
|
|
12
|
+
const globalsPath = path.join(root, 'cypress/globals');
|
|
13
|
+
const profilesPath = path.join(root, 'cypress/profiles');
|
|
14
|
+
|
|
15
|
+
// Common file extensions to check
|
|
16
|
+
const extensions = ['.js', '.ts', '.json', '.mjs', '.cjs'];
|
|
17
|
+
|
|
18
|
+
// Required global files
|
|
19
|
+
const requiredGlobals = [
|
|
20
|
+
'GlobalCredentials',
|
|
21
|
+
'GlobalResources',
|
|
22
|
+
'GlobalValues',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
// Determine profile file name (default is stage)
|
|
26
|
+
const profileName = process.env.CYPRESS_PROFILE || 'stage';
|
|
27
|
+
const requiredProfile = `${profileName}.Profile`;
|
|
28
|
+
|
|
29
|
+
// Check for missing files
|
|
30
|
+
const missingFiles: string[] = [];
|
|
31
|
+
|
|
32
|
+
// Check global files
|
|
33
|
+
requiredGlobals.forEach((file) => {
|
|
34
|
+
const filePath = path.join(globalsPath, file);
|
|
35
|
+
const found = extensions.some((ext) => {
|
|
36
|
+
return existsSync(`${filePath}${ext}`);
|
|
37
|
+
});
|
|
38
|
+
if (!found) {
|
|
39
|
+
missingFiles.push(`cypress/globals/${file}.ts`);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Check profile file
|
|
44
|
+
const profileFilePath = path.join(profilesPath, requiredProfile);
|
|
45
|
+
const profileFound = extensions.some((ext) => {
|
|
46
|
+
return existsSync(`${profileFilePath}${ext}`);
|
|
47
|
+
});
|
|
48
|
+
if (!profileFound) {
|
|
49
|
+
missingFiles.push(`cypress/profiles/${requiredProfile}.ts`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (missingFiles.length > 0) {
|
|
53
|
+
console.error('\nMissing required configuration files in this project:');
|
|
54
|
+
missingFiles.forEach((file) => {
|
|
55
|
+
console.error(` - ${file}`);
|
|
56
|
+
});
|
|
57
|
+
console.error('\nPlease create these files before running setup.');
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export default checkRequiredFiles;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Generate an index.ts file that imports and runs all command files in cypress/commands
|
|
6
|
+
* This should be called from cypress.config.js
|
|
7
|
+
* @author Yuen Ler Chow
|
|
8
|
+
*/
|
|
9
|
+
const genCommandImportFile = () => {
|
|
10
|
+
const root = path.join(__dirname, '../..');
|
|
11
|
+
|
|
12
|
+
const cypressCommandsDir = path.join(root, 'cypress/commands');
|
|
13
|
+
const outputFile = path.join(cypressCommandsDir, 'index.ts');
|
|
14
|
+
const topOfFileComment = '// Auto-generated by dceky - do not edit manually';
|
|
15
|
+
|
|
16
|
+
// Check if the directory exists
|
|
17
|
+
if (!fs.existsSync(cypressCommandsDir)) {
|
|
18
|
+
// Create the directory
|
|
19
|
+
fs.mkdirSync(cypressCommandsDir, { recursive: true });
|
|
20
|
+
// Create an empty file so init doesn't fail
|
|
21
|
+
fs.writeFileSync(outputFile, `${topOfFileComment}\n`);
|
|
22
|
+
return outputFile;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Get all files in the directory
|
|
26
|
+
const files = fs.readdirSync(cypressCommandsDir);
|
|
27
|
+
const commandFiles: string[] = [];
|
|
28
|
+
|
|
29
|
+
// Filter out non-JS/TS files and process each file
|
|
30
|
+
files.forEach((file) => {
|
|
31
|
+
// Skip non-JS/TS files (like .d.ts, .map, etc.)
|
|
32
|
+
if (!file.endsWith('.js') && !file.endsWith('.ts')) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Skip index files
|
|
37
|
+
if (file === 'index.js' || file === 'index.ts') {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Determine the file's path
|
|
42
|
+
const filePath = path.join(cypressCommandsDir, file);
|
|
43
|
+
|
|
44
|
+
// Check if it's a file (not a directory)
|
|
45
|
+
const stats = fs.statSync(filePath);
|
|
46
|
+
if (!stats.isFile()) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Store the file name
|
|
51
|
+
commandFiles.push(file);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Generate require statements and function calls
|
|
55
|
+
const requires: string[] = [];
|
|
56
|
+
const calls: string[] = [];
|
|
57
|
+
|
|
58
|
+
commandFiles.forEach((file) => {
|
|
59
|
+
const requirePath = `./${file}`;
|
|
60
|
+
// Create a safe variable name (replace non-alphanumeric with underscore)
|
|
61
|
+
const importName = file.replace(/\.(js|ts)$/, '');
|
|
62
|
+
const varName = importName.replace(/[^a-zA-Z0-9]/g, '_');
|
|
63
|
+
|
|
64
|
+
requires.push(`const ${varName} = require('${requirePath}');`);
|
|
65
|
+
calls.push(`${varName}.default();`);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Build the final content
|
|
69
|
+
const content = `${topOfFileComment}\n${requires.join('\n')}\n\n${calls.join('\n')}`;
|
|
70
|
+
|
|
71
|
+
// Write to the output file
|
|
72
|
+
fs.writeFileSync(outputFile, content, 'utf8');
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export default genCommandImportFile;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Generate the dynamic configuration file
|
|
6
|
+
*/
|
|
7
|
+
const genDynamicConfigFile = (): string => {
|
|
8
|
+
const root = path.join(__dirname, '../..');
|
|
9
|
+
|
|
10
|
+
const outputFile = path.join(root, 'cypress.config.ts');
|
|
11
|
+
|
|
12
|
+
// Create the dynamic configuration file
|
|
13
|
+
const dynamicConfigFile = [
|
|
14
|
+
'// Auto-generated by dceky - do not edit manually',
|
|
15
|
+
'',
|
|
16
|
+
'import { genConfiguration } from \'dceky\';',
|
|
17
|
+
'',
|
|
18
|
+
'export default genConfiguration();',
|
|
19
|
+
'',
|
|
20
|
+
].join('\n');
|
|
21
|
+
|
|
22
|
+
// Write the configuration file directly
|
|
23
|
+
fs.writeFileSync(outputFile, dynamicConfigFile, 'utf8');
|
|
24
|
+
|
|
25
|
+
return outputFile;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default genDynamicConfigFile;
|
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 path from 'path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Ensure required packages exist in the consumer repo
|
|
6
|
+
* @author Yuen Ler Chow
|
|
7
|
+
*/
|
|
8
|
+
const setupCypressDependencies = (): void => {
|
|
9
|
+
const root = path.join(__dirname, '../..');
|
|
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;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
/*----------------------------------------*/
|
|
4
|
+
/* ---------------- Type ---------------- */
|
|
5
|
+
/*----------------------------------------*/
|
|
6
|
+
|
|
7
|
+
declare global {
|
|
8
|
+
namespace Cypress {
|
|
9
|
+
interface Chainable {
|
|
10
|
+
/**
|
|
11
|
+
* Assert a certain number of elements
|
|
12
|
+
* @author Yuen Ler Chow
|
|
13
|
+
* @param opts object containing all arguments
|
|
14
|
+
* @param opts.item a CSS selector corresponding to the item
|
|
15
|
+
* @param opts.num the precise number of elements expected
|
|
16
|
+
*/
|
|
17
|
+
assertNumElements(
|
|
18
|
+
opts: {
|
|
19
|
+
item: string,
|
|
20
|
+
num: number,
|
|
21
|
+
}
|
|
22
|
+
): Chainable<Element>;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/*----------------------------------------*/
|
|
28
|
+
/* --------------- Command -------------- */
|
|
29
|
+
/*----------------------------------------*/
|
|
30
|
+
|
|
31
|
+
const assertNumElements = () => {
|
|
32
|
+
Cypress.Commands.add(
|
|
33
|
+
'assertNumElements',
|
|
34
|
+
(
|
|
35
|
+
opts: {
|
|
36
|
+
item: string,
|
|
37
|
+
num: number,
|
|
38
|
+
},
|
|
39
|
+
) => {
|
|
40
|
+
cy.log(`Assert ${opts.num} elements match ${opts.item}`);
|
|
41
|
+
cy.get(opts.item).should('have.length', opts.num);
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/*----------------------------------------*/
|
|
47
|
+
/* --------------- Export --------------- */
|
|
48
|
+
/*----------------------------------------*/
|
|
49
|
+
|
|
50
|
+
export default assertNumElements;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
/*----------------------------------------*/
|
|
4
|
+
/* ---------------- Type ---------------- */
|
|
5
|
+
/*----------------------------------------*/
|
|
6
|
+
|
|
7
|
+
declare global {
|
|
8
|
+
namespace Cypress {
|
|
9
|
+
interface Chainable {
|
|
10
|
+
/**
|
|
11
|
+
* Obtain data from a class attribute that starts with a specific prefix
|
|
12
|
+
* and return it
|
|
13
|
+
* @author Allison Zhang
|
|
14
|
+
* @param selector the css selector for finding the element
|
|
15
|
+
* @param classPrefix the prefix to look for in the class attribute
|
|
16
|
+
* @returns the extracted data
|
|
17
|
+
* @example cy.extractDataFromClass('.item', 'data-').then((data) => { ... })
|
|
18
|
+
*/
|
|
19
|
+
extractDataFromClass(
|
|
20
|
+
selector: string,
|
|
21
|
+
classPrefix: string,
|
|
22
|
+
): Chainable<string[]>;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/*----------------------------------------*/
|
|
28
|
+
/* --------------- Command -------------- */
|
|
29
|
+
/*----------------------------------------*/
|
|
30
|
+
|
|
31
|
+
const extractDataFromClass = () => {
|
|
32
|
+
Cypress.Commands.add('extractDataFromClass', (selector: string, classPrefix: string) => {
|
|
33
|
+
return (
|
|
34
|
+
cy
|
|
35
|
+
.get(selector)
|
|
36
|
+
.invoke('attr', 'class')
|
|
37
|
+
.then((classAttr: string) => {
|
|
38
|
+
const classList = classAttr.split(' ');
|
|
39
|
+
const data = classList
|
|
40
|
+
.filter((className) => { return className.startsWith(classPrefix); })
|
|
41
|
+
.map((className) => { return className.replace(classPrefix, ''); });
|
|
42
|
+
return data;
|
|
43
|
+
})
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/*----------------------------------------*/
|
|
49
|
+
/* --------------- Export --------------- */
|
|
50
|
+
/*----------------------------------------*/
|
|
51
|
+
|
|
52
|
+
export default extractDataFromClass;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
/*----------------------------------------*/
|
|
4
|
+
/* ---------------- Type ---------------- */
|
|
5
|
+
/*----------------------------------------*/
|
|
6
|
+
|
|
7
|
+
declare global {
|
|
8
|
+
namespace Cypress {
|
|
9
|
+
interface Chainable {
|
|
10
|
+
/**
|
|
11
|
+
* Obtain data from a class attribute that starts with a specific prefix
|
|
12
|
+
* and with specific contents, and return it
|
|
13
|
+
* @author Allison Zhang
|
|
14
|
+
* @param contents the contents of the element to find
|
|
15
|
+
* @param selector the css selector for finding the element
|
|
16
|
+
* @param classPrefix the prefix to look for in the class attribute
|
|
17
|
+
* @returns the extracted data
|
|
18
|
+
* @example cy.extractDataFromClassByContents('Submit', '.button', 'btn-').then((data) => { ... })
|
|
19
|
+
*/
|
|
20
|
+
extractDataFromClassByContents(
|
|
21
|
+
contents: string,
|
|
22
|
+
selector: string,
|
|
23
|
+
classPrefix: string,
|
|
24
|
+
): Chainable<string[]>;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/*----------------------------------------*/
|
|
30
|
+
/* --------------- Command -------------- */
|
|
31
|
+
/*----------------------------------------*/
|
|
32
|
+
|
|
33
|
+
const extractDataFromClassByContents = () => {
|
|
34
|
+
Cypress.Commands.add('extractDataFromClassByContents', (contents: string, selector: string, classPrefix: string) => {
|
|
35
|
+
return (
|
|
36
|
+
cy
|
|
37
|
+
.get(selector)
|
|
38
|
+
.contains(contents)
|
|
39
|
+
.invoke('attr', 'class')
|
|
40
|
+
.then((classAttr: string) => {
|
|
41
|
+
const classList = classAttr.split(' ');
|
|
42
|
+
const data = classList
|
|
43
|
+
.filter((className) => { return className.startsWith(classPrefix); })
|
|
44
|
+
.map((className) => { return className.replace(classPrefix, ''); });
|
|
45
|
+
return data;
|
|
46
|
+
})
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/*----------------------------------------*/
|
|
52
|
+
/* --------------- Export --------------- */
|
|
53
|
+
/*----------------------------------------*/
|
|
54
|
+
|
|
55
|
+
export default extractDataFromClassByContents;
|
|
@@ -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
|
+
* Obtain JSON data from a request and return it.
|
|
12
|
+
* @author Allison Zhang
|
|
13
|
+
* @param url the URL to fetch the JSON data from
|
|
14
|
+
* @returns the JSON data
|
|
15
|
+
* @example cy.getJSON('https://api.example.com/data').then((data) => { ... })
|
|
16
|
+
*/
|
|
17
|
+
getJSON(
|
|
18
|
+
url: string,
|
|
19
|
+
): Chainable<any>;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/*----------------------------------------*/
|
|
25
|
+
/* --------------- Command -------------- */
|
|
26
|
+
/*----------------------------------------*/
|
|
27
|
+
|
|
28
|
+
const getJSON = () => {
|
|
29
|
+
Cypress.Commands.add('getJSON', (url: string) => {
|
|
30
|
+
return (
|
|
31
|
+
cy
|
|
32
|
+
.request(url)
|
|
33
|
+
.its('body')
|
|
34
|
+
.then((body) => {
|
|
35
|
+
return body;
|
|
36
|
+
})
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/*----------------------------------------*/
|
|
42
|
+
/* --------------- Export --------------- */
|
|
43
|
+
/*----------------------------------------*/
|
|
44
|
+
|
|
45
|
+
export default getJSON;
|
|
@@ -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
|
+
* Get number of elements
|
|
12
|
+
* @author Yuen Ler Chow
|
|
13
|
+
* @param selector a CSS selector corresponding to the item to count
|
|
14
|
+
* @return Cypress chainable containing the number of elements matching the selector
|
|
15
|
+
*/
|
|
16
|
+
getNumElements(
|
|
17
|
+
selector: string,
|
|
18
|
+
): Chainable<number>;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/*----------------------------------------*/
|
|
24
|
+
/* --------------- Command -------------- */
|
|
25
|
+
/*----------------------------------------*/
|
|
26
|
+
|
|
27
|
+
const getNumElements = () => {
|
|
28
|
+
Cypress.Commands.add(
|
|
29
|
+
'getNumElements',
|
|
30
|
+
(
|
|
31
|
+
selector: string,
|
|
32
|
+
) => {
|
|
33
|
+
cy.log(`Count elements matching ${selector}`);
|
|
34
|
+
return cy.get(selector).then(($elements: JQuery<HTMLElement>) => {
|
|
35
|
+
return Cypress.$($elements).length;
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/*----------------------------------------*/
|
|
42
|
+
/* --------------- Export --------------- */
|
|
43
|
+
/*----------------------------------------*/
|
|
44
|
+
|
|
45
|
+
export default getNumElements;
|