Skip to content

Commit

Permalink
feat: crash status (#134)
Browse files Browse the repository at this point in the history
* feat: crash status

* fix: crashes status

* fix: summary status

* feat: post success
  • Loading branch information
bobbyg603 authored Nov 5, 2024
1 parent dcddfe8 commit 6385b36
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 17 deletions.
3 changes: 2 additions & 1 deletion spec/fakes/crash/crash-api-response.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { GroupableThreadCollection, ProcessingStatus } from '@crash';
import { EventType } from '@events';
import { createFakeEvents } from '@spec/fakes/events/events';
import { CrashDetailsRawResponse } from 'src/crash/crash-details/crash-details';
import { CrashDetailsRawResponse, CrashStatus } from 'src/crash/crash-details/crash-details';

export const createFakeCrashApiResponse = () => ({
processed: ProcessingStatus.Complete as number,
Expand All @@ -27,6 +27,7 @@ export const createFakeCrashApiResponse = () => ({
platform: 'NES',
previousCrashId: 998,
processor: 'Pentium 4',
status: CrashStatus.Open,
stackKey: 'myConsoleCrasher(1337)',
stackKeyComment: 'hello world!',
stackKeyId: 117,
Expand Down
24 changes: 17 additions & 7 deletions src/crash/crash-api-client/crash-api-client.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import { BugSplatApiClient } from '@common';
import { CrashApiClient } from '@crash';
import { CrashApiClient, CrashStatus } from '@crash';
import { config } from '@spec/config';
import { postNativeCrashAndSymbols } from '@spec/files/native/post-native-crash';
import { postNativeCrashAndWaitForCrashToProcess } from '@spec/files/native/post-native-crash';

describe('CrashApiClient', () => {
let crashClient: CrashApiClient;
let application: string;
let version: string;
let id: number;
let stackKeyId: number;

beforeEach(async () => {
const { host, email, password } = config;
const bugsplatApiClient = await BugSplatApiClient.createAuthenticatedClientForNode(email, password, host);
application = 'myConsoleCrasher';
version = `${Math.random() * 1000000}`;
const result = await postNativeCrashAndSymbols(
crashClient = new CrashApiClient(bugsplatApiClient);
const result = await postNativeCrashAndWaitForCrashToProcess(
bugsplatApiClient,
crashClient,
config.database,
application,
version
);
id = result.crashId;

crashClient = new CrashApiClient(bugsplatApiClient);
stackKeyId = result.stackKeyId;
});

describe('getCrashById', () => {
Expand All @@ -39,7 +41,15 @@ describe('CrashApiClient', () => {
it('should return 200 for a recent crash that has symbols', async () => {
const response = await crashClient.reprocessCrash(config.database, id);

expect(response.success).toEqual(true);
expect(response.status).toEqual('success');
});
});

describe('postStatus', () => {
it('should return 200', async () => {
const response = await crashClient.postStatus(config.database, stackKeyId, CrashStatus.Open);

expect(response.status).toEqual('success');
});
});
});
});
59 changes: 57 additions & 2 deletions src/crash/crash-api-client/crash-api-client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createFakeBugSplatApiClient } from '@spec/fakes/common/bugsplat-api-cli
import { createFakeFormData } from '@spec/fakes/common/form-data';
import { createFakeResponseBody } from '@spec/fakes/common/response';
import { createFakeCrashApiResponse } from '@spec/fakes/crash/crash-api-response';
import { createCrashDetails } from '../crash-details/crash-details';
import { CrashStatus, createCrashDetails } from '../crash-details/crash-details';

describe('CrashApiClient', () => {
const database = 'fred';
Expand Down Expand Up @@ -170,4 +170,59 @@ describe('CrashApiClient', () => {
}
});
});
});

describe('postStatus', () => {
let client: CrashApiClient;
let fakePostStatusApiResponse;
let fakeBugSplatApiClient;
let result;

beforeEach(async () => {
fakePostStatusApiResponse = { success: true };
const fakeResponse = createFakeResponseBody(200, fakePostStatusApiResponse);
fakeBugSplatApiClient = createFakeBugSplatApiClient(fakeFormData, fakeResponse);
client = new CrashApiClient(fakeBugSplatApiClient);

result = await client.postStatus(database, id, CrashStatus.Closed);
});

it('should call fetch with correct route', () => {
expect(fakeBugSplatApiClient.fetch).toHaveBeenCalledWith('/api/crash/status', jasmine.anything());
});

it('should call fetch with formData containing database, id and status', () => {
expect(fakeFormData.append).toHaveBeenCalledWith('database', database);
expect(fakeFormData.append).toHaveBeenCalledWith('groupId', id.toString());
expect(fakeFormData.append).toHaveBeenCalledWith('status', CrashStatus.Closed.toString());
});

it('should return response json', () => {
expect(result).toEqual(fakePostStatusApiResponse);
});

it('should throw if status is not 200', async () => {
const message = 'Bad request';

try {
const fakePostStatusErrorBody = { message };
const fakeResponse = createFakeResponseBody(400, fakePostStatusErrorBody, false);
const fakeBugSplatApiClient = createFakeBugSplatApiClient(fakeFormData, fakeResponse);
const client = new CrashApiClient(fakeBugSplatApiClient);

await client.postStatus(database, id, CrashStatus.Closed);
fail('postStatus was supposed to throw!');
} catch (error: any) {
expect(error.message).toEqual(message);
}
});

it('should throw if database is falsy', async () => {
try {
await client.postStatus('', id, CrashStatus.Closed);
fail('postStatus was supposed to throw!');
} catch (error: any) {
expect(error.message).toMatch(/to be a non white space string/);
}
});
});
});
33 changes: 31 additions & 2 deletions src/crash/crash-api-client/crash-api-client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ApiClient } from '@common';
import { CrashDetails } from '@crash';
import ac from 'argument-contracts';
import { CrashDetailsRawResponse, createCrashDetails } from '../crash-details/crash-details';
import { CrashDetailsRawResponse, CrashStatus, createCrashDetails } from '../crash-details/crash-details';

