Skip to content

Commit

Permalink
Merge branch 'universal-redux' into fullstack
Browse files Browse the repository at this point in the history
  • Loading branch information
diegohaz committed Dec 16, 2016
2 parents 0c3833a + 64af216 commit 5fe0ab3
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src-clean/services/api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import axios from 'axios'

const facade = {}

const api = axios.create({ baseURL: 'https://jsonplaceholder.typicode.com' })

facade.request = (config) => api.request(config)

;['delete', 'get', 'head'].forEach((method) => {
facade[method] = (url, config) => facade.request({ ...config, method, url })
})

;['post', 'put', 'patch'].forEach((method) => {
facade[method] = (url, data, config) => facade.request({ ...config, method, url, data })
})

export default facade
33 changes: 33 additions & 0 deletions src-clean/services/api/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import axios from 'axios'
import { stub, spy } from 'sinon'

const request = spy()

stub(axios, 'create', () => ({ request }))

const api = require('.').default

beforeEach(() => {
request.reset()
})

test('get', () => {
expect(request.called).toBe(false)
api.get('/test', { foo: 'bar' })
expect(request.calledWith({
method: 'get',
url: '/test',
foo: 'bar'
})).toBe(true)
})

test('post', () => {
expect(request.called).toBe(false)
api.post('/test', { title: 'test' }, { foo: 'bar' })
expect(request.calledWith({
method: 'post',
url: '/test',
foo: 'bar',
data: { title: 'test' }
})).toBe(true)
})
44 changes: 44 additions & 0 deletions src-clean/services/validation/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import isEmail from 'validator/lib/isEmail'
import isInt from 'validator/lib/isInt'
import isIn from 'validator/lib/isIn'
import isURL from 'validator/lib/isURL'

const isEmpty = (value) => value === undefined || value === null || value === ''
const join = (rules) => (value, data) =>
rules.map((rule) => rule(value, data)).filter((error) => !!error)[0]

export const email = (value) => !isEmpty(value) && !isEmail(value) &&
'Invalid email address'

export const url = (value) => !isEmpty(value) && !isURL(value) &&
'Invalid URL'

export const required = (value) => isEmpty(value) &&
'Required field'

export const minLength = (min) => (value) => !isEmpty(value) && value.length < min &&
`Must be at least ${min} characters`

export const maxLength = (max) => (value) => !isEmpty(value) && value.length > max &&
`Must be no more than ${max} characters`

export const integer = (value) => !isInt(value) &&
'Must be an integer'

export const oneOf = (values) => (value) => !isIn(value, values) &&
`Must be one of: ${values.join(', ')}`

export const match = (field) => (value, data) => data && value !== data[field] &&
'Must match'

export const createValidator = (rules) => (data = {}) => {
const errors = {}
Object.keys(rules).forEach((key) => {
const rule = join([].concat(rules[key]))
const error = rule(data[key], data)
if (error) {
errors[key] = error
}
})
return errors
}
100 changes: 100 additions & 0 deletions src-clean/services/validation/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import * as v from '.'

test('email', () => {
expect(v.email('invalid')).toBeTruthy()
expect(v.email('invalid@invalid')).toBeTruthy()
expect(v.email('[email protected]')).toBeFalsy()
})

test('url', () => {
expect(v.url('invalid')).toBeTruthy()
expect(v.url('valid.com')).toBeFalsy()
expect(v.url('valid.com/test')).toBeFalsy()
expect(v.url('http://valid.com')).toBeFalsy()
})

test('required', () => {
expect(v.required('')).toBeTruthy()
expect(v.required(null)).toBeTruthy()
expect(v.required(undefined)).toBeTruthy()
expect(v.required('valid')).toBeFalsy()
})

test('minLength', () => {
expect(v.minLength(5)('1234')).toBeTruthy()
expect(v.minLength(5)('12345')).toBeFalsy()
})

test('maxLength', () => {
expect(v.maxLength(5)('123456')).toBeTruthy()
expect(v.maxLength(5)('12345')).toBeFalsy()
})

test('integer', () => {
expect(v.integer('invalid')).toBeTruthy()
expect(v.integer('2.3')).toBeTruthy()
expect(v.integer('.5')).toBeTruthy()
expect(v.integer('1')).toBeFalsy()
})

test('oneOf', () => {
expect(v.oneOf(['valid', 'test'])('invalid')).toBeTruthy()
expect(v.oneOf(['valid', 'test'])('valid')).toBeFalsy()
expect(v.oneOf(['valid', 'test'])('test')).toBeFalsy()
})

test('match', () => {
expect(v.match('invalid')('123', { password: '321' })).toBeTruthy()
expect(v.match('password')('123', { password: '321' })).toBeTruthy()
expect(v.match('password')('321', { password: '321' })).toBeFalsy()
})

test('createValidator', () => {
const validator = v.createValidator({
email: [v.required, v.email],
password: [v.required, v.minLength(6)],
passwordRepeat: [v.match('password'), v.required]
})

expect(typeof validator).toBe('function')

expect(validator({
email: '',
password: '',
passwordRepeat: null
})).toEqual({
email: v.required(''),
password: v.required(''),
passwordRepeat: v.match('a')('c', { a: 'b' })
}, 'Expected to follow the validation order')

expect(Object.keys(validator({
email: 'invalid',
password: '12345',
passwordRepeat: ''
}))).toEqual(['email', 'password', 'passwordRepeat'])

expect(Object.keys(validator({
email: '[email protected]',
password: '12345',
passwordRepeat: ''
}))).toEqual(['password', 'passwordRepeat'])

expect(Object.keys(validator({
email: '[email protected]',
password: '123456',
passwordRepeat: '654321'
}))).toEqual(['passwordRepeat'])

expect(validator({
email: '[email protected]',
password: '123456',
passwordRepeat: '123456'
})).toEqual({})

expect(validator()).toEqual({
email: v.required(''),
password: v.required(''),
passwordRepeat: v.required('')
})
})

0 comments on commit 5fe0ab3

Please sign in to comment.