Skip to content

Commit

Permalink
v0.1.0 (#5)
Browse files Browse the repository at this point in the history
* feat(commands): run and open commands added for building config then running/opening cypress
* feat(commands): add support for loading path from `cypress.json`
* feat(core): add prettier
  • Loading branch information
prescottprue authored Jan 8, 2019
1 parent bc3f6e0 commit d7a8439
Show file tree
Hide file tree
Showing 16 changed files with 1,884 additions and 1,594 deletions.
38 changes: 31 additions & 7 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,44 @@
module.exports = {
parser: "babel-eslint",
"extends": "airbnb",
'extends': ['airbnb', 'prettier'],
root: true,
plugins: ['import', 'babel', 'prettier'],
settings: {
'import/resolver': {
node: {
moduleDirectory: ['node_modules', '/']
}
}
},
env: {
browser: true,
node: true
},
rules: {
"comma-dangle": [2, "never"],
"import/prefer-default-export": 0,
"no-shadow": 0,
"consistent-return": 0,
"no-new": 0,
"new-cap": 0,
"max-len": 0,
"brace-style": [2, "stroustrup"]
"prettier/prettier": [
'error',
{
singleQuote: true, // airbnb
trailingComma: 'all', // airbnb
}
]
},
plugins: [
"react"
]
overrides: {
files: ['cmds/**'],
rules: {
"comma-dangle": ["error", { "functions": "never" }],
"prettier/prettier": [
'error',
{
singleQuote: true, // airbnb
trailingComma: 'none', // airbnb
}
]
}
}
}
19 changes: 13 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,19 @@ Tests will run faster locally if you tests against the build version of your app

### Folders

`cypress` is the default folder where config is loaded from, but these other common folders are supported:

```
test/ui
test/e2e
```
`cypress` is the default folder where config is loaded from, but you can use another folder by specifiying a different setting for the `integrationFolder` parameter in `cypress.json`:

```json
{
"projectId": "<- your project id ->",
"fixturesFolder": "test/e2e/fixtures",
"integrationFolder": "test/e2e/integration",
"pluginsFile": "test/e2e/plugins/index.js",
"screenshotsFolder": "test/e2e/screenshots",
"videosFolder": "test/e2e/videos",
"supportFile": "test/e2e/support/index.js"
}
```

## Docs

Expand Down
145 changes: 82 additions & 63 deletions cmds/createTestEnvFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,66 @@

const chalk = require('chalk');
const fs = require('fs');
const fig = require('figures');
const pickBy = require('lodash/pickBy');
const get = require('lodash/get');
const size = require('lodash/size');
const keys = require('lodash/keys');
const isUndefined = require('lodash/isUndefined');
const path = require('path');
const envVarBasedOnCIEnv = require('../lib/utils').envVarBasedOnCIEnv;
const getServiceAccount = require('../lib/utils').getServiceAccount;
const getEnvPrefix = require('../lib/utils').getEnvPrefix;
const constants = require('../lib/constants');
const logger = require('../lib/logger');

const {
DEFAULT_BASE_PATH,
DEFAULT_TEST_ENV_FILE_NAME,
DEFAULT_SERVICE_ACCOUNT_PATH
} = constants;

const testEnvFileFullPath = path.join(DEFAULT_BASE_PATH, DEFAULT_TEST_ENV_FILE_NAME);
const serviceAccountPath = path.join(DEFAULT_BASE_PATH, DEFAULT_SERVICE_ACCOUNT_PATH);
envVarBasedOnCIEnv,
getServiceAccount,
getEnvPrefix,
getCypressFolderPath,
readJsonFile
} = require('../lib/utils');
const {
DEFAULT_CONFIG_FILE_NAME,
DEFAULT_TEST_ENV_FILE_NAME
} = require('../lib/constants');
const {
FIREBASE_CONFIG_FILE_PATH,
TEST_ENV_FILE_PATH
} = require('../lib/filePaths');
const logger = require('../lib/logger');