export class CrashApiClient {

Expand Down Expand Up @@ -75,9 +75,38 @@ export class CrashApiClient {

return json as SuccessResponse;
}

async postStatus(database: string, groupId: number, status: CrashStatus): Promise<SuccessResponse> {
ac.assertNonWhiteSpaceString(database, 'database');
ac.assertNumber(groupId, 'groupId');
ac.assertNumber(status, 'status');

const formData = this._client.createFormData();
formData.append('database', database);
formData.append('groupId', groupId.toString());
formData.append('status', status.toString());
const init = {
method: 'POST',
body: formData,
cache: 'no-cache',
credentials: 'include',
redirect: 'follow',
duplex: 'half'
} as RequestInit;

const response = await this._client.fetch<PostStatusResponse>('/api/crash/status', init);
const json = await response.json();

if (response.status !== 200) {
throw new Error((json as ErrorResponse).message);
}

return json as SuccessResponse;
}
}

type SuccessResponse = { success: boolean };
type SuccessResponse = { status: 'success' };
type ErrorResponse = { message: string };
type GetCrashByIdResponse = CrashDetailsRawResponse | ErrorResponse;
type ReprocessCrashResponse = SuccessResponse | ErrorResponse;
type PostStatusResponse = SuccessResponse | ErrorResponse;
5 changes: 3 additions & 2 deletions src/crash/crash-details/crash-details.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AdditionalInfo, ProcessingStatus } from '@crash';
import { AdditionalInfo, CrashStatus, ProcessingStatus } from '@crash';
import { createFakeCrashApiResponse } from '@spec/fakes/crash/crash-api-response';
import ac from 'argument-contracts';
import { createEvents } from '../../events/events-api-client/event';
Expand Down Expand Up @@ -44,7 +44,8 @@ describe('createCrashDetails', () => {
processor: 'OBAN-10.0.7.144',
comments: null,
processed: ProcessingStatus.Complete,
thread: (<any>{ stackFrames: [], stackKeyId: 0 })
thread: (<any>{ stackFrames: [], stackKeyId: 0 }),
status: CrashStatus.Open,
};

const result = createCrashDetails(<any>options);
Expand Down
9 changes: 9 additions & 0 deletions src/crash/crash-details/crash-details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ export enum DefectTrackerType {
Favro = 'Favro',
}

export enum CrashStatus {
Open = 0,
Closed = 1,
Regression = 2,
}

export interface CrashDetails {
processed: ProcessingStatus;

Expand All @@ -50,6 +56,7 @@ export interface CrashDetails {
platform: string;
previousCrashId: number;
processor: string;
status: CrashStatus;
stackKey: string;
stackKeyComment: string;
stackKeyId: number;
Expand Down Expand Up @@ -93,6 +100,7 @@ export function createCrashDetails(options: CrashDetailsRawResponse): CrashDetai
ac.assertType(options.thread, ThreadCollection, 'options.thread');
ac.assertType(options.events, Array, 'options.events');

const status = (options.status || 0) as CrashStatus;
const events = createEvents(options.events as EventResponseObject[]);
const thread = new GroupableThreadCollection({
...<ThreadCollection>options.thread,
Expand Down Expand Up @@ -120,6 +128,7 @@ export function createCrashDetails(options: CrashDetailsRawResponse): CrashDetai
ipAddress,
platform,
processor,
status,
stackKey,
stackKeyComment,
stackKeyDefectLabel,
Expand Down
2 changes: 1 addition & 1 deletion src/crash/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { AdditionalInfo } from './additional-info/additional-info';
export { CrashApiClient } from './crash-api-client/crash-api-client';
export { CrashDetails, DefectTrackerType, ProcessingStatus } from './crash-details/crash-details';
export { CrashDetails, DefectTrackerType, ProcessingStatus, CrashStatus } from './crash-details/crash-details';
export { Module } from './module/module';
export { Register } from './register/register';
export { StackFrame, VariableValuePair } from './stack-frame/stack-frame';
Expand Down
4 changes: 4 additions & 0 deletions src/crashes/crashes-api-row/crashes-api-row.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CrashStatus } from '@crash';
import { safeParseJson } from '../../common/parse';

interface CrashData {
Expand All @@ -14,6 +15,7 @@ interface CrashData {
defectId: string;
defectUrl: string;
defectLabel: string;
status: CrashStatus;
skDefectId: string;
skDefectUrl: string;
skDefectLabel: string;
Expand Down Expand Up @@ -70,6 +72,7 @@ export enum CrashTypeId {
export class CrashesApiRow implements CrashDataWithMappedProperties {
id: number;
groupByCount: number;
status: CrashStatus;
stackKey: string;
stackId: number;
stackKeyId: number;
Expand Down Expand Up @@ -97,6 +100,7 @@ export class CrashesApiRow implements CrashDataWithMappedProperties {
constructor(rawApiRow: CrashesApiResponseRow) {
this.id = Number(rawApiRow.id);
this.groupByCount = Number(rawApiRow.groupByCount) || 0;
this.status = Number(rawApiRow.status) as CrashStatus;
this.stackKey = rawApiRow.stackKey;
this.stackKeyId = Number(rawApiRow.stackKeyId);
this.stackId = Number(rawApiRow.stackId);
Expand Down
3 changes: 2 additions & 1 deletion src/summary/summary-api-client/summary-api-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ export class SummaryApiClient {
row.stackKeyDefectLabel,
row.comments,
Number(row.subKeyDepth),
Number(row.userSum)
Number(row.userSum),
Number(row.status)
)
);

Expand Down
6 changes: 5 additions & 1 deletion src/summary/summary-api-row/summary-api-row.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { CrashStatus } from '@crash';

interface SummaryData {
status: CrashStatus,
stackKey: string,
firstReport: string,
lastReport: string,
Expand Down Expand Up @@ -36,6 +39,7 @@ export class SummaryApiRow implements SummaryDataWithMappedProperties {
public stackKeyDefectLabel: string,
public comments: string,
public subKeyDepth: number,
public userSum: number
public userSum: number,
public status: CrashStatus
) { }
}

0 comments on commit 6385b36

Please sign in to comment.