Skip to content

Commit

Permalink
Merge pull request #1 from wheniwork/feature/first-build
Browse files Browse the repository at this point in the history
first build of component
  • Loading branch information
mlund01 authored May 3, 2018
2 parents efea185 + 5941f7c commit 3ced2d6
Show file tree
Hide file tree
Showing 19 changed files with 2,272 additions and 947 deletions.
8 changes: 7 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
{
"presets": ["react", "es2015"]
"presets": ["env", "stage-0", "react"],
"plugins": ["syntax-dynamic-import"],
"env": {
"test": {
"plugins": ["dynamic-import-node"]
}
}
}
107 changes: 71 additions & 36 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,47 +1,82 @@
{
"globals": {
"Stripe": false,
"CONFIG": false,
"React": true,
"analytics": true
},
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true,
"experimentalObjectRestSpread": true
}
},
"env": {
"browser": true,
"node": true,
"es6": true,
"jest": true,
"jasmine": true
},
"parser": "babel-eslint",
"plugins": ["react"],
"extends": ["eslint:recommended", "plugin:react/recommended"],
"plugins": ["react", "jsx-a11y", "import", "flowtype"],
"rules": {
"comma-dangle": 0,
"no-cond-assign": [2, "always"],
"no-extra-boolean-cast": 0,

"curly": 2,
"default-case": 2,
"eqeqeq": 2,
"no-case-declarations": 2,
"no-else-return": 2,
"no-fallthrough": 2,
"no-redeclare": 2,
"no-warning-comments": [1, { "terms": ["todo"], "location": "start" }],

"no-undef": 2,
"no-undef-init": 2,
"no-undefined": 2,
"no-unused-vars": 2,

"eol-last": 2,
"indent": [
"strict": 0,
"indent": [2, 2, { "SwitchCase": 1 }],
"quotes": [2, "single"],
"linebreak-style": [2, "unix"],
"semi": [2, "always"],
"camelcase": [1, { "properties": "never" }],
"prefer-template": "error",
"no-useless-concat": "error",
"prefer-spread": "error",
"react/jsx-tag-spacing": [2, { "beforeSelfClosing": "always" }],
"keyword-spacing": [
2,
{
"before": true,
"after": true,
"overrides": {
"return": { "after": true },
"throw": { "after": true },
"case": { "after": true }
}
}
],
"no-unused-vars": [
2,
{
"SwitchCase": 1,
"VariableDeclarator": { "var": 2, "let": 2, "const": 3 }
"vars": "all",
"args": "after-used",
"argsIgnorePattern": "state",
"varsIgnorePattern": "React"
}
],
"jsx-quotes": [2, "prefer-double"],
"linebreak-style": [2, "unix"],
"no-trailing-spaces": 1,
"quotes": [2, "double"],
"semi": [2, "always"],

"no-var": 2,
"prefer-const": 2,

"react/display-name": 0,
"react/jsx-wrap-multilines": 2,

"flowtype/define-flow-type": 1
"space-before-blocks": 2,
"space-infix-ops": 2,
"space-before-function-paren": [
2,
{ "anonymous": "always", "named": "never" }
],
"array-bracket-spacing": [2, "never"],
"object-curly-spacing": [2, "always"],
"space-in-parens": [2, "never"],
"block-spacing": [2, "always"],
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
"comma-spacing": [2, { "before": false, "after": true }],
"comma-style": [2, "last"],
"comma-dangle": [2, "always-multiline"],
"prefer-arrow-callback": [2, { "allowNamedFunctions": true }],
"prefer-const": 1,
"react/no-multi-comp": [2, { "ignoreStateless": true }],
"react/no-did-mount-set-state": 2,
"react/no-unescaped-entities": 0,
"no-extra-boolean-cast": 0,
"no-console": ["error", { "allow": ["warn", "error"] }],
"react/jsx-curly-spacing": [2, { "when": "always" }],
"react/no-unused-prop-types": 2
}
}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/.vscode
/node_modules
/build
/coverage
/example/test-app/.gitignore
/example/test-app/node_modules
yarn-error.log
yarn-error.log
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/example
/.vscode
/.vscode
/coverage
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
language: node_js
node_js:
- node
cache: yarn
30 changes: 23 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"name": "ld-redux-components",
"version": "0.0.1",
"description": "Launch Darkly Helper Components that leverage the ld-redux libary",
"description":
"Launch Darkly Helper Components that leverage the ld-redux libary",
"main": "build/index.js",
"repository": "https://github.com/wheniwork/ld-redux-components.git",
"author": "Max Lund <[email protected]>",
Expand All @@ -10,27 +11,42 @@
"build": "./node_modules/.bin/babel src --out-dir build",
"clean": "rimraf build",
"prepare": "yarn clean && yarn build",
"lint": "./node_modules/.bin/eslint src test"
"lint": "./node_modules/.bin/eslint src test spec",
"unit": "./node_modules/.bin/jest",
"test": "yarn lint && yarn unit"
},
"jest": {
"setupTestFrameworkScriptFile": "<rootDir>/test/setup.js",
"testPathIgnorePatterns": ["<rootDir>/example/"],
"coveragePathIgnorePatterns": ["/node_modules/", "<rootDir>/test/"]
},
"dependencies": {
"prop-types": "^15.6.1",
"react": "^16.3.2",
"react-redux": "^5.0.7"
},
"peerDependencies": {
"react": "^16.3.2"
"react": "^16.3.2",
"redux": "^4.0.0"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-eslint": "^8.2.3",
"babel-preset-es2015": "^6.24.1",
"babel-plugin-dynamic-import-node": "^1.2.0",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"eslint-config-airbnb": "^16.1.0",
"eslint-plugin-flowtype": "^2.46.3",
"babel-preset-stage-0": "^6.24.1",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"eslint-plugin-import": "^2.11.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.7.0",
"jest": "^22.4.3",
"prettier-eslint": "^8.8.1",
"react-dom": "^16.3.2",
"react-redux": "^5.0.7",
"redux": "^4.0.0",
"redux-mock-store": "^1.5.1",
"rimraf": "^2.6.2"
}
}
37 changes: 37 additions & 0 deletions spec/components/Feature.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { shallow } from 'enzyme';
import { Feature } from '../../src/components/Feature';

