-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce a type unicity verifier and fix endpoint unicity verifier (#…
…216) We didn't have a way to ensure that the same type name was used twice. It turns out, our endpoint name verifier was also incorrect because it compared Locatables and not strings. Adding unit tests to ensure we never break this again :)
- Loading branch information
Showing
5 changed files
with
161 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { HttpMethod } from "../../models/http"; | ||
import { | ||
ApiNode, | ||
ContractNode, | ||
EndpointNode, | ||
RequestNode | ||
} from "../../models/nodes"; | ||
import { fakeLocatable } from "../../test/fake-locatable"; | ||
import { verifyUniqueEndpointNames } from "./endpoints"; | ||
|
||
describe("unique endpoint names verifier", () => { | ||
test("valid for correct usage", () => { | ||
const contractNode: ContractNode = { | ||
api: fakeLocatable({} as ApiNode), | ||
endpoints: [ | ||
fakeLocatable<EndpointNode>({ | ||
name: fakeLocatable("EndpointOne"), | ||
tags: fakeLocatable([]), | ||
method: fakeLocatable<HttpMethod>("POST"), | ||
path: fakeLocatable("/a"), | ||
request: fakeLocatable({} as RequestNode), | ||
responses: [], | ||
tests: [] | ||
}), | ||
fakeLocatable<EndpointNode>({ | ||
name: fakeLocatable("EndpointTwo"), | ||
tags: fakeLocatable([]), | ||
method: fakeLocatable<HttpMethod>("POST"), | ||
path: fakeLocatable("/b"), | ||
request: fakeLocatable({} as RequestNode), | ||
responses: [], | ||
tests: [] | ||
}) | ||
], | ||
types: [] | ||
}; | ||
expect(verifyUniqueEndpointNames(contractNode)).toHaveLength(0); | ||
}); | ||
|
||
test("invalid for duplicate names", () => { | ||
const contractNode: ContractNode = { | ||
api: fakeLocatable({} as ApiNode), | ||
endpoints: [ | ||
fakeLocatable<EndpointNode>({ | ||
name: fakeLocatable("EndpointOne"), | ||
tags: fakeLocatable([]), | ||
method: fakeLocatable<HttpMethod>("POST"), | ||
path: fakeLocatable("/a"), | ||
request: fakeLocatable({} as RequestNode), | ||
responses: [], | ||
tests: [] | ||
}), | ||
fakeLocatable<EndpointNode>({ | ||
name: fakeLocatable("EndpointOne"), | ||
tags: fakeLocatable([]), | ||
method: fakeLocatable<HttpMethod>("POST"), | ||
path: fakeLocatable("/b"), | ||
request: fakeLocatable({} as RequestNode), | ||
responses: [], | ||
tests: [] | ||
}) | ||
], | ||
types: [] | ||
}; | ||
expect(verifyUniqueEndpointNames(contractNode)).toMatchObject([ | ||
{ | ||
message: "endpoints must have unique names" | ||
} | ||
]); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { uniq } from "lodash"; | ||
import { ContractNode } from "../../models/nodes"; | ||
import { VerificationError } from "../verification-error"; | ||
|
||
export function verifyUniqueEndpointNames( | ||
contract: ContractNode | ||
): VerificationError[] { | ||
const errors: VerificationError[] = []; | ||
const endpointNames = contract.endpoints.map( | ||
endpoint => endpoint.value.name.value | ||
); | ||
if (uniq(endpointNames).length !== endpointNames.length) { | ||
errors.push({ | ||
message: "endpoints must have unique names", | ||
// TODO: use a duplicated endpoint location | ||
location: contract.api.location, | ||
line: contract.api.line | ||
}); | ||
} | ||
return errors; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { ApiNode, ContractNode } from "../../models/nodes"; | ||
import { STRING } from "../../models/types"; | ||
import { fakeLocatable } from "../../test/fake-locatable"; | ||
import { verifyUniqueTypeNames } from "./types"; | ||
|
||
describe("unique type names verifier", () => { | ||
test("valid for correct usage", () => { | ||
const contractNode: ContractNode = { | ||
api: fakeLocatable({} as ApiNode), | ||
endpoints: [], | ||
types: [ | ||
{ | ||
name: "TypeOne", | ||
type: STRING | ||
}, | ||
{ | ||
name: "TypeTwo", | ||
type: STRING | ||
} | ||
] | ||
}; | ||
expect(verifyUniqueTypeNames(contractNode)).toHaveLength(0); | ||
}); | ||
|
||
test("invalid for duplicate names", () => { | ||
const contractNode: ContractNode = { | ||
api: fakeLocatable({} as ApiNode), | ||
endpoints: [], | ||
types: [ | ||
{ | ||
name: "TypeOne", | ||
type: STRING | ||
}, | ||
{ | ||
name: "TypeOne", | ||
type: STRING | ||
} | ||
] | ||
}; | ||
expect(verifyUniqueTypeNames(contractNode)).toMatchObject([ | ||
{ | ||
message: "types must have unique names" | ||
} | ||
]); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { uniq } from "lodash"; | ||
import { ContractNode } from "../../models/nodes"; | ||
import { VerificationError } from "../verification-error"; | ||
|
||
export function verifyUniqueTypeNames( | ||
contract: ContractNode | ||
): VerificationError[] { | ||
const errors: VerificationError[] = []; | ||
const typeNames = contract.types.map(type => type.name); | ||
if (uniq(typeNames).length !== typeNames.length) { | ||
errors.push({ | ||
message: "types must have unique names", | ||
// TODO: use a duplicated type location | ||
location: contract.api.location, | ||
line: contract.api.line | ||
}); | ||
} | ||
return errors; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters