-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from imabp/github-action
feat: add methods: `toJson`, `isOfType`, `update`, `tests` and workflow setup file
- Loading branch information
Showing
10 changed files
with
257 additions
and
64 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,29 @@ | ||
name: PR testing | ||
|
||
on: | ||
pull_request: | ||
types: [opened, reopened, synchronize, ready_for_review] | ||
|
||
jobs: | ||
test-pr: | ||
name: Test PR - ${{ matrix.os }} | ||
runs-on: ${{ matrix.os }} | ||
strategy: | ||
matrix: | ||
os: [ubuntu-latest, macos-latest, windows-latest] | ||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Install Node.js | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: '12.x' | ||
|
||
- name: Install Dependencies | ||
run: yarn install | ||
|
||
- name: Run tests | ||
run: yarn test | ||
|
||
- name: Build Problem Library | ||
run: yarn build |
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 { Problem } from "../src" | ||
import { ProblemInterface } from "../src/types" | ||
|
||
export default class ProblemContextHelper { | ||
|
||
_problemInstance: Problem; | ||
|
||
_instanceOptions: ProblemInterface = { | ||
type: "null-or-falsey-document", | ||
title: "The AsyncAPI document is null or a JS falsey value.", | ||
detail: "The AsyncAPI document is null or a JS falsey value.", | ||
leaveThisWhenCopy:"This is used to test copy function: LEAVE PROPS. This will not be undefined in new copy. ", | ||
skipThisWhenCopy:"This is used to test copy functionL SKIP PROPS. This should be undefined in new copy.", | ||
} | ||
|
||
|
||
constructor() { | ||
this._problemInstance = new Problem(this._instanceOptions); | ||
} | ||
|
||
} |
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,79 @@ | ||
import { Problem } from "../src"; | ||
import { COPY_MODE } from "../src/constants"; | ||
import ProblemContextHelper from "./_helper"; | ||
|
||
const _testContext = new ProblemContextHelper(); | ||
|
||
describe("Class Methods Test Suite", () => { | ||
test("Create Class with Custom Keys", () => { | ||
const customKey = "RCA"; | ||
_testContext._problemInstance[customKey]="Root Cause Analysis" | ||
const testProblem = new Problem(_testContext._problemInstance); | ||
expect(testProblem).toHaveProperty(customKey); | ||
}); | ||
|
||
test("Method: Copy, mode: LEAVE_PROPS", () => { | ||
const _problemCopy = _testContext._problemInstance.copy( | ||
COPY_MODE.LEAVE_PROPS, | ||
["leaveThisWhenCopy"] | ||
); | ||
expect(_problemCopy).toBeInstanceOf(Problem); | ||
expect(_problemCopy.type).toBe(_testContext._problemInstance.type); | ||
expect(_problemCopy.title).toBe(_testContext._problemInstance.title); | ||
// check if skipthiswhencopy is omitted. | ||
expect(_problemCopy.skipThisWhenCopy).toBe(undefined); | ||
// check if leavethiswhencopy is not omitted | ||
expect(_problemCopy.leaveThisWhenCopy).toBe(_testContext._problemInstance.leaveThisWhenCopy); | ||
}); | ||
|
||
test("Method: Copy, mode: SKIP_PROPS", () => { | ||
const _copiedProblem = _testContext._problemInstance.copy( | ||
COPY_MODE.SKIP_PROPS, | ||
["skipThisWhenCopy"] | ||
); | ||
expect(_copiedProblem).toBeInstanceOf(Problem); | ||
// check if leavethiswhencopy is not emitted. | ||
expect(_copiedProblem.leaveThisWhenCopy).toBe(_testContext._problemInstance.leaveThisWhenCopy); | ||
// check if skipthis is omitted | ||
expect(_copiedProblem.skipThisWhenCopy).toBeUndefined(); | ||
}); | ||
|
||
test("Method: isOfType", () => { | ||
const _TYPE_TRUTH_CHECK = "null-or-falsey-document"; | ||
const _TYPE_FALSE_CHECK = "undefined-document"; | ||
expect( | ||
_testContext._problemInstance.isOfType(_TYPE_TRUTH_CHECK) | ||
).toBeTruthy(); | ||
expect( | ||
_testContext._problemInstance.isOfType(_TYPE_FALSE_CHECK) | ||
).toBeFalsy(); | ||
}); | ||
|
||
test("Method: Update", async () => { | ||
const LINK: string = "test-link/"; | ||
const updates = { | ||
link: LINK, | ||
}; | ||
await _testContext._problemInstance.update({ updates }); | ||
expect(_testContext._problemInstance).toHaveProperty("link", LINK); | ||
}); | ||
|
||
test("Method: toJSON", () => { | ||
const _problem = _testContext._problemInstance; | ||
|
||
// Run updates first to add stack property, required for testing isJSON | ||
const updates = { | ||
stack: "./filepath", | ||
}; | ||
_problem.update({ updates }); | ||
|
||
// non-stringified stack | ||
expect(_problem.toJSON({ includeStack: true })).toHaveProperty( | ||
"stack", | ||
updates.stack | ||
); | ||
expect(_problem.toJSON({ includeStack: false })).not.toHaveProperty( | ||
"stack" | ||
); | ||
}); | ||
}); |
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
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
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,9 @@ | ||
export const DEFAULT_KEYS = [ | ||
"type", | ||
"title", | ||
]; | ||
|
||
export enum COPY_MODE { | ||
SKIP_PROPS = "skipProps", | ||
LEAVE_PROPS = "leaveProps", | ||
} |
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 |
---|---|---|
@@ -1,62 +1,87 @@ | ||
import { httpObject, ProblemInterface } from "types"; | ||
|
||
enum COPY_MODE { | ||
SKIP_PROPS = 'skipProps', | ||
LEAVE_PROPS = 'leaveProps' | ||
} | ||
import { DEFAULT_KEYS } from "./constants"; | ||
import { | ||
HttpObject, | ||
ProblemInterface, | ||
ToJsonParamType, | ||
UpdateProblemParamType, | ||
} from "./types"; | ||
|
||
import { COPY_MODE } from "./constants"; | ||
import { objectToProblemMap } from "./util"; | ||
export class Problem extends Error implements ProblemInterface { | ||
public type: string; | ||
public title: string; | ||
public instance?: string; | ||
public detail?: string; | ||
public http?: httpObject | ||
[key: string]: any; | ||
|
||
|
||
constructor(problem: ProblemInterface, customKeys?: string[]) { | ||
super(problem.detail || problem.title); | ||
this.http = problem.http | ||
this.type = problem.type | ||
this.title = problem.title; | ||
this.detail = problem.detail; | ||
this.instance = problem.instance; | ||
this.stack = problem.stack; | ||
customKeys?.map((customKey) => { | ||
this[customKey] = problem[customKey]; | ||
}) | ||
} | ||
public type: string; | ||
public title: string; | ||
public instance?: string; | ||
public detail?: string; | ||
public http?: HttpObject; | ||
[key: string]: any; | ||
|
||
copy(problem: ProblemInterface, mode: COPY_MODE, props: string[]): Problem { | ||
switch (mode) { | ||
|
||
case COPY_MODE.LEAVE_PROPS: | ||
return new Problem(problem, props); | ||
|
||
case COPY_MODE.SKIP_PROPS: | ||
default: | ||
let keysToBeCopied: string[] = []; | ||
for (let key in problem) { | ||
if (props.includes(key)) | ||
continue; | ||
keysToBeCopied.push(key) | ||
} | ||
return new Problem(problem, keysToBeCopied) | ||
} | ||
}; | ||
|
||
toJSON(problem: Problem, includeStack = false): ProblemInterface { | ||
constructor(protected readonly problem: ProblemInterface) { | ||
super(problem.detail || problem.title); | ||
this.http = problem.http; | ||
this.type = problem.type; | ||
this.title = problem.title; | ||
this.detail = problem.detail; | ||
this.instance = problem.instance; | ||
this.stack = problem.stack; | ||
|
||
const { name, message, stack, ...rest } = problem; | ||
// add extra keys | ||
Object.keys(problem) | ||
.filter((el) => !DEFAULT_KEYS.includes(el)) | ||
.forEach((k) => (this[k] = problem[k])); | ||
} | ||
|
||
const jsonObject = { | ||
...rest | ||
copy(mode: COPY_MODE = COPY_MODE.LEAVE_PROPS, props: string[] = []): Problem { | ||
switch (mode) { | ||
// returns a new problem object with preserved keys passed as props | ||
case COPY_MODE.LEAVE_PROPS:{ | ||
let newProblemKeyValuePairs:Record<string,any> = { | ||
type: this.problem.type, | ||
title:this.problem.title, | ||
} | ||
props.forEach((key)=>{ | ||
newProblemKeyValuePairs={...newProblemKeyValuePairs, [key]:this.problem[key]} | ||
}) | ||
const newProblem = new Problem(objectToProblemMap(newProblemKeyValuePairs)); | ||
return newProblem; | ||
} | ||
// skip the copy of keys | ||
case COPY_MODE.SKIP_PROPS: | ||
default: { | ||
let newProblemKeyValuePairs:Record<string,any>={}; | ||
|
||
if (includeStack) | ||
jsonObject.stack = stack; | ||
// loop to copy only the required keys | ||
for (let key in this.problem) { | ||
// Skip only those keys, which are given in props and NOT a default key. | ||
if (props.includes(key) && !DEFAULT_KEYS.includes(key)) continue; | ||
newProblemKeyValuePairs[key] = this.problem[key]; | ||
} | ||
const newProblem = new Problem(objectToProblemMap(newProblemKeyValuePairs)) | ||
return newProblem; | ||
} | ||
} | ||
} | ||
|
||
return jsonObject; | ||
toJSON({ includeStack = false }: ToJsonParamType) { | ||
const { stack, ...rest } = this; | ||
|
||
if (includeStack) { | ||
return { | ||
...this, | ||
stack: this.stack, | ||
}; | ||
} | ||
}; | ||
|
||
return { ...rest }; | ||
} | ||
|
||
isOfType(type: string) { | ||
return this.type === type; | ||
} | ||
|
||
update({ updates }: UpdateProblemParamType) { | ||
Object.keys(updates).forEach((i) => { | ||
this[i] = updates[i]; | ||
}); | ||
} | ||
} |
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 |
---|---|---|
@@ -1,14 +1,24 @@ | ||
import { Problem } from "../problem"; | ||
|
||
export type ProblemInterface = { | ||
http?: httpObject, | ||
type: string, | ||
title: string, // Title should be description of http status, if type is not present. | ||
detail?: string, | ||
instance?: string, // Details to reproduce the error. | ||
stack?: string; | ||
[key: string]: any, // Custom Field of Problem | ||
} | ||
|
||
export type httpObject= { | ||
status: number, // Status Code | ||
[key: string]: any, | ||
type: string; | ||
title: string; | ||
http?: HttpObject; | ||
detail?: string; | ||
instance?: string; | ||
stack?: string; | ||
[key: string]: any; | ||
}; | ||
|
||
export type HttpObject = { | ||
status: number; // Status Code | ||
[key: string]: any; | ||
}; | ||
|
||
export type UpdateProblemParamType = { | ||
updates: { [key: string]: any }; | ||
}; | ||
|
||
export type ToJsonParamType = { | ||
includeStack?:boolean | ||
} |
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,10 @@ | ||
import { ProblemInterface } from "types"; | ||
|
||
export const objectToProblemMap = (obj:Record<string,any>) =>{ | ||
const type: string = obj.type; | ||
const title: string = obj.title; | ||
const problemObject:ProblemInterface = { | ||
type, title, ...obj | ||
} | ||
return problemObject | ||
} |
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