@truedat/dd 4.40.12 → 4.41.0

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 (26) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +6 -6
  3. package/src/api.js +3 -0
  4. package/src/components/DictionaryRoutes.js +17 -1
  5. package/src/components/PendingStructureNoteRow.js +45 -0
  6. package/src/components/PendingStructureNotes.js +149 -0
  7. package/src/components/PendingStructureNotesTable.js +73 -0
  8. package/src/components/StructuresDomainsUploadOption.js +52 -0
  9. package/src/components/StructuresOptions.js +4 -0
  10. package/src/components/__tests__/PendingStructureNoteRow.spec.js +48 -0
  11. package/src/components/__tests__/PendingStructureNotes.spec.js +102 -0
  12. package/src/components/__tests__/PendingStructureNotesTable.spec.js +83 -0
  13. package/src/components/__tests__/StructuresOptions.spec.js +6 -1
  14. package/src/components/__tests__/__snapshots__/DictionaryRoutes.spec.js.snap +4 -0
  15. package/src/components/__tests__/__snapshots__/PendingStructureNoteRow.spec.js.snap +35 -0
  16. package/src/components/__tests__/__snapshots__/PendingStructureNotes.spec.js.snap +126 -0
  17. package/src/components/__tests__/__snapshots__/PendingStructureNotesTable.spec.js.snap +123 -0
  18. package/src/components/__tests__/__snapshots__/StructuresOptions.spec.js.snap +14 -0
  19. package/src/messages/en.js +27 -0
  20. package/src/messages/es.js +30 -0
  21. package/src/reducers/__tests__/ddMessage.spec.js +76 -0
  22. package/src/reducers/ddMessage.js +51 -8
  23. package/src/routines.js +1 -0
  24. package/src/sagas/__tests__/uploadStructuresDomains.spec.js +81 -0
  25. package/src/sagas/index.js +3 -0
  26. package/src/sagas/uploadStructuresDomains.js +35 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.41.0] 2022-03-25
4
+
5
+ ### Added
6
+
7
+ - [TD-4535] Structures domains CSV upload bulk update
8
+
9
+ ## [4.40.14] 2022-03-22
10
+
11
+ ### Added
12
+
13
+ - [TD-4577] View for Pending `StructureNotes`
14
+
3
15
  ## [4.40.10] 2022-03-21
4
16
 
5
17
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dd",
3
- "version": "4.40.12",
3
+ "version": "4.41.0",
4
4
  "description": "Truedat Web Data Dictionary",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -34,7 +34,7 @@
34
34
  "@testing-library/jest-dom": "^5.14.1",
35
35
  "@testing-library/react": "^12.0.0",
36
36
  "@testing-library/user-event": "^13.2.1",
37
- "@truedat/test": "4.40.12",
37
+ "@truedat/test": "4.41.0",
38
38
  "babel-jest": "^27.0.6",
39
39
  "babel-plugin-dynamic-import-node": "^2.3.3",
40
40
  "babel-plugin-lodash": "^3.3.4",
@@ -84,9 +84,9 @@
84
84
  ]
85
85
  },
86
86
  "dependencies": {
87
- "@truedat/auth": "4.40.12",
88
- "@truedat/core": "4.40.12",
89
- "@truedat/df": "4.40.12",
87
+ "@truedat/auth": "4.41.0",
88
+ "@truedat/core": "4.41.0",
89
+ "@truedat/df": "4.41.0",
90
90
  "lodash": "^4.17.21",
91
91
  "path-to-regexp": "^1.7.0",
92
92
  "prop-types": "^15.7.2",
@@ -107,5 +107,5 @@
107
107
  "react-dom": ">= 16.8.6 < 17",
108
108
  "semantic-ui-react": ">= 0.88.2 < 2.1"
109
109
  },
110
- "gitHead": "f8f89f659e97ba1eeb39d9f86c9b8c2c8934518a"
110
+ "gitHead": "f4d8bc5e536b847c7b562a84bfa70955a93166ea"
111
111
  }
package/src/api.js CHANGED
@@ -31,6 +31,8 @@ const API_STRUCTURE_TAG = "/api/data_structure_tags/:id";
31
31
  const API_STRUCTURE_TAGS = "/api/data_structure_tags";
