├── .babelrc
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .npmignore
├── .storybook
├── addons.js
├── config.js
├── custom.scss
└── webpack.config.js
├── .travis.yml
├── LICENSE.md
├── README.md
├── components
├── LazyCard.js
├── index.js
└── lazyCard.scss
├── docs
├── favicon.ico
├── iframe.html
├── index.html
└── static
│ ├── manager.bundle.js
│ ├── manager.bundle.js.map
│ ├── preview.bundle.js
│ └── preview.bundle.js.map
├── package.json
├── stories
└── LazyCard.story.js
├── tests
├── LazyCard.test.js
└── config
│ └── setup.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react"],
3 | "plugins": ["transform-object-rest-spread"]
4 | }
5 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | lib
2 | **/node_modules
3 | **/webpack.config.js
4 | examples/**/server.js
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["standard", "standard-react"],
3 | "env": {
4 | "browser": true,
5 | "node": true
6 | },
7 | "rules": {
8 | "react/no-unused-prop-types": 0
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.log
3 | .DS_Store
4 | dist
5 | lib
6 | coverage
7 | .idea
8 | examples/bundle.js
9 | examples/style.css
10 | npm-debug.log
11 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.log
3 | src
4 | test
5 | examples
6 | coverage
7 |
--------------------------------------------------------------------------------
/.storybook/addons.js:
--------------------------------------------------------------------------------
1 | // To get our default addons (actions and links)
2 | import '@kadira/storybook/addons';
3 | // To add the knobs addon
4 | import '@kadira/storybook-addon-knobs/register'
5 | import '@kadira/storybook-addon-options/register';
--------------------------------------------------------------------------------
/.storybook/config.js:
--------------------------------------------------------------------------------
1 | import { configure, addDecorator } from '@kadira/storybook';
2 | import { setOptions } from '@kadira/storybook-addon-options';
3 | import centered from '@kadira/react-storybook-decorator-centered';
4 |
5 | addDecorator(centered)
6 |
7 | import '../components/lazyCard.scss'
8 | import './custom.scss'
9 |
10 | setOptions({
11 | name: 'REACT-LAZY-CARD',
12 | url: 'https://github.com/housinghq/react-lazy-card',
13 | goFullScreen: false,
14 | showLeftPanel: true,
15 | showDownPanel: true,
16 | showSearchBox: false,
17 | downPanelInRight: false,
18 | });
19 |
20 | function loadStories () {
21 | require('../stories/LazyCard.story.js');
22 | }
23 |
24 | configure(loadStories, module);
25 |
--------------------------------------------------------------------------------
/.storybook/custom.scss:
--------------------------------------------------------------------------------
1 | .rs-img{
2 | width: 400px;
3 | height: 400px;
4 | }
5 |
6 | .content{
7 | color: blue;
8 | font-family:sans-serif;
9 | font-size: 30px;
10 | text-align: center;
11 | text-shadow: 1px 1px 1px rgba(0,0,0,0.3);
12 | margin-top: 150px;
13 | }
--------------------------------------------------------------------------------
/.storybook/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | module: {
5 | loaders: [
6 | {
7 | test: /\.scss$/,
8 | loaders: ["style", "css", "sass"],
9 | include: path.resolve(__dirname, '../')
10 | }
11 | ]
12 | }
13 | };
14 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | cache:
4 | directories:
5 | - node_modules
6 | notifications:
7 | email: false
8 | node_js:
9 | - '6'
10 | before_install:
11 | - npm i -g npm@^3.0.0
12 | before_script:
13 | - npm prune
14 | script:
15 | - npm run test:cover
16 | after_success:
17 | - npm run test:report
18 | - npm run semantic-release
19 | branches:
20 | except:
21 | - "/^v\\d+\\.\\d+\\.\\d+$/"
22 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 loconsolutions
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-lazy-card
2 |
3 | > A lighweight image lazy-loading component written in React
4 |
5 | [](https://codecov.io/gh/housinghq/react-lazy-card)
6 | [](https://travis-ci.org/housinghq/react-lazy-card)
7 | [](https://github.com/housinghq/react-lazy-card)
8 | [](https://raw.githubusercontent.com/housinghq/react-lazy-card/master/LICENSE.md)
9 |
10 | It supports both manual and automatic image lazy-loading.
11 |
12 | Demo is available [here](https://housinghq.github.io/react-lazy-card).
13 |
14 | ## Installation
15 | ```
16 | npm install --save react-lazy-card
17 | ```
18 |
19 | ## Basic Usage
20 | **JSX**:
21 | ```js
22 | import LazyCard from 'react-lazy-card';
23 |
24 | Text 2
25 | ```
26 | **CSS**
27 | ```css
28 | @import "react-lazy-card/dist/slide"
29 | ```
30 |
31 | ## Options
32 |
33 | prop|default|description
34 | ----|-------|-----
35 | className|string|custom classname for lazy-card component
36 | image|string|final image to be loaded
37 | defaultImage|string|pre-loader image to be shown
38 | autoLoad|false|should the component automatically lazyLoad the image
39 | attributes| {} | Additional attributes for component root
40 | title| '' | serves like `alt` attribute for `img` tag
41 | lazyLoad|true|enable/disable lazy load
42 |
43 | #### .load()
44 | If `autoload` is set to false the you have to manually call `.load()` to load the image
45 |
46 | ```js
47 | // This will not load `image` automatically. Will load default1.jpg
48 | const a = Text 1
49 | a.load() // now image will be loaded
50 |
51 | // Alternatively set `autoLoad` to true. So `a.jpg` will automatically replace
52 | // default1.jpg when it is loaded.
53 | Text 1
54 | ```
55 |
56 | ### Development
57 | ```
58 | git clone https://github.com/housinghq/react-lazy-card
59 | cd react-lazy-card
60 | npm install
61 | npm run storybook
62 | ```
63 |
64 | Open an issue before opening a PR. This package is optimised for mobile so its hard to include all the features.
65 |
66 | ###License
67 | MIT @ Loconsolutions
68 |
--------------------------------------------------------------------------------
/components/LazyCard.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react'
2 | import PropTypes from 'prop-types'
3 | import classNames from 'classnames'
4 | import autoBind from 'react-auto-bind'
5 |
6 | export default class LazyCard extends PureComponent {
7 | constructor (props, context) {
8 | super(props, context)
9 | this.state = {
10 | image: props.lazyLoad ? props.defaultImage : (props.defaultImage || props.image)
11 | }
12 |
13 | autoBind(this)
14 | }
15 |
16 | componentDidMount () {
17 | if (this.props.autoLoad) this.load()
18 | }
19 |
20 | componentWillUnmount () {
21 | if (this.img) {
22 | this.img.onload = null
23 | this.img = null
24 | }
25 | }
26 |
27 | load () {
28 | const {image} = this.props
29 | if (image && this.state.image !== image) {
30 | const img = this.img = new Image()
31 | img.onload = () => {
32 | this.setState({
33 | image
34 | })
35 | }
36 | img.src = image
37 | if (img.complete) img.onload()
38 | }
39 | }
40 |
41 | render () {
42 | const {width, image, attributes, children, title, className} = this.props
43 |
44 | const style = {}
45 |
46 | if (width) style.width = width
47 | if (this.state.image) style.backgroundImage = `url('${this.state.image}')`
48 |
49 | const mainClass = classNames('rs-img', className, {
50 | 'rs-loaded': this.state.image === image
51 | })
52 |
53 | return (
54 |
{children}
60 | )
61 | }
62 | }
63 |
64 | LazyCard.propTypes = {
65 | className: PropTypes.string,
66 |
67 | // additional attributes for the root node
68 | attributes: PropTypes.object,
69 |
70 | // should the component automatically lazy Load
71 | autoLoad: PropTypes.bool,
72 |
73 | // width of slide component
74 | width: PropTypes.number,
75 |
76 | // url of the main image
77 | image: PropTypes.string,
78 |
79 | // url of placeholder image
80 | defaultImage: PropTypes.string,
81 |
82 | // title for the image
83 | // serves similar to alt attribute for image
84 | // only for the purpose of SEO
85 | title: PropTypes.string,
86 |
87 | subTitle: PropTypes.string,
88 |
89 | lazyLoad: PropTypes.bool,
90 |
91 | data: PropTypes.object,
92 |
93 | children: PropTypes.oneOfType([
94 | PropTypes.array, PropTypes.object
95 | ])
96 | }
97 |
98 | LazyCard.defaultProps = {
99 | title: '',
100 | attributes: {},
101 | autoLoad: false,
102 | lazyLoad: true,
103 | data: {}
104 | }
105 |
--------------------------------------------------------------------------------
/components/index.js:
--------------------------------------------------------------------------------
1 | import LazyCard from './LazyCard'
2 |
3 | export default LazyCard
4 |
--------------------------------------------------------------------------------
/components/lazyCard.scss:
--------------------------------------------------------------------------------
1 | .rs-img{
2 | height: 100%;
3 | background: no-repeat center;
4 | background-size: cover;
5 | float: left;
6 | opacity: 0.6;
7 | width: 100%;
8 | will-change: opacity;
9 | transition: opacity .3s;
10 | -webkit-transition: opacity .3s;
11 | -moz-transition: opacity .3s;
12 | -o-transition: opacity .3s;
13 | }
14 |
15 | .rs-loaded{
16 | opacity: 1;
17 | }
--------------------------------------------------------------------------------
/docs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/housinghq/react-lazy-card/456edd54f5cd980a794a0c75f3f143fa33f592a4/docs/favicon.ico
--------------------------------------------------------------------------------
/docs/iframe.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 | React Storybook
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | React Storybook
8 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/docs/static/manager.bundle.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"static/manager.bundle.js","sources":["webpack:///static/manager.bundle.js","webpack:///"],"mappings":"AAAA;ACyxEA;AApjBA;AAkuHA;AAgpEA;AAuwEA;AAsqFA;AAk0EA;AAqjEA;AAioEA;AAovDA;AA2yDA;AA0mDA;AA08CA;AAilEA;AAk1DA;AAwsDA;AA+pEA;AAg5DA;AAy7EA;AAqiEA;AAqlEA;AAs3DA;AA0uDA;AA42DA;AAsyDA;AAsxDA;AAiiDA;AAw2CA;AAmwDA;AA+yDA;AA0vEA;AAwGA;AA2yEA;AA4hDA","sourceRoot":""}
--------------------------------------------------------------------------------
/docs/static/preview.bundle.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"static/preview.bundle.js","sources":["webpack:///static/preview.bundle.js","webpack:///?d41d"],"mappings":"AAAA;ACkzEA;AAm5EA;AAqiEA;AAimFA;AAi7EA;AAukEA;AA+hDA;AA66DA;AAioDA;AAo+CA;AAsoDA;AA8gEA;AA6sDA;AA+sEA;AA45DA;AAk4EA;AAmjEA;AA0yEA;AA0hDA","sourceRoot":""}
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-lazy-card",
3 | "version": "0.1.8",
4 | "description": "A lighweight image lazy-loading component written in React",
5 | "main": "dist/index.js",
6 | "jsnext:main": "components/index.js",
7 | "module": "components/index.js",
8 | "files": [
9 | "components",
10 | "dist",
11 | "README"
12 | ],
13 | "scripts": {
14 | "lint": "eslint components/**/*.js tests/**/*.js",
15 | "lintfix": "eslint --fix components/**/*.js tests/**/*.js",
16 | "prepublish": "npm run lint && npm run test && npm run build",
17 | "semantic-release": "semantic-release pre && npm publish && semantic-release post",
18 | "storybook": "start-storybook -p 9002",
19 | "test": "mocha --require tests/config/setup 'tests/**/*.test.js'",
20 | "test:watch": "mocha --require tests/config/setup 'tests/**/*.test.js' --watch",
21 | "test:cover": "istanbul cover -x *.test.js _mocha -- -R spec --require tests/config/setup 'tests/**/*.test.js'",
22 | "test:report": "cat ./coverage/lcov.info | codecov && rm -rf ./coverage",
23 | "build": "rm -rf dist && babel components --out-dir dist && npm run build:styles",
24 | "build:styles": "node-sass components --output dist",
25 | "build:watch": "babel --watch components --out-dir dist",
26 | "docs": "build-storybook -o docs"
27 | },
28 | "repository": {
29 | "type": "git",
30 | "url": "https://github.com/housinghq/react-lazy-card"
31 | },
32 | "keywords": [
33 | "react-swipe",
34 | "react-photostory",
35 | "react-lazy-card",
36 | "lazy-load",
37 | "lazy-image",
38 | "image"
39 | ],
40 | "author": "Ritesh Kumar",
41 | "license": "MIT",
42 | "bugs": {
43 | "url": "https://github.com/housinghq/react-lazy-card/issues"
44 | },
45 | "homepage": "https://github.com/housinghq/react-lazy-card",
46 | "devDependencies": {
47 | "@kadira/react-storybook-decorator-centered": "^1.0.0",
48 | "@kadira/storybook": "^2.24.0",
49 | "@kadira/storybook-addon-actions": "^1.1.1",
50 | "@kadira/storybook-addon-options": "^1.0.1",
51 | "autoprefixer": "^7.1.1",
52 | "babel-cli": "^6.16.0",
53 | "babel-plugin-transform-object-rest-spread": "^6.8.0",
54 | "babel-preset-es2015": "^6.14.0",
55 | "babel-preset-react": "^6.11.1",
56 | "chai": "^4.0.1",
57 | "chai-enzyme": "^0.7.1",
58 | "codecov.io": "^0.1.6",
59 | "commitizen": "^2.8.6",
60 | "cz-conventional-changelog": "^2.0.0",
61 | "enzyme": "^3.0.0",
62 | "enzyme-adapter-react-16": "^1.0.4",
63 | "eslint": "^3.7.1",
64 | "eslint-config-standard": "^10.2.1",
65 | "eslint-config-standard-react": "^5.0.0",
66 | "eslint-plugin-import": "^2.3.0",
67 | "eslint-plugin-node": "^5.0.0",
68 | "eslint-plugin-promise": "^3.5.0",
69 | "eslint-plugin-react": "^7.0.1",
70 | "eslint-plugin-standard": "^3.0.1",
71 | "eventsource-polyfill": "^0.9.6",
72 | "extract-text-webpack-plugin": "^2.1.0",
73 | "isparta": "^4.0.0",
74 | "istanbul": "^1.1.0-alpha.1",
75 | "jsdom": "9.6.0",
76 | "mocha": "^3.1.0",
77 | "node-sass": "^4.5.3",
78 | "react-dom": "^15.4.1 || ^16.0.0",
79 | "rimraf": "^2.5.4",
80 | "sass-loader": "^6.0.5",
81 | "semantic-release": "^6.3.6",
82 | "sinon": "^2.3.2"
83 | },
84 | "dependencies": {
85 | "classnames": "^2.2.5",
86 | "prop-types": "^15.5.10",
87 | "react": "^15.x.x || ^16.0.0",
88 | "react-auto-bind": "^0.3.0"
89 | },
90 | "config": {
91 | "commitizen": {
92 | "path": "node_modules/cz-conventional-changelog"
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/stories/LazyCard.story.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 |
4 | import LazyCard from '../components';
5 |
6 | const stories = storiesOf('App', module)
7 |
8 | const defaultImage = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAAKgAwAEAAAAAQAAAAIAAAAA/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAAOEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/CABEIAAIAAgMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAADAgQBBQAGBwgJCgv/xADDEAABAwMCBAMEBgQHBgQIBnMBAgADEQQSIQUxEyIQBkFRMhRhcSMHgSCRQhWhUjOxJGIwFsFy0UOSNIII4VNAJWMXNfCTc6JQRLKD8SZUNmSUdMJg0oSjGHDiJ0U3ZbNVdaSVw4Xy00Z2gONHVma0CQoZGigpKjg5OkhJSldYWVpnaGlqd3h5eoaHiImKkJaXmJmaoKWmp6ipqrC1tre4ubrAxMXGx8jJytDU1dbX2Nna4OTl5ufo6erz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAECAAMEBQYHCAkKC//EAMMRAAICAQMDAwIDBQIFAgQEhwEAAhEDEBIhBCAxQRMFMCIyURRABjMjYUIVcVI0gVAkkaFDsRYHYjVT8NElYMFE4XLxF4JjNnAmRVSSJ6LSCAkKGBkaKCkqNzg5OkZHSElKVVZXWFlaZGVmZ2hpanN0dXZ3eHl6gIOEhYaHiImKkJOUlZaXmJmaoKOkpaanqKmqsLKztLW2t7i5usDCw8TFxsfIycrQ09TV1tfY2drg4uPk5ebn6Onq8vP09fb3+Pn6/9sAQwAFAwQEBAMFBAQEBQUFBgcMCAcHBwcPCwsJDBEPEhIRDxERExYcFxMUGhURERghGBodHR8fHxMXIiQiHiQcHh8e/9sAQwEFBQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e/9oADAMBAAIRAxEAAAHqpRKaf//aAAgBAQABBQIEv//aAAgBAxEBPwF//9oACAECEQE/AX//2gAIAQEABj8C4l//xAAzEAEAAwACAgICAgMBAQAAAgsBEQAhMUFRYXGBkaGxwfDREOHxIDBAUGBwgJCgsMDQ4P/aAAgBAQABPyGGfyX/2gAMAwEAAhEDEQAAELP/xAAzEQEBAQADAAECBQUBAQABAQkBABEhMRBBUWEgcfCRgaGx0cHh8TBAUGBwgJCgsMDQ4P/aAAgBAxEBPxC//9oACAECEQE/EL//2gAIAQEAAT8QQ3Udr//Z';
9 |
10 | class Manual extends React.Component{
11 | constructor(props){
12 | super(props)
13 | }
14 | handleClick() {
15 | this.refs.slide.load()
16 | }
17 |
18 | render() {
19 | return (
20 |
21 |
26 |
27 |
28 | )
29 | }
30 | }
31 |
32 | stories
33 | .add('Automatic lazy-load', () => (
34 |
36 | ))
37 | .add('Manual lazy-load', () => {
38 | return (
39 |
40 | )
41 | })
42 | .add('With HTML content', () => (
43 |
48 | I AM A CHILD
49 |
50 | ))
51 |
--------------------------------------------------------------------------------
/tests/LazyCard.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { expect } from 'chai'
3 | import { configure, shallow, mount } from 'enzyme'
4 | import sinon from 'sinon'
5 | import Adapter from 'enzyme-adapter-react-16'
6 |
7 | configure({ adapter: new Adapter() })
8 |
9 | const {describe, it} = global
10 |
11 | import LazyCard from '../components'
12 |
13 | describe('LazyCard Component', () => {
14 | it('should set the defaultImage as background if provided', () => {
15 | const wrapper = shallow(
16 |
17 | )
18 |
19 | expect(wrapper.find('.rs-img').get(0).props.style.backgroundImage).to.equal('url(\'b.jpg\')')
20 | })
21 |
22 | it('should set image as background if defaultImage is not provided', () => {
23 | const wrapper = shallow(
24 |
25 | )
26 |
27 | expect(wrapper.find('.rs-img').get(0).props.style.backgroundImage).to.equal('url(\'a.jpg\')')
28 | })
29 |
30 | it('should load `image` when .load() is called', () => {
31 | const wrapper = mount(
32 |
36 | )
37 |
38 | const comp = wrapper.instance()
39 |
40 | const spy = sinon.spy(comp, 'load')
41 |
42 | comp.load()
43 |
44 | expect(spy.calledOnce).to.equal(true)
45 | })
46 |
47 | it('should set width when the width is passed', () => {
48 | const wrapper = shallow(
49 |
53 | )
54 |
55 | wrapper.setProps({
56 | width: 100
57 | })
58 |
59 | expect(wrapper.find('.rs-img').get(0).props.style.width).to.equal(100)
60 | })
61 |
62 | it('should render children when they are passed', () => {
63 | const child = Hello World
64 | const wrapper = shallow(
65 |
70 | {child}
71 |
72 | )
73 |
74 | expect(wrapper.contains(child)).to.equal(true)
75 | })
76 |
77 | it('should not re-render if the props are same', () => {
78 | const render = sinon.spy(LazyCard.prototype, 'render')
79 |
80 | const wrapper = mount(
81 |
85 | )
86 |
87 | expect(render.calledOnce).to.equal(true)
88 |
89 | wrapper.setProps({
90 | image: 'a.jpg'
91 | })
92 |
93 | expect(render.calledTwice).to.equal(false)
94 |
95 | wrapper.setProps({
96 | defaultImage: 'c.jpg'
97 | })
98 |
99 | expect(render.calledTwice).to.equal(true)
100 | })
101 | })
102 |
--------------------------------------------------------------------------------
/tests/config/setup.js:
--------------------------------------------------------------------------------
1 | require('babel-core/register')
2 |
3 | const jsdom = require('jsdom').jsdom
4 | const exposedProperties = ['window', 'navigator', 'document']
5 |
6 | global.document = jsdom('')
7 | global.window = document.defaultView
8 | global.Image = document.defaultView.Image
9 | Object.keys(document.defaultView).forEach((property) => {
10 | if (typeof global[property] === 'undefined') {
11 | exposedProperties.push(property)
12 | global[property] = document.defaultView[property]
13 | }
14 | })
15 |
16 | global.navigator = {
17 | userAgent: 'node.js'
18 | }
19 |
--------------------------------------------------------------------------------