diff --git a/.yarn/versions/f914e4ac.yml b/.yarn/versions/f914e4ac.yml new file mode 100644 index 00000000000..a9650bcd747 --- /dev/null +++ b/.yarn/versions/f914e4ac.yml @@ -0,0 +1,8 @@ +releases: + fast-check: minor + +declined: + - "@fast-check/ava" + - "@fast-check/jest" + - "@fast-check/vitest" + - "@fast-check/worker" diff --git a/packages/fast-check/src/arbitrary/_internals/builders/UriPathArbitraryBuilder.ts b/packages/fast-check/src/arbitrary/_internals/builders/UriPathArbitraryBuilder.ts index 80c0c961423..5893a878d59 100644 --- a/packages/fast-check/src/arbitrary/_internals/builders/UriPathArbitraryBuilder.ts +++ b/packages/fast-check/src/arbitrary/_internals/builders/UriPathArbitraryBuilder.ts @@ -3,6 +3,7 @@ import type { Size } from '../helpers/MaxLengthFromMinLength'; import { webSegment } from '../../webSegment'; import { array } from '../../array'; import { segmentsToPathMapper, segmentsToPathUnmapper } from '../mappers/SegmentsToPath'; +import { oneof } from '../../oneof'; /** @internal */ function sqrtSize(size: Size): [Size, Size] { @@ -21,10 +22,21 @@ function sqrtSize(size: Size): [Size, Size] { } /** @internal */ -export function buildUriPathArbitrary(resolvedSize: Size): Arbitrary { - const [segmentSize, numSegmentSize] = sqrtSize(resolvedSize); +function buildUriPathArbitraryInternal(segmentSize: Size, numSegmentSize: Size): Arbitrary { return array(webSegment({ size: segmentSize }), { size: numSegmentSize }).map( segmentsToPathMapper, segmentsToPathUnmapper, ); } + +/** @internal */ +export function buildUriPathArbitrary(resolvedSize: Size): Arbitrary { + const [segmentSize, numSegmentSize] = sqrtSize(resolvedSize); + if (segmentSize === numSegmentSize) { + return buildUriPathArbitraryInternal(segmentSize, numSegmentSize); + } + return oneof( + buildUriPathArbitraryInternal(segmentSize, numSegmentSize), + buildUriPathArbitraryInternal(numSegmentSize, segmentSize), + ); +} diff --git a/packages/fast-check/test/e2e/__snapshots__/NoRegression.spec.ts.snap b/packages/fast-check/test/e2e/__snapshots__/NoRegression.spec.ts.snap index f2075681a61..4d5dee061b2 100644 --- a/packages/fast-check/test/e2e/__snapshots__/NoRegression.spec.ts.snap +++ b/packages/fast-check/test/e2e/__snapshots__/NoRegression.spec.ts.snap @@ -4998,104 +4998,22 @@ Execution summary: `; exports[`NoRegression > webPath 1`] = ` -[Error: Property failed after 39 tests -{ seed: 42, path: "38:3:1:8:7:3:3:4:3:3:4", endOnFailure: true } -Counterexample: ["/%F0%AA%80%80"] -Shrunk 10 time(s) +[Error: Property failed after 2 tests +{ seed: 42, path: "1:1:2", endOnFailure: true } +Counterexample: ["//"] +Shrunk 2 time(s) Got error: Property failed by returning false Execution summary: √ [""] -√ [""] -√ [""] -√ [""] -√ [""] -√ [""] -√ [""] -√ [""] -√ ["/VnAy7J*"] -√ [""] -√ [""] -√ ["/%F0%AF%A8%A94%F1%B9%A0%93o,"] -√ [""] -√ ["/s"] -√ ["/_1J7+HWJ"] -√ [""] -√ ["/rs%E1%BC%82iRu:%F0%96%A6%96T"] -√ [""] -√ ["/sd1_z5eON"] -√ ["/d"] -√ [""] -√ [""] -√ ["/J4"] -√ [""] -√ ["/U*q%F3%9F%84%9BN"] -√ ["/70O%F1%80%97%B7d"] -√ [""] -√ [""] -√ [""] -√ ["/ZQt"] -√ ["/+g@"] -√ ["/c(z"] -√ [""] -√ [""] -√ [""] -√ ["/E"] -√ ["/LzY0Xwu%F2%82%AB%B5"] -√ [""] -× ["/cJ%F0%AA%AC%A7&'i"] +× ["///%F2%8C%AD%96"] . √ [""] -. √ ["/"] -. √ ["/&'i"] -. × ["/J%F0%AA%AC%A7&'i"] -. . √ [""] -. . × ["/%F0%AA%AC%A7&'i"] -. . . √ [""] -. . . √ ["/&'i"] -. . . √ ["/%20&'i"] -. . . √ ["/%F0%95%A6%94&'i"] -. . . √ ["/%F0%A0%89%9E&'i"] -. . . √ ["/%F0%A5%9B%83&'i"] -. . . √ ["/%F0%A8%83%B5&'i"] -. . . √ ["/%F0%A9%98%8E&'i"] -. . . × ["/%F0%AA%82%9B&'i"] -. . . . √ [""] -. . . . √ ["/'i"] -. . . . √ ["/&'i"] -. . . . √ ["/%F0%A9%AD%95&'i"] -. . . . √ ["/%F0%A9%B7%B8&'i"] -. . . . √ ["/%F0%A9%BD%8A&'i"] -. . . . √ ["/%F0%A9%BF%B3&'i"] -. . . . × ["/%F0%AA%81%87&'i"] -. . . . . √ [""] -. . . . . √ ["/'i"] -. . . . . √ ["/&'i"] -. . . . . × ["/%F0%AA%80%9D&'i"] -. . . . . . √ [""] -. . . . . . √ ["/'i"] -. . . . . . √ ["/&'i"] -. . . . . . × ["/%F0%AA%80%88&'i"] -. . . . . . . √ [""] -. . . . . . . √ ["/'i"] -. . . . . . . √ ["/&'i"] -. . . . . . . √ ["/%F0%A9%BF%BE&'i"] -. . . . . . . × ["/%F0%AA%80%83&'i"] -. . . . . . . . √ [""] -. . . . . . . . √ ["/'i"] -. . . . . . . . √ ["/&'i"] -. . . . . . . . × ["/%F0%AA%80%81&'i"] -. . . . . . . . . √ [""] -. . . . . . . . . √ ["/'i"] -. . . . . . . . . √ ["/&'i"] -. . . . . . . . . × ["/%F0%AA%80%80&'i"] -. . . . . . . . . . √ [""] -. . . . . . . . . . √ ["/'i"] -. . . . . . . . . . √ ["/&'i"] -. . . . . . . . . . √ ["/%F0%A9%BF%BF&'i"] -. . . . . . . . . . × ["/%F0%AA%80%80"] -. . . . . . . . . . . √ [""] -. . . . . . . . . . . √ ["/"] -. . . . . . . . . . . √ ["/%F0%A9%BF%BF"]] +. × ["//%F2%8C%AD%96"] +. . √ ["/%F2%8C%AD%96"] +. . √ ["/"] +. . × ["//"] +. . . √ ["/"] +. . . √ ["/"]] `; exports[`NoRegression > webQueryParameters 1`] = ` @@ -5214,9 +5132,9 @@ Shrunk 4 time(s) Got error: Property failed by returning false Execution summary: -× ["http://e.pv/p%EF%8D%9D"] -. × ["http://a.pv/p%EF%8D%9D"] -. . × ["http://a.av/p%EF%8D%9D"] -. . . × ["http://a.aa/p%EF%8D%9D"] +× ["http://e.pv//"] +. × ["http://a.pv//"] +. . × ["http://a.av//"] +. . . × ["http://a.aa//"] . . . . × ["http://a.aa"]] `; diff --git a/packages/fast-check/test/unit/arbitrary/__snapshots__/webPath.spec.ts.snap b/packages/fast-check/test/unit/arbitrary/__snapshots__/webPath.spec.ts.snap index 38e0af02220..0975fc18c22 100644 --- a/packages/fast-check/test/unit/arbitrary/__snapshots__/webPath.spec.ts.snap +++ b/packages/fast-check/test/unit/arbitrary/__snapshots__/webPath.spec.ts.snap @@ -1,5 +1,221 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[`webPath (integration) > should be able to shrink '//az' 1`] = ` +""//az" +├> "" +├> "/az" +| ├> "" +| ├> "/" +| | └> "" +| ├> "/z" +| | ├> "" +| | ├> "/" +| | | └> "" +| | ├> "/a" +| | | ├> "" +| | | └> "/" +| | | └> "" +| | ├> "/n" +| | | ├> "" +| | | ├> "/" +| | | | └> "" +| | | ├> "/h" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | ├> "/e" +| | | | | ├> "" +| | | | | ├> "/" +| | | | | | └> "" +| | | | | ├> "/c" +| | | | | | ├> "" +| | | | | | ├> "/" +| | | | | | | └> "" +| | | | | | └> "/b" +| | | | | | ├> "" +| | | | | | ├> "/" +| | | | | | | └> "" +| | | | | | └> "/a" +| | | | | | ├> "" +| | | | | | └> "/" +| | | | | | └> "" +| | | | | └> "/d" +| | | | | ├> "" +| | | | | ├> "/" +| | | | | | └> "" +| | | | | └> "/c" +| | | | | ├> "" +| | | | | ├> "/" +| | | | | | └> "" +| | | | | ├> "/a" +| | | | | | ├> "" +| | | | | | └> "/" +| | | | | | └> "" +| | | | | └> "/b" +| | | | | ├> "" +| | | | | ├> "/" +| | | | | | └> "" +| | | | | └> "/a" +| | | | | ├> "" +| | | | | └> "/" +| | | | | └> "" +| | | | └> "/g" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | └> "/f" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | └> "/e" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | ├> "/a" +| | | | | ├> "" +| | | | | └> "/" +| | | | | └> "" +| | | | ├> "/c" +| | | | | ├> "" +| | | | | ├> "/" +| | | | | | └> "" +| | | | | └> "/b" +| | | | | ├> "" +| | | | | ├> "/" +| | | | | | └> "" +| | | | | └> "/a" +| | | | | ├> "" +| | | | | └> "/" +| | | | | └> "" +| | | | └> "/d" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | └> "/c" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | ├> "/a" +| | | | | ├> "" +| | | | | └> "/" +| | | | | └> "" +| | | | └> "/b" +| | | | ├> "" +| | | | └> … +| | | └> … +| | └> … +| └> … +└> …" +`; + +exports[`webPath (integration) > should be able to shrink '/a//z' 1`] = ` +""/a//z" +├> "" +├> "//z" +| ├> "/z" +| | ├> "" +| | ├> "/" +| | | └> "" +| | ├> "/a" +| | | ├> "" +| | | └> "/" +| | | └> "" +| | ├> "/n" +| | | ├> "" +| | | ├> "/" +| | | | └> "" +| | | ├> "/h" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | ├> "/e" +| | | | | ├> "" +| | | | | ├> "/" +| | | | | | └> "" +| | | | | ├> "/c" +| | | | | | ├> "" +| | | | | | ├> "/" +| | | | | | | └> "" +| | | | | | └> "/b" +| | | | | | ├> "" +| | | | | | ├> "/" +| | | | | | | └> "" +| | | | | | └> "/a" +| | | | | | ├> "" +| | | | | | └> "/" +| | | | | | └> "" +| | | | | └> "/d" +| | | | | ├> "" +| | | | | ├> "/" +| | | | | | └> "" +| | | | | └> "/c" +| | | | | ├> "" +| | | | | ├> "/" +| | | | | | └> "" +| | | | | ├> "/a" +| | | | | | ├> "" +| | | | | | └> "/" +| | | | | | └> "" +| | | | | └> "/b" +| | | | | ├> "" +| | | | | ├> "/" +| | | | | | └> "" +| | | | | └> "/a" +| | | | | ├> "" +| | | | | └> "/" +| | | | | └> "" +| | | | └> "/g" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | └> "/f" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | └> "/e" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | ├> "/a" +| | | | | ├> "" +| | | | | └> "/" +| | | | | └> "" +| | | | ├> "/c" +| | | | | ├> "" +| | | | | ├> "/" +| | | | | | └> "" +| | | | | └> "/b" +| | | | | ├> "" +| | | | | ├> "/" +| | | | | | └> "" +| | | | | └> "/a" +| | | | | ├> "" +| | | | | └> "/" +| | | | | └> "" +| | | | └> "/d" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | └> "/c" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | ├> "/a" +| | | | | ├> "" +| | | | | └> "/" +| | | | | └> "" +| | | | └> "/b" +| | | | ├> "" +| | | | ├> "/" +| | | | | └> "" +| | | | └> "/a" +| | | | └> … +| | | └> … +| | └> … +| └> … +└> …" +`; + exports[`webPath (integration) > should be able to shrink '/a/z' 1`] = ` ""/a/z" ├> "" diff --git a/packages/fast-check/test/unit/arbitrary/webPath.spec.ts b/packages/fast-check/test/unit/arbitrary/webPath.spec.ts index 9e413ef785e..7a08e0d6c28 100644 --- a/packages/fast-check/test/unit/arbitrary/webPath.spec.ts +++ b/packages/fast-check/test/unit/arbitrary/webPath.spec.ts @@ -7,12 +7,14 @@ import { URL } from 'url'; import { assertProduceCorrectValues, assertProduceSameValueGivenSameSeed, + assertProduceSomeSpecificValues, assertProduceValuesShrinkableWithoutContext, assertShrinkProducesSameValueWithoutInitialContext, } from './__test-helpers__/ArbitraryAssertions'; import { Value } from '../../../src/check/arbitrary/definition/Value'; import { buildShrinkTree, renderTree } from './__test-helpers__/ShrinkTree'; import { relativeSizeArb, sizeArb } from './__test-helpers__/SizeHelpers'; +import { DefaultSize } from '../../../src/arbitrary/_internals/helpers/MaxLengthFromMinLength'; describe('webPath (integration)', () => { type Extra = WebPathConstraints; @@ -48,10 +50,26 @@ describe('webPath (integration)', () => { }); }); + it(`should be able to produce starting by // when using default-size=${DefaultSize}`, () => { + assertProduceSomeSpecificValues( + () => webPath({ size: DefaultSize }), + (value) => value.startsWith('//'), + ); + }); + + it(`should be able to produce containing // when using default-size=${DefaultSize}`, () => { + assertProduceSomeSpecificValues( + () => webPath({ size: DefaultSize }), + (value) => value.includes('//'), + ); + }); + it.each` rawValue ${'/a/z'} ${'/azerty'} + ${'//az'} + ${'/a//z'} `('should be able to shrink $rawValue', ({ rawValue }) => { // Arrange const arb = webPath(); diff --git a/website/docs/core-blocks/arbitraries/fake-data/internet.md b/website/docs/core-blocks/arbitraries/fake-data/internet.md index 788df931577..57e891e8e23 100644 --- a/website/docs/core-blocks/arbitraries/fake-data/internet.md +++ b/website/docs/core-blocks/arbitraries/fake-data/internet.md @@ -197,7 +197,7 @@ Following the specs specified by RFC 3986 and WHATWG URL Standard. ```js fc.webPath(); -// Examples of generated values: "/OZx@%E4%B6%958j~64", "", "/0cLw*!~%F2%9A%90%BE5I", "/1", "/"… +// Examples of generated values: "/X/x///1/j//6/@/", "", "/B/~", "/'//%F3%AF%93%AA/*/3/%F2%9A%90%BE/A///", "/HzDG-&&)E"… fc.webPath({ size: '+1' }); // Examples of generated values: @@ -283,17 +283,17 @@ Following the specs specified by RFC 3986 and WHATWG URL Standard. ```js fc.webUrl(); -// Examples of generated values: "https://1e.pl", "https://s.snp", "https://h.ot", "https://copze7.wrc", "http://ay84wia.bi"… +// Examples of generated values: "https://1e.pl/", "https://s.snp", "https://h.ot", "https://copze7.wrc/N/", "http://ay84wia.bi/%F3%AA%A1%92/J"… fc.webUrl({ validSchemes: ['ftp', 'ftps'], }); // Examples of generated values: -// • "ftps://iq7rvu2my.tm/'1V&HqX52m" +// • "ftps://iq7rvu2my.tm/%F0%97%BC%9Fu%F3%81%88%B6&10" // • "ftp://7eee69dc78fg.nec" // • "ftp://hye.rbh9r2.hb" -// • "ftp://hmakevcba.uis" -// • "ftps://xb1.5787e.cew/" +// • "ftp://hmakevcba.uis/~%F2%AF%99%80" +// • "ftps://xb1.5787e.cew/d" // • … fc.webUrl({ @@ -301,10 +301,10 @@ fc.webUrl({ withQueryParameters: true, }); // Examples of generated values: -// • "https://db.oaurut3lxuey.yc" -// • "http://91kpzb6.x4tmjg.pa/*yjz,%F1%A0%AA%B0?~v6+#engtho__!/" -// • "http://hqydzxt3ihu.db/_tAUbo?:/#%F3%B9%93%B6qfx" -// • "https://74gl.fp601objrmhm.rx/#tZK%2ae'(c" +// • "https://db.oaurut3lxuey.yc#%F3%84%9B%A1aFY.$/3n7" +// • "http://91kpzb6.x4tmjg.pa//y/%F3%98%89%84/,//?~v6+#engtho__!/" +// • "http://hqydzxt3ihu.db/m/A/M/o/6/?e#%EF%88%9DMq.mx:pU_" +// • "https://74gl.fp601objrmhm.rx/svxJFoL#" // • "http://7.qxq?;Y:f@HiK#ref" // • …