32
32
  const API_STRUCTURE_TYPE = "/api/data_structure_types/:id";
33
33
  const API_STRUCTURE_TYPES = "/api/data_structure_types";
34
+ const API_STRUCTURES_DOMAINS_UPLOAD =
35
+ "/api/data_structures/bulk_upload_domains";
34
36
  const API_STRUCTURES_TAG = "/api/data_structures/:data_structure_id/tags/:id";
35
37
  const API_STRUCTURES_TAGS = "/api/data_structures/:data_structure_id/tags";
36
38
  const API_USER_SEARCH_FILTERS = "/api/user_search_filters";
@@ -79,6 +81,7 @@ export {
79
81
  API_USER_SEARCH_FILTERS,
80
82
  API_USER_SEARCH_FILTER,
81
83
  API_GET_USER_SEARCH_FILTERS,
84
+ API_STRUCTURES_DOMAINS_UPLOAD,
82
85
  API_STRUCTURES_TAG,
83
86
  API_STRUCTURES_TAGS,
84
87
  API_STRUCTURES_UPLOAD,
@@ -2,13 +2,15 @@ import React from "react";
2
2
  import { Route, Switch } from "react-router-dom";
3
3
  import { useActiveRoute } from "@truedat/core/hooks";
4
4
  import {
5
+ PENDING_STRUCTURE_NOTES,
5
6
  PROFILE_EXECUTION,
6
7
  PROFILE_GROUP,
7
- STRUCTURES,
8
8
  STRUCTURE_TAGS,
9
9
  STRUCTURE_TYPES,
10
+ STRUCTURES,
10
11
  SYSTEMS,
11
12
  } from "@truedat/core/routes";
13
+ import PendingStructureNotes from "./PendingStructureNotes";
12
14
  import ProfileExecution from "./ProfileExecution";
13
15
  import ProfileExecutionBreadcrumbs from "./ProfileExecutionBreadcrumbs";
14
16
  import ProfileExecutionLoader from "./ProfileExecutionLoader";
@@ -27,6 +29,10 @@ const TemplatesLoader = React.lazy(() =>
27
29
  import("@truedat/df/templates/components/TemplatesLoader")
28
30
  );
29
31
 
32
+ const DomainsLoader = React.lazy(() =>
33
+ import("@truedat/bg/taxonomy/components/DomainsLoader")
34
+ );
35
+
30
36
  const Loaders = () => (
31
37
  <>
32
38
  <StructuresLoader />
@@ -82,6 +88,16 @@ export const DictionaryRoutes = () => {
82
88
  </>
83
89
  )}
84
90
  />
91
+ <Route
92
+ path={PENDING_STRUCTURE_NOTES}
93
+ render={() => (
94
+ <>
95
+ <SystemsLoader />
96
+ <DomainsLoader />
97
+ <PendingStructureNotes />
98
+ </>
99
+ )}
100
+ />
85
101
  <Route
86
102
  path={PROFILE_GROUP}
87
103
  render={() => (
@@ -0,0 +1,45 @@
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 { useIntl } from "react-intl";
6
+ import { useHistory } from "react-router-dom";
7
+ import { linkTo } from "@truedat/core/routes";
8
+
9
+ const PendingStructureNoteRow = ({ structureNote }) => {
10
+ const { formatMessage } = useIntl();
11
+ const history = useHistory();
12
+ const dataStructure = _.prop("data_structure")(structureNote);
13
+ const path = _.propOr(
14
+ [],
15
+ "data_structure.current_version.path"
16
+ )(structureNote);
17
+ const name = _.prop("data_structure.current_version.name")(structureNote);
18
+ const system = _.prop("data_structure.system.name")(structureNote);
19
+ const domainsNames = _.flow(
20
+ _.prop("data_structure.domains"),
21
+ _.map("name")
22
+ )(structureNote);
23
+
24
+ return (
25
+ <Table.Row
26
+ onClick={() => history.push(linkTo.STRUCTURE_NOTES(dataStructure))}
27
+ >
28
+ <Table.Cell content={name} />
29
+ <Table.Cell
30
+ content={formatMessage({
31
+ id: `structure.notes.status.${structureNote.status}`,
32
+ })}
33
+ />
34
+ <Table.Cell content={system} />
35
+ <Table.Cell content={domainsNames.join(", ")} />
36
+ <Table.Cell content={path.join(" > ")} />
37
+ </Table.Row>
38
+ );
39
+ };
40
+
41
+ PendingStructureNoteRow.propTypes = {
42
+ structureNote: PropTypes.object,
43
+ };
44
+
45
+ export default PendingStructureNoteRow;
@@ -0,0 +1,149 @@
1
+ import _ from "lodash/fp";
2
+ import React, { useState } from "react";
3
+ import { useSelector } from "react-redux";
4
+ import { FormattedMessage, useIntl } from "react-intl";
5
+ import { gql, useQuery } from "@apollo/client";
6
+ import { Checkbox, Form, Header, Icon, Segment } from "semantic-ui-react";
7
+ import { useForm, Controller } from "react-hook-form";
8
+ import PendingStructureNotesTable from "./PendingStructureNotesTable";
9
+
10
+ const DomainDropdownSelector = React.lazy(() =>
11
+ import("@truedat/bg/taxonomy/components/DomainDropdownSelector")
12
+ );
13
+
14
+ export const STRUCTURE_NOTES = gql`
15
+ query STRUCTURE_NOTES($filter: StructureNotesFilter) {
16
+ structure_notes(filter: $filter) {
17
+ id
18
+ status
19
+ data_structure {
20
+ id
21
+ current_version {
22
+ id
23
+ name
24
+ path
25
+ version
26
+ }
27
+ system {
28
+ name
29
+ }
30
+ domains {
31
+ name
32
+ }
33
+ }
34
+ }
35
+ }
36
+ `;
37
+
38
+ const STATUS = ["pending_approval", "draft", "rejected"];
39
+
40
+ export const PendingStructureNotes = () => {
41
+ const { formatMessage } = useIntl();
42
+ const { systems } = useSelector(_.pick(["systems"]));
43
+ const [filter, setFilter] = useState({
44
+ statuses: STATUS,
45
+ });
46
+ const { loading, error, data } = useQuery(STRUCTURE_NOTES, {
47
+ variables: { filter },
48
+ fetchPolicy: "network-only",
49
+ });
50
+ const items = loading || error ? [] : data?.structure_notes;
51
+ const { control } = useForm({
52
+ mode: "all",
53
+ defaultValues: {
54
+ status: STATUS,
55
+ },
56
+ });
57
+
58
+ return (
59
+ <Segment>
60
+ <Header as="h2">
61
+ <Icon name="sticky note outline" circular />
62
+ <Header.Content>
63
+ <FormattedMessage id="pendingStructureNotes.header" />
64
+ <Header.Subheader>
65
+ <FormattedMessage id="pendingStructureNotes.subheader" />
66
+ </Header.Subheader>
67
+ </Header.Content>
68
+ </Header>
69
+ <Form>
70
+ <Header
71
+ as="h5"
72
+ content={formatMessage({ id: "pendingStructureNotes.filters" })}
73
+ />
74
+ <Controller
75
+ control={control}
76
+ name="status"
77
+ render={({ onBlur, onChange, value }) => (
78
+ <Form.Field className="subscriptions-checkbox-filters">
79
+ <label>
80
+ {formatMessage({ id: "pendingStructureNotes.props.status" })}
81
+ </label>
82
+ {STATUS.map((type, idx) => (
83
+ <Checkbox
84
+ onBlur={onBlur}
85
+ key={idx}
86
+ label={
87
+ <label>
88
+ {formatMessage({ id: `structure.notes.status.${type}` })}
89
+ </label>
90
+ }
91
+ onChange={() => {
92
+ const statuses = _.includes(type)(value)
93
+ ? _.filter((t) => t !== type)(value)
94
+ : [...value, type];
95
+ setFilter({ ...filter, statuses });
96
+ onChange(statuses);
97
+ }}
98
+ checked={_.includes(type)(value)}
99
+ />
100
+ ))}
101
+ </Form.Field>
102
+ )}
103
+ />
104
+ <Controller
105
+ control={control}
106
+ name="system_ids"
107
+ render={({ onBlur, onChange, value }) => (
108
+ <Form.Dropdown
109
+ label={formatMessage({
110
+ id: "pendingStructureNotes.props.system",
111
+ })}
112
+ onBlur={onBlur}
113
+ onChange={(e, { value }) => {
114
+ setFilter({ ...filter, system_ids: value });
115
+ onChange(value);
116
+ }}
117
+ options={systems.map(({ name, id }) => ({
118
+ text: name,
119
+ key: id,
120
+ value: id,
121
+ }))}
122
+ selection
123
+ clearable
124
+ multiple
125
+ value={value || []}
126
+ />
127
+ )}
128
+ />
129
+ <Controller
130
+ control={control}
131
+ name="domain_ids"
132
+ render={({ onChange, value }) => (
133
+ <DomainDropdownSelector
134
+ value={value}
135
+ onChange={(_e, { value }) => {
136
+ const domain_ids = _.isNumber(value) ? [value] : [];
137
+ setFilter({ ...filter, domain_ids });
138
+ onChange(value);
139
+ }}
140
+ />
141
+ )}
142
+ />
143
+ </Form>
144
+ <PendingStructureNotesTable structureNotes={items} loading={loading} />
145
+ </Segment>
146
+ );
147
+ };
148
+
149
+ export default PendingStructureNotes;
@@ -0,0 +1,73 @@
1
+ import _ from "lodash/fp";
2
+ import React from "react";
3
+ import PropTypes from "prop-types";
4
+ import { FormattedMessage } from "react-intl";
5
+ import { Table, Header, Icon } from "semantic-ui-react";
6
+ import PendingStructureNoteRow from "./PendingStructureNoteRow";
7
+
8
+ const PendingStructureNotesTable = ({ structureNotes, loading }) => {
9
+ return (
10
+ <>
11
+ {!_.isEmpty(structureNotes) && (
12
+ <Table selectable>
13
+ <Table.Header>
14
+ <Table.Row>
15
+ <Table.HeaderCell
16
+ content={
17
+ <FormattedMessage
18
+ id={"pendingStructureNotes.props.structure"}
19
+ />
20
+ }
21
+ />
22
+ <Table.HeaderCell
23
+ content={
24
+ <FormattedMessage id={"pendingStructureNotes.props.status"} />
25
+ }
26
+ />
27
+ <Table.HeaderCell
28
+ content={
29
+ <FormattedMessage id={"pendingStructureNotes.props.system"} />
30
+ }
31
+ />
32
+ <Table.HeaderCell
33
+ content={
34
+ <FormattedMessage
35
+ id={"pendingStructureNotes.props.domains"}
36
+ />
37
+ }
38
+ />
39
+ <Table.HeaderCell
40
+ content={
41
+ <FormattedMessage id={"pendingStructureNotes.props.path"} />
42
+ }
43
+ />
44
+ </Table.Row>
45
+ </Table.Header>
46
+ <Table.Body>
47
+ {structureNotes.map((structureNote, key) => (
48
+ <PendingStructureNoteRow
49
+ key={key}
50
+ structureNote={structureNote}
51
+ />
52
+ ))}
53
+ </Table.Body>
54
+ </Table>
55
+ )}
56
+ {_.isEmpty(structureNotes) && !loading && (
57
+ <Header as="h4">
58
+ <Icon name="search" />
59
+ <Header.Content>
60
+ <FormattedMessage id="pendingStructureNotes.search.results.empty" />
61
+ </Header.Content>
62
+ </Header>
63
+ )}
64
+ </>
65
+ );
66
+ };
67
+
68
+ PendingStructureNotesTable.propTypes = {
69
+ structureNotes: PropTypes.array,
70
+ loading: PropTypes.bool,
71
+ };
72
+
73
+ export default PendingStructureNotesTable;
@@ -0,0 +1,52 @@
1
+ import React from "react";
2
+ import PropTypes from "prop-types";
3
+ import { connect } from "react-redux";
4
+ import { Dropdown } from "semantic-ui-react";
5
+ import { useIntl } from "react-intl";
6
+ import { UploadModal } from "@truedat/core/components";
7
+ import { uploadStructuresDomains } from "../routines";
8
+
9
+ export const StructuresDomainsUploadOption = ({
10
+ uploadStructuresDomains,
11
+ loading,
12
+ }) => {
13
+ const { formatMessage } = useIntl();
14
+
15
+ return (
16
+ <UploadModal
17
+ icon="upload"
18
+ trigger={
19
+ <Dropdown.Item
20
+ icon="upload"
21
+ text={formatMessage({ id: "structures.actions.uploadDomains.tooltip" })}
22
+ disabled={loading}
23
+ />
24
+ }
25
+ header={formatMessage({
26
+ id: "structures.actions.uploadDomains.confirmation.header",
27
+ })}
28
+ content={formatMessage({
29
+ id: "structures.actions.uploadDomains.confirmation.content",
30
+ })}
31
+ param={"structures_domains"}
32
+ handleSubmit={(data) =>
33
+ uploadStructuresDomains({
34
+ data,
35
+ })
36
+ }
37
+ />
38
+ );
39
+ };
40
+
41
+ StructuresDomainsUploadOption.propTypes = {
42
+ uploadStructuresDomains: PropTypes.func,
43
+ loading: PropTypes.bool,
44
+ };
45
+
46
+ const mapStateToProps = ({ uploadingStructuresDomainsFile }) => ({
47
+ loading: uploadingStructuresDomainsFile,
48
+ });
49
+
50
+ export default connect(mapStateToProps, { uploadStructuresDomains })(
51
+ StructuresDomainsUploadOption
52
+ );
@@ -6,10 +6,12 @@ import StructuresDownloadOption from "./StructuresDownloadOption";
6
6
  import StructuresEditableDownloadOption from "./StructuresEditableDownloadOption";
7
7
  import StructuresUpdateOption from "./StructuresUpdateOption";
8
8
  import StructuresUploadOption from "./StructuresUploadOption";
9
+ import StructuresDomainsUploadOption from "./StructuresDomainsUploadOption";
9
10
 
10
11
  export const StructuresOptions = ({
11
12
  autoPublish,
12
13
  bulkUpload,
14
+ bulkUploadDomains,
13
15
  hasFilterApplied,
14
16
  }) => (
15
17
  <Dropdown
@@ -26,6 +28,7 @@ export const StructuresOptions = ({
26
28
  {bulkUpload ? (
27
29
  <StructuresUploadOption canAutoPublish={!!autoPublish} />
28
30
  ) : null}
31
+ {bulkUploadDomains ? <StructuresDomainsUploadOption /> : null}
29
32
  <Dropdown.Divider />
30
33
  <StructuresUpdateOption />
31
34
  </Dropdown.Menu>
@@ -35,6 +38,7 @@ export const StructuresOptions = ({
35
38
  StructuresOptions.propTypes = {
36
39
  autoPublish: PropTypes.object,
37
40
  bulkUpload: PropTypes.object,
41
+ bulkUploadDomains: PropTypes.object,
38
42
  hasFilterApplied: PropTypes.bool,
39
43
  };
40
44
 
@@ -0,0 +1,48 @@
1
+ import React from "react";
2
+ import { waitFor } from "@testing-library/react";
3
+ import { render } from "@truedat/test/render";
4
+ import PendingStructureNoteRow from "../PendingStructureNoteRow";
5
+
6
+ const renderOpts = {
7
+ messages: {
8
+ en: {
9
+ "pendingStructureNotes.search.results.empty": "Empty",
10
+ "pendingStructureNotes.props.structure": "Structure",
11
+ "pendingStructureNotes.props.status": "Status",
12
+ "pendingStructureNotes.props.system": "System",
13
+ "pendingStructureNotes.props.domains": "Domains",
14
+ "structure.notes.status.deprecated": "Deprecated",
15
+ "structure.notes.status.draft": "Draft",
16
+ "structure.notes.status.rejected": "Rejected",
17
+ },
18
+ },
19
+ };
20
+
21
+ const props = {
22
+ structureNote: {
23
+ id: "7207",
24
+ status: "draft",
25
+ data_structure: {
26
+ current_version: {
27
+ name: "bar",
28
+ path: ["bar rute"],
29
+ },
30
+ domains: [{ name: "bar domain" }],
31
+ system: { name: "bar system" },
32
+ },
33
+ },
34
+ };
35
+
36
+ describe("<PendingStructureNoteRow />", () => {
37
+ it("matches the latest snapshot", async () => {
38
+ const { container, queryByText } = render(
39
+ <PendingStructureNoteRow {...props} />,
40
+ renderOpts
41
+ );
42
+ expect(container).toMatchSnapshot();
43
+
44
+ await waitFor(() => {
45
+ expect(queryByText(/bar system/)).toBeTruthy();
46
+ });
47
+ });
48
+ });
@@ -0,0 +1,102 @@
1
+ import React, { Suspense } from "react";
2
+ import { waitFor } from "@testing-library/react";
3
+ import { render } from "@truedat/test/render";
4
+ import {
5
+ PendingStructureNotes,
6
+ STRUCTURE_NOTES,
7
+ } from "../PendingStructureNotes";
8
+
9
+ jest.mock("react-redux", () => ({
10
+ ...jest.requireActual("react-redux"),
11
+ useSelector: jest.fn((selector) =>
12
+ selector({
13
+ systems: [
14
+ { external_id: "some_external_id", id: 10, name: "some system" },
15
+ ],
16
+ })
17
+ ),
18
+ }));
19
+
20
+ const domains = [
21
+ { id: 1, name: "Domain 1", level: 0 },
22
+ { id: 2, name: "Domain 2", level: 0 },
23
+ ];
24
+
25
+ const messages = {
26
+ en: {
27
+ "structure.notes.status.pending_approval": "Empty",
28
+ "pendingStructureNotes.filters": "Filters",
29
+ "pendingStructureNotes.props.status": "Status",
30
+ "pendingStructureNotes.props.system": "System",
31
+ "pendingStructureNotes.props.domains": "Domains",
32
+ "structure.notes.status.draft": "Draft",
33
+ "structure.notes.status.rejected": "Rejected",
34
+ "pendingStructureNotes.header": "Header",
35
+ "pendingStructureNotes.subheader": "Sub header",
36
+ "pendingStructureNotes.search.results.empty": "Serch Empty",
37
+ "domain.selector.placeholder": "Place Holder",
38
+ "domain.selector.label": "label",
39
+ "template.form.validation.empty_required": "empty required",
40
+ },
41
+ };
42
+
43
+ const structureNotes = {
44
+ loading: false,
45
+ structureNotes: [
46
+ {
47
+ id: "7207",
48
+ status: "draft",
49
+ data_structure: {
50
+ current_version: {
51
+ name: "bar",
52
+ path: ["bar rute"],
53
+ },
54
+ domains: [{ name: "bar domain" }],
55
+ system: { name: "bar system" },
56
+ },
57
+ },
58
+ {
59
+ id: "665214",
60
+ status: "rejected",
61
+ data_structure: {
62
+ current_version: {
63
+ name: "foo",
64
+ path: ["foo rute", "other route"],
65
+ },
66
+ domains: [{ name: "foo domain 1" }, { name: "foo domain 2" }],
67
+ system: { name: "foo system" },
68
+ },
69
+ },
70
+ ],
71
+ };
72
+
73
+ const StructureNotesMock = {
74
+ request: { query: STRUCTURE_NOTES },
75
+ result: { data: { structureNotes } },
76
+ };
77
+
78
+ const renderOpts = {
79
+ mocks: [StructureNotesMock],
80
+ messages,
81
+ state: { domains },
82
+ };
83
+
84
+ describe("<PendingStructureNotes />", () => {
85
+ it("matches the latest snapshot", async () => {
86
+ const { container, queryByText } = render(
87
+ <Suspense fallback={null}>
88
+ <PendingStructureNotes />
89
+ </Suspense>,
90
+ renderOpts
91
+ );
92
+ expect(container).toMatchSnapshot();
93
+
94
+ await waitFor(() => {
95
+ expect(queryByText(/some system/)).toBeTruthy();
96
+ });
97
+
98
+ await waitFor(() => {
99
+ expect(queryByText(/Domain 1/)).toBeTruthy();
100
+ });
101
+ });
102
+ });