@truedat/dq 7.12.7 → 7.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dq",
3
- "version": "7.12.7",
3
+ "version": "7.13.1",
4
4
  "description": "Truedat Web Data Quality Module",
5
5
  "sideEffects": false,
6
6
  "module": "src/index.js",
@@ -53,7 +53,7 @@
53
53
  "@testing-library/jest-dom": "^6.6.3",
54
54
  "@testing-library/react": "^16.3.0",
55
55
  "@testing-library/user-event": "^14.6.1",
56
- "@truedat/test": "7.12.7",
56
+ "@truedat/test": "7.13.1",
57
57
  "identity-obj-proxy": "^3.0.0",
58
58
  "jest": "^29.7.0",
59
59
  "redux-saga-test-plan": "^4.0.6"
@@ -86,5 +86,5 @@
86
86
  "semantic-ui-react": "^3.0.0-beta.2",
87
87
  "swr": "^2.3.3"
88
88
  },
89
- "gitHead": "4fcf1a96c366bb13af6261808308a00cc7480a82"
89
+ "gitHead": "17c040e6539b00eab7870d0d82ac91910e85b7ac"
90
90
  }
package/src/api.js CHANGED
@@ -22,8 +22,7 @@ const API_RULE_IMPLEMENTATIONS_XLSX_UPLOAD_JOBS =
22
22
  "/api/rule_implementations/xlsx/upload_jobs";
23
23
  const API_RULE_IMPLEMENTATIONS_XLSX_UPLOAD_JOB =
24
24
  "/api/rule_implementations/xlsx/upload_jobs/:id";
25
- const API_RULE_IMPLEMENTATIONS_FROM_RULE =
26
- "/api/rules/:id/rule_implementations";
25
+ const API_RULE_IMPLEMENTATIONS_FROM_RULE = "/api/rules/rule_implementations";
27
26
  const API_RULE_IMPLEMENTATIONS_SEARCH = "/api/rule_implementations/search";
28
27
  const API_RULE_IMPLEMENTATION_FILTERS_SEARCH =
29
28
  "/api/rule_implementation_filters/search";
@@ -111,47 +111,27 @@ export const ImplementationActions = ({
111
111
  <Button
112
112
  primary
113
113
  content={formatMessage({ id: "actions.publish" })}
114
- onClick={() =>
115
- publishImplementation({
116
- id,
117
- redirectUrl: linkTo.IMPLEMENTATION({ implementation_id: id }),
118
- })
119
- }
114
+ onClick={() => publishImplementation({ id })}
120
115
  />
121
116
  ) : null}
122
117
  {actions?.restore ? (
123
118
  <Button
124
119
  primary
125
120
  content={formatMessage({ id: "actions.restore" })}
126
- onClick={() =>
127
- restoreImplementation({
128
- id,
129
- redirectUrl: linkTo.IMPLEMENTATION({ implementation_id: id }),
130
- })
131
- }
121
+ onClick={() => restoreImplementation({ id })}
132
122
  />
133
123
  ) : null}
134
124
  {actions?.reject ? (
135
125
  <Button
136
126
  secondary
137
127
  content={formatMessage({ id: "actions.reject" })}
138
- onClick={() =>
139
- rejectImplementation({
140
- id,
141
- redirectUrl: linkTo.IMPLEMENTATION({ implementation_id: id }),
142
- })
143
- }
128
+ onClick={() => rejectImplementation({ id })}
144
129
  />
145
130
  ) : null}
146
131
  {actions?.submit ? (
147
132
  <Button
148
133
  content={formatMessage({ id: "actions.submit" })}
149
- onClick={() =>
150
- submitImplementation({
151
- id,
152
- redirectUrl: linkTo.IMPLEMENTATION({ implementation_id: id }),
153
- })
154
- }
134
+ onClick={() => submitImplementation({ id })}
155
135
  />
156
136
  ) : null}
157
137
  {actions?.execute ? <ExecutionPopup onSubmit={handleExecute} /> : null}
@@ -4,7 +4,7 @@ import { connect } from "react-redux";
4
4
  import { Container } from "semantic-ui-react";
5
5
  import { getLinkedImplementationsToRulesColumns } from "../selectors";
6
6
  import {
7
- useRuleImplementationSearch,
7
+ useRuleImplementationFromRulesSearch,
8
8
  useRuleImplementationFilters,
9
9
  } from "../hooks/useImplementations";
10
10
  import RuleImplementationsTable from "./RuleImplementationsTable";
