Skip to content
This repository was archived by the owner on Sep 20, 2021. It is now read-only.

Commit f642796

Browse files
committed
Initial commit
0 parents  commit f642796

12 files changed

+507
-0
lines changed

.circleci/config.yml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
version: 2
2+
jobs:
3+
build:
4+
working_directory: ~/mern-starter
5+
docker:
6+
- image: circleci/node:latest
7+
steps:
8+
- checkout
9+
- restore_cache:
10+
key: dependency-cache-{{ checksum "package.json" }}
11+
- run:
12+
name: npm-install
13+
command: npm install
14+
- save_cache:
15+
key: dependency-cache-{{ checksum "package.json" }}
16+
paths:
17+
- ./node_modules
18+
- run:
19+
name: test
20+
command: npm run test
21+

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
coverage/**
2+
dist/**
3+
node_modules/**
4+
package-lock.json
5+
*.lock

.npmignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.circleci/**
2+
.vscode/**
3+
coverage/**
4+
.gitignore
5+
.mocha
6+
.npmignore
7+
package-lock.json
8+
tsconfig.json

.vscode/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"editor.formatOnSave": true
3+
}

karma.conf.js

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Karma configuration
2+
module.exports = function (config) {
3+
config.set({
4+
frameworks: ["karma-typescript", "mocha", "chai"],
5+
files: [
6+
{ pattern: "src/**/*.tsx" }
7+
],
8+
9+
preprocessors: {
10+
"**/*.tsx": ["karma-typescript"]
11+
},
12+
port: 8081,
13+
browsers: ["jsdom"],
14+
reporters: ["mocha", "karma-typescript"],
15+
autoWatch: false,
16+
singleRun: true,
17+
concurrency: Infinity,
18+
// reporter options
19+
mochaReporter: {
20+
output: 'full'
21+
},
22+
karmaTypescriptConfig: {
23+
coverageOptions: {
24+
instrumentation: true,
25+
exclude: /\.(d|spec|test)\.ts/i,
26+
threshold: {
27+
file: {
28+
statements: -10,
29+
branches: 100,
30+
functions: 100,
31+
lines: 100,
32+
}
33+
}
34+
},
35+
reports: {
36+
"html": "coverage",
37+
"text-summary": ""
38+
}
39+
}
40+
})
41+
}

package.json

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{
2+
"name": "@snowcoders/react-checkbox",
3+
"version": "0.1.0",
4+
"keywords": [
5+
"Unstyled",
6+
"Base",
7+
"Checkbox"
8+
],
9+
"private": false,
10+
"repository": "https://github.com/snowcoders/react-checkbox",
11+
"main": "dist/component.js",
12+
"types": "dist/component.d.ts",
13+
"scripts": {
14+
"build": "npm run build-scss && npm run build-typescript",
15+
"build-scss": "node-sass src/styles.scss dist/styles.css",
16+
"build-typescript": "tsc",
17+
"clean": "rimraf coverage dist",
18+
"prepare": "npm run clean && npm run build",
19+
"test": "npm run karma",
20+
"karma": "karma start ./karma.conf.js"
21+
},
22+
"author": "Snowcoders",
23+
"license": "MIT",
24+
"dependencies": {
25+
"classnames": "^2.2.5",
26+
"@snowcoders/react-unstyled-button": "~1.1.5"
27+
},
28+
"peerDependencies": {
29+
"react": ">=15.4.0 <^16.2.0"
30+
},
31+
"devDependencies": {
32+
"@types/chai": "^4.0.10",
33+
"@types/classnames": "^2.2.3",
34+
"@types/enzyme": "^3.1.6",
35+
"@types/mocha": "^2.2.45",
36+
"@types/react": "^16.0.34",
37+
"@types/sinon": "^4.1.2",
38+
"chai": "^4.1.2",
39+
"enzyme": "^3.3.0",
40+
"enzyme-adapter-react-16": "^1.1.1",
41+
"jsdom": "^11.5.1",
42+
"karma": "^2.0.0",
43+
"karma-chai": "^0.1.0",
44+
"karma-coverage": "^1.1.1",
45+
"karma-jsdom-launcher": "^6.1.2",
46+
"karma-mocha": "^1.3.0",
47+
"karma-mocha-reporter": "^2.2.4",
48+
"karma-sinon": "^1.0.5",
49+
"karma-source-map-support": "^1.2.0",
50+
"karma-sourcemap-loader": "^0.3.7",
51+
"karma-sourcemap-writer": "^0.1.2",
52+
"karma-typescript": "^3.0.9",
53+
"karma-typescript-es6-transform": "^1.0.3",
54+
"karma-typescript-preprocessor": "^0.3.1",
55+
"mocha": "^4.1.0",
56+
"mocha-typescript": "^1.1.12",
57+
"node-sass": "^4.7.2",
58+
"react": "^16.2.0",
59+
"react-dom": "^16.2.0",
60+
"rimraf": "^2.6.2",
61+
"sinon": "^4.1.3",
62+
"source-map-support": "^0.5.0",
63+
"ts-node": "^4.1.0",
64+
"tsconfig-paths": "^2.6.0",
65+
"typescript": "^2.6.2"
66+
}
67+
}