/**
* @param {functions.Event} event - Function event
* @param {functions.Context} context - Functions context
* @return {Promise}
*/
function createTestEnvFile() {
const envPrefix = getEnvPrefix();

// Get UID from environment (falls back to test/e2e/config.json for local)
function createTestEnvFile(envName) {
const envPrefix = getEnvPrefix(envName);
// Get UID from environment (falls back to cypress/config.json for local)
const uid = envVarBasedOnCIEnv('TEST_UID');

const varName = `${envPrefix}TEST_UID`;
const testFolderPath = getCypressFolderPath();
const configPath = `${testFolderPath}/${DEFAULT_CONFIG_FILE_NAME}`;
// Throw if UID is missing in environment
if (!uid) {
return Promise.reject(new Error(
`${envPrefix}TEST_UID is missing from environment. Confirm that ${
constants.DEFAULT_TEST_FOLDER_PATH
}/config.json contains either ${envPrefix}TEST_UID or TEST_UID.`
));
/* eslint-disable */
const errMsg = `${chalk.cyan(varName)} is missing from environment. Confirm that ${chalk.cyan(configPath)} contains either ${chalk.cyan(varName)} or ${chalk.cyan('TEST_UID')}.`;
/* eslint-enable */
return Promise.reject(new Error(errMsg));
}

const FIREBASE_PROJECT_ID = envVarBasedOnCIEnv('FIREBASE_PROJECT_ID');

logger.info(`Generating custom auth token for Firebase project with projectId: ${chalk.cyan(FIREBASE_PROJECT_ID)}`);
// Get project from .firebaserc
const firebaserc = readJsonFile(FIREBASE_CONFIG_FILE_PATH);
const FIREBASE_PROJECT_ID =
envVarBasedOnCIEnv(`${envPrefix}FIREBASE_PROJECT_ID`) ||
get(
firebaserc,
`projects.${envName}`,
get(firebaserc, 'projects.default', '')
);

logger.info(
`Generating custom auth token for Firebase project with projectId: ${chalk.cyan(
FIREBASE_PROJECT_ID
)}`
);

// Get service account from local file falling back to environment variables
const serviceAccount = getServiceAccount();
const serviceAccount = getServiceAccount(envName);

// Confirm service account has all parameters
const serviceAccountMissingParams = pickBy(serviceAccount, isUndefined);
Expand All @@ -62,16 +75,22 @@ function createTestEnvFile() {
return Promise.reject(new Error(errMsg));
}

// Get project ID from environment variable
const projectId = process.env.GCLOUD_PROJECT || envVarBasedOnCIEnv('FIREBASE_PROJECT_ID');

// Remove firebase- prefix
const cleanedProjectId = projectId.replace('firebase-', '');
const cleanedProjectId = FIREBASE_PROJECT_ID.replace('firebase-', '');

// Handle service account not matching settings in config.json (local)
if (serviceAccount.project_id !== FIREBASE_PROJECT_ID && serviceAccount.project_id !== projectId) {
if (
envName !== 'local' &&
serviceAccount.project_id !== FIREBASE_PROJECT_ID
) {
/* eslint-disable no-console */
logger.warn(`project_id "${chalk.cyan(serviceAccount.project_id)}" does not match env var: "${chalk.cyan(envVarBasedOnCIEnv('FIREBASE_PROJECT_ID'))}"`);
logger.warn(
`project_id in service account (${chalk.cyan(
serviceAccount.project_id
)}) does not match associated project in .firebaserc (${chalk.cyan(
FIREBASE_PROJECT_ID
)})`
);
/* eslint-enable no-console */
}

Expand All @@ -90,22 +109,25 @@ function createTestEnvFile() {
return appFromSA
.auth()
.createCustomToken(uid, { isTesting: true })
.then((customToken) => {
.then(customToken => {
/* eslint-disable no-console */
logger.success(
`Custom token generated successfully, writing to ${chalk.cyan(constants.DEFAULT_TEST_ENV_FILE_NAME)}`
`Custom token generated successfully, writing to ${chalk.cyan(
DEFAULT_TEST_ENV_FILE_NAME
)}`
);
/* eslint-enable no-console */
// Remove firebase app
appFromSA.delete();
const currentCypressEnvSettings = readJsonFile(TEST_ENV_FILE_PATH);

// Create config object to be written into test env file
const newCypressConfig = {
// Create config object to be written into test env file by combining with existing config
const newCypressConfig = Object.assign({}, currentCypressEnvSettings, {
TEST_UID: envVarBasedOnCIEnv('TEST_UID'),
FIREBASE_API_KEY: envVarBasedOnCIEnv('FIREBASE_API_KEY'),
FIREBASE_PROJECT_ID,
FIREBASE_AUTH_JWT: customToken
};
});
const stageProjectId = envVarBasedOnCIEnv('STAGE_FIREBASE_PROJECT_ID');
const stageApiKey = envVarBasedOnCIEnv('STAGE_FIREBASE_API_KEY');

Expand All @@ -115,23 +137,17 @@ function createTestEnvFile() {
}

// Write config file to cypress.env.json
fs.writeFileSync(testEnvFileFullPath, JSON.stringify(newCypressConfig, null, 2));

logger.success(`${chalk.cyan(constants.DEFAULT_TEST_ENV_FILE_NAME)} updated successfully`);

// Create service account file if it does not already exist (for use in reporter)
if (!fs.existsSync(serviceAccountPath)) {
// Write service account file as string
fs.writeFileSync(
serviceAccountPath,
JSON.stringify(serviceAccount, null, 2)
);
fs.writeFileSync(
TEST_ENV_FILE_PATH,
JSON.stringify(newCypressConfig, null, 2)
);

logger.success(`${chalk.cyan('serviceAccount.json')} created successfully`);
}
logger.success(
`${chalk.cyan(DEFAULT_TEST_ENV_FILE_NAME)} updated successfully`
);
return customToken;
})
.catch((err) => {
.catch(err => {
/* eslint-disable no-console */
logger.error(
`Custom token could not be generated for uid: ${chalk.cyan(uid)}`,
Expand All @@ -151,17 +167,20 @@ function createTestEnvFile() {
* # make sure you serviceAccount.json exists
* cypress-firebase createEnv
*/
module.exports = function (program) {
module.exports = function runCreateTestEnvFile(program) {
program
.command('createTestEnvFile')
.command('createTestEnvFile [envName]')
.description(
'Build configuration file containing a token for authorizing a firebase instance'
)
.action((directory, options) => createTestEnvFile(options)
.then(() => process.exit(0))
.catch((err) => {
logger.error(`Test env file could not be created:\n${err.message}`);
process.exit(1);
return Promise.reject(err);
}));
.action(envArg => {
const envName = typeof envArg === 'string' ? envArg : 'local';
return createTestEnvFile(envName)
.then(() => process.exit(0))
.catch(err => {
logger.error(`Test env file could not be created:\n${err.message}`);
process.exit(1);
return Promise.reject(err);
});
});
};
2 changes: 2 additions & 0 deletions cmds/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ module.exports = function setupCommands(client) {
}

client.createTestEnvFile = loadCommand('createTestEnvFile');
client.run = loadCommand('run');
client.open = loadCommand('open');

return client;
};
35 changes: 35 additions & 0 deletions cmds/open.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* run commander component
* To use add require('../cmds/run.js')(program) to your commander.js based node executable before program.parse
*/

const chalk = require('chalk');
const { runCommand } = require('../lib/utils');
const logger = require('../lib/logger');

/**
* @name open
* @description Create test environment config then open Cypress Test Runner
* @param {String} envName
*/
module.exports = function open(program) {
program
.command('open [envName]')
.description(
'Build configuration file containing a token for authorizing a firebase instance'
)
.action((envArg) => {
const envName = typeof envArg === 'string' ? envArg : 'local';
return runCommand({ command: `cypress-firebase createTestEnvFile ${envName}` })
.then(() => {
logger.info(`Opening test runner for environment: ${chalk.cyan(envName)}`);
return runCommand({ command: 'npx', args: ['cypress', 'open', '--env', `envName=${envName}`] });
})
.then(() => process.exit(0))
.catch((err) => {
logger.error(`Test runner open could not be completed:\n${err.message}`);
process.exit(1);
return Promise.reject(err);
});
});
};
35 changes: 35 additions & 0 deletions cmds/run.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* run commander component
* To use add require('../cmds/run.js')(program) to your commander.js based node executable before program.parse
*/

const chalk = require('chalk');
const { runCommand } = require('../lib/utils');
const logger = require('../lib/logger');

/**
* @name run
* @description Deploy to Firebase only on build branches (master, stage, prod)
* @param {String} envName
*/
module.exports = function run(program) {
program
.command('run [envName]')
.description(
'Build configuration file containing a token for authorizing a firebase instance'
)
.action((envArg) => {
const envName = typeof envArg === 'string' ? envArg : 'local';
return runCommand({ command: `cypress-firebase createTestEnvFile ${envName}` })
.then(() => {
logger.info(`Starting test run for environment: ${chalk.cyan(envName)}`);
return runCommand({ command: 'npx', args: ['cypress', 'run', '--env', `envName=${envName}`] });
})
.then(() => process.exit(0))
.catch((err) => {
logger.error(`Run could not be completed:\n${err.message}`);
process.exit(1);
return Promise.reject(err);
});
});
};
Loading

0 comments on commit d7a8439

Please sign in to comment.