mirror of
https://github.com/status-im/sourcecred.git
synced 2025-02-17 06:56:36 +00:00
Add GitState
, Environment
types to version
(#691)
Summary: These types will shortly be added to the global `VersionInfo`. For now, we include the types and validation logic only. Test Plan: Unit tests suffice. wchargin-branch: add-rich-version-types
This commit is contained in:
parent
2d28bd5de4
commit
01071866be
@ -5,6 +5,52 @@ export type VersionInfo = {|
|
|||||||
+minor: number,
|
+minor: number,
|
||||||
+patch: number,
|
+patch: number,
|
||||||
|};
|
|};
|
||||||
|
export type GitState = {|
|
||||||
|
+commitHash: string,
|
||||||
|
+commitTimestamp: string, // YYYYmmdd-HHMM, in commit-local time
|
||||||
|
+dirty: boolean, // does the worktree have unstaged/uncommitted changes?
|
||||||
|
|};
|
||||||
|
export type Environment = "development" | "production" | "test";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the given string as a `GitState`, throwing an error if it is
|
||||||
|
* not valid. The argument should be the result of calling
|
||||||
|
* `JSON.stringify` with a valid `GitState`. Thus, this is a checked
|
||||||
|
* version of `JSON.parse`.
|
||||||
|
*/
|
||||||
|
export function parseGitState(raw: ?string): GitState {
|
||||||
|
if (typeof raw !== "string") {
|
||||||
|
throw new Error("gitState: not a string: " + String(raw));
|
||||||
|
}
|
||||||
|
const parsed: mixed = Object.freeze(JSON.parse(raw));
|
||||||
|
if (parsed == null || typeof parsed !== "object") {
|
||||||
|
throw new Error("gitState: not a JSON object: " + String(parsed));
|
||||||
|
}
|
||||||
|
// This intermediate variable helps out Flow's inference...
|
||||||
|
const gitState: Object = parsed;
|
||||||
|
if (
|
||||||
|
typeof gitState.commitHash !== "string" ||
|
||||||
|
typeof gitState.commitTimestamp !== "string" ||
|
||||||
|
typeof gitState.dirty !== "boolean" ||
|
||||||
|
Object.keys(gitState).length !== 3
|
||||||
|
) {
|
||||||
|
throw new Error("gitState: bad shape: " + JSON.stringify(gitState));
|
||||||
|
}
|
||||||
|
return gitState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the given string as an `Environment`, throwing an error if it
|
||||||
|
* is not valid. The input should be a valid `Environment`.
|
||||||
|
*/
|
||||||
|
export function parseEnvironment(raw: ?string): Environment {
|
||||||
|
if (raw !== "development" && raw !== "production" && raw !== "test") {
|
||||||
|
throw new Error(
|
||||||
|
"environment: " + (raw == null ? String(raw) : JSON.stringify(raw))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
export const VERSION_INFO = Object.freeze({
|
export const VERSION_INFO = Object.freeze({
|
||||||
major: 0,
|
major: 0,
|
||||||
|
109
src/app/version.test.js
Normal file
109
src/app/version.test.js
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// @flow
|
||||||
|
|
||||||
|
import {type Environment, parseEnvironment, parseGitState} from "./version";
|
||||||
|
|
||||||
|
describe("app/version", () => {
|
||||||
|
// Like `VersionInfo`, but with some extra properties that will
|
||||||
|
// shortly be added to that type.
|
||||||
|
const version = () => ({
|
||||||
|
major: 3,
|
||||||
|
minor: 13,
|
||||||
|
patch: 37,
|
||||||
|
gitState: {
|
||||||
|
commitHash: "d0e1a2d3b4e5",
|
||||||
|
commitTimestamp: "20010203-0405",
|
||||||
|
dirty: true,
|
||||||
|
},
|
||||||
|
environment: "test",
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("parseGitState", () => {
|
||||||
|
it("fails given literal `undefined`", () => {
|
||||||
|
expect(() => parseGitState(undefined)).toThrow(
|
||||||
|
"gitState: not a string: undefined"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("fails given literal `null`", () => {
|
||||||
|
expect(() => parseGitState(null)).toThrow("gitState: not a string: null");
|
||||||
|
});
|
||||||
|
it("fails given JSON `null`", () => {
|
||||||
|
expect(() => parseGitState("null")).toThrow(
|
||||||
|
"gitState: not a JSON object: null"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("fails given invalid JSON", () => {
|
||||||
|
expect(() => parseGitState("wat")).toThrow(
|
||||||
|
"Unexpected token w in JSON at position 0"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("fails given a JSON string", () => {
|
||||||
|
expect(() => parseGitState(JSON.stringify("wat"))).toThrow(
|
||||||
|
"gitState: not a JSON object: wat"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("fails given a non-stringified `GitState`", () => {
|
||||||
|
// $ExpectFlowError
|
||||||
|
expect(() => parseGitState(version().gitState)).toThrow(
|
||||||
|
"gitState: not a string: [object Object]"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("fails given a JSON object missing a property", () => {
|
||||||
|
const gitState = version().gitState;
|
||||||
|
delete gitState.dirty;
|
||||||
|
expect(() => parseGitState(JSON.stringify(gitState))).toThrow(
|
||||||
|
"gitState: bad shape: {"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
function expectBadShape(gitState) {
|
||||||
|
expect(() => parseGitState(JSON.stringify(gitState))).toThrow(
|
||||||
|
"gitState: bad shape: {"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
it("fails given a JSON object with an extra property", () => {
|
||||||
|
expectBadShape({...version().gitState, wat: "wot"});
|
||||||
|
});
|
||||||
|
it("fails given a JSON object with bad `commitHash`", () => {
|
||||||
|
expectBadShape({...version().gitState, commitHash: true});
|
||||||
|
expectBadShape({...version().gitState, commitHash: 27});
|
||||||
|
expectBadShape({...version().gitState, commitHash: null});
|
||||||
|
});
|
||||||
|
it("fails given a JSON object with bad `commitTimestamp`", () => {
|
||||||
|
expectBadShape({...version().gitState, commitTimestamp: true});
|
||||||
|
expectBadShape({...version().gitState, commitTimestamp: 27});
|
||||||
|
expectBadShape({...version().gitState, commitTimestamp: null});
|
||||||
|
});
|
||||||
|
it("fails given a JSON object with bad `dirty`", () => {
|
||||||
|
expectBadShape({...version().gitState, dirty: "true"});
|
||||||
|
expectBadShape({...version().gitState, dirty: 27});
|
||||||
|
expectBadShape({...version().gitState, dirty: null});
|
||||||
|
});
|
||||||
|
it("parses a valid `GitState`", () => {
|
||||||
|
const gitState = version().gitState;
|
||||||
|
expect(parseGitState(JSON.stringify(gitState))).toEqual(gitState);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("parseEnvironment", () => {
|
||||||
|
it("parses each of the valid environments", () => {
|
||||||
|
const allEnvs = {development: true, production: true, test: true};
|
||||||
|
function _unused_staticCheck(x: Environment): true {
|
||||||
|
return allEnvs[x];
|
||||||
|
}
|
||||||
|
for (const env of Object.keys(allEnvs)) {
|
||||||
|
expect(parseEnvironment(env)).toEqual(env);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("fails given literal `undefined`", () => {
|
||||||
|
expect(() => parseEnvironment(undefined)).toThrow(
|
||||||
|
"environment: undefined"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("fails given literal `null`", () => {
|
||||||
|
expect(() => parseEnvironment(null)).toThrow("environment: null");
|
||||||
|
});
|
||||||
|
it("fails given a non-environment string", () => {
|
||||||
|
expect(() => parseEnvironment("wat")).toThrow('environment: "wat"');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user