12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703 |
- import { Map, fromJS } from "immutable"
- import {
- mapToList,
- parseSearch,
- serializeSearch,
- validatePattern,
- validateMinLength,
- validateMaxLength,
- validateDateTime,
- validateGuid,
- validateNumber,
- validateInteger,
- validateParam,
- validateFile,
- validateMaximum,
- validateMinimum,
- fromJSOrdered,
- getAcceptControllingResponse,
- createDeepLinkPath,
- escapeDeepLinkPath,
- getExtensions,
- getCommonExtensions,
- sanitizeUrl,
- requiresValidationURL,
- extractFileNameFromContentDispositionHeader,
- deeplyStripKey,
- getSampleSchema,
- paramToIdentifier,
- paramToValue,
- generateCodeVerifier,
- createCodeChallenge,
- } from "core/utils"
- import {
- isAbsoluteUrl,
- buildBaseUrl,
- buildUrl,
- } from "core/utils/url"
- import win from "core/window"
- describe("utils", () => {
-
- describe("mapToList", () =>{
-
- it("should convert a map to a list, setting `key`", () =>{
- // With
- const aMap = fromJS({
- a: {
- one: 1,
- },
- b: {
- two: 2,
- }
- })
-
- // When
- const aList = mapToList(aMap, "someKey")
-
- // Then
- expect(aList.toJS()).toEqual([
- { someKey: "a", one: 1 },
- { someKey: "b", two: 2 },
- ])
- })
-
- it("should flatten an arbitrarily deep map", () =>{
- // With
- const aMap = fromJS({
- a: {
- one: {
- alpha: true
- }
- },
- b: {
- two: {
- bravo: true
- },
- three: {
- charlie: true
- }
- }
- })
-
- // When
- const aList = mapToList(aMap, ["levelA", "levelB"])
-
- // Then
- expect(aList.toJS()).toEqual([
- { levelA: "a", levelB: "one", alpha: true },
- { levelA: "b", levelB: "two", bravo: true },
- { levelA: "b", levelB: "three", charlie: true },
- ])
-
- })
-
- it("should handle an empty map", () =>{
- // With
- const aMap = fromJS({})
-
- // When
- const aList = mapToList(aMap, ["levelA", "levelB"])
-
- // Then
- expect(aList.toJS()).toEqual([])
- })
-
- })
-
- describe("extractFileNameFromContentDispositionHeader", () =>{
- it("should extract quoted filename", () =>{
- let cdHeader = "attachment; filename=\"file name.jpg\""
- let expectedResult = "file name.jpg"
- expect(extractFileNameFromContentDispositionHeader(cdHeader)).toEqual(expectedResult)
- })
-
- it("should extract filename", () =>{
- let cdHeader = "attachment; filename=filename.jpg"
- let expectedResult = "filename.jpg"
- expect(extractFileNameFromContentDispositionHeader(cdHeader)).toEqual(expectedResult)
- })
-
- it("should extract quoted filename in utf-8", () =>{
- let cdHeader = "attachment; filename*=UTF-8''\"%D1%84%D0%B0%D0%B9%D0%BB.txt\""
- let expectedResult = "файл.txt"
- expect(extractFileNameFromContentDispositionHeader(cdHeader)).toEqual(expectedResult)
- })
-
- it("should extract filename in utf-8", () =>{
- let cdHeader = "attachment; filename*=utf-8'ru'%D1%84%D0%B0%D0%B9%D0%BB.txt"
- let expectedResult = "файл.txt"
- expect(extractFileNameFromContentDispositionHeader(cdHeader)).toEqual(expectedResult)
- })
-
- it("should not extract filename and return null", () =>{
- let cdHeader = "attachment; no file name provided"
- let expectedResult = null
- expect(extractFileNameFromContentDispositionHeader(cdHeader)).toEqual(expectedResult)
- })
- })
-
- describe("validateMaximum", () => {
- it("doesn't return for valid input", () => {
- expect(validateMaximum(9, 10)).toBeFalsy()
- expect(validateMaximum(19, 20)).toBeFalsy()
- })
-
- it("returns a message for invalid input", () => {
- expect(validateMaximum(1, 0)).toEqual("Value must be less than 0")
- expect(validateMaximum(10, 9)).toEqual("Value must be less than 9")
- expect(validateMaximum(20, 19)).toEqual("Value must be less than 19")
- })
- })
-
- describe("validateMinimum", () => {
- it("doesn't return for valid input", () => {
- expect(validateMinimum(2, 1)).toBeFalsy()
- expect(validateMinimum(20, 10)).toBeFalsy()
- })
-
- it("returns a message for invalid input", () => {
- expect(validateMinimum(-1, 0)).toEqual("Value must be greater than 0")
- expect(validateMinimum(1, 2)).toEqual("Value must be greater than 2")
- expect(validateMinimum(10, 20)).toEqual("Value must be greater than 20")
- })
- })
-
- describe("validateNumber", () => {
- let errorMessage = "Value must be a number"
-
- it("doesn't return for whole numbers", () => {
- expect(validateNumber(0)).toBeFalsy()
- expect(validateNumber(1)).toBeFalsy()
- expect(validateNumber(20)).toBeFalsy()
- expect(validateNumber(5000000)).toBeFalsy()
- expect(validateNumber("1")).toBeFalsy()
- expect(validateNumber("2")).toBeFalsy()
- expect(validateNumber(-1)).toBeFalsy()
- expect(validateNumber(-20)).toBeFalsy()
- expect(validateNumber(-5000000)).toBeFalsy()
- })
-
- it("doesn't return for negative numbers", () => {
- expect(validateNumber(-1)).toBeFalsy()
- expect(validateNumber(-20)).toBeFalsy()
- expect(validateNumber(-5000000)).toBeFalsy()
- })
-
- it("doesn't return for decimal numbers", () => {
- expect(validateNumber(1.1)).toBeFalsy()
- expect(validateNumber(2.5)).toBeFalsy()
- expect(validateNumber(-30.99)).toBeFalsy()
- })
-
- it("returns a message for strings", () => {
- expect(validateNumber("")).toEqual(errorMessage)
- expect(validateNumber(" ")).toEqual(errorMessage)
- expect(validateNumber("test")).toEqual(errorMessage)
- })
-
- it("returns a message for invalid input", () => {
- expect(validateNumber(undefined)).toEqual(errorMessage)
- expect(validateNumber(null)).toEqual(errorMessage)
- expect(validateNumber({})).toEqual(errorMessage)
- expect(validateNumber([])).toEqual(errorMessage)
- expect(validateNumber(true)).toEqual(errorMessage)
- expect(validateNumber(false)).toEqual(errorMessage)
- })
- })
-
- describe("validateInteger", () => {
- let errorMessage = "Value must be an integer"
-
- it("doesn't return for positive integers", () => {
- expect(validateInteger(0)).toBeFalsy()
- expect(validateInteger(1)).toBeFalsy()
- expect(validateInteger(20)).toBeFalsy()
- expect(validateInteger(5000000)).toBeFalsy()
- expect(validateInteger("1")).toBeFalsy()
- expect(validateInteger("2")).toBeFalsy()
- expect(validateInteger(-1)).toBeFalsy()
- expect(validateInteger(-20)).toBeFalsy()
- expect(validateInteger(-5000000)).toBeFalsy()
- })
-
- it("doesn't return for negative integers", () => {
- expect(validateInteger(-1)).toBeFalsy()
- expect(validateInteger(-20)).toBeFalsy()
- expect(validateInteger(-5000000)).toBeFalsy()
- })
-
- it("returns a message for decimal values", () => {
- expect(validateInteger(1.1)).toEqual(errorMessage)
- expect(validateInteger(2.5)).toEqual(errorMessage)
- expect(validateInteger(-30.99)).toEqual(errorMessage)
- })
-
- it("returns a message for strings", () => {
- expect(validateInteger("")).toEqual(errorMessage)
- expect(validateInteger(" ")).toEqual(errorMessage)
- expect(validateInteger("test")).toEqual(errorMessage)
- })
-
- it("returns a message for invalid input", () => {
- expect(validateInteger(undefined)).toEqual(errorMessage)
- expect(validateInteger(null)).toEqual(errorMessage)
- expect(validateInteger({})).toEqual(errorMessage)
- expect(validateInteger([])).toEqual(errorMessage)
- expect(validateInteger(true)).toEqual(errorMessage)
- expect(validateInteger(false)).toEqual(errorMessage)
- })
- })
-
- describe("validateFile", () => {
- let errorMessage = "Value must be a file"
-
- it("validates against objects which are instances of 'File'", () => {
- let fileObj = new win.File([], "Test File")
- expect(validateFile(fileObj)).toBeFalsy()
- expect(validateFile(null)).toBeFalsy()
- expect(validateFile(undefined)).toBeFalsy()
- expect(validateFile(1)).toEqual(errorMessage)
- expect(validateFile("string")).toEqual(errorMessage)
- })
- })
-
- describe("validateDateTime", () => {
- let errorMessage = "Value must be a DateTime"
-
- it("doesn't return for valid dates", () => {
- expect(validateDateTime("Mon, 25 Dec 1995 13:30:00 +0430")).toBeFalsy()
- })
-
- it("returns a message for invalid input'", () => {
- expect(validateDateTime(null)).toEqual(errorMessage)
- expect(validateDateTime("string")).toEqual(errorMessage)
- })
- })
-
- describe("validateGuid", () => {
- let errorMessage = "Value must be a Guid"
-
- it("doesn't return for valid guid", () => {
- expect(validateGuid("8ce4811e-cec5-4a29-891a-15d1917153c1")).toBeFalsy()
- expect(validateGuid("{8ce4811e-cec5-4a29-891a-15d1917153c1}")).toBeFalsy()
- expect(validateGuid("8CE4811E-CEC5-4A29-891A-15D1917153C1")).toBeFalsy()
- expect(validateGuid("6ffefd8e-a018-e811-bbf9-60f67727d806")).toBeFalsy()
- expect(validateGuid("6FFEFD8E-A018-E811-BBF9-60F67727D806")).toBeFalsy()
- expect(validateGuid("00000000-0000-0000-0000-000000000000")).toBeFalsy()
- })
-
- it("returns a message for invalid input'", () => {
- expect(validateGuid(1)).toEqual(errorMessage)
- expect(validateGuid("string")).toEqual(errorMessage)
- })
- })
-
- describe("validateMaxLength", () => {
- it("doesn't return for valid input", () => {
- expect(validateMaxLength("a", 1)).toBeFalsy()
- expect(validateMaxLength("abc", 5)).toBeFalsy()
- })
-
- it("returns a message for invalid input'", () => {
- expect(validateMaxLength("abc", 0)).toEqual("Value must be no longer than 0 characters")
- expect(validateMaxLength("abc", 1)).toEqual("Value must be no longer than 1 character")
- expect(validateMaxLength("abc", 2)).toEqual("Value must be no longer than 2 characters")
- })
- })
-
- describe("validateMinLength", () => {
- it("doesn't return for valid input", () => {
- expect(validateMinLength("a", 1)).toBeFalsy()
- expect(validateMinLength("abc", 2)).toBeFalsy()
- })
-
- it("returns a message for invalid input'", () => {
- expect(validateMinLength("", 1)).toEqual("Value must be at least 1 character")
- expect(validateMinLength("abc", 5)).toEqual("Value must be at least 5 characters")
- expect(validateMinLength("abc", 8)).toEqual("Value must be at least 8 characters")
- })
- })
-
- describe("validatePattern", () => {
- let rxPattern = "^(red|blue)"
- let errorMessage = "Value must follow pattern " + rxPattern
-
- it("doesn't return for a match", () => {
- expect(validatePattern("red", rxPattern)).toBeFalsy()
- expect(validatePattern("blue", rxPattern)).toBeFalsy()
- })
-
- it("returns a message for invalid pattern", () => {
- expect(validatePattern("pink", rxPattern)).toEqual(errorMessage)
- expect(validatePattern("123", rxPattern)).toEqual(errorMessage)
- })
-
- it("fails gracefully when an invalid regex value is passed", () => {
- expect(() => validatePattern("aValue", "---")).not.toThrow()
- expect(() => validatePattern("aValue", 1234)).not.toThrow()
- expect(() => validatePattern("aValue", null)).not.toThrow()
- expect(() => validatePattern("aValue", [])).not.toThrow()
- })
- })
-
- describe("validateParam", () => {
- let param = null
- let value = null
- let result = null
-
- const assertValidateParam = (param, value, expectedError) => {
- // Swagger 2.0 version
- result = validateParam( fromJS(param), fromJS(value))
- expect( result ).toEqual( expectedError )
-
- // OAS3 version, using `schema` sub-object
- let oas3Param = {
- required: param.required,
- schema: {
- ...param,
- required: undefined
- }
- }
- result = validateParam( fromJS(oas3Param), fromJS(value), {
- isOAS3: true
- })
- expect( result ).toEqual( expectedError )
- }
-
- const assertValidateOas3Param = (param, value, expectedError) => {
- // for cases where you _only_ want to try OAS3
- result = validateParam(fromJS(param), value, {
- isOAS3: true
- })
- expect( result ).toEqual( expectedError )
- }
-
- it("should check the isOAS3 flag when validating parameters", () => {
- // This should "skip" validation because there is no `schema` property
- // and we are telling `validateParam` this is an OAS3 spec
- param = fromJS({
- required: true
- })
- value = ""
- result = validateParam( param, value, {
- isOAS3: true
- } )
- expect( result ).toEqual( [] )
- })
-
- it("validates required OAS3 objects", () => {
- // valid object
- param = {
- required: true,
- schema: {
- type: "object"
- }
- }
- value = {
- abc: 123
- }
- assertValidateOas3Param(param, value, [])
-
- // valid object-as-string
- param = {
- required: true,
- schema: {
- type: "object"
- }
- }
- value = JSON.stringify({
- abc: 123
- })
- assertValidateOas3Param(param, value, [])
-
- // invalid object-as-string
- param = {
- required: true,
- schema: {
- type: "object"
- }
- }
- value = "{{}"
- assertValidateOas3Param(param, value, ["Parameter string value must be valid JSON"])
-
- // missing when required
- param = {
- required: true,
- schema: {
- type: "object"
- },
- }
- value = undefined
- assertValidateOas3Param(param, value, ["Required field is not provided"])
- })
-
- it("validates optional OAS3 objects", () => {
- // valid object
- param = {
- schema: {
- type: "object"
- }
- }
- value = {
- abc: 123
- }
- assertValidateOas3Param(param, value, [])
-
- // valid object-as-string
- param = {
- schema: {
- type: "object"
- }
- }
- value = JSON.stringify({
- abc: 123
- })
- assertValidateOas3Param(param, value, [])
-
- // invalid object-as-string
- param = {
- schema: {
- type: "object"
- }
- }
- value = "{{}"
- assertValidateOas3Param(param, value, ["Parameter string value must be valid JSON"])
-
- // missing when not required
- param = {
- schema: {
- type: "object"
- },
- }
- value = undefined
- assertValidateOas3Param(param, value, [])
- })
-
- it("validates required strings", () => {
- // invalid string
- param = {
- required: true,
- type: "string"
- }
- value = ""
- assertValidateParam(param, value, ["Required field is not provided"])
-
- // valid string
- param = {
- required: true,
- type: "string"
- }
- value = "test string"
- assertValidateParam(param, value, [])
-
- // valid string with min and max length
- param = {
- required: true,
- type: "string",
- maxLength: 50,
- minLength: 1
- }
- value = "test string"
- assertValidateParam(param, value, [])
- })
-
- it("handles OAS3 `Parameter.content`", () => {
- // invalid string
- param = {
- content: {
- "text/plain": {
- schema: {
- required: true,
- type: "string"
- }
- }
- }
- }
- value = ""
- assertValidateOas3Param(param, value, ["Required field is not provided"])
-
- // valid string
- param = {
- content: {
- "text/plain": {
- schema: {
- required: true,
- type: "string"
- }
- }
- }
- }
- value = "test string"
- assertValidateOas3Param(param, value, [])
-
- // invalid (empty) JSON string
- param = {
- content: {
- "application/json": {
- schema: {
- required: true,
- type: "object"
- }
- }
- }
- }
- value = ""
- assertValidateOas3Param(param, value, ["Required field is not provided"])
- // invalid (malformed) JSON string
- param = {
- content: {
- "application/json": {
- schema: {
- required: true,
- type: "object"
- }
- }
- }
- }
- value = "{{}"
- assertValidateOas3Param(param, value, ["Parameter string value must be valid JSON"])
-
- // valid (empty object) JSON string
- param = {
- content: {
- "application/json": {
- schema: {
- required: true,
- type: "object"
- }
- }
- }
- }
- value = "{}"
- assertValidateOas3Param(param, value, [])
-
- // valid (empty object) JSON object
- param = {
- content: {
- "application/json": {
- schema: {
- required: true,
- type: "object"
- }
- }
- }
- }
- value = {}
- assertValidateOas3Param(param, value, [])
-
- // should skip JSON validation for non-JSON media types
- param = {
- content: {
- "application/definitely-not-json": {
- schema: {
- required: true,
- type: "object"
- }
- }
- }
- }
- value = "{{}"
- assertValidateOas3Param(param, value, [])
- })
-
- it("validates required strings with min and max length", () => {
- // invalid string with max length
- param = {
- required: true,
- type: "string",
- maxLength: 5
- }
- value = "test string"
- assertValidateParam(param, value, ["Value must be no longer than 5 characters"])
-
- // invalid string with max length 0
- param = {
- required: true,
- type: "string",
- maxLength: 0
- }
- value = "test string"
- assertValidateParam(param, value, ["Value must be no longer than 0 characters"])
-
- // invalid string with min length
- param = {
- required: true,
- type: "string",
- minLength: 50
- }
- value = "test string"
- assertValidateParam(param, value, ["Value must be at least 50 characters"])
- })
-
- it("validates optional strings", () => {
- // valid (empty) string
- param = {
- required: false,
- type: "string"
- }
- value = ""
- assertValidateParam(param, value, [])
-
- // valid string
- param = {
- required: false,
- type: "string"
- }
- value = "test"
- assertValidateParam(param, value, [])
- })
-
- it("validates required files", () => {
- // invalid file
- param = {
- required: true,
- type: "file"
- }
- value = undefined
- assertValidateParam(param, value, ["Required field is not provided"])
-
- // valid file
- param = {
- required: true,
- type: "file"
- }
- value = new win.File([""], "file.txt")
- assertValidateParam(param, value, [])
- })
-
- it("validates optional files", () => {
- // invalid file
- param = {
- required: false,
- type: "file"
- }
- value = "not a file"
- assertValidateParam(param, value, ["Value must be a file"])
-
- // valid (empty) file
- param = {
- required: false,
- type: "file"
- }
- value = undefined
- assertValidateParam(param, value, [])
-
- // valid file
- param = {
- required: false,
- type: "file"
- }
- value = new win.File([""], "file.txt")
- assertValidateParam(param, value, [])
- })
-
- it("validates required arrays", () => {
- // invalid (empty) array
- param = {
- required: true,
- type: "array"
- }
- value = []
- assertValidateParam(param, value, ["Required field is not provided"])
- // invalid (empty) array, represented as a string
- param = {
- required: true,
- type: "array"
- }
- value = ""
- assertValidateParam(param, value, ["Required field is not provided"])
-
- // invalid (not an array)
- param = {
- required: true,
- type: "array"
- }
- value = undefined
- assertValidateParam(param, value, ["Required field is not provided"])
-
- // invalid array, items do not match correct type
- param = {
- required: true,
- type: "array",
- items: {
- type: "string"
- }
- }
- value = [1]
- assertValidateParam(param, value, [{index: 0, error: "Value must be a string"}])
-
- // valid array, with no 'type' for items
- param = {
- required: true,
- type: "array"
- }
- value = [1]
- assertValidateParam(param, value, [])
- // valid array, with no 'type' for items, represented as a string
- param = {
- required: true,
- type: "array"
- }
- value = "[1]"
- assertValidateParam(param, value, [])
-
- // valid array, items match type
- param = {
- required: true,
- type: "array",
- items: {
- type: "string"
- }
- }
- value = ["1"]
- assertValidateParam(param, value, [])
- })
-
- it("validates optional arrays", () => {
- // valid, empty array
- param = {
- required: false,
- type: "array"
- }
- value = []
- assertValidateParam(param, value, [])
-
- // invalid, items do not match correct type
- param = {
- required: false,
- type: "array",
- items: {
- type: "number"
- }
- }
- value = ["number"]
- assertValidateParam(param, value, [{index: 0, error: "Value must be a number"}])
-
- // valid
- param = {
- required: false,
- type: "array",
- items: {
- type: "string"
- }
- }
- value = ["test"]
- assertValidateParam(param, value, [])
- })
-
- it("validates required booleans", () => {
- // invalid boolean value
- param = {
- required: true,
- type: "boolean"
- }
- value = undefined
- assertValidateParam(param, value, ["Required field is not provided"])
-
- // invalid boolean value (not a boolean)
- param = {
- required: true,
- type: "boolean"
- }
- value = "test string"
- assertValidateParam(param, value, ["Value must be a boolean"])
-
- // valid boolean value
- param = {
- required: true,
- type: "boolean"
- }
- value = "true"
- assertValidateParam(param, value, [])
-
- // valid boolean value
- param = {
- required: true,
- type: "boolean"
- }
- value = false
- assertValidateParam(param, value, [])
- })
-
- it("validates optional booleans", () => {
- // valid (empty) boolean value
- param = {
- required: false,
- type: "boolean"
- }
- value = undefined
- assertValidateParam(param, value, [])
-
- // invalid boolean value (not a boolean)
- param = {
- required: false,
- type: "boolean"
- }
- value = "test string"
- assertValidateParam(param, value, ["Value must be a boolean"])
-
- // valid boolean value
- param = {
- required: false,
- type: "boolean"
- }
- value = "true"
- assertValidateParam(param, value, [])
-
- // valid boolean value
- param = {
- required: false,
- type: "boolean"
- }
- value = false
- assertValidateParam(param, value, [])
- })
-
- it("validates required numbers", () => {
- // invalid number, string instead of a number
- param = {
- required: true,
- type: "number"
- }
- value = "test"
- assertValidateParam(param, value, ["Value must be a number"])
-
- // invalid number, undefined value
- param = {
- required: true,
- type: "number"
- }
- value = undefined
- assertValidateParam(param, value, ["Required field is not provided"])
-
- // valid number with min and max
- param = {
- required: true,
- type: "number",
- minimum: 5,
- maximum: 99
- }
- value = 10
- assertValidateParam(param, value, [])
-
- // valid negative number with min and max
- param = {
- required: true,
- type: "number",
- minimum: -50,
- maximum: -5
- }
- value = -10
- assertValidateParam(param, value, [])
-
- // invalid number with maximum:0
- param = {
- required: true,
- type: "number",
-
- maximum: 0
- }
- value = 1
- assertValidateParam(param, value, ["Value must be less than 0"])
-
- // invalid number with minimum:0
- param = {
- required: true,
- type: "number",
- minimum: 0
- }
- value = -10
- assertValidateParam(param, value, ["Value must be greater than 0"])
- })
-
- it("validates optional numbers", () => {
- // invalid number, string instead of a number
- param = {
- required: false,
- type: "number"
- }
- value = "test"
- assertValidateParam(param, value, ["Value must be a number"])
-
- // valid (empty) number
- param = {
- required: false,
- type: "number"
- }
- value = undefined
- assertValidateParam(param, value, [])
-
- // valid number
- param = {
- required: false,
- type: "number"
- }
- value = 10
- assertValidateParam(param, value, [])
- })
-
- it("validates required integers", () => {
- // invalid integer, string instead of an integer
- param = {
- required: true,
- type: "integer"
- }
- value = "test"
- assertValidateParam(param, value, ["Value must be an integer"])
-
- // invalid integer, undefined value
- param = {
- required: true,
- type: "integer"
- }
- value = undefined
- assertValidateParam(param, value, ["Required field is not provided"])
-
- // valid integer, but 0 is falsy in JS
- param = {
- required: true,
- type: "integer"
- }
- value = 0
- assertValidateParam(param, value, [])
-
- // valid integer
- param = {
- required: true,
- type: "integer"
- }
- value = 10
- assertValidateParam(param, value, [])
- })
-
- it("validates optional integers", () => {
- // invalid integer, string instead of an integer
- param = {
- required: false,
- type: "integer"
- }
- value = "test"
- assertValidateParam(param, value, ["Value must be an integer"])
-
- // valid (empty) integer
- param = {
- required: false,
- type: "integer"
- }
- value = undefined
- assertValidateParam(param, value, [])
-
- // integers
- param = {
- required: false,
- type: "integer"
- }
- value = 10
- assertValidateParam(param, value, [])
- })
- })
-
- describe("fromJSOrdered", () => {
- it("should create an OrderedMap from an object", () => {
- const param = {
- value: "test"
- }
-
- const result = fromJSOrdered(param).toJS()
- expect( result ).toEqual( { value: "test" } )
- })
-
- it("should not use an object's length property for Map size", () => {
- const param = {
- length: 5
- }
-
- const result = fromJSOrdered(param).toJS()
- expect( result ).toEqual( { length: 5 } )
- })
-
- it("should create an OrderedMap from an array", () => {
- const param = [1, 1, 2, 3, 5, 8]
-
- const result = fromJSOrdered(param).toJS()
- expect( result ).toEqual( [1, 1, 2, 3, 5, 8] )
- })
- })
-
- describe("getAcceptControllingResponse", () => {
- it("should return the first 2xx response with a media type", () => {
- const responses = fromJSOrdered({
- "200": {
- content: {
- "application/json": {
- schema: {
- type: "object"
- }
- }
- }
- },
- "201": {
- content: {
- "application/json": {
- schema: {
- type: "object"
- }
- }
- }
- }
- })
-
- expect(getAcceptControllingResponse(responses)).toEqual(responses.get("200"))
- })
- it("should skip 2xx responses without defined media types", () => {
- const responses = fromJSOrdered({
- "200": {
- content: {
- "application/json": {
- schema: {
- type: "object"
- }
- }
- }
- },
- "201": {
- content: {
- "application/json": {
- schema: {
- type: "object"
- }
- }
- }
- }
- })
-
- expect(getAcceptControllingResponse(responses)).toEqual(responses.get("201"))
- })
- it("should default to the `default` response if it has defined media types", () => {
- const responses = fromJSOrdered({
- "200": {
- description: "quite empty"
- },
- "201": {
- description: "quite empty"
- },
- default: {
- content: {
- "application/json": {
- schema: {
- type: "object"
- }
- }
- }
- }
- })
-
- expect(getAcceptControllingResponse(responses)).toEqual(responses.get("default"))
- })
- it("should return null if there are no suitable controlling responses", () => {
- const responses = fromJSOrdered({
- "200": {
- description: "quite empty"
- },
- "201": {
- description: "quite empty"
- },
- "default": {
- description: "also empty.."
- }
- })
-
- expect(getAcceptControllingResponse(responses)).toBe(null)
- })
- it("should return null if an empty OrderedMap is passed", () => {
- const responses = fromJSOrdered()
-
- expect(getAcceptControllingResponse(responses)).toBe(null)
- })
- it("should return null if anything except an OrderedMap is passed", () => {
- const responses = {}
-
- expect(getAcceptControllingResponse(responses)).toBe(null)
- })
- })
-
- describe("createDeepLinkPath", () => {
- it("creates a deep link path replacing spaces with underscores", () => {
- const result = createDeepLinkPath("tag id with spaces")
- expect(result).toEqual("tag%20id%20with%20spaces")
- })
-
- it("trims input when creating a deep link path", () => {
- let result = createDeepLinkPath(" spaces before and after ")
- expect(result).toEqual("spaces%20before%20and%20after")
-
- result = createDeepLinkPath(" ")
- expect(result).toEqual("")
- })
-
- it("creates a deep link path with special characters", () => {
- const result = createDeepLinkPath("!@#$%^&*(){}[]")
- expect(result).toEqual("!@#$%^&*(){}[]")
- })
-
- it("returns an empty string for invalid input", () => {
- expect( createDeepLinkPath(null) ).toEqual("")
- expect( createDeepLinkPath(undefined) ).toEqual("")
- expect( createDeepLinkPath(1) ).toEqual("")
- expect( createDeepLinkPath([]) ).toEqual("")
- expect( createDeepLinkPath({}) ).toEqual("")
- })
- })
-
- describe("escapeDeepLinkPath", () => {
- it("creates and escapes a deep link path", () => {
- const result = escapeDeepLinkPath("tag id with spaces?")
- expect(result).toEqual("tag_id_with_spaces\\?")
- })
-
- it("escapes a deep link path that starts with a number", () => {
- const result = escapeDeepLinkPath("123")
- expect(result).toEqual("\\31 23")
- })
-
- it("escapes a deep link path with a class selector", () => {
- const result = escapeDeepLinkPath("hello.world")
- expect(result).toEqual("hello\\.world")
- })
-
- it("escapes a deep link path with an id selector", () => {
- const result = escapeDeepLinkPath("hello#world")
- expect(result).toEqual("hello\\#world")
- })
-
- it("escapes a deep link path with a space", () => {
- const result = escapeDeepLinkPath("hello world")
- expect(result).toEqual("hello_world")
- })
-
- it("escapes a deep link path with a percent-encoded space", () => {
- const result = escapeDeepLinkPath("hello%20world")
- expect(result).toEqual("hello_world")
- })
- })
-
- describe("getExtensions", () => {
- const objTest = Map([[ "x-test", "a"], ["minimum", "b"]])
- it("does not error on empty array", () => {
- const result1 = getExtensions([])
- expect(result1).toEqual([])
- const result2 = getCommonExtensions([])
- expect(result2).toEqual([])
- })
- it("gets only the x- keys", () => {
- const result = getExtensions(objTest)
- expect(result).toEqual(Map([[ "x-test", "a"]]))
- })
- it("gets the common keys", () => {
- const result = getCommonExtensions(objTest, true)
- expect(result).toEqual(Map([[ "minimum", "b"]]))
- })
- })
-
- describe("deeplyStripKey", () => {
- it("should filter out a specified key", () => {
- const input = {
- $$ref: "#/this/is/my/ref",
- a: {
- $$ref: "#/this/is/my/other/ref",
- value: 12345
- }
- }
- const result = deeplyStripKey(input, "$$ref")
- expect(result).toEqual({
- a: {
- value: 12345
- }
- })
- })
-
- it("should filter out a specified key by predicate", () => {
- const input = {
- $$ref: "#/this/is/my/ref",
- a: {
- $$ref: "#/keep/this/one",
- value: 12345
- }
- }
- const result = deeplyStripKey(input, "$$ref", (v) => v !== "#/keep/this/one")
- expect(result).toEqual({
- a: {
- value: 12345,
- $$ref: "#/keep/this/one"
- }
- })
- })
-
- it("should only call the predicate when the key matches", () => {
- const input = {
- $$ref: "#/this/is/my/ref",
- a: {
- $$ref: "#/this/is/my/other/ref",
- value: 12345
- }
- }
- let count = 0
-
- const result = deeplyStripKey(input, "$$ref", () => {
- count++
- return true
- })
- expect(count).toEqual(2)
- })
- })
-
- describe("parse and serialize search", () => {
- beforeEach(() => {
- // jsdom in Jest 25+ prevents modifying window.location,
- // so we replace with a stubbed version
- delete win.location
- win.location = {
- search: ""
- }
- })
- afterEach(() => {
- win.location.search = ""
- })
-
- describe("parsing", () => {
- it("works with empty search", () => {
- win.location.search = ""
- expect(parseSearch()).toEqual({})
- })
-
- it("works with only one key", () => {
- win.location.search = "?foo"
- expect(parseSearch()).toEqual({foo: ""})
- })
-
- it("works with keys and values", () => {
- win.location.search = "?foo=fooval&bar&baz=bazval"
- expect(parseSearch()).toEqual({foo: "fooval", bar: "", baz: "bazval"})
- })
-
- it("decode url encoded components", () => {
- win.location.search = "?foo=foo%20bar"
- expect(parseSearch()).toEqual({foo: "foo bar"})
- })
- })
-
- describe("serializing", () => {
- it("works with empty map", () => {
- expect(serializeSearch({})).toEqual("")
- })
-
- it("works with multiple keys with and without values", () => {
- expect(serializeSearch({foo: "", bar: "barval"})).toEqual("foo=&bar=barval")
- })
-
- it("encode url components", () => {
- expect(serializeSearch({foo: "foo bar"})).toEqual("foo=foo%20bar")
- })
- })
- })
-
- describe("sanitizeUrl", () => {
- it("should sanitize a `javascript:` url", () => {
- const res = sanitizeUrl("javascript:alert('bam!')")
-
- expect(res).toEqual("about:blank")
- })
-
- it("should sanitize a `data:` url", () => {
- const res = sanitizeUrl(`data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=`)
-
- expect(res).toEqual("about:blank")
- })
-
- it("should not modify a `http:` url", () => {
- const res = sanitizeUrl(`http://swagger.io/`)
-
- expect(res).toEqual("http://swagger.io/")
- })
-
- it("should not modify a `https:` url", () => {
- const res = sanitizeUrl(`https://swagger.io/`)
-
- expect(res).toEqual("https://swagger.io/")
- })
-
- it("should gracefully handle empty strings", () => {
- expect(sanitizeUrl("")).toEqual("")
- })
-
- it("should gracefully handle non-string values", () => {
- expect(sanitizeUrl(123)).toEqual("")
- expect(sanitizeUrl(null)).toEqual("")
- expect(sanitizeUrl(undefined)).toEqual("")
- expect(sanitizeUrl([])).toEqual("")
- expect(sanitizeUrl({})).toEqual("")
- })
- })
- describe("isAbsoluteUrl", () => {
- it("check if url is absolute", () => {
- expect(!!isAbsoluteUrl("http://example.com")).toEqual(true)
- expect(!!isAbsoluteUrl("https://secure-example.com")).toEqual(true)
- expect(!!isAbsoluteUrl("HTTP://uppercase-example.com")).toEqual(true)
- expect(!!isAbsoluteUrl("HTTP://uppercase-secure-example.com")).toEqual(true)
- expect(!!isAbsoluteUrl("http://trailing-slash.com/")).toEqual(true)
- expect(!!isAbsoluteUrl("ftp://file-transfer-protocol.com")).toEqual(true)
- expect(!!isAbsoluteUrl("//no-protocol.com")).toEqual(true)
- })
- it("check if url is not absolute", () => {
- expect(!!isAbsoluteUrl("/url-relative-to-host/base-path/path")).toEqual(false)
- expect(!!isAbsoluteUrl("url-relative-to-base/base-path/path")).toEqual(false)
- })
- })
- describe("buildBaseUrl", () => {
- const specUrl = "https://petstore.swagger.io/v2/swagger.json"
-
- const noServerSelected = ""
- const absoluteServerUrl = "https://server-example.com/base-path/path"
- const serverUrlRelativeToBase = "server-example/base-path/path"
- const serverUrlRelativeToHost = "/server-example/base-path/path"
- it("build base url with no server selected", () => {
- expect(buildBaseUrl(noServerSelected, specUrl)).toBe("https://petstore.swagger.io/v2/swagger.json")
- })
- it("build base url from absolute server url", () => {
- expect(buildBaseUrl(absoluteServerUrl, specUrl)).toBe("https://server-example.com/base-path/path")
- })
- it("build base url from relative server url", () => {
- expect(buildBaseUrl(serverUrlRelativeToBase, specUrl)).toBe("https://petstore.swagger.io/v2/server-example/base-path/path")
- expect(buildBaseUrl(serverUrlRelativeToHost, specUrl)).toBe("https://petstore.swagger.io/server-example/base-path/path")
- })
- })
- describe("buildUrl", () => {
- const specUrl = "https://petstore.swagger.io/v2/swagger.json"
-
- const noUrl = ""
- const absoluteUrl = "https://example.com/base-path/path"
- const urlRelativeToBase = "relative-url/base-path/path"
- const urlRelativeToHost = "/relative-url/base-path/path"
- const noServerSelected = ""
- const absoluteServerUrl = "https://server-example.com/base-path/path"
- const serverUrlRelativeToBase = "server-example/base-path/path"
- const serverUrlRelativeToHost = "/server-example/base-path/path"
-
- it("build no url", () => {
- expect(buildUrl(noUrl, specUrl, { selectedServer: absoluteServerUrl })).toBe(undefined)
- expect(buildUrl(noUrl, specUrl, { selectedServer: serverUrlRelativeToBase })).toBe(undefined)
- expect(buildUrl(noUrl, specUrl, { selectedServer: serverUrlRelativeToHost })).toBe(undefined)
- })
- it("build absolute url", () => {
- expect(buildUrl(absoluteUrl, specUrl, { selectedServer: absoluteServerUrl })).toBe("https://example.com/base-path/path")
- expect(buildUrl(absoluteUrl, specUrl, { selectedServer: serverUrlRelativeToBase })).toBe("https://example.com/base-path/path")
- expect(buildUrl(absoluteUrl, specUrl, { selectedServer: serverUrlRelativeToHost })).toBe("https://example.com/base-path/path")
- })
- it("build relative url with no server selected", () => {
- expect(buildUrl(urlRelativeToBase, specUrl, { selectedServer: noServerSelected })).toBe("https://petstore.swagger.io/v2/relative-url/base-path/path")
- expect(buildUrl(urlRelativeToHost, specUrl, { selectedServer: noServerSelected })).toBe("https://petstore.swagger.io/relative-url/base-path/path")
- })
- it("build relative url with absolute server url", () => {
- expect(buildUrl(urlRelativeToBase, specUrl, { selectedServer: absoluteServerUrl })).toBe("https://server-example.com/base-path/relative-url/base-path/path")
- expect(buildUrl(urlRelativeToHost, specUrl, { selectedServer: absoluteServerUrl })).toBe("https://server-example.com/relative-url/base-path/path")
- })
- it("build relative url with server url relative to base", () => {
- expect(buildUrl(urlRelativeToBase, specUrl, { selectedServer: serverUrlRelativeToBase })).toBe("https://petstore.swagger.io/v2/server-example/base-path/relative-url/base-path/path")
- expect(buildUrl(urlRelativeToHost, specUrl, { selectedServer: serverUrlRelativeToBase })).toBe("https://petstore.swagger.io/relative-url/base-path/path")
- })
- it("build relative url with server url relative to host", () => {
- expect(buildUrl(urlRelativeToBase, specUrl, { selectedServer: serverUrlRelativeToHost })).toBe("https://petstore.swagger.io/server-example/base-path/relative-url/base-path/path")
- expect(buildUrl(urlRelativeToHost, specUrl, { selectedServer: serverUrlRelativeToHost })).toBe("https://petstore.swagger.io/relative-url/base-path/path")
- })
- })
-
- describe("requiresValidationURL", () => {
- it("Should tell us if we require a ValidationURL", () => {
- const res = requiresValidationURL("https://example.com")
- expect(res).toBe(true)
- })
- it(".. and localhost is not", () => {
- const res = requiresValidationURL("http://localhost")
- expect(res).toBe(false)
- })
- it(".. and neither does 127.0.0.1", () => {
- const res = requiresValidationURL("http://127.0.0.1")
- expect(res).toBe(false)
- })
- it(".. even without the proto", () => {
- const res = requiresValidationURL("127.0.0.1")
- expect(res).toBe(false)
- })
- it(".. and also not with 'none'", () => {
- const res = requiresValidationURL("none")
- expect(res).toBe(false)
- })
- it(".. and also not with 'none'", () => {
- const res = requiresValidationURL("none")
- expect(res).toBe(false)
- })
- it(".. and also not with ''", () => {
- const res = requiresValidationURL("")
- expect(res).toBe(false)
- })
- })
- describe("getSampleSchema", () => {
- const oriDate = Date
-
- beforeEach(() => {
- Date = function () {
- this.toISOString = function () {
- return "2018-07-07T07:07:05.189Z"
- }
- }
- })
-
- afterEach(() => {
- Date = oriDate
- })
-
- it("should stringify string values if json content-type", () => {
- // Given
- const res = getSampleSchema({
- type: "string",
- format: "date-time"
- }, "text/json")
-
- // Then
- expect(res).toEqual(JSON.stringify(new Date().toISOString()))
- })
- it("should not unnecessarily stringify string values for other content-types", () => {
- // Given
- const res = getSampleSchema({
- type: "string",
- format: "date-time"
- })
-
- // Then
- expect(res).toEqual(new Date().toISOString())
- })
- it("should not unnecessarily stringify non-object values", () => {
- // Given
- const res = getSampleSchema({
- type: "number"
- })
-
- // Then
- expect(res).toEqual(0)
- })
- it("should not unnecessarily stringify non-object values if content-type is json", () => {
- // Given
- const res = getSampleSchema({
- type: "number"
- }, "application/json")
-
- // Then
- expect(res).toEqual(0)
- })
- })
-
- describe("paramToIdentifier", () => {
- it("should convert an Immutable parameter map to an identifier", () => {
- const param = fromJS({
- name: "id",
- in: "query"
- })
- const res = paramToIdentifier(param)
-
- expect(res).toEqual("query.id.hash-606199662")
- })
- it("should convert an Immutable parameter map to a set of identifiers", () => {
- const param = fromJS({
- name: "id",
- in: "query"
- })
- const res = paramToIdentifier(param, { returnAll: true })
-
- expect(res).toEqual([
- "query.id.hash-606199662",
- "query.id",
- "id"
- ])
- })
-
- it("should convert an unhashable Immutable parameter map to an identifier", () => {
- const param = fromJS({
- name: "id",
- in: "query"
- })
-
- param.hashCode = null
-
- const res = paramToIdentifier(param)
-
- expect(res).toEqual("query.id")
- })
-
- it("should convert an unhashable Immutable parameter map to a set of identifiers", () => {
- const param = fromJS({
- name: "id",
- in: "query"
- })
-
- param.hashCode = null
-
- const res = paramToIdentifier(param, { returnAll: true })
-
- expect(res).toEqual([
- "query.id",
- "id"
- ])
- })
-
- it("should convert an Immutable parameter map lacking an `in` value to an identifier", () => {
- const param = fromJS({
- name: "id"
- })
-
- const res = paramToIdentifier(param)
-
- expect(res).toEqual("id")
- })
-
- it("should convert an Immutable parameter map lacking an `in` value to an identifier", () => {
- const param = fromJS({
- name: "id"
- })
-
- const res = paramToIdentifier(param, { returnAll: true })
-
- expect(res).toEqual(["id"])
- })
-
- it("should throw gracefully when given a non-Immutable parameter input", () => {
- const param = {
- name: "id"
- }
-
- let error = null
- let res = null
-
- try {
- const res = paramToIdentifier(param)
- } catch(e) {
- error = e
- }
-
- expect(error).toBeInstanceOf(Error)
- expect(error.message).toContain("received a non-Im.Map parameter as input")
- expect(res).toEqual(null)
- })
- })
-
- describe("paramToValue", () => {
- it("should identify a hash-keyed value", () => {
- const param = fromJS({
- name: "id",
- in: "query"
- })
-
- const paramValues = {
- "query.id.hash-606199662": "asdf"
- }
-
- const res = paramToValue(param, paramValues)
-
- expect(res).toEqual("asdf")
- })
-
- it("should identify a in+name value", () => {
- const param = fromJS({
- name: "id",
- in: "query"
- })
-
- const paramValues = {
- "query.id": "asdf"
- }
-
- const res = paramToValue(param, paramValues)
-
- expect(res).toEqual("asdf")
- })
-
- it("should identify a name value", () => {
- const param = fromJS({
- name: "id",
- in: "query"
- })
-
- const paramValues = {
- "id": "asdf"
- }
-
- const res = paramToValue(param, paramValues)
-
- expect(res).toEqual("asdf")
- })
- })
- describe("generateCodeVerifier", () => {
- it("should generate a value of at least 43 characters", () => {
- const codeVerifier = generateCodeVerifier()
- // Source: https://tools.ietf.org/html/rfc7636#section-4.1
- expect(codeVerifier.length).toBeGreaterThanOrEqual(43)
- })
- })
- describe("createCodeChallenge", () => {
- it("should hash the input using SHA256 and output the base64 url encoded value", () => {
- // The `codeVerifier` has been randomly generated
- const codeVerifier = "cY8OJ9MKvZ7hxQeIyRYD7KFmKA5znSFJ2rELysvy2UI"
- // This value is the `codeVerifier` hashed using SHA256, which has been
- // encoded using base64 url format.
- // Source: https://tools.ietf.org/html/rfc7636#section-4.2
- const expectedCodeChallenge = "LD9lx2p2PbvGkojuJy7-Elex7RnckzmqR7oIXjd4u84"
- expect(createCodeChallenge(codeVerifier)).toBe(expectedCodeChallenge)
- })
- })
- })
|