/* global require, chai, describe, before, it */ // 数据模板定义(Data Temaplte Definition,DTD) /* ## BDD 1. 结构 describe suite [ describe ] before after beforeEach afterEach it test done 搜索 this.async = fn && fn.length 2. 常用 expect expect().to .equal .deep.equal .not.equal .match .have.length .with.length .have.property .have.deep.property .to.be.a .to.be.an .that .least .most .within 3. 速度 搜索 test.speed slow > 75 75 / 2 < medium < 75 fast < 75 / 2 */ var expect = chai.expect var Mock, $, _ describe('DTD', function() { before(function(done) { require(['mock', 'underscore', 'jquery'], function() { Mock = arguments[0] _ = arguments[1] $ = arguments[2] expect(Mock).to.not.equal(undefined) expect(_).to.not.equal(undefined) expect($).to.not.equal(undefined) done() }) }) describe('Literal', function() { it('', function() { var data = Mock.mock(this.test.title) expect(data).to.equal(this.test.title) }) it('foo', function() { var data = Mock.mock(this.test.title) expect(data).to.equal(this.test.title) }) it(1, function() { var data = Mock.mock(this.test.title) expect(data).to.equal(this.test.title) }) it(true, function() { var data = Mock.mock(this.test.title) expect(data).to.equal(this.test.title) }) it(false, function() { var data = Mock.mock(this.test.title) expect(data).to.equal(this.test.title) }) it({}, function() { var data = Mock.mock(this.test.title) expect(data).to.deep.equal(this.test.title) }) it([], function() { var data = Mock.mock(this.test.title) expect(data).to.deep.equal(this.test.title) }) it(function() {}, function() { var data = Mock.mock(this.test.title) expect(data).to.equal(undefined) }) }) describe('String', function() { // `'name|min-max': 'value'` it('name|min-max', function() { var data = Mock.mock({ 'name|1-10': '★号' }) expect(data.name).to.have.length.within(2, 20) }) // `'name|count': 'value'` it('name|count', function() { var data = Mock.mock({ 'name|10': '★号' }) expect(data.name).to.be.a('string') .that.have.length(20) }) }) describe('Number', function() { // `'name|+step': value` it('name|+step', function() { var data = Mock.mock({ 'list|10': [{ 'name|+1': 100 }] }) expect(data.list).to.be.an('array').with.length(10) _.each(data.list, function(item, index) { expect(item).to.have.property('name') .that.be.a('number') if (index === 0) expect(item.name).to.equal(100) else expect(item.name).to.equal( data.list[index - 1].name + 1 ) }) }) // `'name|min-max': value` it('name|min-max', function() { var data = Mock.mock({ 'name|1-100': 100 }) expect(data).to.have.property('name') .that.be.a('number').within(1, 100) }) it('name|max-min', function() { var data = Mock.mock({ 'name|100-1': 100 }) expect(data).to.have.property('name') .that.be.a('number').within(1, 100) }) it('name|-min--max', function() { var data = Mock.mock({ 'name|-100--1': 100 }) expect(data).to.have.property('name') .that.be.a('number').within(-100, -1) }) it('name|-max--min', function() { var data = Mock.mock({ 'name|-1--100': 100 }) expect(data).to.have.property('name') .that.be.a('number').within(-100, -1) }) it('name|min-min', function() { var data = Mock.mock({ 'name|10-10': 100 }) expect(data).to.have.property('name') .that.be.a('number').equal(10) }) it('name|count', function() { var data = Mock.mock({ 'name|10': 100 }) expect(data).to.have.property('name') .that.be.a('number').equal(10) }) // `'name|min-max.dmin-dmax': value` // 1 整数部分 2 小数部分 var RE_FLOAT = /([\+\-]?\d+)\.?(\d+)?/ function validNumber(number, min, max, dmin, dmax) { expect(number).to.be.a('number') RE_FLOAT.lastIndex = 0 var parts = RE_FLOAT.exec('' + number) expect(+parts[1]).to.be.a('number').within(min, max) expect(parts[2]).to.have.length.within(dmin, dmax) } it('name|min-max.dmin-dmax', function() { var data = Mock.mock({ 'name|1-10.1-10': 123.456 }) validNumber(data.name, 1, 10, 1, 10) }) it('name|min-max.dcount', function() { var data = Mock.mock({ 'name|1-10.10': 123.456 }) validNumber(data.name, 1, 10, 10, 10) }) it('name|count.dmin-dmax', function() { var data = Mock.mock({ 'name|10.1-10': 123.456 }) validNumber(data.name, 10, 10, 1, 10) }) it('name|count.dcount', function() { var data = Mock.mock({ 'name|10.10': 123.456 }) validNumber(data.name, 10, 10, 10, 10) }) it('name|.dmin-dmax', function() { var data = Mock.mock({ 'name|.1-10': 123.456 }) validNumber(data.name, 123, 123, 1, 10) }) it('name|.dcount', function() { var data = Mock.mock({ 'name|.10': 123.456 }) validNumber(data.name, 123, 123, 10, 10) }) }) describe('Boolean', function() { // `'name|1': value` it('name|1', function() { var data = Mock.mock({ 'name|1': true }) expect(data).to.have.property('name') .that.be.a('boolean') }) // `'name|min-max': value` it('name|min-max', function() { var data = Mock.mock({ 'name|8-2': true }) expect(data).to.have.property('name') .that.be.a('boolean') }) }) describe('Object', function() { var methods = { GET: '@URL', POST: '@URL', HEAD: '@URL', PUT: '@URL', DELETE: '@URL' } var methodCount, tpl, data // `'name|min-max': {}` it('name|min-max', function() { methodCount = _.keys(methods).length // 5 for (var min = 0, max; min <= methodCount + 1; min++) { tpl = {} max = Mock.Random.integer(0, methodCount) // methods|0-? |1-? |2-? |3-? |4-? |5-? |6-? tpl['methods|' + min + '-' + max] = methods data = Mock.mock(tpl) expect(_.keys(data.methods)).to.have.length .that.within(Math.min(min, max), Math.max(min, max)) } }) // `'name|count': {}` it('name|count', function() { methodCount = _.keys(methods).length // 5 for (var count = 0; count <= methodCount + 1; count++) { tpl = {} tpl['methods|' + count] = methods data = Mock.mock(tpl) expect(_.keys(data.methods)).to.have.length( Math.min(count, methodCount) ) } }) }) describe('Array', function() { // `'name': [{}, {} ...]` it('name', function() { var value = [{ foo: 'foo' }, { bar: 'bar' }, { foobar: 'foobar' }] var data = Mock.mock({ name: value }) expect(data).to.have.property('name') .that.be.an('array').with.length(3) .that.not.equal(value) expect(data).to.have.property('name') for (var i = 0; i < data.name.length; i++) { expect(data.name[i]).to.not.equal(value[i]) expect(data.name[i]).to.deep.equal(value[i]) } }) // `'name|1': [{}, {} ...]` it('name|1: [1, 2, 4, 8]', function() { // number array var value = [1, 2, 4, 8] var data = Mock.mock({ 'name|1': value }) expect(data).to.have.property('name') .that.be.a('number') expect(value).to.include(data.name) }) it('name|1: ["GET", "POST", "HEAD", "DELETE"]', function() { // string array var value = ['GET', 'POST', 'HEAD', 'DELETE'] var data = Mock.mock({ 'name|1': value }) expect(data).to.have.property('name') .that.be.a('string') expect(value).to.include(data.name) }) it('name|1 [{}]', function() { // object array var value = [{}] var data = Mock.mock({ 'name|1': value }) expect(data).to.have.property('name') .that.be.a('object') .that.deep.equal({}) expect(data.name).to.not.equal(value[0]) }) it('name|1 [{}, {}, {}]', function() { // object array var data = Mock.mock({ 'name|1': [{}, {}, {}] }) expect(data).to.have.property('name') .that.be.a('object') .that.deep.equal({}) }) it('name|1 [{}, {}, {}]', function() { // object array var value = [{ method: 'GET' }, { method: 'POST' }, { method: 'HEAD' }, { method: 'DELETE' }] var data = Mock.mock({ 'name|1': value }) expect(data).to.have.property('name') .that.be.a('object') .that.have.property('method') .that.be.a('string') expect(_.pluck(value, 'method')).include(data.name.method) }) // `'name|+1': [{}, {} ...]` it('name|+1: ["a", "b", "c"]', function() { var data = Mock.mock({ 'list|5': [{ 'name|+1': ['a', 'b', 'c'] }] }) expect(data).to.have.property('list') .that.be.an('array').with.length(5) expect(data.list[0].name).to.equal('a') expect(data.list[1].name).to.equal('b') expect(data.list[2].name).to.equal('c') expect(data.list[3].name).to.equal('a') expect(data.list[4].name).to.equal('b') }) it('name|+1: ["@integer", "@email", "@boolean"]', function() { var data = Mock.mock({ 'list|5-10': [{ 'name|+1': ['@integer', '@email', '@boolean'] }] }) expect(data).to.have.property('list') .that.be.an('array').have.length.within(5, 10) expect(data.list[0].name).to.be.a('number') expect(data.list[1].name).to.be.a('string') expect(data.list[2].name).to.be.a('boolean') expect(data.list[3].name).to.be.a('number') expect(data.list[4].name).to.be.a('string') }) // `'name|min-max': [{}, {} ...]` it('name|min-min', function() { var data = Mock.mock({ 'name|1-1': [{}] }) expect(data.name).to.be.an('array').with.length(1) _.each(data.name, function(item /*, index*/ ) { expect(item).to.deep.equal({}) }) }) it('name|min-max [{}]', function() { var data = Mock.mock({ 'name|1-10': [{}] }) expect(data.name).to.be.an('array').with.length.within(1, 10) _.each(data.name, function(item /*, index*/ ) { expect(item).to.deep.equal({}) }) }) it('name|max-min [{}]', function() { var data = Mock.mock({ 'name|10-1': [{}] }) expect(data.name).to.be.an('array').with.length.within(1, 10) _.each(data.name, function(item /*, index*/ ) { expect(item).to.deep.equal({}) }) }) it('name|min-max [{}, {}]', function() { var data = Mock.mock({ 'name|1-10': [{}, {}] }) expect(data.name).to.be.an('array').with.length.within(2, 20) _.each(data.name, function(item /*, index*/ ) { expect(item).to.deep.equal({}) }) }) it('name|max-min [{}, {}]', function() { var data = Mock.mock({ 'name|10-1': [{}, {}] }) expect(data.name).to.be.an('array').with.length.within(2, 20) _.each(data.name, function(item /*, index*/ ) { expect(item).to.deep.equal({}) }) }) // `'name|count': [{}, {} ...]` it('name|count [{}]', function() { var data = Mock.mock({ 'name|10': [{}] }) expect(data.name).to.be.an('array').with.length(10) _.each(data.name, function(item /*, index*/ ) { expect(item).to.deep.equal({}) }) }) it('name|count [{}, {}]', function() { var data = Mock.mock({ 'name|10': [{}, {}] }) expect(data.name).to.be.an('array').with.length(20) _.each(data.name, function(item /*, index*/ ) { expect(item).to.deep.equal({}) }) }) }) describe('Function', function() { // `'name': function(){}` it('name: function', function() { var data = Mock.mock({ prop: 'hello', name: function( /*root, path*/ ) { return this.prop } }) expect(data).to.have.property('name') .that.be.a('string').equal('hello') }) // 无序的 function it('name: function', function() { var data = Mock.mock({ name2: function() { return this.prop * 2 }, prop: 1, name4: function() { return this.prop * 4 } }) expect(data.name2).to.equal(2) expect(data.name4).to.equal(4) }) // #25 改变了非函数属性的顺序,查找起来不方便 it('name: function', function() { var data = Mock.mock({ name: function() {}, first: '', second: '', third: '' }) var keys = _.keys(data) expect(keys[0]).equal('first') expect(keys[1]).equal('second') expect(keys[2]).equal('third') expect(keys[3]).equal('name') }) }) /* 按照 http://www.regexr.com/ 的 Reference 设计测试用例。 https://github.com/nuysoft/Mock/blob/7c1e3a686bcc515855f1f583d70ae0ee89acc65e/test/regexp.js#L120 */ describe('RegExp', function() { function validRegExp(regexp) { if (arguments.length > 1) { for (var i = 0; i < arguments.length; i++) { validRegExp(arguments[i]) } } it(regexp, function() { var data = Mock.mock(regexp) this.test.title += ' => ' + data expect(regexp.test(data)).to.be.true }) } describe('Character Classes', function() { validRegExp(/./) validRegExp( /[a-z]/, /[A-Z]/, /[0-9]/ ) validRegExp( /\w/, /\W/, /\s/, /\S/, /\d/, /\D/ ) validRegExp( /[.]/, /[\w]/, /[\W]/, /[\s]/, /[\S]/, /[\d]/, /[\D]/ ) validRegExp( /[^.]/, /[^\w]/, /[^\W]/, /[^\s]/, /[^\S]/, /[^\d]/, /[^\D]/ ) }) describe('Quantifiers', function() { validRegExp( /\d?/, /\d+/, /\d*/ ) // {n}, {n,}, {n,m}, {0,1} ?, {1,0} +, {0,} * validRegExp( /\d{5}/, /\d{5,}/, /\d{5,10}/, /\d{0,1}/, /\d{0,}/ ) validRegExp(/[\u4E00-\u9FA5]+/) // 汉字 }) describe('Anchors', function() { validRegExp(/^/) validRegExp(/$/) validRegExp(/^foo/) validRegExp(/foo$/) validRegExp(/\bfoo/) validRegExp(/\Bfoo/) }) describe('Escaped Characters', function() { validRegExp(/\000/) validRegExp(/\xFF/) validRegExp(/\uFFFF/) validRegExp(/\cI/) }) describe('Groups & Lookaround', function() { validRegExp(/(ABC)/) validRegExp(/(ABC)\1/) validRegExp(/(?:ABC)/) validRegExp(/(?=ABC)/) validRegExp(/(?!ABC)/) // validRegExp(/(?<=ABC)/) // validRegExp(/(?