Feature.defaultProps = {
flagId: 'testFlag',
flags: { testFlag: true },
};

describe('Feature', () => {
it('will render children when variation is not set', () => {
const feature = shallow(
<Feature>
<div id="match">Hello</div>
</Feature>
);
expect(feature.find('#match').length).toBe(1);
});

it('will render children if variation prop is set to the correct value', () => {
const feature = shallow(
<Feature variation={ true }>
<div id="match">Hello</div>
</Feature>
);
expect(feature.find('#match').length).toBe(1);
});

it('will not render children if variation prop is set to the incorrect value', () => {
const feature = shallow(
<Feature variation={ false }>
<div id="match">Hello</div>
</Feature>
);
expect(feature.find('#match').length).toBe(0);
});
});
15 changes: 15 additions & 0 deletions spec/components/Variant.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { shallow } from 'enzyme';
import Variant from '../../src/components/Variant';

describe('Variant', () => {
// THIS CANNOT BE TESTED UNTIL https://github.com/airbnb/enzyme/pull/1513 is released
it.skip('will render children when variation is set to correct value', () => {
const wrapper = shallow(
<Variant variation={ true }>
<div>Hello</div>
</Variant>
);
expect(wrapper.props('flagValue')).to.equal(true);
});
});
50 changes: 50 additions & 0 deletions spec/components/VariantRenderer.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import { shallow } from 'enzyme';
import VariantRenderer from '../../src/components/VariantRenderer';

describe('VariantRenderer', () => {
it('will render children when variation prop matches flagValue prop', () => {
const feature = shallow(
<VariantRenderer flagValue={ true } variation={ true }>
<div id="match">Hello</div>
</VariantRenderer>
);
expect(feature.find('#match').length).toBe(1);
});

it('will not render children when variation prop does not match flagValue prop', () => {
const feature = shallow(
<VariantRenderer flagValue={ false } variation={ true }>
<div id="match">Hello</div>
</VariantRenderer>
);
expect(feature.find('#match').length).toBe(0);
});

it('will not render children if flagValue is undefined', () => {
// For testing purposes, variation is set to undefined to ensure that
// even if flagValue and variation are equal, nothing is rendered if
// flagValue is equal to undefined
const feature = shallow(
<VariantRenderer flagValue={ undefined } variation={ undefined }>
<div id="match">Hello</div>
</VariantRenderer>
);
expect(feature.find('#match').length).toBe(0);
});

it('will render children if flagValue is undefined or null and isDefault prop is set', () => {
const feature = shallow(
<VariantRenderer flagValue={ undefined } isDefault>
<div id="match">Hello</div>
</VariantRenderer>
);
const feature2 = shallow(
<VariantRenderer flagValue={ null } isDefault>
<div id="match">Hello</div>
</VariantRenderer>
);
expect(feature.find('#match').length).toBe(1);
expect(feature2.find('#match').length).toBe(1);
});
});
16 changes: 16 additions & 0 deletions spec/config.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import config, { LDRComponentConfig } from '../src/config';

beforeEach(() => {
jest.resetModules();
});

describe('Config', () => {
it('will be a singleton', () => {
expect(config instanceof LDRComponentConfig).toBe(true);
});

it('will set the redexKey in the init method', () => {
config.init({ reduxKey: 'LD' });
expect(config.settings.reduxKey).toBe('LD');
});
});
13 changes: 13 additions & 0 deletions spec/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Feature, Variant, ldrComponentConfig } from '../src';

describe('ld-redux-component module', () => {
it('will export Feature', () => {
expect(Feature).toBeTruthy();
});
it('will export Variant', () => {
expect(Variant).toBeTruthy();
});
it('will export ldrComponentConfig', () => {
expect(ldrComponentConfig).toBeTruthy();
});
});
35 changes: 35 additions & 0 deletions src/components/Feature.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import FlagContext from '../utils/FlagContext';
import Config from '../config';

export class Feature extends Component {
render() {
const { children, flagId, variation, flags } = this.props;

const renderNode =
variation !== undefined
? flags[flagId] === variation && children
: children;

return (
<FlagContext.Provider value={ flags[flagId] }>
{renderNode}
</FlagContext.Provider>
);
}
}

Feature.propTypes = {
children: PropTypes.node.isRequired,
flagId: PropTypes.string.isRequired,
variation: PropTypes.any,
flags: PropTypes.object.isRequired,
};

const mapStateToProps = state => ({
flags: state[Config.settings.reduxKey],
});

export default connect(mapStateToProps)(Feature);
Loading

0 comments on commit 3ced2d6

Please sign in to comment.