readme.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[![npm (scoped)](https://img.shields.io/npm/v/@snowcoders/react-checkbox.svg)](https://www.npmjs.com/package/@snowcoders/react-checkbox)
2+
[![CircleCI branch](https://img.shields.io/circleci/project/github/snowcoders/react-checkbox.svg)](https://circleci.com/gh/snowcoders/react-checkbox)
3+
4+
# Use it
5+
`npm install --save @snowcoders/react-checkbox save-prefix ~`
6+
7+
# Parent Library
8+
This component is part of a larger components library, [react-ui-base](https://github.com/snowcoders/react-ui-base). The goal is to keep all the core logic and base css styles in a single location, that way building out new UI component libraries cheaper and faster (and less buggy).
9+
10+
We highly recommend visiting the react-ui-base repository to understand how to customize the css along with see examples.
11+
12+
You can also view all the components on our demo site https://snowcoders.github.io/react-ui-base/
13+
14+
# This component
15+
This component renders it's children in a HTMLDivElement centered within the entire page. Other features provided by this component:
16+
- Tabbing within the checkbox component will stay within the checkbox component
17+
- Clicking the background will fire onBackgroundClick allowing you to close the checkbox
18+
- Pressing the Escape key will also run the onBackgroundClick
19+
- When the checkbox closes, it will set the active element back to whatever it was before it opened

src/component.test.tsx

+184
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
import * as React from 'react';
2+
import * as ReactDOM from 'react-dom';
3+
4+
import { Checkbox, ICheckboxProps } from "./component";
5+
6+
import { expect } from 'chai';
7+
import { mock, spy } from 'sinon';
8+
import { shallow, ShallowWrapper, mount, configure, ReactWrapper } from "enzyme";
9+
10+
// Configure enzyme
11+
import * as Adapter from "enzyme-adapter-react-16";
12+
configure({ adapter: new Adapter() });
13+
14+
describe("Checkbox", () => {
15+
let defaultProps: ICheckboxProps;
16+
beforeEach(() => {
17+
defaultProps = {
18+
};
19+
});
20+
21+
it("Render", () => {
22+
let wrapper = shallow(<Checkbox {...defaultProps} />);
23+
expect(wrapper).to.have.length(1);
24+
});
25+
26+
describe("Classname", () => {
27+
it("Default has classname", () => {
28+
let wrapper = shallow(<Checkbox {...defaultProps} />);
29+
let rootElement = wrapper.first();
30+
expect(rootElement.props().className).to.contain('sci-react-checkbox');
31+
});
32+
33+
it("Disable style has no classname", () => {
34+
let wrapper = shallow(<Checkbox {...defaultProps} className="blue" isBaseStylesDisabled={true} />);
35+
let rootElement = wrapper.first();
36+
expect(rootElement.props().className).to.not.contain('sci-react-checkbox');
37+
});
38+
39+
it("Class name override", () => {
40+
let wrapper = shallow(<Checkbox {...defaultProps} className="blue" />);
41+
let rootElement = wrapper.first();
42+
expect(rootElement.props().className).to.contain('sci-react-checkbox');
43+
expect(rootElement.props().className).to.contain('blue');
44+
});
45+
});
46+
47+
describe("Uncontrolled", () => {
48+
beforeEach(() => {
49+
defaultProps = {
50+
checked: true
51+
};
52+
});
53+
54+
it("Does not maintain it's own state", () => {
55+
// Render and validate the checkbox is checked
56+
let wrapper = mount(<Checkbox {...defaultProps} />);
57+
expect(wrapper.getDOMNode().classList.contains("checked"), "Should have class 'checked'").to.be.true;
58+
59+
// Find and click on the visual
60+
let visual = wrapper.find(".visual");
61+
expect(visual.length, "visual.length").not.to.equal(0);
62+
// For some reason we are getting this node twice... just make sure it's the same thing
63+
expect(visual.at(0).getDOMNode() === visual.at(1).getDOMNode()).to.be.true;
64+
visual.first().simulate("click");
65+
// Now for some reason, onChange isn't called whne we click the visual element, lets run it manually
66+
wrapper.find(".data").props().onChange({
67+
isDefaultPrevented: () => { return false }
68+
} as any);
69+
70+
// Now check the className
71+
expect(wrapper.getDOMNode().classList.contains("checked"), "Should have class 'checked'").to.be.true;
72+
});
73+
74+
it("Callback onChange", (done: MochaDone) => {
75+
// Props setup
76+
defaultProps.onChange = done;
77+
let onChangeSpy = spy(defaultProps, "onChange");
78+
79+
// Render and validate the checkbox is checked
80+
let wrapper = mount(<Checkbox {...defaultProps} />);
81+
expect(wrapper.getDOMNode().classList.contains("checked"), "Should have class 'checked'").to.be.true;
82+
83+
// Find and click on the visual
84+
let visual = wrapper.find(".visual");
85+
expect(visual.length, "visual.length").not.to.equal(0);
86+
// For some reason we are getting this node twice... just make sure it's the same thing
87+
expect(visual.at(0).getDOMNode() === visual.at(1).getDOMNode()).to.be.true;
88+
visual.first().simulate("click");
89+
// Now for some reason, onChange isn't called whne we click the visual element, lets run it manually
90+
wrapper.find(".data").props().onChange(null);
91+
});
92+
93+
it("Has no label", () => {
94+
let wrapper = shallow(<Checkbox {...defaultProps} />);
95+
expect(wrapper.find(".text").length).to.equal(0);
96+
});
97+
98+
it("Has label", () => {
99+
defaultProps.labelText = "I'm a label!";
100+
let wrapper = shallow(<Checkbox {...defaultProps} />);
101+
expect(wrapper.find(".text").length).to.equal(1);
102+
expect(wrapper.find(".text").text()).to.equal(defaultProps.labelText);
103+
});
104+
});
105+
106+
describe("Controlled", () => {
107+
beforeEach(() => {
108+
defaultProps = {
109+
defaultChecked: true
110+
};
111+
});
112+
113+
it("Maintains it's own state", () => {
114+
// Render and validate the checkbox is checked
115+
let wrapper = mount(<Checkbox {...defaultProps} />);
116+
expect(wrapper.getDOMNode().classList.contains("checked"), "Should have class 'checked'").to.be.true;
117+
118+
// Find and click on the visual
119+
let visual = wrapper.find(".visual");
120+
expect(visual.length, "visual.length").not.to.equal(0);
121+
// For some reason we are getting this node twice... just make sure it's the same thing
122+
expect(visual.at(0).getDOMNode() === visual.at(1).getDOMNode()).to.be.true;
123+
visual.first().simulate("click");
124+
// Now for some reason, onChange isn't called whne we click the visual element, lets run it manually
125+
wrapper.find(".data").props().onChange({
126+
isDefaultPrevented: () => { return false }
127+
} as any);
128+
129+
// Now check the className
130+
expect(wrapper.getDOMNode().classList.contains("checked"), "Should have class 'checked'").to.be.false;
131+
});
132+
133+
it("State does not change if default is prevented", () => {
134+
// Render and validate the checkbox is checked
135+
let wrapper = mount(<Checkbox {...defaultProps} />);
136+
expect(wrapper.getDOMNode().classList.contains("checked"), "Should have class 'checked'").to.be.true;
137+
138+
// Find and click on the visual
139+
let visual = wrapper.find(".visual");
140+
expect(visual.length, "visual.length").not.to.equal(0);
141+
// For some reason we are getting this node twice... just make sure it's the same thing
142+
expect(visual.at(0).getDOMNode() === visual.at(1).getDOMNode()).to.be.true;
143+
visual.first().simulate("click");
144+
// Now for some reason, onChange isn't called whne we click the visual element, lets run it manually
145+
wrapper.find(".data").props().onChange({
146+
isDefaultPrevented: () => { return true }
147+
} as any);
148+
149+
// Now check the className
150+
expect(wrapper.getDOMNode().classList.contains("checked"), "Should have class 'checked'").to.be.true;
151+
});
152+
153+
it("Callback onChange", (done: MochaDone) => {
154+
// Props setup
155+
defaultProps.onChange = done;
156+
let onChangeSpy = spy(defaultProps, "onChange");
157+
158+
// Render and validate the checkbox is checked
159+
let wrapper = mount(<Checkbox {...defaultProps} />);
160+
expect(wrapper.getDOMNode().classList.contains("checked"), "Should have class 'checked'").to.be.true;
161+
162+
// Find and click on the visual
163+
let visual = wrapper.find(".visual");
164+
expect(visual.length, "visual.length").not.to.equal(0);
165+
// For some reason we are getting this node twice... just make sure it's the same thing
166+
expect(visual.at(0).getDOMNode() === visual.at(1).getDOMNode()).to.be.true;
167+
visual.first().simulate("click");
168+
// Now for some reason, onChange isn't called whne we click the visual element, lets run it manually
169+
wrapper.find(".data").props().onChange(null);
170+
});
171+
172+
it("Has no label", () => {
173+
let wrapper = shallow(<Checkbox {...defaultProps} />);
174+
expect(wrapper.find(".text").length).to.equal(0);
175+
});
176+
177+
it("Has label", () => {
178+
defaultProps.labelText = "I'm a label!";
179+
let wrapper = shallow(<Checkbox {...defaultProps} />);
180+
expect(wrapper.find(".text").length).to.equal(1);
181+
expect(wrapper.find(".text").text()).to.equal(defaultProps.labelText);
182+
});
183+
});
184+
});

0 commit comments

Comments
 (0)