@truedat/dq 7.12.9 → 7.12.10

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.9",
3
+ "version": "7.12.10",
4
4
  "description": "Truedat Web Data Quality Module",
5
5
  "sideEffects": false,
6
6
  "module": "src/index.js",
@@ -86,5 +86,5 @@
86
86
  "semantic-ui-react": "^3.0.0-beta.2",
87
87
  "swr": "^2.3.3"
88
88
  },
89
- "gitHead": "8b7fd09088e71d0bb6e1a7291250e0f76df27d6e"
89
+ "gitHead": "3f6e84517a5ec6ea8bc4bf5bd1e05a614ed6418b"
90
90
  }
@@ -1,49 +1,33 @@
1
1
  import _ from "lodash/fp";
2
- import { useEffect, useState } from "react";
3
2
  import PropTypes from "prop-types";
4
- import { connect } from "react-redux";
5
- import { getSortInfo, sortColumn } from "@truedat/core/services/sort";
6
3
  import { Checkbox, Table, Header, Icon } from "semantic-ui-react";
7
4
  import { useIntl } from "react-intl";
8
5
  import { useSearchContext } from "@truedat/core/search/SearchContext";
9
- import { sortImplementations } from "../routines";
10
6
  import RuleImplementationRow from "./RuleImplementationRow";
