├── .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 | [![codecov](https://codecov.io/gh/housinghq/react-lazy-card/branch/master/graph/badge.svg)](https://codecov.io/gh/housinghq/react-lazy-card) 6 | [![Build Status](https://travis-ci.org/housinghq/react-lazy-card.svg?branch=master)](https://travis-ci.org/housinghq/react-lazy-card) 7 | [![npm](https://img.shields.io/npm/v/react-lazy-card.svg?maxAge=2592000)](https://github.com/housinghq/react-lazy-card) 8 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](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 | --------------------------------------------------------------------------------