Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/components/ApproveRejectButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const ApproveRejectButtons: React.FunctionComponent<{

const approve = () => {
testRunService
.approve(testRun.id, testRun.merge)
.approveBulk([testRun.id], testRun.merge)
.then(() =>
enqueueSnackbar("Approved", {
variant: "success",
Expand All @@ -27,7 +27,7 @@ export const ApproveRejectButtons: React.FunctionComponent<{

const reject = () => {
testRunService
.reject(testRun.id)
.rejectBulk([testRun.id])
.then(() =>
enqueueSnackbar("Rejected", {
variant: "success",
Expand Down
28 changes: 8 additions & 20 deletions src/components/TestDetailsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ import {
import { ToggleButton } from "@material-ui/lab";
import { useHotkeys } from "react-hotkeys-hook";
import { TestRun } from "../types";
import {
testRunService,
testVariationService,
staticService,
} from "../services";
import { testRunService, staticService } from "../services";
import { TestStatus } from "../types/testStatus";
import { useHistory, Prompt } from "react-router-dom";
import { IgnoreArea } from "../types/ignoreArea";
Expand Down Expand Up @@ -112,12 +108,11 @@ const TestDetailsModal: React.FunctionComponent<{
};

const saveTestRun = (ignoreAreas: IgnoreArea[], successMessage: string) => {
Promise.all([
// update in test run
testRunService.setIgnoreAreas(testRun.id, ignoreAreas),
// update in variation
testVariationService.setIgnoreAreas(testRun.testVariationId, ignoreAreas),
])
testRunService
.updateIgnoreAreas({
ids: [testRun.id],
ignoreAreas,
})
.then(() => {
enqueueSnackbar(successMessage, {
variant: "success",
Expand Down Expand Up @@ -349,15 +344,8 @@ const TestDetailsModal: React.FunctionComponent<{
<CommentsPopper
text={testRun.comment}
onSave={(comment) =>
Promise.all([
// update in test run
testRunService.setComment(testRun.id, comment),
// update in variation
testVariationService.setComment(
testRun.testVariationId,
comment
),
])
testRunService
.update(testRun.id, { comment })
.then(() =>
enqueueSnackbar("Comment updated", {
variant: "success",
Expand Down
69 changes: 39 additions & 30 deletions src/components/TestRunList/BulkOperation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { useSnackbar } from "notistack";
import { Delete, LayersClear, ThumbDown, ThumbUp } from "@material-ui/icons";
import { testRunService } from "../../services";
import { TestStatus } from "../../types";
import { head } from "lodash";

export const BulkOperation: React.FunctionComponent<BaseComponentProps> = (
props: BaseComponentProps
Expand All @@ -23,6 +24,34 @@ export const BulkOperation: React.FunctionComponent<BaseComponentProps> = (
false
);
const [isProcessing, setIsProcessing] = React.useState(false);
const ids: string[] = React.useMemo(
() => Object.keys(props.state.selection),
[props.state.selection]
);
const isMerge: boolean = React.useMemo(
() =>
!!head(
props.rows.filter((value: RowModel) =>
ids.includes(value.id.toString())
)
)?.merge,
// eslint-disable-next-line
[ids]
);
const idsEligibleForApproveOrReject: string[] = React.useMemo(
() =>
props.rows
.filter(
(value: RowModel) =>
ids.includes(value.id.toString()) &&
[TestStatus.new, TestStatus.unresolved].includes(
value.status.toString()
)
)
.map((value: RowModel) => value.id.toString()),
// eslint-disable-next-line
[ids]
);

const selectedRows: Record<React.ReactText, boolean> = props.state.selection;
const count = Object.keys(selectedRows).length;
Expand Down Expand Up @@ -78,38 +107,20 @@ export const BulkOperation: React.FunctionComponent<BaseComponentProps> = (
}
};

const isRowEligibleForApproveOrReject = (id: string) => {
//Find the test status of the current row
let currentRow: any = props.rows.find((value: RowModel) =>
value.id.toString().includes(id)
);
let currentRowStatus = JSON.stringify(currentRow.status);
//In line with how we can approve/reject only new and unresolved from details modal.
return (
currentRowStatus.includes(TestStatus.new) ||
currentRowStatus.includes(TestStatus.unresolved)
);
};

const processAction = (id: string) => {
const getBulkAction = () => {
if (deleteDialogOpen) {
testRunService.remove(id);
}
if (isRowEligibleForApproveOrReject(id)) {
processApproveReject(id);
return testRunService.removeBulk(ids);
}
if (clearIgnoreDialogOpen) {
testRunService.setIgnoreAreas(id, []);
if (rejectDialogOpen) {
return testRunService.rejectBulk(idsEligibleForApproveOrReject);
}
};

const processApproveReject = (id: string) => {
if (approveDialogOpen) {
testRunService.approve(id, false);
}
if (rejectDialogOpen) {
testRunService.reject(id);
return testRunService.approveBulk(idsEligibleForApproveOrReject, isMerge);
}
return testRunService.updateIgnoreAreas({
ids,
ignoreAreas: [],
});
};

const dismissDialog = () => {
Expand Down Expand Up @@ -182,9 +193,7 @@ export const BulkOperation: React.FunctionComponent<BaseComponentProps> = (
}
onSubmit={() => {
setIsProcessing(true);
Promise.all(
Object.keys(selectedRows).map((id: string) => processAction(id))
)
getBulkAction()
.then(() => {
setIsProcessing(false);
enqueueSnackbar(`${count} test runs processed.`, {
Expand Down
72 changes: 43 additions & 29 deletions src/services/testRun.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TestRun } from "../types";
import { handleResponse, authHeader } from "../_helpers/service.helpers";
import { API_URL } from "../_config/env.config";
import { IgnoreArea } from "../types/ignoreArea";
import { UpdateIgnoreAreaDto } from "../types/ignoreArea";

const ENDPOINT_URL = "/test-runs";

Expand All @@ -17,61 +17,74 @@ async function getList(buildId: string): Promise<TestRun[]> {
).then(handleResponse);
}

async function remove(id: string): Promise<TestRun> {
async function removeBulk(ids: string[]): Promise<void> {
const requestOptions = {
method: "DELETE",
headers: authHeader(),
method: "POST",
headers: { "Content-Type": "application/json", ...authHeader() },
body: JSON.stringify(ids),
};

return fetch(`${API_URL}${ENDPOINT_URL}/${id}`, requestOptions).then(
return fetch(`${API_URL}${ENDPOINT_URL}/delete`, requestOptions).then(
handleResponse
);
}

async function approve(id: string, merge: boolean): Promise<TestRun> {
async function rejectBulk(ids: string[]): Promise<void> {
const requestOptions = {
method: "GET",
headers: authHeader(),
method: "POST",
headers: { "Content-Type": "application/json", ...authHeader() },
body: JSON.stringify(ids),
};

return fetch(`${API_URL}${ENDPOINT_URL}/reject`, requestOptions).then(
handleResponse
);
}

async function approveBulk(ids: string[], merge: boolean): Promise<void> {
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/json", ...authHeader() },
body: JSON.stringify(ids),
};

return fetch(
`${API_URL}${ENDPOINT_URL}/approve?id=${id}&merge=${merge}`,
`${API_URL}${ENDPOINT_URL}/approve?merge=${merge}`,
requestOptions
).then(handleResponse);
}

async function reject(id: string): Promise<TestRun> {
async function updateIgnoreAreas(data: UpdateIgnoreAreaDto): Promise<void> {
const requestOptions = {
method: "GET",
headers: authHeader(),
method: "POST",
headers: { "Content-Type": "application/json", ...authHeader() },
body: JSON.stringify(data),
};

return fetch(`${API_URL}${ENDPOINT_URL}/reject/${id}`, requestOptions).then(
handleResponse
);
return fetch(
`${API_URL}${ENDPOINT_URL}/ignoreAreas/update`,
requestOptions
).then(handleResponse);
}

async function setIgnoreAreas(
id: string,
ignoreAreas: IgnoreArea[]
): Promise<TestRun> {
async function addIgnoreAreas(data: UpdateIgnoreAreaDto): Promise<void> {
const requestOptions = {
method: "PUT",
method: "POST",
headers: { "Content-Type": "application/json", ...authHeader() },
body: JSON.stringify(ignoreAreas),
body: JSON.stringify(data),
};

return fetch(
`${API_URL}${ENDPOINT_URL}/ignoreArea/${id}`,
`${API_URL}${ENDPOINT_URL}/ignoreAreas/add`,
requestOptions
).then(handleResponse);
}

async function setComment(id: string, comment: string): Promise<TestRun> {
async function update(id: string, data: { comment: string }): Promise<TestRun> {
const requestOptions = {
method: "PUT",
headers: { "Content-Type": "application/json", ...authHeader() },
body: JSON.stringify({ comment }),
body: JSON.stringify(data),
};

return fetch(`${API_URL}${ENDPOINT_URL}/comment/${id}`, requestOptions).then(
Expand All @@ -81,9 +94,10 @@ async function setComment(id: string, comment: string): Promise<TestRun> {

export const testRunService = {
getList,
remove,
approve,
reject,
setIgnoreAreas,
setComment,
removeBulk,
rejectBulk,
approveBulk,
updateIgnoreAreas,
addIgnoreAreas,
update,
};
31 changes: 0 additions & 31 deletions src/services/testVariation.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { TestVariation, Build } from "../types";
import { handleResponse, authHeader } from "../_helpers/service.helpers";
import { API_URL } from "../_config/env.config";
import { IgnoreArea } from "../types/ignoreArea";

const ENDPOINT_URL = "/test-variations";

Expand All @@ -28,34 +27,6 @@ async function getDetails(id: String): Promise<TestVariation> {
);
}

async function setIgnoreAreas(
variationId: string,
ignoreAreas: IgnoreArea[]
): Promise<TestVariation> {
const requestOptions = {
method: "PUT",
headers: { "Content-Type": "application/json", ...authHeader() },
body: JSON.stringify(ignoreAreas),
};

return fetch(
`${API_URL}${ENDPOINT_URL}/ignoreArea/${variationId}`,
requestOptions
).then(handleResponse);
}

async function setComment(id: string, comment: string): Promise<TestVariation> {
const requestOptions = {
method: "PUT",
headers: { "Content-Type": "application/json", ...authHeader() },
body: JSON.stringify({ comment }),
};

return fetch(`${API_URL}${ENDPOINT_URL}/comment/${id}`, requestOptions).then(
handleResponse
);
}

async function merge(projectId: String, branchName: String): Promise<Build> {
const requestOptions = {
method: "GET",
Expand All @@ -82,8 +53,6 @@ async function remove(id: String): Promise<TestVariation> {
export const testVariationService = {
getList,
getDetails,
setIgnoreAreas,
setComment,
merge,
remove,
};
5 changes: 5 additions & 0 deletions src/types/ignoreArea.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ export interface IgnoreArea {
width: number;
height: number;
}

export interface UpdateIgnoreAreaDto {
ids: string[];
ignoreAreas: IgnoreArea[];
}