@truedat/dq 4.37.1 → 4.37.5

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.
Files changed (30) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/package.json +4 -4
  3. package/src/components/ExecutionDetails.js +17 -9
  4. package/src/components/ImplementationsRoutes.js +4 -0
  5. package/src/components/RuleEventRow.js +47 -0
  6. package/src/components/RuleEvents.js +31 -0
  7. package/src/components/RuleImplementationSelectedFilters.js +23 -1
  8. package/src/components/RuleRoutes.js +26 -2
  9. package/src/components/RuleSelectedFilters.js +21 -1
  10. package/src/components/RuleTabs.js +16 -2
  11. package/src/components/RulesRoutes.js +13 -1
  12. package/src/components/__tests__/ExecutionDetails.spec.js +31 -24
  13. package/src/components/__tests__/RuleEventRow.spec.js +33 -0
  14. package/src/components/__tests__/RuleEvents.spec.js +64 -0
  15. package/src/components/__tests__/RuleRoutes.spec.js +23 -0
  16. package/src/components/__tests__/__snapshots__/ExecutionDetails.spec.js.snap +2 -5
  17. package/src/components/__tests__/__snapshots__/RuleEventRow.spec.js.snap +38 -0
  18. package/src/components/__tests__/__snapshots__/RuleEvents.spec.js.snap +78 -0
  19. package/src/components/__tests__/__snapshots__/RuleRoutes.spec.js.snap +3 -0
  20. package/src/messages/en.js +6 -0
  21. package/src/messages/es.js +9 -0
  22. package/src/reducers/__tests__/ruleActiveFilters.spec.js +19 -7
  23. package/src/reducers/__tests__/ruleImplementationActiveFilters.spec.js +19 -7
  24. package/src/reducers/index.js +2 -0
  25. package/src/reducers/ruleActiveFilters.js +5 -0
  26. package/src/reducers/ruleImplementationActiveFilters.js +7 -0
  27. package/src/reducers/ruleImplementationFilters.js +1 -1
  28. package/src/reducers/ruleImplementationFiltersLoading.js +14 -0
  29. package/src/selectors/__tests__/getParsedEvents.spec.js +173 -0
  30. package/src/selectors/getParsedEvents.js +55 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.37.5] 2022-02-06
4
+
5
+ ### Changed
6
+
7
+ - [TD-4426]
8
+ - On `ExecutionDetails` decode detail fields with prefix `base64_`
9
+ - Option to create messages with `ruleResult.details.props.<field_name>` to replace detail key
10
+
11
+ ## [4.37.4] 2022-02-04
12
+
13
+ ### Changed
14
+
15
+ - [TD-4424] Disable user filters while rule filters are loading
16
+
17
+ ## [4.37.3] 2022-02-03
18
+
19
+ ### Added
20
+
21
+ - [TD-2929] Added support for `UserSearchFilters` on `Rules` and `RuleImplementations`
22
+
23
+ ## [4.37.2] 2022-02-02
24
+
25
+ ### Added
26
+
27
+ - [TD-4294] Rule audit tab
28
+
3
29
  ## [4.37.1] 2022-02-02
4
30
 
5
31
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dq",
3
- "version": "4.37.1",
3
+ "version": "4.37.5",
4
4
  "description": "Truedat Web Data Quality Module",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -82,8 +82,8 @@
82
82
  },
83
83
  "dependencies": {
84
84
  "@apollo/client": "^3.4.10",
85
- "@truedat/core": "4.37.1",
86
- "@truedat/df": "4.37.1",
85
+ "@truedat/core": "4.37.5",
86
+ "@truedat/df": "4.37.5",
87
87
  "axios": "^0.19.2",
88
88
  "graphql": "^15.5.3",
89
89
  "path-to-regexp": "^1.7.0",
@@ -103,5 +103,5 @@
103
103
  "react-dom": ">= 16.8.6 < 17",
104
104
  "semantic-ui-react": ">= 0.88.2 < 2.1"
105
105
  },
106
- "gitHead": "36ffd7e86efe27f38c3ae1bb616eb9eb4d444d12"
106
+ "gitHead": "98ff8669e99824ef1bdbd3d12035e6371029e4ca"
107
107
  }
