Skip to content

Commit

Permalink
wip: more matching improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
mefellows committed Dec 4, 2017
1 parent da9443f commit 7666498
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 98 deletions.
123 changes: 64 additions & 59 deletions examples/e2e/data/animalData.json
Original file line number Diff line number Diff line change
@@ -1,61 +1,66 @@
[{
"first_name": "Billy",
"last_name": "Goat",
"animal": "goat",
"age": 21,
"gender": "M",
"location": {
"description": "Melbourne Zoo",
"country": "Australia",
"post_code": 3000
[
{
"first_name": "Billy",
"last_name": "Goat",
"animal": "goat",
"age": 21,
"date": "2017-12-04T14:47:18.582Z",
"gender": "M",
"location": {
"description": "Melbourne Zoo",
"country": "Australia",
"post_code": 3000
},
"eligibility": {
"available": true,
"previously_married": false
},
"interests": [
"walks in the garden/meadow",
"munching on a paddock bomb",
"parkour"
]
},
"eligibility": {
"available": true,
"previously_married": false
{
"first_name": "Nanny",
"animal": "goat",
"last_name": "Doe",
"age": 27,
"date": "2017-12-04T14:47:18.582Z",
"gender": "F",
"location": {
"description": "Werribee Zoo",
"country": "Australia",
"post_code": 3000
},
"eligibility": {
"available": true,
"previously_married": true
},
"interests": [
"walks in the garden/meadow",
"parkour"
]
},
"interests": [
"walks in the garden/meadow",
"munching on a paddock bomb",
"parkour"
]
},
{
"first_name": "Nanny",
"animal": "goat",
"last_name": "Doe",
"age": 27,
"gender": "F",
"location": {
"description": "Werribee Zoo",
"country": "Australia",
"post_code": 3000
},
"eligibility": {
"available": true,
"previously_married": true
},
"interests": [
"walks in the garden/meadow",
"parkour"
]
},
{
"first_name": "Simba",
"last_name": "Cantwaittobeking",
"animal": "lion",
"age": 4,
"gender": "M",
"location": {
"description": "Werribee Zoo",
"country": "Australia",
"post_code": 3000
},
"eligibility": {
"available": true,
"previously_married": true
},
"interests": [
"walks in the garden/meadow",
"parkour"
]
}]
{
"first_name": "Simba",
"last_name": "Cantwaittobeking",
"animal": "lion",
"age": 4,
"date": "2017-12-04T14:47:18.582Z",
"gender": "M",
"location": {
"description": "Werribee Zoo",
"country": "Australia",
"post_code": 3000
},
"eligibility": {
"available": true,
"previously_married": true
},
"interests": [
"walks in the garden/meadow",
"parkour"
]
}
]
5 changes: 5 additions & 0 deletions examples/e2e/test/consumer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ describe('Pact', () => {
// API we don't care about
const animalBodyExpectation = {
'id': like(1),
'date': term({
// Testing ISO8601 date time regex
matcher: '^([\\+-]?\\d{4}(?!\\d{2}\\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$',
generate: '2017-12-04T14:47:18.582Z'
}),
'first_name': like('Billy'),
'last_name': like('Goat'),
'animal': like('goat'),
Expand Down
2 changes: 1 addition & 1 deletion examples/e2e/test/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const opts = {
pactBrokerUsername: 'dXfltyFMgNOFZAxr8io9wJ37iUpY42M',
pactBrokerPassword: 'O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1',
tags: ['prod', 'test'],
consumerVersion: '1.0.0'
consumerVersion: '1.0.1'
}

pact.publishPacts(opts)
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,7 @@
"lodash.isfunction": "3.0.8",
"lodash.isnil": "4.0.0",
"lodash.isundefined": "3.0.1",
"lodash.omitby": "4.6.0",
"moment": "^2.19.3"
"lodash.omitby": "4.6.0"
},
"devDependencies": {
"@pact-foundation/karma-pact": "2.x.x",
Expand Down
117 changes: 81 additions & 36 deletions src/dsl/matchers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/** @module Matchers */
/** @module Matchers
*
* For specific matcher types (e.g. IpV6), the values generated are not random
* but are fixed, to prevent contract invalidation after each run of the consumer test.
*/

import { isNil, isFunction, isUndefined } from 'lodash';
import * as moment from 'moment';

/**
* The term matcher.
Expand Down Expand Up @@ -31,87 +34,128 @@ export function term(opts: { generate: string, matcher: string }) {
}

/**
* Create a UUIDv4 matcher
* UUIDv4 matcher.
* @param {string} uuuid - a UUID to use as an example.
*/
export function likeUUIDv4(uuid?: string) {
export function uuidV4(uuid?: string) {
return term({
generate: uuid || 'ce118b6e-d8e1-11e7-9296-cec278b6b50a',
matcher: '/^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$/'
});
}


/**
* Create a IPv4 matcher
* @param {string} ip - an IPv4 address to use as an example
* IPv4 matcher.
* @param {string} ip - an IPv4 address to use as an example. Defaults to `127.0.0.13`
*/
export function likeIpv4(ip: string) {
export function ipv4(ip?: string) {
return term({
generate: ip,
generate: ip || '127.0.0.13',
matcher: '(\\d{1,3}\\.)+\\d{1,3}'
});
}

/**
* Create a IPv6 matcher
* @param {string} ip - an IPv6 address to use as an example
* IPv6 matcher.
* @param {string} ip - an IPv6 address to use as an example. Defaults to '::ffff:192.0.2.128'
*/
export function likeIpv6(ip: string) {
export function ipv6(ip?: string) {
return term({
generate: ip,
generate: ip || '::ffff:192.0.2.128',
matcher: '(\\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,6}\\Z)|(\\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}\\Z)|(\\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}\\Z)|(\\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}\\Z)|(\\A([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}\\Z)|(\\A([0-9a-f]{1,4}:){1,6}(:[0-9a-f]{1,4}){1,1}\\Z)|(\\A(([0-9a-f]{1,4}:){1,7}|:):\\Z)|(\\A:(:[0-9a-f]{1,4}){1,7}\\Z)|(\\A((([0-9a-f]{1,4}:){6})(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3})\\Z)|(\\A(([0-9a-f]{1,4}:){5}[0-9a-f]{1,4}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3})\\Z)|(\\A([0-9a-f]{1,4}:){5}:[0-9a-f]{1,4}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)|(\\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,4}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)|(\\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,3}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)|(\\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,2}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)|(\\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,1}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)|(\\A(([0-9a-f]{1,4}:){1,5}|:):(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)|(\\A:(:[0-9a-f]{1,4}){1,5}:(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\Z)'
});
}




/**
* ISO8601 DateTime matcher
* @param {string} date - an ISO8601 Date and Time string, e.g. 2013-02-04T22:44:30.652Z
*/
export function iso8601DateTime(date?: string) {
return term({
generate: date || '2013-02-01T22:44:30.652Z',
matcher: '^([\\+-]?\\d{4}(?!\\d{2}\\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$'
});
}

/**
* Create a DateTime matcher
* @param {string} date - an ISO8601 DateTime string.
* ISO8601 Date matcher.
* @param {string} date - a basic yyyy-MM-dd date string e.g. 2000-09-31
*/
export function likeDateISO8601(date?: string) {
export function iso8601Date(date?: string) {
return term({
generate: date || moment().toISOString(),
generate: date || '2013-02-01',
matcher: '^([\\+-]?\\d{4}(?!\\d{2}\\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))?)'
});
}

/**
* Create a DateTime matcher
* @param {string} date - an ISO8601 DateTime string.
* RFC822 Date matcher.
* @param {string} date - a basic yyyy-MM-dd date string e.g. 2000-09-31
*/
export function likeIso8601DateTime(date?: string) {
export function iso8601Date(date?: string) {
return term({
generate: date || moment().toISOString(),
matcher: '^([\\+-]?\\d{4}(?!\\d{2}\\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))?)'
generate: date || '2013-02-01',
matcher: '(?x)(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\\s\\d{2}\\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\\s\\d{4}\\s\\d{2}:\\d{2}:\\d{2}\\s(\\+|-)\\d{4}'
});
}


/**
* Create a DateTime matcher
* @param {string} date - an RFC822 DateTime string.
* ISO8601 Time Matcher, matches a pattern of the format "'T'HH:mm:ss".
* @param {string} date - a ISO8601 formatted time string e.g. T22:44:30.652Z
*/
export function likeRfc2822DateTime(date: string) {
export function iso8601Time(time?: string) {
return term({
generate: date,
matcher: '/(?x)(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\\s\\d{ 2}\\s(Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec)\\s\\d{ 4}\\s\\d{ 2}: \\d{ 2}: \\d{ 2}\\s(\\+| -) \\d{ 4}/'
generate: time || 'T22:44:30.652Z',
matcher: '^(T\\d\\d:\\d\\d(:\\d\\d)?(\\.\\d+)?(([+-]\\d\\d:\\d\\d)|Z)?)?$'
});
}

/**
* Create a Simple Date matcher
* @param {string} date - a basic YYYY-MM-dd date string e.g. 2000-09-31
* RFC3339 Timestamp matcher, a subset of ISO8609
* @param {string} date - an RFC3339 Date and Time string, e.g. 2013-02-04T22:44:30.652Z
*/
export function likeDateSimple(date: string) {
export function rfc3339Timestamp(timestamp?: string) {
return term({
generate: date,
matcher: '/^\d{4}-[01]\d-[0-3]\d$/'
generate: date || '2013-02-01T22:44:30.652Z',
matcher: '^([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\\.[0-9]+)?(([Zz])|([\+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))$'
});
}

/**
* Hexadecimal Matcher.
* @param {string} hex - a hex value.
*/
export function Hex(hex?: string) {
return term({
generate: hex || '3F',
matcher: '[0-9a-fA-F]+'
});
}

/**
* Decimal Matcher.
* @param {float} hex - a hex value.
*/
export function decimal(float?: number) {
return somethingLike<number>(float || 13.01);
}

/**
* Integer Matcher.
* @param {integer} int - an int value.
*/
export function integer(int?: number) {
return somethingLike<number>(int || 13);
}

/**
* Boolean Matcher.
*/
export function boolean() {
return somethingLike<boolean>(true);
}

/**
* The eachLike matcher
* @param {any} content
Expand Down Expand Up @@ -149,8 +193,9 @@ export function somethingLike<T>(value: T) {
};
}

// Alias this for convenience
// Convenience alias'
export { somethingLike as like };
export { term as regex };

export interface MatcherResult {
json_class: string;
Expand Down

0 comments on commit 7666498

Please sign in to comment.