@@ -15,7 +15,7 @@ export const RuleFormImplementations = ({ rule, columns }) => {
15
15
  const searchProps = {
16
16
  initialSortColumn: "implementation_key.raw",
17
17
  initialSortDirection: "ascending",
18
- useSearch: useRuleImplementationSearch,
18
+ useSearch: useRuleImplementationFromRulesSearch,
19
19
  useFilters: useRuleImplementationFilters,
20
20
  pageSize: 20,
21
21
  defaultFilters: {
@@ -1,6 +1,28 @@
1
1
  import { render, waitForLoad } from "@truedat/test/render";
2
+ import { useSearchContext } from "@truedat/core/search/SearchContext";
3
+ import {
4
+ useRuleImplementationFromRulesSearch,
5
+ useRuleImplementationFilters,
6
+ } from "../../hooks/useImplementations";
2
7
  import { RuleFormImplementations } from "../RuleFormImplementations";
3
8
 
9
+ jest.mock("@truedat/core/search/SearchContext", () => {
10
+ const originalModule = jest.requireActual(
11
+ "@truedat/core/search/SearchContext"
12
+ );
13
+
14
+ return {
15
+ __esModule: true,
16
+ ...originalModule,
17
+ useSearchContext: jest.fn(),
18
+ };
19
+ });
20
+
21
+ jest.mock("../../hooks/useImplementations", () => ({
22
+ useRuleImplementationFromRulesSearch: jest.fn(),
23
+ useRuleImplementationFilters: jest.fn(),
24
+ }));
25
+
4
26
  describe("<RuleFormImplementations />", () => {
5
27
  const rule = { id: 1, name: "rule name" };
6
28
  const updateDeletionQuery = jest.fn();
@@ -10,6 +32,24 @@ describe("<RuleFormImplementations />", () => {
10
32
  deletedRender: false,
11
33
  };
12
34
 
35
+ beforeEach(() => {
36
+ jest.clearAllMocks();
37
+ useRuleImplementationFromRulesSearch.mockReturnValue({
38
+ trigger: jest.fn(),
39
+ });
40
+ useRuleImplementationFilters.mockReturnValue({
41
+ trigger: jest.fn(),
42
+ });
43
+ useSearchContext.mockReturnValue({
44
+ searchData: {
45
+ data: [],
46
+ scroll_id: null,
47
+ },
48
+ searchMust: { status: ["pending"] },
49
+ setOnSearchChange: jest.fn(),
50
+ });
51
+ });
52
+
13
53
  it("matches the latest snapshot", async () => {
14
54
  const rendered = render(<RuleFormImplementations {...props} />);
15
55
  await waitForLoad(rendered);
@@ -31,4 +71,11 @@ describe("<RuleFormImplementations />", () => {
31
71
  rendered.container.querySelector(".implementation-actions")
32
72
  ).toBeInTheDocument();
33
73
  });
74
+
75
+ it("uses useRuleImplementationFromRulesSearch hook", async () => {
76
+ const rendered = render(<RuleFormImplementations {...props} />);
77
+ await waitForLoad(rendered);
78
+
79
+ expect(useRuleImplementationFromRulesSearch).toHaveBeenCalled();
80
+ });
34
81
  });
@@ -0,0 +1,35 @@
1
+ import _ from "lodash/fp";
2
+ import useSWRMutations from "swr/mutation";
3
+ import { renderHook } from "@testing-library/react";
4
+ import { apiJsonPost } from "@truedat/core/services/api";
5
+ import { API_RULE_IMPLEMENTATIONS_FROM_RULE } from "../../api";
6
+ import { useRuleImplementationFromRulesSearch } from "../useImplementations";
7
+
8
+ jest.mock("swr/mutation", () => ({
9
+ __esModule: true,
10
+ ...jest.requireActual("swr/mutation"),
11
+ default: jest.fn(),
12
+ }));
13
+
14
+ jest.mock("@truedat/core/services/api", () => ({
15
+ __esModule: true,
16
+ ...jest.requireActual("@truedat/core/services/api"),
17
+ apiJsonPost: jest.fn(),
18
+ }));
19
+
20
+ describe("useRuleImplementationFromRulesSearch", () => {
21
+ beforeEach(() => {
22
+ jest.clearAllMocks();
23
+ });
24
+
25
+ it("calls useSWRMutations with correct api route", () => {
26
+ renderHook(() => useRuleImplementationFromRulesSearch());
27
+ const [url, func] = _.last(useSWRMutations.mock.calls);
28
+ const arg = { rule_id: 1, page: 1 };
29
+ expect(url).toBe(API_RULE_IMPLEMENTATIONS_FROM_RULE);
30
+ func(url, { arg });
31
+
32
+ expect(apiJsonPost).toHaveBeenCalledWith(url, arg);
33
+ });
34
+ });
35
+
@@ -11,6 +11,7 @@ import {
11
11
  import {
12
12
  API_RULE_IMPLEMENTATIONS_SEARCH,
13
13
  API_RULE_IMPLEMENTATION_FILTERS_SEARCH,
14
+ API_RULE_IMPLEMENTATIONS_FROM_RULE,
14
15
  API_RULE_IMPLEMENTATIONS_XLSX_DOWNLOAD,
15
16
  API_RULE_IMPLEMENTATIONS_XLSX_UPLOAD,
16
17
  API_RULE_IMPLEMENTATIONS_XLSX_UPLOAD_JOBS,
@@ -41,6 +42,12 @@ export const useRuleImplementationSearch = () => {
41
42
  });
42
43
  };
43
44
 
45
+ export const useRuleImplementationFromRulesSearch = () => {
46
+ return useSWRMutations(API_RULE_IMPLEMENTATIONS_FROM_RULE, (url, { arg }) => {
47
+ return apiJsonPost(url, arg);
48
+ });
49
+ };
50
+
44
51
  export const useImplementationsDownload = () => {
45
52
  return useSWRMutations(
46
53
  API_RULE_IMPLEMENTATIONS_XLSX_DOWNLOAD,
@@ -11,12 +11,12 @@ import {
11
11
  submitImplementation,
12
12
  publishImplementation,
13
13
  rejectImplementation,
14
+ restoreImplementation,
14
15
  } from "../../routines";
15
16
  import { ruleRedirect } from "..";
16
17
 
17
18
  const fooState = { foo: "bar" };
18
19
  const initialState = "";
19
- const redirectUrl = "/foo/bar";
20
20
 
21
21
  describe("reducers: ruleImplementationRedirect", () => {
22
22
  it("should provide the initial state", () => {
@@ -65,30 +65,38 @@ describe("reducers: ruleImplementationRedirect", () => {
65
65
  });
66
66
 
67
67
  it("should return the redirectUrl from the payload on deleteImplementation.SUCCESS action", () => {
68
+ const redirectUrl = "/foo/bar";
68
69
  const payload = { redirectUrl };
69
70
  expect(ruleRedirect(fooState, deleteImplementation.success(payload))).toBe(
70
71
  redirectUrl
71
72
  );
72
73
  });
73
74
 
74
- it("should return the redirectUrl from the payload on submitImplementation.SUCCESS action", () => {
75
- const payload = { redirectUrl };
75
+ it("should return the current state on submitImplementation.SUCCESS action", () => {
76
+ const payload = { data: {} };
76
77
  expect(ruleRedirect(fooState, submitImplementation.success(payload))).toBe(
77
- redirectUrl
78
+ fooState
78
79
  );
79
80
  });
80
81
 
81
- it("should return the redirectUrl from the payload on publishImplementation.SUCCESS action", () => {
82
- const payload = { redirectUrl };
82
+ it("should return the current state on publishImplementation.SUCCESS action", () => {
83
+ const payload = { data: {} };
83
84
  expect(ruleRedirect(fooState, publishImplementation.success(payload))).toBe(
84
- redirectUrl
85
+ fooState
85
86
  );
86
87
  });
87
88
 
88
- it("should return the redirectUrl from the payload on rejectImplementation.SUCCESS action", () => {
89
- const payload = { redirectUrl };
89
+ it("should return the current state on rejectImplementation.SUCCESS action", () => {
90
+ const payload = { data: {} };
90
91
  expect(ruleRedirect(fooState, rejectImplementation.success(payload))).toBe(
91
- redirectUrl
92
+ fooState
93
+ );
94
+ });
95
+
96
+ it("should return the current state on restoreImplementation.SUCCESS action", () => {
97
+ const payload = { data: {} };
98
+ expect(ruleRedirect(fooState, restoreImplementation.success(payload))).toBe(
99
+ fooState
92
100
  );
93
101
  });
94
102
  });
@@ -52,13 +52,10 @@ export const ruleRedirect = (state = initialState, { type, payload, meta }) => {
52
52
  case deleteImplementation.SUCCESS:
53
53
  return payload?.redirectUrl || state;
54
54
  case publishImplementation.SUCCESS:
55
- return payload?.redirectUrl || state;
56
55
  case submitImplementation.SUCCESS:
57
- return payload?.redirectUrl || state;
58
56
  case rejectImplementation.SUCCESS:
59
- return payload?.redirectUrl || state;
60
57
  case restoreImplementation.SUCCESS:
61
- return payload?.redirectUrl || state;
58
+ return state;
62
59
  default:
63
60
  return state;
64
61
  }
@@ -4,7 +4,7 @@ import {
4
4
  publishImplementationSaga,
5
5
  } from "../publishImplementation";
6
6
  import { PUBLISH_IMPLEMENTATION } from "../../api/mutations";
7
- import { publishImplementation } from "../../routines";
7
+ import { publishImplementation, fetchRuleImplementation } from "../../routines";
8
8
 
9
9
  describe("sagas: publishImplementationRequestSaga", () => {
10
10
  it("should invoke publishImplementationSaga on publishImplementation.TRIGGER", () => {
@@ -29,8 +29,7 @@ describe("sagas: publishImplementationRequestSaga", () => {
29
29
  describe("sagas: publishImplementationSaga", () => {
30
30
  const client = { mutate: jest.fn() };
31
31
  const id = "123";
32
- const redirectUrl = "foo";
33
- const payload = { id, redirectUrl };
32
+ const payload = { id };
34
33
  const data = { foo: "bar" };
35
34
 
36
35
  it("should put a success action when a response is returned", () => {
@@ -46,7 +45,9 @@ describe("sagas: publishImplementationSaga", () => {
46
45
  variables: payload,
47
46
  })
48
47
  .next({ data })
49
- .put(publishImplementation.success({ data, redirectUrl }))
48
+ .put(publishImplementation.success({ data }))
49
+ .next()
50
+ .put(fetchRuleImplementation.trigger({ id: `${id}` }))
50
51
  .next()
51
52
  .put(publishImplementation.fulfill())
52
53
  .next()
@@ -4,7 +4,7 @@ import {
4
4
  rejectImplementationSaga,
5
5
  } from "../rejectImplementation";
6
6
  import { REJECT_IMPLEMENTATION } from "../../api/mutations";
7
- import { rejectImplementation } from "../../routines";
7
+ import { rejectImplementation, fetchRuleImplementation } from "../../routines";
8
8
 
9
9
  describe("sagas: rejectImplementationRequestSaga", () => {
10
10
  it("should invoke rejectImplementationSaga on rejectImplementation.TRIGGER", () => {
@@ -29,8 +29,7 @@ describe("sagas: rejectImplementationRequestSaga", () => {
29
29
  describe("sagas: rejectImplementationSaga", () => {
30
30
  const client = { mutate: jest.fn() };
31
31
  const id = "123";
32
- const redirectUrl = "foo";
33
- const payload = { id, redirectUrl };
32
+ const payload = { id };
34
33
  const data = { foo: "bar" };
35
34
 
36
35
  it("should put a success action when a response is returned", () => {
@@ -46,7 +45,9 @@ describe("sagas: rejectImplementationSaga", () => {
46
45
  variables: payload,
47
46
  })
48
47
  .next({ data })
49
- .put(rejectImplementation.success({ data, redirectUrl }))
48
+ .put(rejectImplementation.success({ data }))
49
+ .next()
50
+ .put(fetchRuleImplementation.trigger({ id: `${id}` }))
50
51
  .next()
51
52
  .put(rejectImplementation.fulfill())
52
53
  .next()
@@ -4,7 +4,7 @@ import {
4
4
  submitImplementationSaga,
5
5
  } from "../submitImplementation";
6
6
  import { SUBMIT_IMPLEMENTATION } from "../../api/mutations";
7
- import { submitImplementation } from "../../routines";
7
+ import { submitImplementation, fetchRuleImplementation } from "../../routines";
8
8
 
9
9
  describe("sagas: submitImplementationRequestSaga", () => {
10
10
  it("should invoke submitImplementationSaga on submitImplementation.TRIGGER", () => {
@@ -29,8 +29,7 @@ describe("sagas: submitImplementationRequestSaga", () => {
29
29
  describe("sagas: submitImplementationSaga", () => {
30
30
  const client = { mutate: jest.fn() };
31
31
  const id = "123";
32
- const redirectUrl = "foo";
33
- const payload = { id, redirectUrl };
32
+ const payload = { id };
34
33
  const data = { foo: "bar" };
35
34
 
36
35
  it("should put a success action when a response is returned", () => {
@@ -46,7 +45,9 @@ describe("sagas: submitImplementationSaga", () => {
46
45
  variables: payload,
47
46
  })
48
47
  .next({ data })
49
- .put(submitImplementation.success({ data, redirectUrl }))
48
+ .put(submitImplementation.success({ data }))
49
+ .next()
50
+ .put(fetchRuleImplementation.trigger({ id: `${id}` }))
50
51
  .next()
51
52
  .put(submitImplementation.fulfill())
52
53
  .next()
@@ -1,17 +1,18 @@
1
1
  import { call, put, takeLatest, getContext } from "redux-saga/effects";
2
2
  import { PUBLISH_IMPLEMENTATION } from "../api/mutations";
3
- import { publishImplementation } from "../routines";
3
+ import { publishImplementation, fetchRuleImplementation } from "../routines";
4
4
 
5
5
  export function* publishImplementationSaga({ payload }) {
6
6
  const client = yield getContext("client");
7
7
  try {
8
- const { id, redirectUrl } = payload;
8
+ const { id } = payload;
9
9
  yield put(publishImplementation.request({ id }));
10
10
  const { data } = yield call(client.mutate, {
11
11
  mutation: PUBLISH_IMPLEMENTATION,
12
12
  variables: payload,
13
13
  });
14
- yield put(publishImplementation.success({ data, redirectUrl }));
14
+ yield put(publishImplementation.success({ data }));
15
+ yield put(fetchRuleImplementation.trigger({ id: `${id}` }));
15
16
  } catch (error) {
16
17
  yield put(publishImplementation.failure(error.message));
17
18
  } finally {
@@ -1,17 +1,18 @@
1
1
  import { call, put, takeLatest, getContext } from "redux-saga/effects";
2
2
  import { REJECT_IMPLEMENTATION } from "../api/mutations";
3
- import { rejectImplementation } from "../routines";
3
+ import { rejectImplementation, fetchRuleImplementation } from "../routines";
4
4
 
5
5
  export function* rejectImplementationSaga({ payload }) {
6
6
  const client = yield getContext("client");
7
7
  try {
8
- const { id, redirectUrl } = payload;
8
+ const { id } = payload;
9
9
  yield put(rejectImplementation.request({ id }));
10
10
  const { data } = yield call(client.mutate, {
11
11
  mutation: REJECT_IMPLEMENTATION,
12
12
  variables: payload,
13
13
  });
14
- yield put(rejectImplementation.success({ data, redirectUrl }));
14
+ yield put(rejectImplementation.success({ data }));
15
+ yield put(fetchRuleImplementation.trigger({ id: `${id}` }));
15
16
  } catch (error) {
16
17
  yield put(rejectImplementation.failure(error.message));
17
18
  } finally {
@@ -1,17 +1,18 @@
1
1
  import { call, put, takeLatest, getContext } from "redux-saga/effects";
2
2
  import { RESTORE_IMPLEMENTATION } from "../api/mutations";
3
- import { restoreImplementation } from "../routines";
3
+ import { restoreImplementation, fetchRuleImplementation } from "../routines";
4
4
 
5
5
  export function* restoreImplementationSaga({ payload }) {
6
6
  const client = yield getContext("client");
7
7
  try {
8
- const { id, redirectUrl } = payload;
8
+ const { id } = payload;
9
9
  yield put(restoreImplementation.request({ id }));
10
10
  const { data } = yield call(client.mutate, {
11
11
  mutation: RESTORE_IMPLEMENTATION,
12
12
  variables: payload,
13
13
  });
14
- yield put(restoreImplementation.success({ data, redirectUrl }));
14
+ yield put(restoreImplementation.success({ data }));
15
+ yield put(fetchRuleImplementation.trigger({ id: `${id}` }));
15
16
  } catch (error) {
16
17
  yield put(restoreImplementation.failure(error.message));
17
18
  } finally {
@@ -1,17 +1,18 @@
1
1
  import { call, put, takeLatest, getContext } from "redux-saga/effects";
2
2
  import { SUBMIT_IMPLEMENTATION } from "../api/mutations";
3
- import { submitImplementation } from "../routines";
3
+ import { submitImplementation, fetchRuleImplementation } from "../routines";
4
4
 
5
5
  export function* submitImplementationSaga({ payload }) {
6
6
  const client = yield getContext("client");
7
7
  try {
8
- const { id, redirectUrl } = payload;
8
+ const { id } = payload;
9
9
  yield put(submitImplementation.request({ id }));
10
10
  const { data } = yield call(client.mutate, {
11
11
  mutation: SUBMIT_IMPLEMENTATION,
12
12
  variables: payload,
13
13
  });
14
- yield put(submitImplementation.success({ data, redirectUrl }));
14
+ yield put(submitImplementation.success({ data }));
15
+ yield put(fetchRuleImplementation.trigger({ id: `${id}` }));
15
16
  } catch (error) {
16
17
  yield put(submitImplementation.failure(error.message));
17
18
  } finally {