@@ -28,7 +28,7 @@ const GeneralInformation = ({ ruleImplementation, ruleResult }) => {
28
28
 
29
29
  <Table.Row>
30
30
  <Table.Cell>
31
- {formatMessage({ id: "ruleResult.props.date" })}{" "}
31
+ {formatMessage({ id: "ruleResult.props.date" })}
32
32
  </Table.Cell>
33
33
  <Table.Cell>
34
34
  <DateTime value={ruleResult.date} />
@@ -37,14 +37,14 @@ const GeneralInformation = ({ ruleImplementation, ruleResult }) => {
37
37
 
38
38
  <Table.Row>
39
39
  <Table.Cell>
40
- {formatMessage({ id: "ruleResult.props.records" })}{" "}
40
+ {formatMessage({ id: "ruleResult.props.records" })}
41
41
  </Table.Cell>
42
42
  <Table.Cell>{formatNumber(ruleResult.records)}</Table.Cell>
43
43
  </Table.Row>
44
44
 
45
45
  <Table.Row>
46
46
  <Table.Cell>
47
- {formatMessage({ id: "ruleResult.props.errors" })}{" "}
47
+ {formatMessage({ id: "ruleResult.props.errors" })}
48
48
  </Table.Cell>
49
49
  <Table.Cell>{formatNumber(ruleResult.errors)}</Table.Cell>
50
50
  </Table.Row>
@@ -58,13 +58,19 @@ GeneralInformation.propTypes = {
58
58
  };
59
59
 
60
60
  const DetailRow = ({ details }) => {
61
+ const { formatMessage } = useIntl();
61
62
  return _.flow(
62
63
  _.keys,
63
64
  _.map((key) => (
64
65
  <Table.Row key={key}>
65
- <Table.Cell>{key}</Table.Cell>
66
66
  <Table.Cell>
67
- {key === "Query"
67
+ {formatMessage({
68
+ id: `ruleResult.details.props.${key.replace(/^(base64_)/, "")}`,
69
+ defaultMessage: key.replace(/^(base64_)/, ""),
70
+ })}
71
+ </Table.Cell>
72
+ <Table.Cell>
73
+ {key === "Query" || key.startsWith("base64_")
68
74
  ? Buffer.from(details[key], "base64").toString()
69
75
  : JSON.stringify(details[key], null, 2)}
70
76
  </Table.Cell>
@@ -73,11 +79,13 @@ const DetailRow = ({ details }) => {
73
79
  )(details);
74
80
  };
75
81
 
76
- export const ExecutionDetails = ({ ruleImplementation, rule_result_id }) => {
82
+ DetailRow.propTypes = { details: PropTypes.object };
83
+
84
+ export const ExecutionDetails = ({ ruleImplementation, ruleResultId }) => {
77
85
  const { formatMessage } = useIntl();
78
- const { rule_result_id: id } = useParams();
86
+ const { rule_result_id: paramsId } = useParams();
79
87
 
80
- const result_id = _.defaultTo(_.toNumber(id))(rule_result_id);
88
+ const result_id = _.defaultTo(_.toNumber(paramsId))(ruleResultId);
81
89
 
82
90
  const ruleResult = _.find(_.propEq("id", result_id))(
83
91
  ruleImplementation.results
@@ -128,7 +136,7 @@ export const ExecutionDetails = ({ ruleImplementation, rule_result_id }) => {
128
136
 
129
137
  ExecutionDetails.propTypes = {
130
138
  ruleImplementation: PropTypes.object,
131
- rule_result_id: PropTypes.number,
139
+ ruleResultId: PropTypes.number,
132
140
  };
133
141
 
134
142
  const mapStateToProps = (state) => ({
@@ -8,6 +8,9 @@ import RuleImplementationsLoader from "./RuleImplementationsLoader";
8
8
  const TemplatesLoader = React.lazy(() =>
9
9
  import("@truedat/df/templates/components/TemplatesLoader")
10
10
  );
11
+ const UserSearchFiltersLoader = React.lazy(() =>
12
+ import("@truedat/dd/components/UserSearchFiltersLoader")
13
+ );
11
14
 
12
15
  const ImplementationsRoutes = () => (
13
16
  <Route
@@ -17,6 +20,7 @@ const ImplementationsRoutes = () => (
17
20
  <RuleImplementationsLoader />
18
21
  <ImplementationFiltersLoader />
19
22
  <TemplatesLoader scope="qe" />
23
+ <UserSearchFiltersLoader scope="rule_implementation" />
20
24
  <RuleImplementations exact />
21
25
  </>
22
26
  )}
@@ -0,0 +1,47 @@
1
+ import _ from "lodash/fp";
2
+ import React from "react";
3
+ import PropTypes from "prop-types";
4
+ import { Feed } from "semantic-ui-react";
5
+ import { useIntl } from "react-intl";
6
+ import Moment from "react-moment";
7
+
8
+ export const RuleEventRow = ({ user, user_name, ts, payload }) => {
9
+ const { formatMessage, locale } = useIntl();
10
+ const userName = _.propOr(user_name, "user_name")(user);
11
+
12
+ return _.isEmpty(payload) ? null : (
13
+ <Feed.Event>
14
+ <Feed.Content>
15
+ <Feed.Summary>
16
+ <Feed.User>{userName}</Feed.User>{" "}
17
+ <Feed.Date>
18
+ <Moment locale={locale} date={ts} format="YYYY-MM-DD HH:mm" />
19
+ </Feed.Date>
20
+ </Feed.Summary>
21
+ {payload.map(({ field, action, value }, i) => (
22
+ <Feed.Extra
23
+ key={i}
24
+ text
25
+ content={formatMessage(
26
+ {
27
+ id: `rules.events.action_${action}${
28
+ typeof value === "undefined" || _.isObject(value) ? "" : "_to"
29
+ }`,
30
+ },
31
+ [field, JSON.stringify(value)]
32
+ )}
33
+ />
34
+ ))}
35
+ </Feed.Content>
36
+ </Feed.Event>
37
+ );
38
+ };
39
+
40
+ RuleEventRow.propTypes = {
41
+ user: PropTypes.object,
42
+ user_name: PropTypes.string,
43
+ ts: PropTypes.string,
44
+ payload: PropTypes.array,
45
+ };
46
+
47
+ export default RuleEventRow;
@@ -0,0 +1,31 @@
1
+ import React from "react";
2
+ import PropTypes from "prop-types";
3
+ import { Feed, Segment } from "semantic-ui-react";
4
+ import { connect } from "react-redux";
5
+ import { getParsedEvents } from "../selectors";
6
+ import { RuleEventRow } from "./RuleEventRow";
7
+
8
+ export const RuleEvents = ({ events, eventsLoading }) => {
9
+ return eventsLoading ? null : (
10
+ <Segment attached="bottom">
11
+ <Feed size="small">
12
+ {events.map((e, i) => (
13
+ <RuleEventRow key={i} {...e} />
14
+ ))}
15
+ </Feed>
16
+ </Segment>
17
+ );
18
+ };
19
+ RuleEvents.propTypes = {
20
+ events: PropTypes.array.isRequired,
21
+ eventsLoading: PropTypes.bool,
22
+ };
23
+
24
+ const mapStateToProps = (state) => {
25
+ return {
26
+ events: getParsedEvents(state),
27
+ eventsLoading: state.eventsLoading,
28
+ };
29
+ };
30
+
31
+ export default connect(mapStateToProps)(RuleEvents);
@@ -4,6 +4,11 @@ import { connect } from "react-redux";
4
4
  import { injectIntl } from "react-intl";
5
5
  import { makeOption } from "@truedat/core/services/i18n";
6
6
  import { SelectedFilters } from "@truedat/core/components";
7
+ import {
8
+ applyUserSearchFilter,
9
+ deleteUserSearchFilter,
10
+ saveUserSearchFilters,
11
+ } from "@truedat/dd/routines";
7
12
  import {
8
13
  closeImplementationFilter,
9
14
  openImplementationFilter,
@@ -24,29 +29,46 @@ const translations = (formatMessage) => ({
24
29
 
25
30
  export const mapStateToProps = (state, ownProps) => {
26
31
  const formatMessage = _.pathOr(_.prop("id"), "intl.formatMessage")(ownProps);
27
- const { ruleImplementationSelectedFilter: selectedFilter } = state;
32
+ const {
33
+ ruleImplementationFiltersLoading: loading,
34
+ ruleImplementationSelectedFilter: selectedFilter,
35
+ } = state;
28
36
  const i18nValues = _.flow(
29
37
  getRuleImplementationSelectedFilterValues,
30
38
  _.map(makeOption(translations(formatMessage), selectedFilter))
31
39
  )(state);
32
40
 
41
+ const {
42
+ selectedUserSearchFilter: selectedUserFilter,
43
+ ruleImplementationActiveFilters: activeFilters,
44
+ userSearchFilters: userFilters,
45
+ } = state;
46
+
33
47
  return {
48
+ loading,
34
49
  selectedFilter,
35
50
  selectedFilters: getRuleImplementationSelectedFilters(state),
36
51
  selectedFilterActiveValues:
37
52
  getRuleImplementationSelectedFilterActiveValues(state),
38
53
  selectedFilterValues: i18nValues,
54
+ selectedUserFilter,
55
+ activeFilters,
56
+ userFilters,
57
+ userFilterScope: "rule_implementation",
39
58
  };
40
59
  };
41
60
 
42
61
  const mapDispatchToProps = (dispatch) =>
43
62
  bindActionCreators(
44
63
  {
64
+ applyUserFilter: applyUserSearchFilter,
45
65
  closeFilter: closeImplementationFilter,
66
+ deleteUserFilter: deleteUserSearchFilter,
46
67
  openFilter: openImplementationFilter,
47
68
  removeFilter: removeImplementationFilter,
48
69
  resetFilters: resetImplementationFilters,
49
70
  toggleFilterValue: toggleImplementationFilterValue,
71
+ saveFilters: saveUserSearchFilters,
50
72
  },
51
73
  dispatch
52
74
  );
@@ -9,6 +9,7 @@ import { useAuthorized } from "@truedat/core/hooks";
9
9
  import {
10
10
  RULE,
11
11
  RULE_EDIT,
12
+ RULE_EVENTS,
12
13
  RULE_IMPLEMENTATION_RESULT_DETAILS,
13
14
  RULE_IMPLEMENTATION_RESULTS_DETAILS,
14
15
  RULE_IMPLEMENTATION,
@@ -32,6 +33,7 @@ import NewRule from "./NewRule";
32
33
  import NewRuleImplementation from "./NewRuleImplementation";
33
34
  import Rule from "./Rule";
34
35
  import RuleCrumbs from "./RuleCrumbs";
36
+ import RuleEvents from "./RuleEvents";
35
37
  import RuleImplementation from "./RuleImplementation";
36
38
  import RuleImplementationEvents from "./RuleImplementationEvents";
37
39
  import RuleImplementationLoader from "./RuleImplementationLoader";
@@ -61,13 +63,19 @@ const ImplementationStructuresLoader = React.lazy(() =>
61
63
  const QualityTemplatesLoader = () => <TemplatesLoader scope="dq" />;
62
64
  const ImplementationTemplatesLoader = () => <TemplatesLoader scope="ri" />;
63
65
 
66
+ const RuleEventsLoader = () => {
67
+ const match = useRouteMatch();
68
+ const id = _.path("params.id")(match);
69
+ return <EventsLoader resource_id={id} resource_type="rule" />;
70
+ };
71
+
64
72
  const ImplementationEventsLoader = () => {
65
73
  const match = useRouteMatch();
66
74
  const id = _.path("params.implementation_id")(match);
67
75
  return <EventsLoader resource_id={id} resource_type="implementation" />;
68
76
  };
69
77
 
70
- const RuleRoutes = ({
78
+ export const RuleRoutes = ({
71
79
  ruleLoaded,
72
80
  ruleImplementationLoaded,
73
81
  implementationStructures,
@@ -135,6 +143,22 @@ const RuleRoutes = ({
135
143
  </>
136
144
  )}
137
145
  />
146
+
147
+ <Route
148
+ exact
149
+ path={RULE_EVENTS}
150
+ render={() => (
151
+ <>
152
+ <RuleCrumbs />
153
+ <Segment>
154
+ <RuleEventsLoader />
155
+ {ruleLoaded && <Rule />}
156
+ {ruleLoaded && <RuleEvents />}
157
+ </Segment>
158
+ </>
159
+ )}
160
+ />
161
+
138
162
  <Route
139
163
  exact
140
164
  path={RULE_IMPLEMENTATIONS}
@@ -288,7 +312,7 @@ const RuleRoutes = ({
288
312
  <RuleImplementationLoader />
289
313
  {ruleLoaded && ruleImplementationLoaded && (
290
314
  <RuleImplementation>
291
- <ExecutionDetails rule_result_id={latest.id} />
315
+ <ExecutionDetails ruleResultId={latest.id} />
292
316
  </RuleImplementation>
293
317
  )}
294
318
  </Segment>
@@ -4,6 +4,11 @@ import { connect } from "react-redux";
4
4
  import { injectIntl } from "react-intl";
5
5
  import { makeOption } from "@truedat/core/services/i18n";
6
6
  import { SelectedFilters } from "@truedat/core/components";
7
+ import {
8
+ applyUserSearchFilter,
9
+ deleteUserSearchFilter,
10
+ saveUserSearchFilters,
11
+ } from "@truedat/dd/routines";
7
12
  import {
8
13
  closeRuleFilter,
9
14
  openRuleFilter,
@@ -24,28 +29,43 @@ const translations = (formatMessage) => ({
24
29
 
25
30
  export const mapStateToProps = (state, ownProps) => {
26
31
  const formatMessage = _.pathOr(_.prop("id"), "intl.formatMessage")(ownProps);
27
- const { ruleSelectedFilter: selectedFilter } = state;
32
+ const { ruleFiltersLoading: loading, ruleSelectedFilter: selectedFilter } =
33
+ state;
28
34
  const i18nValues = _.flow(
29
35
  getRuleSelectedFilterValues,
30
36
  _.map(makeOption(translations(formatMessage), selectedFilter))
31
37
  )(state);
32
38
 
39
+ const {
40
+ selectedUserSearchFilter: selectedUserFilter,
41
+ ruleActiveFilters: activeFilters,
42
+ userSearchFilters: userFilters,
43
+ } = state;
44
+
33
45
  return {
46
+ loading,
34
47
  selectedFilter,
35
48
  selectedFilters: getRuleSelectedFilters(state),
36
49
  selectedFilterActiveValues: getRuleSelectedFilterActiveValues(state),
37
50
  selectedFilterValues: i18nValues,
51
+ selectedUserFilter,
52
+ activeFilters,
53
+ userFilters,
54
+ userFilterScope: "rule",
38
55
  };
39
56
  };
40
57
 
41
58
  const mapDispatchToProps = (dispatch) =>
42
59
  bindActionCreators(
43
60
  {
61
+ applyUserFilter: applyUserSearchFilter,
44
62
  closeFilter: closeRuleFilter,
63
+ deleteUserFilter: deleteUserSearchFilter,
45
64
  openFilter: openRuleFilter,
46
65
  removeFilter: removeRuleFilter,
47
66
  resetFilters: resetRuleFilters,
48
67
  toggleFilterValue: toggleRuleFilterValue,
68
+ saveFilters: saveUserSearchFilters,
49
69
  },
50
70
  dispatch
51
71
  );
@@ -6,7 +6,12 @@ import { Link } from "react-router-dom";
6
6
  import { connect } from "react-redux";
7
7
  import { FormattedMessage } from "react-intl";
8
8
  import { usePath } from "@truedat/core/hooks";
9
- import { RULE, RULE_IMPLEMENTATIONS, linkTo } from "@truedat/core/routes";
9
+ import {
10
+ RULE,
11
+ RULE_IMPLEMENTATIONS,
12
+ RULE_EVENTS,
13
+ linkTo,
14
+ } from "@truedat/core/routes";
10
15
 
11
16
  const RuleTabs = ({ rule }) => {
12
17
  const path = usePath();
@@ -22,12 +27,21 @@ const RuleTabs = ({ rule }) => {
22
27
  >
23
28
  <FormattedMessage id="tabs.dq.ruleImplementations" />
24
29
  </Menu.Item>
30
+ <Menu.Item
31
+ active={path === RULE_EVENTS}
32
+ as={Link}
33
+ to={linkTo.RULE_EVENTS({
34
+ id: rule.id,
35
+ })}
36
+ >
37
+ <FormattedMessage id="tabs.dq.rule.audit" />
38
+ </Menu.Item>
25
39
  </Menu>
26
40
  );
27
41
  };
28
42
 
29
43
  RuleTabs.propTypes = {
30
- rule: PropTypes.object
44
+ rule: PropTypes.object,
31
45
  };
32
46
 
33
47
  const mapStateToProps = ({ rule }) => ({ rule });
@@ -13,13 +13,25 @@ const DomainsLoader = React.lazy(() =>
13
13
  const TemplatesLoader = React.lazy(() =>
14
14
  import("@truedat/df/templates/components/TemplatesLoader")
15
15
  );
16
+ const UserSearchFiltersLoader = React.lazy(() =>
17
+ import("@truedat/dd/components/UserSearchFiltersLoader")
18
+ );
16
19
  const QualityTemplatesLoader = () => <TemplatesLoader scope="dq" />;
17
20
 
18
21
  const RulesRoutes = () => (
19
22
  <>
20
23
  <Route path={RULES} component={RulesLoader} />
21
24
  <Route path={RULES} component={RuleFiltersLoader} />
22
- <Route path={RULES} component={Rules} exact />
25
+ <Route
26
+ exact
27
+ path={RULES}
28
+ render={() => (
29
+ <>
30
+ <UserSearchFiltersLoader scope="rule" />
31
+ <Rules />
32
+ </>
33
+ )}
34
+ />
23
35
  <Switch>
24
36
  <Route
25
37
  exact
@@ -11,41 +11,48 @@ jest.mock("react-router-dom", () => ({
11
11
 
12
12
  const renderOpts = {
13
13
  messages: {
14
- en: messages.en,
14
+ en: {
15
+ ...messages.en,
16
+ "ruleResult.details.props.test": "TestMessage",
17
+ },
15
18
  },
16
19
  };
17
20
 
18
- describe("<ExecutionDetetails>", () => {
19
- const rule = {
20
- result_type: "percentage",
21
- minimum: 50,
22
- goal: 100,
23
- };
24
- const ruleImplementation = {
25
- results: [{ foo: "bar", id: 100, details: { Query: "ImZvbyI=" } }],
26
- };
27
- const customColumns = [{ foo: "bar", name: "foo" }];
28
- const props = {
29
- rule,
30
- ruleImplementation,
31
- customColumns,
32
- };
33
-
21
+ describe("<ExecutionDetails>", () => {
34
22
  it("matches the lastest snapshot", () => {
23
+ const props = {
24
+ ruleImplementation: {
25
+ results: [{ foo: "bar", id: 100, details: { Query: "ImZvbyI=" } }],
26
+ },
27
+ };
35
28
  const { container } = render(<ExecutionDetails {...props} />, renderOpts);
36
29
  expect(container).toMatchSnapshot();
37
30
  });
38
31
 
32
+ it("decodes details with base64 prefix", () => {
33
+ const props = {
34
+ ruleImplementation: {
35
+ results: [
36
+ {
37
+ foo: "bar",
38
+ id: 100,
39
+ details: {
40
+ value: "valor",
41
+ base64_test: "QmFzZTY0X3ZhbHVl", //base64 for Base64_value
42
+ },
43
+ },
44
+ ],
45
+ },
46
+ };
47
+ const { getByText } = render(<ExecutionDetails {...props} />, renderOpts);
48
+ expect(getByText("TestMessage")).toBeInTheDocument();
49
+ expect(getByText("Base64_value")).toBeInTheDocument();
50
+ });
51
+
39
52
  it("without details", () => {
40
53
  const propsWithoutDetails = {
41
- ...props,
42
54
  ruleImplementation: {
43
- ...props.ruleImplementation,
44
- results: {
45
- ..._.map((result) => _.omit(["details"])(result))(
46
- props.ruleImplementation.results
47
- ),
48
- },
55
+ results: [{ foo: "bar", id: 100 }],
49
56
  },
50
57
  };
51
58
  const { container } = render(
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+ import { render } from "@truedat/test/render";
3
+ import { RuleEventRow } from "../RuleEventRow";
4
+
5
+ describe("<RuleEventsRow />", () => {
6
+ const props = {
7
+ payload: [
8
+ {
9
+ field: "field1",
10
+ action: "changed",
11
+ value: "new value",
12
+ },
13
+ ],
14
+ user_name: "some.user@domain.tld",
15
+ user: {
16
+ email: "some.user@domain.tld",
17
+ full_name: "Some User",
18
+ id: 142,
19
+ user_name: "some.user@domain.tld",
20
+ },
21
+ ts: "2021-09-16T07:36:32.848603Z",
22
+ };
23
+ const renderOpts = {
24
+ messages: {
25
+ en: { "rules.events.action_changed_to": "Field {0} changed to: {1}" },
26
+ },
27
+ };
28
+
29
+ it("matches the latest snapshot", () => {
30
+ const { container } = render(<RuleEventRow {...props} />, renderOpts);
31
+ expect(container).toMatchSnapshot();
32
+ });
33
+ });
@@ -0,0 +1,64 @@
1
+ import React from "react";
2
+ import { render } from "@truedat/test/render";
3
+ import { RuleEvents } from "../RuleEvents";
4
+ import { getParsedEvents } from "../../selectors/getParsedEvents";
5
+
6
+ describe("<RuleEvents />", () => {
7
+ const events = [
8
+ {
9
+ id: 100217,
10
+ service: "td_dd",
11
+ resource_id: 777,
12
+ resource_type: "rule",
13
+ event: "rule_updated",
14
+ payload: {
15
+ domain_id: 140,
16
+ },
17
+ user_id: 142,
18
+ user_name: null,
19
+ user: {
20
+ email: "some.user@domain.tld",
21
+ full_name: "Some User",
22
+ id: 142,
23
+ user_name: "some.user@domain.tld",
24
+ },
25
+ ts: "2021-09-16T07:36:32.848603Z",
26
+ },
27
+ {
28
+ id: 100436,
29
+ service: "td_dd",
30
+ resource_id: 777,
31
+ resource_type: "rule",
32
+ event: "rule_updated",
33
+ payload: {
34
+ domain_id: 168,
35
+ },
36
+ user_id: 171,
37
+ user_name: null,
38
+ user: {
39
+ email: "some.user@domain.tld",
40
+ full_name: "Some User",
41
+ id: 171,
42
+ user_name: "some.user",
43
+ },
44
+ ts: "2021-09-16T09:31:03.061864Z",
45
+ },
46
+ ];
47
+ const renderOpts = {
48
+ messages: {
49
+ en: {
50
+ "rules.events.action_created": "Rule created",
51
+ "rules.events.action_changed": "Field {0} changed: {1}",
52
+ "rules.events.action_changed_to": "Field {0} changed to: {1}",
53
+ "rules.events.action_updated": "Rule updated",
54
+ },
55
+ },
56
+ };
57
+
58
+ const props = { events: getParsedEvents({ events }), eventsLoading: false };
59
+
60
+ it("matches the latest snapshot", () => {
61
+ const { container } = render(<RuleEvents {...props} />, renderOpts);
62
+ expect(container).toMatchSnapshot();
63
+ });
64
+ });
@@ -0,0 +1,23 @@
1
+ import React from "react";
2
+ import { render } from "@truedat/test/render";
3
+ import { RuleRoutes } from "../RuleRoutes";
4
+
5
+ describe("<RuleRoutes>", () => {
6
+ const props = {
7
+ rule: {},
8
+ implementationStructures: [],
9
+ ruleLoaded: true,
10
+ template: {},
11
+ ruleImplementation: {},
12
+ ruleImplementationLoaded: true,
13
+ implementationStructuresLoaded: true,
14
+ systemsLoading: true,
15
+ templatesLoaded: true,
16
+ structuresAliasesLoading: true,
17
+ };
18
+
19
+ it("matches the lastest snapshot", () => {
20
+ const { container } = render(<RuleRoutes {...props} />, {});
21
+ expect(container).toMatchSnapshot();
22
+ });
23
+ });