@truedat/cx 4.36.7 → 4.36.8
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/CHANGELOG.md +6 -0
- package/package.json +7 -6
- package/src/configurations/components/ConfigurationActions.js +1 -1
- package/src/configurations/components/ConfigurationCards.js +1 -1
- package/src/configurations/components/__tests__/__snapshots__/ConfigurationCards.spec.js.snap +5 -5
- package/src/messages/en.js +32 -25
- package/src/messages/es.js +32 -25
- package/src/sources/components/EditSource.js +3 -3
- package/src/sources/components/Source.js +3 -3
- package/src/sources/components/SourceActions.js +107 -79
- package/src/sources/components/SourceForm.js +15 -24
- package/src/sources/components/SourceRoutes.js +8 -18
- package/src/sources/components/{SourcesSelector.js → SourceSelector.js} +0 -0
- package/src/sources/components/Sources.js +53 -47
- package/src/sources/components/SourcesTable.js +88 -0
- package/src/sources/components/__tests__/SourceActions.spec.js +27 -6
- package/src/sources/components/__tests__/Sources.spec.js +68 -18
- package/src/sources/components/__tests__/SourcesTable.spec.js +59 -0
- package/src/sources/components/__tests__/__snapshots__/EditSource.spec.js.snap +3 -3
- package/src/sources/components/__tests__/__snapshots__/Source.spec.js.snap +1 -1
- package/src/sources/components/__tests__/__snapshots__/SourceActions.spec.js.snap +53 -65
- package/src/sources/components/__tests__/__snapshots__/SourceForm.spec.js.snap +10 -8
- package/src/sources/components/__tests__/__snapshots__/Sources.spec.js.snap +170 -62
- package/src/sources/components/__tests__/__snapshots__/SourcesTable.spec.js.snap +217 -0
- package/src/sources/components/index.js +3 -3
- package/src/sources/reducers/__tests__/sourceRedirect.spec.js +28 -5
- package/src/sources/reducers/source.js +4 -3
- package/src/sources/reducers/sourceRedirect.js +7 -1
- package/src/sources/routines.js +6 -4
- package/src/sources/sagas/__tests__/disableSource.spec.js +82 -0
- package/src/sources/sagas/__tests__/enableSource.spec.js +82 -0
- package/src/sources/sagas/disableSource.js +39 -0
- package/src/sources/sagas/enableSource.js +39 -0
- package/src/sources/sagas/index.js +13 -7
- package/src/sources/components/SourceCards.js +0 -115
- package/src/sources/components/__tests__/SourceCards.spec.js +0 -45
- package/src/sources/components/__tests__/__snapshots__/SourceCards.spec.js.snap +0 -421
|
@@ -31,10 +31,12 @@ export class SourceForm extends React.Component {
|
|
|
31
31
|
static propTypes = {
|
|
32
32
|
applyTemplate: PropTypes.func,
|
|
33
33
|
intl: PropTypes.object,
|
|
34
|
+
source: PropTypes.object,
|
|
34
35
|
template: PropTypes.object,
|
|
36
|
+
templates: PropTypes.array,
|
|
35
37
|
templatesLoaded: PropTypes.bool,
|
|
36
38
|
selectTemplate: PropTypes.func,
|
|
37
|
-
|
|
39
|
+
onSubmit: PropTypes.func,
|
|
38
40
|
};
|
|
39
41
|
|
|
40
42
|
state = initialState;
|
|
@@ -88,19 +90,10 @@ export class SourceForm extends React.Component {
|
|
|
88
90
|
|
|
89
91
|
handleSubmit = (e) => {
|
|
90
92
|
e.preventDefault();
|
|
91
|
-
const { applyTemplate,
|
|
92
|
-
const source = _.pick(["external_id", "type"])(this.state);
|
|
93
|
-
|
|
93
|
+
const { applyTemplate, onSubmit } = this.props;
|
|
94
|
+
const source = _.pick(["id", "external_id", "type"])(this.state);
|
|
94
95
|
const config = _.flow(_.prop("content"), applyTemplate)(this.state);
|
|
95
|
-
|
|
96
|
-
// call routine submit (POST or PUT depending action)
|
|
97
|
-
// get it from props
|
|
98
|
-
handleSubmit({
|
|
99
|
-
source: {
|
|
100
|
-
...source,
|
|
101
|
-
config: config,
|
|
102
|
-
},
|
|
103
|
-
});
|
|
96
|
+
onSubmit({ source: { ...source, config: config } });
|
|
104
97
|
};
|
|
105
98
|
|
|
106
99
|
render() {
|
|
@@ -124,7 +117,7 @@ export class SourceForm extends React.Component {
|
|
|
124
117
|
<Form>
|
|
125
118
|
<Form.Field required>
|
|
126
119
|
<label>
|
|
127
|
-
|
|
120
|
+
<FormattedMessage id="source.external_id" />
|
|
128
121
|
{_.isEmpty(external_id) ? (
|
|
129
122
|
<Label pointing="left">
|
|
130
123
|
<FormattedMessage id="template.form.validation.empty_required" />
|
|
@@ -139,11 +132,11 @@ export class SourceForm extends React.Component {
|
|
|
139
132
|
/>
|
|
140
133
|
</Form.Field>
|
|
141
134
|
<Form.Field required>
|
|
142
|
-
<label>
|
|
135
|
+
<label>
|
|
136
|
+
<FormattedMessage id="type.selector.label" />
|
|
137
|
+
</label>
|
|
143
138
|
<Form.Dropdown
|
|
144
|
-
placeholder={formatMessage({
|
|
145
|
-
id: "type.selector.placeholder",
|
|
146
|
-
})}
|
|
139
|
+
placeholder={formatMessage({ id: "type.selector.placeholder" })}
|
|
147
140
|
name="type"
|
|
148
141
|
search
|
|
149
142
|
selection
|
|
@@ -159,7 +152,7 @@ export class SourceForm extends React.Component {
|
|
|
159
152
|
{type && templatesLoaded && (
|
|
160
153
|
<Form.Field>
|
|
161
154
|
<label className="label">
|
|
162
|
-
|
|
155
|
+
<FormattedMessage id="source.config.label" />
|
|
163
156
|
</label>
|
|
164
157
|
|
|
165
158
|
<DynamicSourceForm
|
|
@@ -177,11 +170,9 @@ export class SourceForm extends React.Component {
|
|
|
177
170
|
primary
|
|
178
171
|
disabled={this.isInvalid()}
|
|
179
172
|
onClick={this.handleSubmit}
|
|
180
|
-
content={
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
/>
|
|
184
|
-
}
|
|
173
|
+
content={formatMessage({
|
|
174
|
+
id: _.isEmpty(source) ? "actions.create" : "actions.save",
|
|
175
|
+
})}
|
|
185
176
|
/>
|
|
186
177
|
</div>
|
|
187
178
|
</Form>
|
|
@@ -9,22 +9,21 @@ import { useAuthorized } from "@truedat/core/hooks";
|
|
|
9
9
|
import {
|
|
10
10
|
SOURCE,
|
|
11
11
|
SOURCES,
|
|
12
|
-
|
|
12
|
+
SOURCES_NEW,
|
|
13
13
|
SOURCE_EDIT,
|
|
14
|
-
|
|
15
|
-
SOURCE_JOBS_NEW
|
|
14
|
+
SOURCE_JOBS_NEW,
|
|
16
15
|
} from "@truedat/core/routes";
|
|
17
16
|
import NewSource from "./NewSource";
|
|
18
17
|
import NewJob from "./NewJob";
|
|
19
18
|
import EditSource from "./EditSource";
|
|
20
19
|
import Sources from "./Sources";
|
|
21
|
-
import SourcesLoader from "./SourcesLoader";
|
|
22
20
|
import SourceLoader from "./SourceLoader";
|
|
23
21
|
import Source from "./Source";
|
|
24
22
|
|
|
25
23
|
const TemplateLoader = React.lazy(() =>
|
|
26
24
|
import("@truedat/df/templates/components/TemplateLoader")
|
|
27
25
|
);
|
|
26
|
+
|
|
28
27
|
const TemplatesLoader = React.lazy(() =>
|
|
29
28
|
import("@truedat/df/templates/components/TemplatesLoader")
|
|
30
29
|
);
|
|
@@ -49,7 +48,7 @@ export const SourceRoutes = ({ source, sourceLoading, templatesLoading }) => {
|
|
|
49
48
|
/>
|
|
50
49
|
<Route
|
|
51
50
|
exact
|
|
52
|
-
path={
|
|
51
|
+
path={SOURCES_NEW}
|
|
53
52
|
render={() => (
|
|
54
53
|
<>
|
|
55
54
|
<TemplatesLoader scope="cx" />
|
|
@@ -76,24 +75,15 @@ export const SourceRoutes = ({ source, sourceLoading, templatesLoading }) => {
|
|
|
76
75
|
path={SOURCE}
|
|
77
76
|
render={() => (
|
|
78
77
|
<>
|
|
78
|
+
<SourceLoader />
|
|
79
79
|
<Segment>
|
|
80
|
-
<SourceLoader />
|
|
81
80
|
<TemplatesLoader scope="cx" />
|
|
82
81
|
{!templatesLoading && <Source />}
|
|
83
82
|
</Segment>
|
|
84
83
|
</>
|
|
85
84
|
)}
|
|
86
85
|
/>
|
|
87
|
-
<Route
|
|
88
|
-
exact
|
|
89
|
-
path={SOURCES}
|
|
90
|
-
render={() => (
|
|
91
|
-
<>
|
|
92
|
-
<SourcesLoader />
|
|
93
|
-
<Sources />
|
|
94
|
-
</>
|
|
95
|
-
)}
|
|
96
|
-
/>
|
|
86
|
+
<Route exact path={SOURCES} render={() => <Sources />} />
|
|
97
87
|
</Switch>
|
|
98
88
|
) : (
|
|
99
89
|
<Unauthorized />
|
|
@@ -106,13 +96,13 @@ export const SourceRoutes = ({ source, sourceLoading, templatesLoading }) => {
|
|
|
106
96
|
SourceRoutes.propTypes = {
|
|
107
97
|
source: PropTypes.object,
|
|
108
98
|
sourceLoading: PropTypes.bool,
|
|
109
|
-
templatesLoading: PropTypes.bool
|
|
99
|
+
templatesLoading: PropTypes.bool,
|
|
110
100
|
};
|
|
111
101
|
|
|
112
102
|
const mapStateToProps = ({ source, sourceLoading, templatesLoading }) => ({
|
|
113
103
|
source,
|
|
114
104
|
sourceLoading,
|
|
115
|
-
templatesLoading
|
|
105
|
+
templatesLoading,
|
|
116
106
|
});
|
|
117
107
|
|
|
118
108
|
export default connect(mapStateToProps)(SourceRoutes);
|
|
File without changes
|
|
@@ -1,45 +1,65 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
2
|
import React, { useState } from "react";
|
|
3
|
-
import
|
|
4
|
-
import { connect } from "react-redux";
|
|
3
|
+
import { matchSorter } from "match-sorter";
|
|
5
4
|
import { useIntl } from "react-intl";
|
|
6
5
|
import { Link } from "react-router-dom";
|
|
7
|
-
import { Button,
|
|
6
|
+
import { Button, Header, Icon, Input, Segment } from "semantic-ui-react";
|
|
8
7
|
import { FormattedMessage } from "react-intl";
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
8
|
+
import { gql, useQuery } from "@apollo/client";
|
|
9
|
+
import { SOURCES_NEW } from "@truedat/core/routes";
|
|
10
|
+
import SourcesTable from "./SourcesTable";
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
export const SOURCES = gql`
|
|
13
|
+
query SOURCES {
|
|
14
|
+
sources {
|
|
15
|
+
id
|
|
16
|
+
externalId
|
|
17
|
+
active
|
|
18
|
+
type
|
|
19
|
+
events(limit: 1) {
|
|
20
|
+
id
|
|
21
|
+
type
|
|
22
|
+
message
|
|
23
|
+
insertedAt
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
13
28
|
|
|
14
|
-
const
|
|
15
|
-
_.flow(
|
|
16
|
-
_.at(["type", "external_id"]),
|
|
17
|
-
_.map(toSearchable),
|
|
18
|
-
_.some(_.includes(toSearchable(filter)))
|
|
19
|
-
);
|
|
29
|
+
const lowerDeburrTrim = _.flow(_.toLower, _.deburr, _.trim);
|
|
20
30
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
const sortByExternalId = _.sortBy(({ externalId }) =>
|
|
32
|
+
lowerDeburrTrim(externalId)
|
|
33
|
+
);
|
|
24
34
|
|
|
25
|
-
export const Sources = (
|
|
26
|
-
const [
|
|
27
|
-
const filteredSources = filterData(searchFilter, sources);
|
|
35
|
+
export const Sources = () => {
|
|
36
|
+
const [searchTerm, setSearchTerm] = useState("");
|
|
28
37
|
const { formatMessage } = useIntl();
|
|
38
|
+
const { loading, error, data } = useQuery(SOURCES);
|
|
39
|
+
const items = loading || error ? [] : data?.sources;
|
|
40
|
+
const sources =
|
|
41
|
+
searchTerm === ""
|
|
42
|
+
? sortByExternalId(items)
|
|
43
|
+
: matchSorter(items, searchTerm, {
|
|
44
|
+
keys: [
|
|
45
|
+
"externalId",
|
|
46
|
+
"type",
|
|
47
|
+
"events.0.message",
|
|
48
|
+
"events.0.type",
|
|
49
|
+
"events.0.insertedAt",
|
|
50
|
+
],
|
|
51
|
+
threshold: matchSorter.rankings.CONTAINS,
|
|
52
|
+
});
|
|
29
53
|
|
|
30
|
-
|
|
31
|
-
setSearchFilter(value);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
return sourcesLoading ? null : (
|
|
54
|
+
return (
|
|
35
55
|
<Segment>
|
|
36
56
|
<Header as="h2">
|
|
37
57
|
<Button
|
|
38
58
|
floated="right"
|
|
39
59
|
primary
|
|
40
60
|
as={Link}
|
|
41
|
-
to={
|
|
42
|
-
content={
|
|
61
|
+
to={SOURCES_NEW}
|
|
62
|
+
content={formatMessage({ id: "sources.actions.create" })}
|
|
43
63
|
/>
|
|
44
64
|
<Icon name="plug" circular />
|
|
45
65
|
<Header.Content>
|
|
@@ -49,29 +69,15 @@ export const Sources = ({ sources, sourcesLoading }) => {
|
|
|
49
69
|
</Header.Subheader>
|
|
50
70
|
</Header.Content>
|
|
51
71
|
</Header>
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
/>
|
|
60
|
-
</Grid.Column>
|
|
61
|
-
</Grid>
|
|
62
|
-
<SourceCards sources={filteredSources} />
|
|
72
|
+
<Input
|
|
73
|
+
onChange={(_e, { value }) => setSearchTerm(value)}
|
|
74
|
+
value={searchTerm}
|
|
75
|
+
icon={{ name: "search", link: true }}
|
|
76
|
+
placeholder={formatMessage({ id: "sources.search.placeholder" })}
|
|
77
|
+
/>
|
|
78
|
+
{loading || error ? null : <SourcesTable sources={sources} />}
|
|
63
79
|
</Segment>
|
|
64
80
|
);
|
|
65
81
|
};
|
|
66
82
|
|
|
67
|
-
|
|
68
|
-
sources: PropTypes.array,
|
|
69
|
-
sourcesLoading: PropTypes.bool
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const mapStateToProps = ({ sources, sourcesLoading }) => ({
|
|
73
|
-
sources,
|
|
74
|
-
sourcesLoading
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
export default connect(mapStateToProps)(Sources);
|
|
83
|
+
export default Sources;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { Table } from "semantic-ui-react";
|
|
5
|
+
import { Link } from "react-router-dom";
|
|
6
|
+
import { FormattedMessage } from "react-intl";
|
|
7
|
+
import { useIntl } from "react-intl";
|
|
8
|
+
import { DateTime } from "@truedat/core/components";
|
|
9
|
+
import { linkTo } from "@truedat/core/routes";
|
|
10
|
+
|
|
11
|
+
export const HeaderRow = () => {
|
|
12
|
+
const { formatMessage } = useIntl();
|
|
13
|
+
const headers = [
|
|
14
|
+
"source.external_id",
|
|
15
|
+
"source.type",
|
|
16
|
+
"source.status",
|
|
17
|
+
"source.latestEvent.insertedAt",
|
|
18
|
+
"source.latestEvent.type",
|
|
19
|
+
"source.latestEvent.message",
|
|
20
|
+
];
|
|
21
|
+
return (
|
|
22
|
+
<Table.Row>
|
|
23
|
+
{headers.map((id, key) => (
|
|
24
|
+
<Table.HeaderCell key={key} content={formatMessage({ id })} />
|
|
25
|
+
))}
|
|
26
|
+
</Table.Row>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const SourceRow = ({ active, externalId, type, events }) => {
|
|
31
|
+
const event = _.head(events);
|
|
32
|
+
const disabled = !active;
|
|
33
|
+
const positive = event?.type === "SUCCEEDED";
|
|
34
|
+
const negative = event?.type === "FAILED";
|
|
35
|
+
return (
|
|
36
|
+
<Table.Row>
|
|
37
|
+
<Table.Cell>
|
|
38
|
+
<Link to={linkTo.SOURCE({ external_id: externalId })}>
|
|
39
|
+
{externalId}
|
|
40
|
+
</Link>
|
|
41
|
+
</Table.Cell>
|
|
42
|
+
<Table.Cell disabled={disabled}>{type}</Table.Cell>
|
|
43
|
+
<Table.Cell disabled={disabled}>
|
|
44
|
+
{active ? null : <FormattedMessage id="source.disabled" />}
|
|
45
|
+
</Table.Cell>
|
|
46
|
+
<Table.Cell disabled={disabled} positive={positive} negative={negative}>
|
|
47
|
+
<DateTime value={event?.insertedAt} />
|
|
48
|
+
</Table.Cell>
|
|
49
|
+
<Table.Cell disabled={disabled} positive={positive} negative={negative}>
|
|
50
|
+
{event?.type}
|
|
51
|
+
</Table.Cell>
|
|
52
|
+
<Table.Cell disabled={disabled} positive={positive} negative={negative}>
|
|
53
|
+
{_.truncate({ length: 90 })(event?.message)}
|
|
54
|
+
</Table.Cell>
|
|
55
|
+
</Table.Row>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
SourceRow.propTypes = {
|
|
60
|
+
active: PropTypes.bool,
|
|
61
|
+
externalId: PropTypes.string,
|
|
62
|
+
type: PropTypes.string,
|
|
63
|
+
events: PropTypes.arrayOf(PropTypes.object),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const SourcesTable = ({ sources }) => {
|
|
67
|
+
const { formatMessage } = useIntl();
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<Table>
|
|
71
|
+
<caption className="text-right">
|
|
72
|
+
{formatMessage({ id: "sources.count" }, { count: _.size(sources) })}
|
|
73
|
+
</caption>
|
|
74
|
+
<Table.Header>
|
|
75
|
+
<HeaderRow />
|
|
76
|
+
</Table.Header>
|
|
77
|
+
<Table.Body>
|
|
78
|
+
{sources.map((props, key) => (
|
|
79
|
+
<SourceRow key={key} {...props} />
|
|
80
|
+
))}
|
|
81
|
+
</Table.Body>
|
|
82
|
+
</Table>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
SourcesTable.propTypes = { sources: PropTypes.array };
|
|
87
|
+
|
|
88
|
+
export default SourcesTable;
|
|
@@ -1,18 +1,39 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { render } from "@truedat/test/render";
|
|
3
3
|
import { SourceActions } from "../SourceActions";
|
|
4
4
|
|
|
5
|
+
const renderOpts = {
|
|
6
|
+
messages: {
|
|
7
|
+
en: {
|
|
8
|
+
"source.actions.delete": "delete",
|
|
9
|
+
"source.actions.delete.confirmation.content": "confirm delete content",
|
|
10
|
+
"source.actions.delete.confirmation.header": "confirm delete header",
|
|
11
|
+
"source.actions.disable": "disable",
|
|
12
|
+
"source.actions.disable.confirmation.content": "confirm disable content",
|
|
13
|
+
"source.actions.disable.confirmation.header": "confirm disable header",
|
|
14
|
+
"source.actions.edit": "edit",
|
|
15
|
+
"source.actions.enable": "enable",
|
|
16
|
+
"source.actions.enable.confirmation.content": "confirm enable content",
|
|
17
|
+
"source.actions.enable.confirmation.header": "confirm enable header",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
5
22
|
describe("<SourceActions />", () => {
|
|
6
23
|
const source = {
|
|
7
24
|
external_id: "Micro1",
|
|
8
25
|
config: { a: 1 },
|
|
9
|
-
type: "micro"
|
|
26
|
+
type: "micro",
|
|
27
|
+
};
|
|
28
|
+
const props = {
|
|
29
|
+
source,
|
|
30
|
+
deleteSource: jest.fn(),
|
|
31
|
+
enableSource: jest.fn(),
|
|
32
|
+
disableSource: jest.fn(),
|
|
10
33
|
};
|
|
11
|
-
const deleteSource = jest.fn();
|
|
12
34
|
|
|
13
|
-
const props = { source, deleteSource };
|
|
14
35
|
it("matches the latest snapshot", () => {
|
|
15
|
-
const
|
|
16
|
-
expect(
|
|
36
|
+
const { container } = render(<SourceActions {...props} />, renderOpts);
|
|
37
|
+
expect(container).toMatchSnapshot();
|
|
17
38
|
});
|
|
18
39
|
});
|
|
@@ -1,29 +1,79 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { Sources } from "../Sources";
|
|
2
|
+
import userEvent from "@testing-library/user-event";
|
|
3
|
+
import { render } from "@truedat/test/render";
|
|
4
|
+
import { Sources, SOURCES } from "../Sources";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
const messages = {
|
|
7
|
+
en: {
|
|
8
|
+
"sources.actions.create": "create",
|
|
9
|
+
"sources.header": "header",
|
|
10
|
+
"sources.search.placeholder": "search",
|
|
11
|
+
"sources.count": "{count} sources found",
|
|
12
|
+
"sources.subheader": "subheader",
|
|
13
|
+
"source.latestEvent.insertedAt": "insertedAt",
|
|
14
|
+
"source.latestEvent.message": "message",
|
|
15
|
+
"source.latestEvent.type": "type",
|
|
16
|
+
"source.status": "status",
|
|
17
|
+
"source.type": "type",
|
|
18
|
+
"source.external_id": "external_id",
|
|
19
|
+
},
|
|
20
|
+
};
|
|
9
21
|
|
|
10
22
|
describe("<Sources />", () => {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
sources: []
|
|
23
|
+
const props = {
|
|
24
|
+
loading: false,
|
|
25
|
+
sources: [],
|
|
14
26
|
};
|
|
27
|
+
const event = {
|
|
28
|
+
id: 456,
|
|
29
|
+
type: "eventType",
|
|
30
|
+
message: "eventMessage",
|
|
31
|
+
insertedAt: "2020-01-01T12:34:56.000Z",
|
|
32
|
+
};
|
|
33
|
+
const source1 = {
|
|
34
|
+
id: 123,
|
|
35
|
+
externalId: "aaaa",
|
|
36
|
+
active: true,
|
|
37
|
+
type: "sourceType1",
|
|
38
|
+
events: [event],
|
|
39
|
+
};
|
|
40
|
+
const source2 = {
|
|
41
|
+
id: 456,
|
|
42
|
+
externalId: "bbbb",
|
|
43
|
+
active: true,
|
|
44
|
+
type: "sourceType2",
|
|
45
|
+
events: [event],
|
|
46
|
+
};
|
|
47
|
+
const sources = [source1, source2];
|
|
48
|
+
const sourcesMock = {
|
|
49
|
+
request: { query: SOURCES },
|
|
50
|
+
result: { data: { sources } },
|
|
51
|
+
};
|
|
52
|
+
const renderOpts = { mocks: [sourcesMock], messages };
|
|
15
53
|
|
|
16
|
-
it("matches the latest snapshot", () => {
|
|
17
|
-
const
|
|
18
|
-
|
|
54
|
+
it("matches the latest snapshot", async () => {
|
|
55
|
+
const { container, findByText } = render(
|
|
56
|
+
<Sources {...props} />,
|
|
57
|
+
renderOpts
|
|
58
|
+
);
|
|
59
|
+
await findByText("2 sources found");
|
|
60
|
+
expect(container).toMatchSnapshot();
|
|
19
61
|
});
|
|
20
62
|
|
|
21
|
-
it("renders
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
expect(wrapper.findWhere(n => n.prop("sources")).props().sources).toEqual(
|
|
26
|
-
[]
|
|
63
|
+
it("renders count and filters rows matching search term", async () => {
|
|
64
|
+
const { findByText, getByRole, queryAllByRole } = render(
|
|
65
|
+
<Sources {...props} />,
|
|
66
|
+
renderOpts
|
|
27
67
|
);
|
|
68
|
+
await findByText("2 sources found");
|
|
69
|
+
expect(queryAllByRole("row")).toHaveLength(3); // 2 rows + header
|
|
70
|
+
|
|
71
|
+
userEvent.type(getByRole("textbox"), source1.externalId);
|
|
72
|
+
await findByText("1 sources found");
|
|
73
|
+
expect(queryAllByRole("row")).toHaveLength(2); // 1 row + header
|
|
74
|
+
|
|
75
|
+
userEvent.type(getByRole("textbox"), "x");
|
|
76
|
+
await findByText("0 sources found");
|
|
77
|
+
expect(queryAllByRole("row")).toHaveLength(1); // header only
|
|
28
78
|
});
|
|
29
79
|
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "@truedat/test/render";
|
|
3
|
+
import { SourcesTable } from "../SourcesTable";
|
|
4
|
+
|
|
5
|
+
const renderOpts = {
|
|
6
|
+
messages: {
|
|
7
|
+
en: {
|
|
8
|
+
"source.disabled": "disabled",
|
|
9
|
+
"source.external_id": "external_id",
|
|
10
|
+
"source.latestEvent.insertedAt": "eventInsertedAt",
|
|
11
|
+
"source.latestEvent.message": "eventMessage",
|
|
12
|
+
"source.latestEvent.type": "eventType",
|
|
13
|
+
"source.status": "status",
|
|
14
|
+
"source.type": "type",
|
|
15
|
+
"sources.count": "{count} sources found",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
describe("<SourcesTable />", () => {
|
|
21
|
+
const sources = [
|
|
22
|
+
{
|
|
23
|
+
id: 1,
|
|
24
|
+
externalId: "con_url",
|
|
25
|
+
type: "a",
|
|
26
|
+
config: {
|
|
27
|
+
a: "aaa",
|
|
28
|
+
lista: ["bbb", "ddd"],
|
|
29
|
+
url_cx: [{ url_name: "google", url_value: "https://google.es" }],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{ id: 2, externalId: "id1", type: "app-admin", config: {} },
|
|
33
|
+
{ id: 3, externalId: "id2", type: "app-admin", config: { a: 1 } },
|
|
34
|
+
{ id: 4, externalId: "id3", type: "app-admin", config: { a: "yyyyb" } },
|
|
35
|
+
{ id: 5, externalId: "id4", type: "a", config: { lista: ["codigo6"] } },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
it("matches the latest snapshot", () => {
|
|
39
|
+
const { container } = render(
|
|
40
|
+
<SourcesTable sources={sources} />,
|
|
41
|
+
renderOpts
|
|
42
|
+
);
|
|
43
|
+
expect(container).toMatchSnapshot();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("contains a message when no sources are found", () => {
|
|
47
|
+
const { queryByText } = render(<SourcesTable sources={[]} />, renderOpts);
|
|
48
|
+
expect(queryByText(/0 sources found/)).toBeTruthy();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("contains a caption, a header row and a row for each source", () => {
|
|
52
|
+
const { queryAllByRole, queryByText } = render(
|
|
53
|
+
<SourcesTable sources={sources} />,
|
|
54
|
+
renderOpts
|
|
55
|
+
);
|
|
56
|
+
expect(queryByText(/5 sources found/)).toBeTruthy();
|
|
57
|
+
expect(queryAllByRole("row")).toHaveLength(sources.length + 1);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
exports[`<EditSource /> matches the latest snapshot 1`] = `
|
|
4
4
|
<Fragment>
|
|
5
5
|
<SourceBreadcrumbs
|
|
6
|
-
text="
|
|
6
|
+
text="source.actions.edit"
|
|
7
7
|
/>
|
|
8
8
|
<Container
|
|
9
9
|
as={[Function]}
|
|
@@ -18,12 +18,12 @@ exports[`<EditSource /> matches the latest snapshot 1`] = `
|
|
|
18
18
|
/>
|
|
19
19
|
<HeaderContent>
|
|
20
20
|
<MemoizedFormattedMessage
|
|
21
|
-
id="
|
|
21
|
+
id="source.actions.edit"
|
|
22
22
|
/>
|
|
23
23
|
</HeaderContent>
|
|
24
24
|
</Header>
|
|
25
25
|
<injectIntl(Connect(SourceForm))
|
|
26
|
-
|
|
26
|
+
onSubmit={[MockFunction]}
|
|
27
27
|
source={
|
|
28
28
|
Object {
|
|
29
29
|
"config": Object {
|