11
7
  export const RuleImplementationsTable = ({
12
8
  addAll,
13
9
  checkedAll,
14
10
  checkRow,
15
11
  executeImplementationsOn,
16
- implementationsSort,
17
- sortImplementations,
18
12
  columns,
19
- ruleImplementationsLoading,
20
13
  isRowChecked,
21
14
  }) => {
22
- const { searchData } = useSearchContext();
15
+ const {
16
+ searchData,
17
+ loading,
18
+ sortColumn,
19
+ sortDirection,
20
+ handleSortSelection,
21
+ } = useSearchContext();
23
22
 
24
23
  const { formatMessage } = useIntl();
25
24
 
26
- const [sortedColumn, setColumn] = useState(
27
- _.prop("column")(getSortInfo(implementationsSort))
28
- );
29
-
30
- const [direction, setDirection] = useState(
31
- _.prop("direction")(getSortInfo(implementationsSort))
32
- );
33
-
34
- const ruleImplementations = searchData?.data;
25
+ const ruleImplementations = searchData?.data || [];
35
26
 
36
27
  const validColumns = _.reject(
37
28
  ({ hideOn }) => _.isFunction(hideOn) && hideOn(ruleImplementations)
38
29
  )(columns);
39
30
 
40
- useEffect(() => {
41
- const { column: sortedColumn, direction: direction } =
42
- getSortInfo(implementationsSort);
43
- setColumn(sortedColumn);
44
- setDirection(direction);
45
- }, [implementationsSort]);
46
-
47
31
  return (
48
32
  <>
49
33
  {!_.isEmpty(ruleImplementations) ? (
@@ -71,22 +55,15 @@ export const RuleImplementationsTable = ({
71
55
  }`,
72
56
  })}
73
57
  sorted={
74
- _.path("sort.name")(column) === sortedColumn
75
- ? direction
58
+ _.path("sort.name")(column) === sortColumn
59
+ ? sortDirection
76
60
  : null
77
61
  }
78
62
  className={
79
63
  _.path("sort.name")(column) ? "" : "disabled"
80
64
  }
81
65
  onClick={() =>
82
- sortColumn(
83
- column,
84
- sortImplementations,
85
- setDirection,
86
- setColumn,
87
- direction,
88
- sortedColumn
89
- )
66
+ handleSortSelection(_.path("sort.name")(column))
90
67
  }
91
68
  />
92
69
  ))
@@ -108,7 +85,7 @@ export const RuleImplementationsTable = ({
108
85
  </Table>
109
86
  </div>
110
87
  ) : null}
111
- {_.isEmpty(ruleImplementations) && !ruleImplementationsLoading ? (
88
+ {_.isEmpty(ruleImplementations) && !loading ? (
112
89
  <Header as="h4">
113
90
  <Icon name="search" />
114
91
  <Header.Content>
@@ -125,20 +102,8 @@ RuleImplementationsTable.propTypes = {
125
102
  checkedAll: PropTypes.bool,
126
103
  checkRow: PropTypes.func,
127
104
  executeImplementationsOn: PropTypes.bool,
128
- implementationsSort: PropTypes.array,
129
105
  isRowChecked: PropTypes.func,
130
- ruleImplementationsLoading: PropTypes.bool,
131
- sortImplementations: PropTypes.func,
132
- ruleImplementations: PropTypes.array,
133
106
  columns: PropTypes.array,
134
107
  };
135
108
 
136
- const mapStateToProps = (state, props) => ({
137
- ruleImplementations: props.ruleImplementations || state.ruleImplementations,
138
- ruleImplementationsLoading: state.ruleImplementationsLoading,
139
- implementationsSort: _.path("ruleImplementationQuery.sort")(state),
140
- });
141
-
142
- export default connect(mapStateToProps, { sortImplementations })(
143
- RuleImplementationsTable
144
- );
109
+ export default RuleImplementationsTable;
@@ -52,7 +52,12 @@ describe("<Implementations />", () => {
52
52
  ],
53
53
  scroll_id: null,
54
54
  },
55
+ loading: false,
55
56
  searchMust: { status: ["pending"] },
57
+ sortColumn: "implementation_key.sort",
58
+ sortDirection: "ascending",
59
+ handleSortSelection: jest.fn(),
60
+ toggleHiddenFilterValue: jest.fn(),
56
61
  setOnSearchChange: jest.fn(),
57
62
  });
58
63
  });
@@ -1,6 +1,20 @@
1
1
  import { render, waitForLoad } from "@truedat/test/render";
2
2
  import { RuleFormImplementations } from "../RuleFormImplementations";
3
3
 
4
+ jest.mock("@truedat/core/search/SearchContext", () => {
5
+ const originalModule = jest.requireActual(
6
+ "@truedat/core/search/SearchContext"
7
+ );
8
+
9
+ return {
10
+ __esModule: true,
11
+ ...originalModule,
12
+ useSearchContext: jest.fn(),
13
+ };
14
+ });
15
+
16
+ const { useSearchContext } = require("@truedat/core/search/SearchContext");
17
+
4
18
  describe("<RuleFormImplementations />", () => {
5
19
  const rule = { id: 1, name: "rule name" };
6
20
  const updateDeletionQuery = jest.fn();
@@ -10,22 +24,45 @@ describe("<RuleFormImplementations />", () => {
10
24
  deletedRender: false,
11
25
  };
12
26
 
27
+ const renderOpts = {
28
+ state: {
29
+ rule: { id: 1, name: "rule name" },
30
+ },
31
+ };
32
+
33
+ beforeEach(() => {
34
+ useSearchContext.mockReturnValue({
35
+ searchData: {
36
+ data: [],
37
+ scroll_id: null,
38
+ },
39
+ loading: false,
40
+ searchMust: {},
41
+ sortColumn: "implementation_key.raw",
42
+ sortDirection: "ascending",
43
+ handleSortSelection: jest.fn(),
44
+ toggleHiddenFilterValue: jest.fn(),
45
+ setOnSearchChange: jest.fn(),
46
+ });
47
+ });
48
+
13
49
  it("matches the latest snapshot", async () => {
14
- const rendered = render(<RuleFormImplementations {...props} />);
50
+ const rendered = render(<RuleFormImplementations {...props} />, renderOpts);
15
51
  await waitForLoad(rendered);
16
52
  expect(rendered.container).toMatchSnapshot();
17
53
  });
18
54
 
19
55
  it("renders null when rule is empty", async () => {
20
56
  const rendered = render(
21
- <RuleFormImplementations {...{ ...props, rule: {} }} />
57
+ <RuleFormImplementations {...{ ...props, rule: {} }} />,
58
+ renderOpts
22
59
  );
23
60
  await waitForLoad(rendered);
24
61
  expect(rendered.container.firstChild).toBeNull();
25
62
  });
26
63
 
27
64
  it("renders RuleFormImplementations when rule is not empty", async () => {
28
- const rendered = render(<RuleFormImplementations {...props} />);
65
+ const rendered = render(<RuleFormImplementations {...props} />, renderOpts);
29
66
  await waitForLoad(rendered);
30
67
  expect(
31
68
  rendered.container.querySelector(".implementation-actions")
@@ -1,3 +1,4 @@
1
+ import { waitFor } from "@testing-library/react";
1
2
  import userEvent from "@testing-library/user-event";
2
3
  import { render, waitForLoad } from "@truedat/test/render";
3
4
  import { useSearchContext } from "@truedat/core/search/SearchContext";
@@ -22,25 +23,56 @@ describe("<RuleImplementationsTable />", () => {
22
23
  { name: "result", sort: { name: "bar.raw" } },
23
24
  ];
24
25
  const implementationsSort = [{ "name.raw": "desc" }];
25
- const sortImplementations = jest.fn();
26
+
26
27
  const ruleImplementationsLoading = false;
27
28
  const props = {
28
29
  ruleImplementations,
29
30
  columns,
30
31
  ruleImplementationsLoading,
31
32
  implementationsSort,
32
- sortImplementations,
33
33
  };
34
34
 
35
+ const mockState = {
36
+ sortColumn: "name.raw",
37
+ sortDirection: "descending",
38
+ rerenderFn: null,
39
+ };
40
+
41
+ const handleSortSelection = jest.fn((columnName) => {
42
+ if (mockState.sortColumn !== columnName) {
43
+ mockState.sortColumn = columnName;
44
+ mockState.sortDirection = "ascending";
45
+ } else {
46
+ mockState.sortDirection =
47
+ mockState.sortDirection === "ascending" ? "descending" : "ascending";
48
+ }
49
+ // Update the mock return value
50
+ useSearchContext.mockReturnValue(createMockSearchContext());
51
+ // Re-render if component is already rendered
52
+ if (mockState.rerenderFn) {
53
+ mockState.rerenderFn(<RuleImplementationsTable {...props} />);
54
+ }
55
+ });
56
+
57
+ const createMockSearchContext = () => ({
58
+ searchData: {
59
+ data: ruleImplementations,
60
+ scroll_id: null,
61
+ },
62
+ loading: false,
63
+ searchMust: {},
64
+ sortColumn: mockState.sortColumn,
65
+ sortDirection: mockState.sortDirection,
66
+ handleSortSelection,
67
+ setOnSearchChange: jest.fn(),
68
+ });
69
+
35
70
  beforeEach(() => {
36
- useSearchContext.mockReturnValue({
37
- searchData: {
38
- data: ruleImplementations,
39
- scroll_id: null,
40
- },
41
- searchMust: {},
42
- setOnSearchChange: jest.fn(),
43
- });
71
+ mockState.sortColumn = "name.raw";
72
+ mockState.sortDirection = "descending";
73
+ mockState.rerenderFn = null;
74
+ handleSortSelection.mockClear();
75
+ useSearchContext.mockReturnValue(createMockSearchContext());
44
76
  });
45
77
 
46
78
  it("matches the latest snapshot", async () => {
@@ -61,6 +93,7 @@ describe("<RuleImplementationsTable />", () => {
61
93
  it("handles sort when column header is clicked", async () => {
62
94
  const user = userEvent.setup({ delay: null });
63
95
  const rendered = render(<RuleImplementationsTable {...props} />);
96
+ mockState.rerenderFn = rendered.rerender;
64
97
  await waitForLoad(rendered);
65
98
 
66
99
  const headerCells = rendered.container.querySelectorAll("th");
@@ -68,13 +101,24 @@ describe("<RuleImplementationsTable />", () => {
68
101
  // Click on the second header cell
69
102
  await user.click(headerCells[1]);
70
103
 
71
- // Check that it's now sorted ascending
72
- expect(headerCells[1].getAttribute("class")).toContain("ascending sorted");
104
+ // Wait for the class to update after re-render
105
+ await waitFor(() => {
106
+ const updatedHeaderCells = rendered.container.querySelectorAll("th");
107
+ expect(updatedHeaderCells[1].getAttribute("class")).toContain(
108
+ "ascending sorted"
109
+ );
110
+ });
73
111
 
74
112
  // Click again to sort descending
75
- await user.click(headerCells[1]);
113
+ const updatedHeaderCells = rendered.container.querySelectorAll("th");
114
+ await user.click(updatedHeaderCells[1]);
76
115
 
77
- // Check that it's now sorted descending
78
- expect(headerCells[1].getAttribute("class")).toContain("descending sorted");
116
+ // Wait for the class to update after re-render
117
+ await waitFor(() => {
118
+ const finalHeaderCells = rendered.container.querySelectorAll("th");
119
+ expect(finalHeaderCells[1].getAttribute("class")).toContain(
120
+ "descending sorted"
121
+ );
122
+ });
79
123
  });
80
124
  });
@@ -145,7 +145,7 @@ exports[`<Implementations /> matches the latest snapshot 1`] = `
145
145
  class=""
146
146
  >
147
147
  <th
148
- class="two wide"
148
+ class="two wide ascending sorted"
149
149
  >
150
150
  ruleImplementations.props.implementation_key
151
151
  </th>
@@ -155,7 +155,7 @@ exports[`<Implementations /> matches the latest snapshot 1`] = `
155
155
  ruleImplementations.props.rule
156
156
  </th>
157
157
  <th
158
- class="two wide ascending sorted disabled"
158
+ class="two wide disabled"
159
159
  >
160
160
  ruleImplementations.props.business_concepts
161
161
  </th>
@@ -5,7 +5,6 @@ import {
5
5
  toggleImplementationFilterValue,
6
6
  searchImplementations,
7
7
  selectImplementationPage,
8
- sortImplementations,
9
8
  } from "../../routines";
10
9
  import { ruleImplementationQuery } from "..";
11
10
 
@@ -60,18 +59,6 @@ describe("reducers: ruleImplementationQuery", () => {
60
59
  });
61
60
  });
62
61
 
63
- describe("action: sortImplementations.TRIGGER", () => {
64
- it("should set sort from payload and set page to 1", () => {
65
- const payload = [{ name2: "asc" }];
66
- expect(
67
- ruleImplementationQuery(fooState, {
68
- type: sortImplementations.TRIGGER,
69
- payload,
70
- })
71
- ).toMatchObject({ sort: [{ name2: "asc" }] });
72
- });
73
- });
74
-
75
62
  describe("action: searchImplementations.TRIGGER", () => {
76
63
  const query = "some query";
77
64
  it("should set the query from the payload", () => {
@@ -5,7 +5,6 @@ import {
5
5
  toggleImplementationFilterValue,
6
6
  searchImplementations,
7
7
  selectImplementationPage,
8
- sortImplementations,
9
8
  } from "../routines";
10
9
 
11
10
  const defaultPage = 1;
@@ -43,10 +42,7 @@ const ruleImplementationQuery = (state = initialState, { type, payload }) => {
43
42
  const { activePage } = payload;
44
43
  return { ...state, page: activePage };
45
44
  }
46
- case sortImplementations.TRIGGER: {
47
- const sort = payload;
48
- return { ...state, sort, page: defaultPage };
49
- }
45
+
50
46
  default:
51
47
  return state;
52
48
  }
package/src/routines.js CHANGED
@@ -97,7 +97,7 @@ export const setImplementationDefaultFilters = createRoutine(
97
97
  "SET_IMPLEMENTATION_DEFAULT_FILTRERS"
98
98
  );
99
99
  export const deleteImplementation = createRoutine("DELETE_IMPLEMENTATION");
100
- export const sortImplementations = createRoutine("SORT_IMPLEMENTATIONS");
100
+
101
101
  export const sortRules = createRoutine("SORT_RULES");
102
102
  export const submitImplementation = createRoutine("SUBMIT_IMPLEMENTATION");
103
103
  export const toggleImplementationFilterValue = createRoutine(