├── .babelrc
├── .eslintrc
├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── README.md
├── demo
├── .env.example
├── index.html
├── now.json
└── src
│ ├── Divider
│ └── index.js
│ ├── InnerContainer
│ └── index.js
│ ├── Items
│ └── index.js
│ ├── OuterContainer
│ └── index.js
│ ├── Title
│ └── index.js
│ ├── global.js
│ └── index.js
├── media
└── react-local-currency.png
├── package.json
├── src
├── api
│ ├── get-rates.js
│ └── ip-data.js
├── index.js
└── utils
│ ├── conversor.js
│ └── request.js
├── tests
├── get-rates.mock.json
├── index.test.js
└── ip-data.mock.json
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | presets: [
3 | '@babel/preset-env',
4 | '@babel/preset-react'
5 | ],
6 | plugins: [
7 | ['@babel/plugin-proposal-class-properties'],
8 | ['@babel/plugin-transform-runtime', { 'regenerator': true }]
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["standard", "standard-react", "plugin:jest/recommended"],
3 | "parser": "babel-eslint"
4 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # Dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # Testing
9 | /coverage
10 |
11 | # Production
12 | /build
13 | /example
14 | /dist
15 | /demo/dist
16 |
17 | # Misc
18 | .DS_Store
19 |
20 | # Env
21 | .env
22 | .env.local
23 |
24 | # Log
25 | npm-debug.log*
26 | yarn-debug.log*
27 | yarn-error.log*
28 |
29 | # Cache
30 | /.cache
31 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 |
3 | language: node_js
4 | node_js:
5 | - 8
6 |
7 | before_install:
8 | - npm install codecov.io coveralls
9 |
10 | after_success:
11 | - cat ./coverage/lcov.info | ./node_modules/codecov.io/bin/codecov.io.js
12 | - cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
13 |
14 | branches:
15 | only:
16 | - master
17 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Prerequisites
2 |
3 | [Node.js](http://nodejs.org/) >= 6 must be installed.
4 |
5 | ## Installation
6 |
7 | - Running `npm install` in the component's root directory will install everything you need for development.
8 |
9 | ## Demo Development Server
10 |
11 | - `npm start` will run a development server with the component's demo app at [http://localhost:3000](http://localhost:3000) with hot module reloading.
12 |
13 | ## Running Tests
14 |
15 | - `npm test` will run the tests once.
16 |
17 | - `npm run test:coverage` will run the tests and produce a coverage report in `coverage/`.
18 |
19 | - `npm run test:watch` will run the tests on every change.
20 |
21 | ## Building
22 |
23 | - `npm run build` will build the component for publishing to npm and also bundle the demo app.
24 |
25 | - `npm run clean` will delete built resources.
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # React Local Currency
3 |
4 | [![Travis][build-badge]][build] [![npm package][npm-badge]][npm] [![Coveralls][codecov-badge]][codecov]
5 |
6 |
7 |
8 |
9 |
10 |
11 | ## Installation
12 |
13 | First, install the component:
14 |
15 | ```bash
16 | yarn add react-local-currency
17 | ```
18 | or
19 | ```bash
20 | npm i react-local-currency --save
21 | ```
22 |
23 | ## Usage
24 |
25 | ```js
26 | import * as React from 'react'
27 | import LocalCurrency from 'react-local-currency'
28 |
29 | const ReactLocalCurrency = () => (
30 | {
36 | if (error) return `Error! ${error.message}`
37 |
38 | if (loading) return 'Loading ...'
39 |
40 | if (!data) return null
41 |
42 | return (
43 |
44 |
45 | My service price: 7 USD.
46 |
47 |
48 | My currency based on my IP: {`${data.currency}`}
49 |
50 |
51 | My local price is: {`${data.amount} ${data.currency}`}
52 |
53 |
54 | )
55 | }}
56 | />
57 | )
58 |
59 | export default ReactLocalCurrency
60 | ```
61 |
62 | To see a full example, look at the [demo](https://react-local-currency.unichat.io) and the [source](https://github.com/unichat-io/react-local-currency/tree/master/demo/src) 👩🏻💻 👨🏻💻
63 |
64 | ## Credits
65 |
66 | Thanks to [Nadia Ilustraciones](http://nadiailustraciones.com) for donating the logo!
67 |
68 | ## Authors
69 |
70 | - [Sebastián Lorenzo](https://github.com/slorenzo)
71 |
72 | ## Sponsored by
73 |
74 | - [UNICHAT](https://unichat.io)
75 |
76 | ## License
77 |
78 | MIT license. Copyright © 2018.
79 |
80 | [build-badge]: https://travis-ci.org/unichat-io/react-local-currency.svg?branch=master
81 | [build]: https://travis-ci.org/unichat-io/react-local-currency
82 |
83 | [npm-badge]: https://img.shields.io/npm/v/react-local-currency.svg
84 | [npm]: https://www.npmjs.org/package/react-local-currency
85 |
86 | [codecov-badge]: https://codecov.io/gh/unichat-io/react-local-currency/branch/master/graph/badge.svg
87 | [codecov]: https://codecov.io/gh/unichat-io/react-local-currency
88 |
--------------------------------------------------------------------------------
/demo/.env.example:
--------------------------------------------------------------------------------
1 | REACT_IPDATA_API_KEY=
2 | REACT_APP_OXR_API_ID=
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | React Local Currency Demo
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/demo/now.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "name": "react-local-currency-demo",
4 | "alias": [
5 | "react-local-currency"
6 | ],
7 | "type": "static",
8 | "static": {
9 | "public": "dist",
10 | "rewrites": [
11 | {
12 | "source": "**",
13 | "destination": "/index.html"
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/demo/src/Divider/index.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components'
2 |
3 | const Divider = styled.hr`
4 | border: 0;
5 | background: #1A237E;
6 | box-shadow: 0px 0px 5px 1px #1A237E;
7 | `
8 |
9 | export default Divider
10 |
--------------------------------------------------------------------------------
/demo/src/InnerContainer/index.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components'
2 |
3 | const Container = styled.main`
4 | width: max-content;
5 | padding: 30px;
6 | background-color: #3f51b5;
7 | color: white;
8 | border-radius: 5px;
9 | box-shadow: 0px 2px 10px 0px #1A237E;
10 | `
11 |
12 | export default Container
13 |
--------------------------------------------------------------------------------
/demo/src/Items/index.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components'
2 |
3 | const Container = styled.div`
4 | margin: 40px 0;
5 | > h3 {
6 | font-weight: 200;
7 | }
8 | `
9 |
10 | export default Container
11 |
--------------------------------------------------------------------------------
/demo/src/OuterContainer/index.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components'
2 |
3 | const OuterContainer = styled.div`
4 | height: 100%;
5 | display: flex;
6 | align-items: center;
7 | justify-content: center;
8 | background-color: #283593;
9 | `
10 |
11 | export default OuterContainer
12 |
--------------------------------------------------------------------------------
/demo/src/Title/index.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components'
2 |
3 | const Title = styled.h1`
4 | font-weight: 200;
5 | `
6 |
7 | export default Title
8 |
--------------------------------------------------------------------------------
/demo/src/global.js:
--------------------------------------------------------------------------------
1 | import { createGlobalStyle } from 'styled-components'
2 |
3 | const GlobalStyle = createGlobalStyle`
4 | html, body, #demo {
5 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
6 | height: 100%;
7 | margin: 0;
8 | font-size: 13px;
9 | }
10 | `
11 |
12 | export default GlobalStyle
13 |
--------------------------------------------------------------------------------
/demo/src/index.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import { render } from 'react-dom'
3 |
4 | import LocalCurrency from '../../src'
5 |
6 | import Title from './Title'
7 | import Items from './Items'
8 | import OuterContainer from './OuterContainer'
9 | import InnerContainer from './InnerContainer'
10 | import Divider from './Divider'
11 |
12 | import GlobalStyles from './global'
13 |
14 | class ReactLocalCurrencyDemo extends React.Component {
15 | render () {
16 | return (
17 |
18 |
19 |
20 |
21 |
22 | Shows the price of your services
in the customer's currency
💶 💷 💵 💴
23 |
24 |
25 | {
31 | if (error) return `Error! ${error.message}`
32 |
33 | if (loading) return 'Loading ...'
34 |
35 | if (!data) return null
36 |
37 | return (
38 |
39 |
40 | My service price: 7 USD.
41 |
42 |
43 | My currency based on my IP: {`${data.currency}`}
44 |
45 |
46 | My local price is: {`${data.amount} ${data.currency}`}
47 |
48 |
49 | )
50 | }}
51 | />
52 |
53 |
54 |
55 | )
56 | }
57 | }
58 |
59 | render(, document.querySelector('#demo'))
60 |
--------------------------------------------------------------------------------
/media/react-local-currency.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unichat-io/react-local-currency/dad089dd5980f9d76bed6ab01d4e271ea2a7bc80/media/react-local-currency.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-local-currency",
3 | "version": "1.1.0",
4 | "description": "💶 💷 Shows the price of your services in the customer's currency 💵 💴",
5 | "main": "dist/react-local-currency.js",
6 | "umd:main": "dist/react-local-currency.umd.js",
7 | "module": "dist/react-local-currency.m.js",
8 | "source": "src/index.js",
9 | "files": [
10 | "dist/",
11 | "README.md"
12 | ],
13 | "scripts": {
14 | "example": "parcel ./demo/index.html --out-dir example",
15 | "build": "microbundle -o dist/ --sourcemap false --compress false --external url-join urlJoin",
16 | "dev": "microbundle watch -o dist/ --sourcemap false --compress false --external url-join urlJoin",
17 | "eslint": "eslint ./src && eslint ./demo",
18 | "test": "jest",
19 | "coverage": "jest --coverage",
20 | "snapshots": "jest -u",
21 | "prepublishOnly": "npm run build"
22 | },
23 | "dependencies": {
24 | "money": "github:ducdigital/money.js",
25 | "url-join": "^4.0.0"
26 | },
27 | "peerDependencies": {
28 | "react": "16.x"
29 | },
30 | "jest": {
31 | "testPathIgnorePatterns": [
32 | "/node_modules/",
33 | "/demo/",
34 | "/example/",
35 | "/dist/",
36 | "/media/"
37 | ],
38 | "automock": false,
39 | "verbose": true,
40 | "testRegex": "\\.test\\.js$",
41 | "testURL": "http://localhost/"
42 | },
43 | "devDependencies": {
44 | "@babel/core": "^7.2.2",
45 | "@babel/plugin-proposal-class-properties": "^7.3.0",
46 | "@babel/plugin-transform-runtime": "^7.2.0",
47 | "@babel/preset-env": "^7.3.1",
48 | "@babel/preset-react": "^7.0.0",
49 | "babel-eslint": "^10.0.1",
50 | "enzyme": "^3.8.0",
51 | "enzyme-adapter-react-16": "^1.8.0",
52 | "eslint": "^5.12.1",
53 | "eslint-config-standard": "^12.0.0",
54 | "eslint-config-standard-react": "^7.0.2",
55 | "eslint-plugin-import": "^2.16.0",
56 | "eslint-plugin-jest": "^22.1.3",
57 | "eslint-plugin-node": "^8.0.1",
58 | "eslint-plugin-promise": "^4.0.1",
59 | "eslint-plugin-react": "^7.12.4",
60 | "eslint-plugin-standard": "^4.0.0",
61 | "fetch-mock": "^7.3.0",
62 | "jest": "^24.0.0",
63 | "microbundle": "^0.9.0",
64 | "parcel-bundler": "^1.11.0",
65 | "prop-types": "^15.6.2",
66 | "react": "^16.7.0",
67 | "react-dom": "^16.7.0",
68 | "styled-components": "^4.1.3"
69 | },
70 | "author": "Sebastián Lorenzo ",
71 | "homepage": "",
72 | "license": "MIT",
73 | "repository": "https://github.com/unichat-io/react-local-currency",
74 | "keywords": [
75 | "react-component",
76 | "currency",
77 | "currencies",
78 | "money",
79 | "exchange",
80 | "convert"
81 | ]
82 | }
83 |
--------------------------------------------------------------------------------
/src/api/get-rates.js:
--------------------------------------------------------------------------------
1 | const getRates = (OXR_API_ID, base) => {
2 | const url = `https://openexchangerates.org/api/latest.json?base=${base}&app_id=${OXR_API_ID}`
3 |
4 | return fetch(url, { method: 'GET' }) // eslint-disable-line
5 | }
6 |
7 | export default getRates
8 |
--------------------------------------------------------------------------------
/src/api/ip-data.js:
--------------------------------------------------------------------------------
1 | import urlJoin from 'url-join'
2 |
3 | const ipdata = (ip, apiKey) => {
4 | const url = urlJoin('https://api.ipdata.co/', `?api-key=${apiKey}`)
5 |
6 | return fetch(url, { method: 'GET' }) // eslint-disable-line
7 | }
8 |
9 | export default ipdata
10 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | import getRates from './api/get-rates'
5 | import ipdata from './api/ip-data'
6 |
7 | import conversor from './utils/conversor'
8 | import { checkHttpStatus, parseJSON } from './utils/request'
9 |
10 | class LocalCurrency extends React.PureComponent {
11 | static displayName = 'LocalCurrency'
12 |
13 | static propTypes = {
14 | accept: PropTypes.array,
15 | amount: PropTypes.number.isRequired,
16 | base: PropTypes.string.isRequired,
17 | IPDATA_API_KEY: PropTypes.string.isRequired,
18 | OXR_API_ID: PropTypes.string.isRequired,
19 | children: PropTypes.func,
20 | render: PropTypes.func
21 | };
22 |
23 | static defaultProps = {
24 | children: null,
25 | render: null,
26 | accept: []
27 | }
28 |
29 | state = {
30 | data: null,
31 | loading: true,
32 | error: null
33 | }
34 |
35 | async componentDidMount () {
36 | const { OXR_API_ID, amount, base } = this.props
37 |
38 | try {
39 | const { currency } = await this.getDataFromIPData()
40 |
41 | const r = await getRates(OXR_API_ID, base)
42 | .then(checkHttpStatus)
43 | .then(parseJSON)
44 |
45 | const fxInstance = conversor(r)
46 |
47 | this.setState({
48 | data: {
49 | amount: fxInstance(amount).from(base).to(currency.code),
50 | currency: currency.code
51 | },
52 | loading: null,
53 | error: null
54 | })
55 | } catch (error) {
56 | this.setState({
57 | error,
58 | loading: null
59 | })
60 | }
61 | }
62 |
63 | async getDataFromIPData () {
64 | const { IPDATA_API_KEY, accept } = this.props
65 |
66 | const { currency, threat } = await ipdata(null, IPDATA_API_KEY)
67 | .then(checkHttpStatus)
68 | .then(parseJSON)
69 |
70 | if (threat.is_tor || threat.is_proxy || threat.is_anonymous) {
71 | throw new Error('Unable to find the customer\'s currency')
72 | }
73 |
74 | if (!accept.lenght && accept.includes(currency)) {
75 | throw new Error('Invalid currency')
76 | }
77 |
78 | return { currency }
79 | }
80 |
81 | render () {
82 | const { children, render } = this.props
83 |
84 | if (children) {
85 | return children(this.state)
86 | }
87 | if (render) {
88 | return render(this.state)
89 | }
90 |
91 | console.error(
92 | 'Component LocalCurrency:',
93 | 'no children or render prop are present'
94 | )
95 |
96 | return null
97 | }
98 | }
99 |
100 | export default LocalCurrency
101 |
--------------------------------------------------------------------------------
/src/utils/conversor.js:
--------------------------------------------------------------------------------
1 | import * as fx from 'money'
2 |
3 | const conversor = ({ rates, base }) => {
4 | const fxInstance = fx.factory()
5 | fxInstance.rates = rates
6 | fxInstance.base = base
7 |
8 | return fxInstance
9 | }
10 |
11 | export default conversor
12 |
--------------------------------------------------------------------------------
/src/utils/request.js:
--------------------------------------------------------------------------------
1 | const checkHttpStatus = (response) => {
2 | if (response.status >= 200 && response.status < 300) {
3 | return response
4 | }
5 | const error = new Error(response.statusText)
6 | error.response = response
7 | throw error
8 | }
9 |
10 | const parseJSON = response => response.json()
11 |
12 | export {
13 | checkHttpStatus,
14 | parseJSON
15 | }
16 |
--------------------------------------------------------------------------------
/tests/get-rates.mock.json:
--------------------------------------------------------------------------------
1 | {
2 | "timestamp": 1543158004,
3 | "base": "USD",
4 | "rates": {
5 | "AED": 3.673175,
6 | "AFN": 76.0855,
7 | "ALL": 109.825382,
8 | "AMD": 484.137923,
9 | "ANG": 1.775895,
10 | "AOA": 310.4535,
11 | "ARS": 37.564,
12 | "AUD": 1.381788,
13 | "AWG": 1.800506,
14 | "AZN": 1.7025,
15 | "BAM": 1.724308,
16 | "BBD": 2,
17 | "BDT": 83.929782,
18 | "BGN": 1.726675,
19 | "BHD": 0.377162,
20 | "BIF": 1784.000614,
21 | "BMD": 1,
22 | "BND": 1.375544,
23 | "BOB": 6.913367,
24 | "BRL": 3.83135,
25 | "BSD": 1,
26 | "BTC": 0.00026174781,
27 | "BTN": 70.624959,
28 | "BWP": 10.554971,
29 | "BYN": 2.108284,
30 | "BZD": 2.016658,
31 | "CAD": 1.323951,
32 | "CDF": 1644.261765,
33 | "CHF": 0.997195,
34 | "CLF": 0.024214,
35 | "CLP": 674.718354,
36 | "CNH": 6.945373,
37 | "CNY": 6.94837,
38 | "COP": 3190.8,
39 | "CRC": 601.086612,
40 | "CUC": 1,
41 | "CUP": 25.75,
42 | "CVE": 97.55025,
43 | "CZK": 22.86915,
44 | "DJF": 178,
45 | "DKK": 6.582197,
46 | "DOP": 49.93479,
47 | "DZD": 118.67,
48 | "EGP": 17.892,
49 | "ERN": 14.99759,
50 | "ETB": 27.946453,
51 | "EUR": 0.88164,
52 | "FJD": 2.111099,
53 | "FKP": 0.77991,
54 | "GBP": 0.77991,
55 | "GEL": 2.653677,
56 | "GGP": 0.77991,
57 | "GHS": 4.902385,
58 | "GIP": 0.77991,
59 | "GMD": 49.555,
60 | "GNF": 9085.381617,
61 | "GTQ": 7.718767,
62 | "GYD": 209.319266,
63 | "HKD": 7.82575,
64 | "HNL": 24.395916,
65 | "HRK": 6.5575,
66 | "HTG": 73.323442,
67 | "HUF": 284.42,
68 | "IDR": 14540,
69 | "ILS": 3.73425,
70 | "IMP": 0.77991,
71 | "INR": 70.604,
72 | "IQD": 1191,
73 | "IRR": 42495.428797,
74 | "ISK": 123.720231,
75 | "JEP": 0.77991,
76 | "JMD": 125.976131,
77 | "JOD": 0.709504,
78 | "JPY": 112.95,
79 | "KES": 102.58,
80 | "KGS": 68.708449,
81 | "KHR": 4047.461927,
82 | "KMF": 434.62122,
83 | "KPW": 900,
84 | "KRW": 1133.85,
85 | "KWD": 0.304256,
86 | "KYD": 0.833771,
87 | "KZT": 366.357352,
88 | "LAK": 8544.631351,
89 | "LBP": 1513.596726,
90 | "LKR": 179.68559,
91 | "LRD": 158.049825,
92 | "LSL": 13.86,
93 | "LYD": 1.395132,
94 | "MAD": 9.513262,
95 | "MDL": 17.1885,
96 | "MGA": 3620,
97 | "MKD": 54.235464,
98 | "MMK": 1600.799201,
99 | "MNT": 2489.666667,
100 | "MOP": 8.064407,
101 | "MRO": 357,
102 | "MRU": 36.57,
103 | "MUR": 34.550198,
104 | "MVR": 15.450044,
105 | "MWK": 724.019018,
106 | "MXN": 20.4115,
107 | "MYR": 4.197449,
108 | "MZN": 60.500323,
109 | "NAD": 13.860293,
110 | "NGN": 364,
111 | "NIO": 32.3905,
112 | "NOK": 8.596975,
113 | "NPR": 113.105282,
114 | "NZD": 1.474492,
115 | "OMR": 0.384996,
116 | "PAB": 1,
117 | "PEN": 3.377985,
118 | "PGK": 3.370749,
119 | "PHP": 52.399,
120 | "PKR": 134.43,
121 | "PLN": 3.7853,
122 | "PYG": 5930.926074,
123 | "QAR": 3.64275,
124 | "RON": 4.109993,
125 | "RSD": 104.38,
126 | "RUB": 66.2125,
127 | "RWF": 890.104418,
128 | "SAR": 3.7519,
129 | "SBD": 7.99389,
130 | "SCR": 13.676927,
131 | "SDG": 47.633916,
132 | "SEK": 9.093394,
133 | "SGD": 1.375298,
134 | "SHP": 0.77991,
135 | "SLL": 8390,
136 | "SOS": 578.79812,
137 | "SRD": 7.458,
138 | "SSP": 130.2634,
139 | "STD": 21050.59961,
140 | "STN": 21.6,
141 | "SVC": 8.746825,
142 | "SYP": 514.993439,
143 | "SZL": 13.860418,
144 | "THB": 33.0755,
145 | "TJS": 9.424641,
146 | "TMT": 3.499986,
147 | "TND": 2.916373,
148 | "TOP": 2.29206,
149 | "TRY": 5.287506,
150 | "TTD": 6.74333,
151 | "TWD": 30.942037,
152 | "TZS": 2300.1,
153 | "UAH": 27.763611,
154 | "UGX": 3738.744588,
155 | "USD": 1,
156 | "UYU": 32.531043,
157 | "UZS": 8281.619259,
158 | "VEF": 248487.642241,
159 | "VES": 77.02285,
160 | "VND": 23263.302672,
161 | "VUV": 110.226271,
162 | "WST": 2.610819,
163 | "XAF": 578.317929,
164 | "XAG": 0.06998147,
165 | "XAU": 0.00081755,
166 | "XCD": 2.70255,
167 | "XDR": 0.718712,
168 | "XOF": 578.317929,
169 | "XPD": 0.0008913,
170 | "XPF": 105.207637,
171 | "XPT": 0.00118908,
172 | "YER": 250.349279,
173 | "ZAR": 13.858315,
174 | "ZMW": 11.880976,
175 | "ZWL": 322.355011
176 | }
177 | }
--------------------------------------------------------------------------------
/tests/index.test.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import expect from 'expect'
3 | import Enzyme, { shallow } from 'enzyme'
4 | import Adapter from 'enzyme-adapter-react-16'
5 |
6 | import fetchMock from 'fetch-mock'
7 |
8 | import LocalCurrency from '../src'
9 |
10 | Enzyme.configure({ adapter: new Adapter() })
11 |
12 | const noop = () => undefined
13 | const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms))
14 |
15 | describe('React Local Currency', () => {
16 | beforeAll(() => {
17 | fetchMock.mock('https://openexchangerates.org/api/latest.json?base=USD&app_id=test', require('./get-rates.mock.json'))
18 | fetchMock.mock('https://api.ipdata.co/?api-key=test', require('./ip-data.mock.json'))
19 | })
20 |
21 | it('It renders without breaking using render as property', () => {
22 | const wrapper = shallow(
23 |
30 | )
31 |
32 | expect(wrapper.length).toBe(1)
33 | })
34 |
35 | it('It renders without breaking using render as children elements', () => {
36 | const wrapper = shallow(
37 |
43 | {() => }
44 |
45 | )
46 |
47 | expect(wrapper.length).toBe(1)
48 | })
49 |
50 | it('It renders breaking - Wrong initialize ', () => {
51 | const wrapper = shallow(
52 |
58 | )
59 |
60 | expect(wrapper.isEmptyRender()).toBe(true)
61 | })
62 |
63 | it('Initialize sets initial state', async () => {
64 | const wrapper = shallow(
65 |
72 | )
73 |
74 | expect(wrapper.state().loading).toBe(true)
75 | expect(wrapper.state().error).toBe(null)
76 | expect(wrapper.state().data).toBe(null)
77 | })
78 |
79 | it('It should convert USD to ARS', async () => {
80 | const wrapper = shallow(
81 |
88 | )
89 |
90 | await wait(100)
91 |
92 | expect(wrapper.state().loading).toBe(null)
93 | expect(wrapper.state().error).toBe(null)
94 | expect(wrapper.state().data.currency).toBe('ARS')
95 | expect(wrapper.state().data.amount).toBe(262.948)
96 | })
97 | })
98 |
--------------------------------------------------------------------------------
/tests/ip-data.mock.json:
--------------------------------------------------------------------------------
1 | {
2 | "currency": {
3 | "name": "Argentine Peso",
4 | "code": "ARS",
5 | "symbol": "AR$",
6 | "native": "$",
7 | "plural": "Argentine pesos"
8 | },
9 | "threat": {
10 | "is_tor": false,
11 | "is_proxy": false,
12 | "is_anonymous": false,
13 | "is_known_attacker": false,
14 | "is_known_abuser": false,
15 | "is_threat": false,
16 | "is_bogon": false
17 | }
18 | }
--------------------------------------------------------------------------------