@truedat/dd 4.47.4 → 4.47.7

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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.47.7] 2022-07-02
4
+
5
+ ## Added
6
+
7
+ - [TD-4176] Added description in structure tag
8
+
9
+ ## Changed
10
+
11
+ - [TD-4176]
12
+ - Changed description by comment in structure tag link
13
+ - Commend now is not mandatory field
14
+
15
+ ## [4.47.5] 2022-06-30
16
+
17
+ ### Added
18
+
19
+ - [TD-4894] Multiple column operator in implementation creation
20
+
3
21
  ## [4.47.0] 2022-06-22
4
22
 
5
23
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dd",
3
- "version": "4.47.4",
3
+ "version": "4.47.7",
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.16.4",
35
35
  "@testing-library/react": "^12.0.0",
36
36
  "@testing-library/user-event": "^13.2.1",
37
- "@truedat/test": "4.47.4",
37
+ "@truedat/test": "4.47.7",
38
38
  "babel-jest": "^28.1.0",
39
39
  "babel-plugin-dynamic-import-node": "^2.3.3",
40
40
  "babel-plugin-lodash": "^3.3.4",
@@ -88,9 +88,9 @@
88
88
  },
89
89
  "dependencies": {
90
90
  "@apollo/client": "^3.6.4",
91
- "@truedat/auth": "4.47.4",
92
- "@truedat/core": "4.47.4",
93
- "@truedat/df": "4.47.4",
91
+ "@truedat/auth": "4.47.7",
92
+ "@truedat/core": "4.47.7",
93
+ "@truedat/df": "4.47.7",
94
94
  "lodash": "^4.17.21",
95
95
  "path-to-regexp": "^1.7.0",
96
96
  "prop-types": "^15.8.1",
@@ -112,5 +112,5 @@
112
112
  "react-dom": ">= 16.8.6 < 17",
113
113
  "semantic-ui-react": ">= 0.88.2 < 2.1"
114
114
  },
115
- "gitHead": "9d38ae9759ce669fe1b459a3ee80c314d33871e0"
115
+ "gitHead": "5e85149774b055fd61014633988cdf6aa9b9da4f"
116
116
  }
@@ -4,6 +4,7 @@ export const STRUCTURE_TAG_DETAIL = gql`
4
4
  fragment StructureTagDetail on StructureTag {
5
5
  id
6
6
  name
7
+ description
7
8
  domainIds
8
9
  structureCount
9
10
  }
@@ -10,7 +10,7 @@ import { deleteLinkStructureTag, linkStructureTag } from "../routines";
10
10
 
11
11
  export const LinkStructureTagForm = ({
12
12
  deleteLinkStructureTag,
13
- description,
13
+ comment,
14
14
  linkedStructureTags,
15
15
  linkId,
16
16
  linkStructureTag,
@@ -29,7 +29,11 @@ export const LinkStructureTagForm = ({
29
29
  const options = _.flow(
30
30
  _.filter(({ id }) => _.includes(id)(availableTags)),
31
31
  _.sortBy(accentInsensitivePathOrder("name")),
32
- _.map(({ id, name }) => ({ value: id, text: name }))
32
+ _.map(({ id, name, description }) => ({
33
+ value: id,
34
+ text: name,
35
+ description: description,
36
+ }))
33
37
  )(structureTags);
34
38
  const defaultTag = _.negate(_.isNil)(tagId)
35
39
  ? tagId
@@ -43,7 +47,7 @@ export const LinkStructureTagForm = ({
43
47
  const payload = {
44
48
  structureId,
45
49
  tagId: params.tag,
46
- tag: { description: params.description },
50
+ tag: { comment: params.comment },
47
51
  };
48
52
  linkStructureTag(payload);
49
53
  };
@@ -51,7 +55,7 @@ export const LinkStructureTagForm = ({
51
55
  const { handleSubmit, control, formState } = useForm({
52
56
  mode: "all",
53
57
  defaultValues: {
54
- description: description || "",
58
+ comment: comment || "",
55
59
  tag: defaultTag,
56
60
  },
57
61
  });
@@ -87,16 +91,15 @@ export const LinkStructureTagForm = ({
87
91
  />
88
92
  <Controller
89
93
  control={control}
90
- name="description"
91
- rules={{ required: true }}
94
+ name="comment"
92
95
  render={({
93
96
  field: { onBlur, onChange, value },
94
97
  fieldState: { error },
95
98
  }) => (
96
99
  <Form.TextArea
97
- data-testid="description-id"
100
+ data-testid="comment-id"
98
101
  error={!!error}
99
- name="description"
102
+ name="comment"
100
103
  label={formatMessage({ id: "structure.tag.textArea.label" })}
101
104
  placeholder={formatMessage({
102
105
  id: "structure.tag.textArea.placeholder",
@@ -110,7 +113,7 @@ export const LinkStructureTagForm = ({
110
113
  <div className="actions">
111
114
  <Button
112
115
  type="submit"
113
- disabled={!isDirty || !isValid}
116
+ disabled={(!isDirty && options.length > 1) || !isValid}
114
117
  primary
115
118
  content={formatMessage({ id: submitTitle })}
116
119
  />
@@ -130,7 +133,7 @@ export const LinkStructureTagForm = ({
130
133
 
131
134
  LinkStructureTagForm.propTypes = {
132
135
  deleteLinkStructureTag: PropTypes.func,
133
- description: PropTypes.string,
136
+ comment: PropTypes.string,
134
137
  linkedStructureTags: PropTypes.array,
135
138
  linkId: PropTypes.number,
136
139
  linkStructureTag: PropTypes.func,
@@ -1,19 +1,22 @@
1
1
  import _ from "lodash/fp";
2
2
  import React, { useEffect, useState } from "react";
3
3
  import PropTypes from "prop-types";
4
- import { Icon, Label, Popup } from "semantic-ui-react";
4
+ import { useIntl } from "react-intl";
5
+ import { Icon, Label, Popup, Header } from "semantic-ui-react";
5
6
  import { connect } from "react-redux";
6
7
  import LinkStructureTagForm from "./LinkStructureTagForm";
7
8
 
8
- const LinkedStructureTag = ({
9
+ export const LinkedStructureTag = ({
9
10
  id,
10
11
  _embedded,
11
12
  editable,
12
- description,
13
+ comment,
13
14
  loading,
14
15
  structureTags,
15
16
  }) => {
17
+ const { formatMessage } = useIntl();
16
18
  const name = _embedded.data_structure_tag.name;
19
+ const description = _embedded.data_structure_tag.description;
17
20
  const tagId = _embedded.data_structure_tag.id;
18
21
  const [openDescription, setOpenDescription] = useState(false);
19
22
  const [openForm, setOpenForm] = useState(false);
@@ -24,16 +27,46 @@ const LinkedStructureTag = ({
24
27
 
25
28
  const trigger = editable ? <Icon link name="edit" /> : null;
26
29
 
30
+ const renderTooltip = () => {
31
+ const descriptionTooltip = _.isEmpty(description) ? null : (
32
+ <Header as="h2" subheader={description} />
33
+ );
34
+
35
+ const commentTooltip = _.isEmpty(comment) ? null : (
36
+ <>
37
+ <Header
38
+ as="h5"
39
+ content={formatMessage({ id: "structure.tag.tooltip.commentTitle" })}
40
+ />
41
+ <p>{comment}</p>
42
+ </>
43
+ );
44
+
45
+ return (
46
+ <>
47
+ {descriptionTooltip}
48
+ {commentTooltip}
49
+ </>
50
+ );
51
+ };
52
+
27
53
  return (
28
54
  <Popup
29
55
  basic
30
- content={description}
31
56
  open={openDescription}
32
57
  onOpen={() => {
33
- if (!openForm) setOpenDescription(true);
58
+ const commentCondition = !_.isEmpty(comment);
59
+ const descriptionCondition = !_.isEmpty(description);
60
+ const openFormCondition = !openForm;
61
+
62
+ const openTooltipCondition =
63
+ (commentCondition || descriptionCondition) && openFormCondition;
64
+
65
+ if (openTooltipCondition) setOpenDescription(true);
34
66
  }}
35
67
  onClose={() => setOpenDescription(false)}
36
68
  positionFixed
69
+ className="popup-tag"
37
70
  trigger={
38
71
  <Label tag style={{ marginLeft: "1.5em" }}>
39
72
  {_.isEmpty(structureTags) ? null : (
@@ -49,7 +82,7 @@ const LinkedStructureTag = ({
49
82
  flowing
50
83
  content={
51
84
  <LinkStructureTagForm
52
- description={description}
85
+ comment={comment}
53
86
  linkId={id}
54
87
  tagId={tagId}
55
88
  />
@@ -64,13 +97,15 @@ const LinkedStructureTag = ({
64
97
  {name}
65
98
  </Label>
66
99
  }
67
- />
100
+ >
101
+ {renderTooltip()}
102
+ </Popup>
68
103
  );
69
104
  };
70
105
 
71
106
  LinkedStructureTag.propTypes = {
72
107
  _embedded: PropTypes.object,
73
- description: PropTypes.string,
108
+ comment: PropTypes.string,
74
109
  editable: PropTypes.bool,
75
110
  id: PropTypes.number,
76
111
  loading: PropTypes.bool,
@@ -11,23 +11,37 @@ export const StructureFieldsDropdown = ({
11
11
  fluid,
12
12
  inline,
13
13
  onSelectField,
14
+ onSelectFields,
14
15
  structureFields,
15
16
  filters,
16
17
  value,
17
18
  typeCastModifiers,
19
+ multiple,
18
20
  }) => {
19
21
  const { formatMessage } = useIntl();
20
22
  const onClick = ({ value, modifier }) => {
23
+ onSelectField(dropdownItemToField(value), modifier);
24
+ };
25
+
26
+ const onChangeStructureFieldsDropdown = (valueOrValues) => {
27
+ return _.flow(
28
+ _.map((value) => {
29
+ return dropdownItemToField(value);
30
+ }),
31
+ multiple ? onSelectFields : onSelectField
32
+ )(Array.isArray(valueOrValues) ? valueOrValues : [valueOrValues]);
33
+ };
34
+
35
+ const dropdownItemToField = (value) => {
21
36
  const [data_structure_id, parent_index] = _.isString(value)
22
37
  ? value.split("/").map(Number)
23
38
  : [value, undefined];
24
- const field = _.isNil(parent_index)
39
+ return _.isNil(parent_index)
25
40
  ? _.find({ data_structure_id: data_structure_id })(structureFields)
26
41
  : _.find({
27
42
  data_structure_id: data_structure_id,
28
43
  parent_index: parent_index,
29
44
  })(structureFields);
30
- onSelectField(field, modifier);
31
45
  };
32
46
 
33
47
  const formatOption = (field) => {
@@ -100,11 +114,13 @@ export const StructureFieldsDropdown = ({
100
114
 
101
115
  return (
102
116
  <OptionGroup
117
+ multiple={multiple}
103
118
  fluid={fluid}
104
119
  inline={inline}
105
120
  label={label}
106
121
  value={value}
107
122
  onClick={onClick}
123
+ onChange={onChangeStructureFieldsDropdown}
108
124
  placeholder={formatMessage({
109
125
  id: "structureFields.dropdown.placeholder",
110
126
  })}
@@ -117,11 +133,14 @@ StructureFieldsDropdown.propTypes = {
117
133
  label: PropTypes.string,
118
134
  fluid: PropTypes.bool,
119
135
  inline: PropTypes.bool,
120
- value: PropTypes.number,
136
+ // value string format: <data_structure_id>/<parent_index>
137
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
121
138
  structureFields: PropTypes.array,
122
139
  onSelectField: PropTypes.func,
140
+ onSelectFields: PropTypes.func,
123
141
  filters: PropTypes.object,
124
142
  typeCastModifiers: PropTypes.array,
143
+ multiple: PropTypes.bool,
125
144
  };
126
145
 
127
146
  const mapStateToProps = (state, props) => ({
@@ -16,7 +16,7 @@ export const StructureTagForm = ({
16
16
  const { formatMessage } = useIntl();
17
17
  const { handleSubmit, control, formState } = useForm({
18
18
  mode: "all",
19
- defaultValues: _.pick(["name", "domainIds"])(structureTag),
19
+ defaultValues: _.pick(["name", "description", "domainIds"])(structureTag),
20
20
  });
21
21
 
22
22
  const { isDirty, isValid } = formState;
@@ -46,6 +46,28 @@ export const StructureTagForm = ({
46
46
  />
47
47
  )}
48
48
  />
49
+ <Controller
50
+ control={control}
51
+ name="description"
52
+ rules={{ required: false }}
53
+ render={({
54
+ field: { onBlur, onChange, value },
55
+ fieldState: { error },
56
+ }) => (
57
+ <Form.Input
58
+ autoComplete="off"
59
+ error={error}
60
+ id="description"
61
+ label={formatMessage({ id: "structureTagForm.props.description" })}
62
+ onBlur={onBlur}
63
+ onChange={(_e, { value }) => onChange(value)}
64
+ placeholder={formatMessage({
65
+ id: "structureTagForm.props.description",
66
+ })}
67
+ value={value}
68
+ />
69
+ )}
70
+ />
49
71
  <Controller
50
72
  control={control}
51
73
  name="domainIds"
@@ -36,6 +36,9 @@ export const StructureTagsCards = ({ deleteStructureTag, structureTags }) => {
36
36
  >
37
37
  {_.prop("name")(structureTag)}
38
38
  </Card.Header>
39
+ <Card.Description>
40
+ {_.prop("description")(structureTag)}
41
+ </Card.Description>
39
42
  </Card.Content>
40
43
  <Card.Content extra>
41
44
  <div className="ui actions">
@@ -11,26 +11,27 @@ jest.spyOn(React, "useContext").mockImplementation(() => intl);
11
11
  describe("<LinkStructureTagForm />", () => {
12
12
  const deleteLinkStructureTag = jest.fn();
13
13
  const linkStructureTag = jest.fn();
14
- const description = "foo";
14
+ const structureTags = [
15
+ { id: 1, name: "Tag1", description: "description test" },
16
+ { id: 2, name: "Tag2", description: "large desc".repeat(5) },
17
+ { id: 3, name: "Tag without description" },
18
+ ];
15
19
  const linkedStructureTags = [
16
20
  {
17
21
  id: 1,
18
- description: "foo",
22
+ comment: "foo",
19
23
  inserted_at: "foo",
20
24
  updated_at: "foo",
21
25
  _embedded: {
22
26
  data_structure: { id: 1, external_id: "baz" },
23
- data_structure_tag: { id: 1, name: "bar" }
24
- }
25
- }
26
- ];
27
- const structureTags = [
28
- { id: 1, name: "foo" },
29
- { id: 2, name: "bar" }
27
+ data_structure_tag: { ...structureTags[2] },
28
+ },
29
+ },
30
30
  ];
31
31
 
32
+ const comment = "foo";
32
33
  const structureId = 1;
33
- const tagId = 1;
34
+ const tagId = 3;
34
35
  const linkId = 1;
35
36
 
36
37
  const propsCreate = {
@@ -38,18 +39,18 @@ describe("<LinkStructureTagForm />", () => {
38
39
  linkedStructureTags,
39
40
  linkStructureTag,
40
41
  structureId,
41
- structureTags
42
+ structureTags,
42
43
  };
43
44
 
44
45
  const propsUpdate = {
45
46
  deleteLinkStructureTag,
46
- description,
47
+ comment,
47
48
  linkedStructureTags,
48
49
  linkId,
49
50
  linkStructureTag,
50
51
  structureId,
51
52
  structureTags,
52
- tagId
53
+ tagId,
53
54
  };
54
55
 
55
56
  it("matches the latest snapshot create", async () => {
@@ -69,6 +70,64 @@ describe("<LinkStructureTagForm />", () => {
69
70
  expect(container).toMatchSnapshot();
70
71
  });
71
72
 
73
+ it("matches the latest snapshot create without comment", async () => {
74
+ const linkedStructureTagWithoutComment = {
75
+ ...linkedStructureTags[0],
76
+ };
77
+ delete linkedStructureTagWithoutComment.comment;
78
+
79
+ const propsCreateWithoutComment = {
80
+ ...propsCreate,
81
+ linkedStructureTags: [linkedStructureTagWithoutComment],
82
+ };
83
+
84
+ const { container, getByRole, findByText } = render(
85
+ <LinkStructureTagForm {...propsCreateWithoutComment} />
86
+ );
87
+
88
+ // Select tag
89
+ userEvent.click(await findByText("Tag2"));
90
+
91
+ await waitFor(() =>
92
+ expect(getByRole("button", { name: /add/ })).not.toBeDisabled()
93
+ );
94
+ expect(container).toMatchSnapshot();
95
+ });
96
+
97
+ it("create button enabled if there is only one tag available", async () => {
98
+ const propsCreateWithOneStrutureTagAvailable = {
99
+ ...propsCreate,
100
+ structureTags: [structureTags[1], structureTags[2]],
101
+ };
102
+
103
+ const { container, getByRole } = render(
104
+ <LinkStructureTagForm {...propsCreateWithOneStrutureTagAvailable} />
105
+ );
106
+ await waitFor(() =>
107
+ expect(getByRole("button", { name: /add/ })).not.toBeDisabled()
108
+ );
109
+ expect(container).toMatchSnapshot();
110
+ });
111
+
112
+ it("Tag dropdown show tag description", async () => {
113
+ const { getByText } = render(<LinkStructureTagForm {...propsCreate} />);
114
+ await waitFor(() =>
115
+ expect(getByText("description test")).toBeInTheDocument()
116
+ );
117
+ });
118
+
119
+ it("Tag dropdown with tag with large description show ellipsis", async () => {
120
+ const { getByText } = render(<LinkStructureTagForm {...propsCreate} />);
121
+
122
+ const tagElement = getByText("Tag2");
123
+
124
+ await waitFor(() => expect(tagElement).toBeInTheDocument());
125
+
126
+ const descriptionElement = tagElement.parentElement.firstElementChild;
127
+
128
+ expect(descriptionElement).toHaveClass("description");
129
+ });
130
+
72
131
  it("calls ", async () => {
73
132
  const { queryByTestId, findByRole, findByText, getByRole } = render(
74
133
  <LinkStructureTagForm {...{ ...propsCreate, linkedStructureTags: [] }} />
@@ -80,30 +139,25 @@ describe("<LinkStructureTagForm />", () => {
80
139
  );
81
140
 
82
141
  // Select tag
83
- userEvent.click(await findByText("bar"));
142
+ userEvent.click(await findByText("Tag1"));
84
143
 
85
- // Submit button should still be disabled
144
+ // Submit button should now be enabled
86
145
  await waitFor(() =>
87
- expect(getByRole("button", { name: /add/ })).toBeDisabled()
146
+ expect(getByRole("button", { name: /add/ })).not.toBeDisabled()
88
147
  );
89
148
 
90
149
  // Description
91
150
  // Issue: https://github.com/testing-library/user-event/issues/346
92
- userEvent.type(queryByTestId("description-id"), "x");
93
- userEvent.type(queryByTestId("description-id"), "yz");
94
-
95
- // Submit button should now be enabled
96
- await waitFor(() =>
97
- expect(getByRole("button", { name: /add/ })).not.toBeDisabled()
98
- );
151
+ userEvent.type(queryByTestId("comment-id"), "x");
152
+ userEvent.type(queryByTestId("comment-id"), "yz");
99
153
 
100
154
  userEvent.click(await findByRole("button", { name: /add/ }));
101
155
 
102
156
  await waitFor(() =>
103
157
  expect(linkStructureTag).toHaveBeenCalledWith({
104
158
  structureId,
105
- tagId: 2,
106
- tag: { description: "xyz" }
159
+ tagId: 1,
160
+ tag: { comment: "xyz" },
107
161
  })
108
162
  );
109
163
  });
@@ -123,7 +177,7 @@ describe("<LinkStructureTagForm />", () => {
123
177
  await waitFor(() =>
124
178
  expect(deleteLinkStructureTag).toHaveBeenCalledWith({
125
179
  structureId,
126
- tagId
180
+ tagId,
127
181
  })
128
182
  );
129
183
  });
@@ -0,0 +1,133 @@
1
+ import React from "react";
2
+ import { render } from "@truedat/test/render";
3
+ import { waitFor, fireEvent } from "@testing-library/react";
4
+ import { LinkedStructureTag } from "../LinkedStructureTag";
5
+
6
+ describe("<LinkedStructureTag />", () => {
7
+ const structureTags = [
8
+ { id: 1, name: "Tag1", description: "description test" },
9
+ { id: 2, name: "Tag2", description: "large desc".repeat(5) },
10
+ { id: 3, name: "Tag without description" },
11
+ ];
12
+
13
+ const props = {
14
+ id: 1,
15
+ _embedded: {
16
+ data_structure: { id: 1, external_id: "baz" },
17
+ data_structure_tag: { ...structureTags[2] },
18
+ },
19
+ editable: true,
20
+ comment: "foo comment",
21
+ loading: false,
22
+ structureTags,
23
+ };
24
+
25
+ const state = {
26
+ editableStructureTags: structureTags,
27
+ linkingStructureTags: false,
28
+ deletingStructureTags: false,
29
+ };
30
+
31
+ const renderOpts = {
32
+ state,
33
+ };
34
+
35
+ it("matches the latest snapshot", () => {
36
+ const { container } = render(<LinkedStructureTag {...props} />, renderOpts);
37
+ expect(container).toMatchSnapshot();
38
+ });
39
+
40
+ it("Show update modal when click in tad edit icon", async () => {
41
+ const { getByText, container } = render(
42
+ <LinkedStructureTag {...props} />,
43
+ renderOpts
44
+ );
45
+ fireEvent.click(container.getElementsByClassName("edit")[0]);
46
+ await waitFor(() => expect(getByText("Tag1")).toBeTruthy());
47
+ });
48
+
49
+ it("Show tooltip with description and comment", async () => {
50
+ const tagWithDescriptionProps = {
51
+ ...props,
52
+ _embedded: {
53
+ ...props._embedded,
54
+ data_structure_tag: { ...structureTags[0] },
55
+ },
56
+ };
57
+
58
+ const { getByText } = render(
59
+ <LinkedStructureTag {...tagWithDescriptionProps} />,
60
+ renderOpts
61
+ );
62
+
63
+ fireEvent.mouseEnter(getByText("Tag1"));
64
+
65
+ await waitFor(() => expect(getByText("Comment")).toBeTruthy());
66
+ await waitFor(() => expect(getByText("foo comment")).toBeTruthy());
67
+ await waitFor(() =>
68
+ expect(getByText(structureTags[0].description)).toBeTruthy()
69
+ );
70
+ });
71
+
72
+ it("Show tooltip with description", async () => {
73
+ const tagWithDescriptionWithoutCommentProps = {
74
+ ...props,
75
+ _embedded: {
76
+ ...props._embedded,
77
+ data_structure_tag: { ...structureTags[0] },
78
+ },
79
+ comment: undefined,
80
+ };
81
+
82
+ const { getByText, queryByText } = render(
83
+ <LinkedStructureTag {...tagWithDescriptionWithoutCommentProps} />,
84
+ renderOpts
85
+ );
86
+
87
+ fireEvent.mouseEnter(getByText("Tag1"));
88
+
89
+ await waitFor(() => expect(queryByText("Comment")).toBeNull());
90
+ await waitFor(() => expect(queryByText("foo comment")).toBeNull());
91
+ await waitFor(() =>
92
+ expect(getByText(structureTags[0].description)).toBeTruthy()
93
+ );
94
+ });
95
+
96
+ it("Show tooltip with comment", async () => {
97
+ const { getByText, queryByText } = render(
98
+ <LinkedStructureTag {...props} />,
99
+ renderOpts
100
+ );
101
+ fireEvent.mouseEnter(getByText("Tag without description"));
102
+
103
+ await waitFor(() => expect(getByText("Comment")).toBeTruthy());
104
+ await waitFor(() => expect(getByText("foo comment")).toBeTruthy());
105
+ await waitFor(() =>
106
+ expect(queryByText(structureTags[0].description)).toBeNull()
107
+ );
108
+ });
109
+
110
+ it("Tooltip not show without description and without comment", async () => {
111
+ const tagWithoutDescriptionWithoutComment = {
112
+ ...props,
113
+ comment: undefined,
114
+ };
115
+
116
+ const { getByText, queryByText, container } = render(
117
+ <LinkedStructureTag {...tagWithoutDescriptionWithoutComment} />,
118
+ renderOpts
119
+ );
120
+
121
+ fireEvent.mouseEnter(getByText("Tag without description"));
122
+
123
+ await waitFor(() => expect(queryByText("Comment")).toBeNull());
124
+ await waitFor(() => expect(queryByText("foo comment")).toBeNull());
125
+ await waitFor(() =>
126
+ expect(queryByText(structureTags[0].description)).toBeNull()
127
+ );
128
+
129
+ await waitFor(() =>
130
+ expect(container.getElementsByClassName("popup")).toHaveLength(0)
131
+ );
132
+ });
133
+ });
@@ -9,6 +9,9 @@ import {
9
9
  jest.mock("@truedat/core/hooks", () => ({
10
10
  useAuthorized: jest.fn(() => true),
11
11
  }));
12
+ jest
13
+ .spyOn(global.Date, "now")
14
+ .mockImplementation(() => new Date("2022-01-01T11:01:58.135Z").valueOf());
12
15
 
13
16
  const dataset = {
14
17
  __typename: "ReferenceDataset",
@@ -23,6 +23,10 @@ const datasetsMock = {
23
23
 
24
24
  const renderOpts = { mocks: [datasetsMock] };
25
25
 
26
+ jest
27
+ .spyOn(global.Date, "now")
28
+ .mockImplementation(() => new Date("2022-01-01T11:01:58.135Z").valueOf());
29
+
26
30
  describe("<ReferenceDatasets />", () => {
27
31
  it("matches the latest snapshot", async () => {
28
32
  const { container, findByText } = render(<ReferenceDatasets />, renderOpts);
@@ -2,6 +2,10 @@ import React from "react";
2
2
  import { render } from "@truedat/test/render";
3
3
  import ReferenceDatasetsTable from "../ReferenceDatasetsTable";
4
4
 
5
+ jest
6
+ .spyOn(global.Date, "now")
7
+ .mockImplementation(() => new Date("2022-01-01T11:01:58.135Z").valueOf());
8
+
5
9
  const props = {
6
10
  datasets: [
7
11
  {
@@ -19,6 +19,7 @@ describe("<StructureTagForm />", () => {
19
19
  const structureTag = {
20
20
  id: 1,
21
21
  name: "foo",
22
+ description: "bar",
22
23
  domainIds: [],
23
24
  };
24
25
  const saving = false;
@@ -45,7 +46,7 @@ describe("<StructureTagForm />", () => {
45
46
  expect(getByRole("button", { name: /save/i })).toBeDisabled()
46
47
  );
47
48
 
48
- // Description
49
+ // Name
49
50
  userEvent.type(getByRole("textbox", { name: /name/i }), "foo");
50
51
 
51
52
  // Submit button should now be enabled
@@ -53,6 +54,9 @@ describe("<StructureTagForm />", () => {
53
54
  expect(getByRole("button", { name: /save/i })).not.toBeDisabled()
54
55
  );
55
56
 
57
+ // Name
58
+ userEvent.type(getByRole("textbox", { name: /description/i }), "bar");
59
+
56
60
  // Submit
57
61
  userEvent.click(getByRole("button", { name: /save/i }));
58
62
 
@@ -61,6 +65,7 @@ describe("<StructureTagForm />", () => {
61
65
  });
62
66
  expect(onSubmit.mock.calls[0][0]).toMatchObject({
63
67
  name: "foofoo",
68
+ description: "barbar",
64
69
  domainIds: [],
65
70
  });
66
71
  });
@@ -14,6 +14,7 @@ const structureTagsMock = {
14
14
  __typename: "StructureTag",
15
15
  id: "1",
16
16
  name: "tag1",
17
+ description: "tag_desc_1",
17
18
  domainIds: [],
18
19
  structureCount: 1,
19
20
  },
@@ -21,6 +22,7 @@ const structureTagsMock = {
21
22
  __typename: "StructureTag",
22
23
  id: "2",
23
24
  name: "tag2",
25
+ description: "tag_desc_2",
24
26
  domainIds: ["1"],
25
27
  structureCount: 1,
26
28
  },
@@ -1,6 +1,6 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`<LinkStructureTagForm /> matches the latest snapshot create 1`] = `
3
+ exports[`<LinkStructureTagForm /> create button enabled if there is only one tag available 1`] = `
4
4
  <div>
5
5
  <div
6
6
  class="ui container"
@@ -36,7 +36,7 @@ exports[`<LinkStructureTagForm /> matches the latest snapshot create 1`] = `
36
36
  class="divider text"
37
37
  role="alert"
38
38
  >
39
- bar
39
+ Tag2
40
40
  </div>
41
41
  <i
42
42
  aria-hidden="true"
@@ -53,10 +53,128 @@ exports[`<LinkStructureTagForm /> matches the latest snapshot create 1`] = `
53
53
  role="option"
54
54
  style="pointer-events: all;"
55
55
  >
56
+ <span
57
+ class="description"
58
+ >
59
+ large desclarge desclarge desclarge desclarge desc
60
+ </span>
61
+ <span
62
+ class="text"
63
+ >
64
+ Tag2
65
+ </span>
66
+ </div>
67
+ </div>
68
+ </div>
69
+ </div>
70
+ <div
71
+ class="field"
72
+ >
73
+ <label>
74
+ structure.tag.textArea.label
75
+ </label>
76
+ <textarea
77
+ data-testid="comment-id"
78
+ name="comment"
79
+ placeholder="structure.tag.textArea.placeholder"
80
+ rows="3"
81
+ />
82
+ </div>
83
+ <div
84
+ class="actions"
85
+ >
86
+ <button
87
+ class="ui primary button"
88
+ type="submit"
89
+ >
90
+ structure.tag.add
91
+ </button>
92
+ </div>
93
+ </form>
94
+ </div>
95
+ </div>
96
+ `;
97
+
98
+ exports[`<LinkStructureTagForm /> matches the latest snapshot create 1`] = `
99
+ <div>
100
+ <div
101
+ class="ui container"
102
+ style="width: 300px;"
103
+ >
104
+ <form
105
+ class="ui form"
106
+ >
107
+ <div
108
+ class="field"
109
+ >
110
+ <label>
111
+ structure.tag.dropdown.label
112
+ </label>
113
+ <div
114
+ aria-disabled="false"
115
+ aria-expanded="false"
116
+ class="ui search selection dropdown"
117
+ name="tag"
118
+ role="combobox"
119
+ >
120
+ <input
121
+ aria-autocomplete="list"
122
+ autocomplete="off"
123
+ class="search"
124
+ tabindex="0"
125
+ type="text"
126
+ value=""
127
+ />
128
+ <div
129
+ aria-atomic="true"
130
+ aria-live="polite"
131
+ class="divider default text"
132
+ role="alert"
133
+ >
134
+ structure.tag.dropdown.placeholder
135
+ </div>
136
+ <i
137
+ aria-hidden="true"
138
+ class="dropdown icon"
139
+ />
140
+ <div
141
+ class="menu transition"
142
+ role="listbox"
143
+ >
144
+ <div
145
+ aria-checked="false"
146
+ aria-selected="true"
147
+ class="selected item"
148
+ role="option"
149
+ style="pointer-events: all;"
150
+ >
151
+ <span
152
+ class="description"
153
+ >
154
+ description test
155
+ </span>
156
+ <span
157
+ class="text"
158
+ >
159
+ Tag1
160
+ </span>
161
+ </div>
162
+ <div
163
+ aria-checked="false"
164
+ aria-selected="false"
165
+ class="item"
166
+ role="option"
167
+ style="pointer-events: all;"
168
+ >
169
+ <span
170
+ class="description"
171
+ >
172
+ large desclarge desclarge desclarge desclarge desc
173
+ </span>
56
174
  <span
57
175
  class="text"
58
176
  >
59
- bar
177
+ Tag2
60
178
  </span>
61
179
  </div>
62
180
  </div>
@@ -69,8 +187,8 @@ exports[`<LinkStructureTagForm /> matches the latest snapshot create 1`] = `
69
187
  structure.tag.textArea.label
70
188
  </label>
71
189
  <textarea
72
- data-testid="description-id"
73
- name="description"
190
+ data-testid="comment-id"
191
+ name="comment"
74
192
  placeholder="structure.tag.textArea.placeholder"
75
193
  rows="3"
76
194
  />
@@ -92,6 +210,119 @@ exports[`<LinkStructureTagForm /> matches the latest snapshot create 1`] = `
92
210
  </div>
93
211
  `;
94
212
 
213
+ exports[`<LinkStructureTagForm /> matches the latest snapshot create without comment 1`] = `
214
+ <div>
215
+ <div
216
+ class="ui container"
217
+ style="width: 300px;"
218
+ >
219
+ <form
220
+ class="ui form"
221
+ >
222
+ <div
223
+ class="field"
224
+ >
225
+ <label>
226
+ structure.tag.dropdown.label
227
+ </label>
228
+ <div
229
+ aria-disabled="false"
230
+ aria-expanded="true"
231
+ class="ui active visible search selection dropdown"
232
+ name="tag"
233
+ role="combobox"
234
+ >
235
+ <input
236
+ aria-autocomplete="list"
237
+ autocomplete="off"
238
+ class="search"
239
+ tabindex="0"
240
+ type="text"
241
+ value=""
242
+ />
243
+ <div
244
+ aria-atomic="true"
245
+ aria-live="polite"
246
+ class="divider text"
247
+ role="alert"
248
+ >
249
+ Tag2
250
+ </div>
251
+ <i
252
+ aria-hidden="true"
253
+ class="dropdown icon clear"
254
+ />
255
+ <div
256
+ class="visible menu transition"
257
+ role="listbox"
258
+ >
259
+ <div
260
+ aria-checked="false"
261
+ aria-selected="false"
262
+ class="item"
263
+ role="option"
264
+ style="pointer-events: all;"
265
+ >
266
+ <span
267
+ class="description"
268
+ >
269
+ description test
270
+ </span>
271
+ <span
272
+ class="text"
273
+ >
274
+ Tag1
275
+ </span>
276
+ </div>
277
+ <div
278
+ aria-checked="true"
279
+ aria-selected="true"
280
+ class="active selected item"
281
+ role="option"
282
+ style="pointer-events: all;"
283
+ >
284
+ <span
285
+ class="description"
286
+ >
287
+ large desclarge desclarge desclarge desclarge desc
288
+ </span>
289
+ <span
290
+ class="text"
291
+ >
292
+ Tag2
293
+ </span>
294
+ </div>
295
+ </div>
296
+ </div>
297
+ </div>
298
+ <div
299
+ class="field"
300
+ >
301
+ <label>
302
+ structure.tag.textArea.label
303
+ </label>
304
+ <textarea
305
+ data-testid="comment-id"
306
+ name="comment"
307
+ placeholder="structure.tag.textArea.placeholder"
308
+ rows="3"
309
+ />
310
+ </div>
311
+ <div
312
+ class="actions"
313
+ >
314
+ <button
315
+ class="ui primary button"
316
+ type="submit"
317
+ >
318
+ structure.tag.add
319
+ </button>
320
+ </div>
321
+ </form>
322
+ </div>
323
+ </div>
324
+ `;
325
+
95
326
  exports[`<LinkStructureTagForm /> matches the latest snapshot edit 1`] = `
96
327
  <div>
97
328
  <div
@@ -128,7 +359,7 @@ exports[`<LinkStructureTagForm /> matches the latest snapshot edit 1`] = `
128
359
  class="divider text"
129
360
  role="alert"
130
361
  >
131
- foo
362
+ Tag without description
132
363
  </div>
133
364
  <i
134
365
  aria-hidden="true"
@@ -138,6 +369,19 @@ exports[`<LinkStructureTagForm /> matches the latest snapshot edit 1`] = `
138
369
  class="menu transition"
139
370
  role="listbox"
140
371
  >
372
+ <div
373
+ aria-checked="true"
374
+ aria-selected="true"
375
+ class="active selected item"
376
+ role="option"
377
+ style="pointer-events: all;"
378
+ >
379
+ <span
380
+ class="text"
381
+ >
382
+ Tag without description
383
+ </span>
384
+ </div>
141
385
  <div
142
386
  aria-checked="false"
143
387
  aria-selected="false"
@@ -145,23 +389,33 @@ exports[`<LinkStructureTagForm /> matches the latest snapshot edit 1`] = `
145
389
  role="option"
146
390
  style="pointer-events: all;"
147
391
  >
392
+ <span
393
+ class="description"
394
+ >
395
+ description test
396
+ </span>
148
397
  <span
149
398
  class="text"
150
399
  >
151
- bar
400
+ Tag1
152
401
  </span>
153
402
  </div>
154
403
  <div
155
- aria-checked="true"
156
- aria-selected="true"
157
- class="active selected item"
404
+ aria-checked="false"
405
+ aria-selected="false"
406
+ class="item"
158
407
  role="option"
159
408
  style="pointer-events: all;"
160
409
  >
410
+ <span
411
+ class="description"
412
+ >
413
+ large desclarge desclarge desclarge desclarge desc
414
+ </span>
161
415
  <span
162
416
  class="text"
163
417
  >
164
- foo
418
+ Tag2
165
419
  </span>
166
420
  </div>
167
421
  </div>
@@ -174,8 +428,8 @@ exports[`<LinkStructureTagForm /> matches the latest snapshot edit 1`] = `
174
428
  structure.tag.textArea.label
175
429
  </label>
176
430
  <textarea
177
- data-testid="description-id"
178
- name="description"
431
+ data-testid="comment-id"
432
+ name="comment"
179
433
  placeholder="structure.tag.textArea.placeholder"
180
434
  rows="3"
181
435
  >
@@ -0,0 +1,16 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`<LinkedStructureTag /> matches the latest snapshot 1`] = `
4
+ <div>
5
+ <div
6
+ class="ui tag label"
7
+ style="margin-left: 1.5em;"
8
+ >
9
+ <i
10
+ aria-hidden="true"
11
+ class="edit link icon"
12
+ />
13
+ Tag without description
14
+ </div>
15
+ </div>
16
+ `;
@@ -26,6 +26,26 @@ exports[`<StructureTagForm /> matches the latest snapshot 1`] = `
26
26
  />
27
27
  </div>
28
28
  </div>
29
+ <div
30
+ class="field"
31
+ >
32
+ <label
33
+ for="description"
34
+ >
35
+ Description
36
+ </label>
37
+ <div
38
+ class="ui input"
39
+ >
40
+ <input
41
+ autocomplete="off"
42
+ id="description"
43
+ placeholder="Description"
44
+ type="text"
45
+ value="bar"
46
+ />
47
+ </div>
48
+ </div>
29
49
  <div
30
50
  class="actions"
31
51
  >
@@ -17,6 +17,11 @@ exports[`<StructureTagsCards /> matches the latest snapshot, renders a link for
17
17
  >
18
18
  tag1
19
19
  </a>
20
+ <div
21
+ class="description"
22
+ >
23
+ tag_desc_1
24
+ </div>
20
25
  </div>
21
26
  <div
22
27
  class="extra content"
@@ -47,6 +52,11 @@ exports[`<StructureTagsCards /> matches the latest snapshot, renders a link for
47
52
  >
48
53
  tag2
49
54
  </a>
55
+ <div
56
+ class="description"
57
+ >
58
+ tag_desc_2
59
+ </div>
50
60
  </div>
51
61
  <div
52
62
  class="extra content"
@@ -36,21 +36,32 @@ exports[`<ValueConditionStructure /> matches the latest snapshot 1`] = `
36
36
  role="listbox"
37
37
  >
38
38
  <div
39
- class="divider"
40
- />
41
- <div
42
- class="header"
39
+ aria-checked="false"
40
+ aria-disabled="true"
41
+ aria-selected="false"
42
+ class="disabled item"
43
+ role="option"
44
+ style="pointer-events: all;"
43
45
  >
44
- <i
45
- aria-hidden="true"
46
- class="table icon"
46
+ <div
47
+ class="divider"
47
48
  />
48
- bar
49
+ <div
50
+ class="header"
51
+ >
52
+ <i
53
+ aria-hidden="true"
54
+ class="table icon"
55
+ />
56
+ bar
57
+ </div>
49
58
  </div>
50
59
  <div
51
- aria-selected="false"
52
- class="item group"
60
+ aria-checked="false"
61
+ aria-selected="true"
62
+ class="selected item group"
53
63
  role="option"
64
+ style="pointer-events: all;"
54
65
  >
55
66
  <i
56
67
  aria-hidden="true"
@@ -308,8 +308,9 @@ export default {
308
308
  "structure.tag.dropdown.label": "Select tag",
309
309
  "structure.tag.dropdown.placeholder": "Tag name",
310
310
  "structure.tag.edit": "Edit",
311
- "structure.tag.textArea.label": "Tag description",
312
- "structure.tag.textArea.placeholder": "Introduce a description",
311
+ "structure.tag.textArea.label": "Tag comments",
312
+ "structure.tag.textArea.placeholder": "Introduce a comment",
313
+ "structure.tag.tooltip.commentTitle": "Comment",
313
314
  "structure.type": "Type",
314
315
  "structure.type.Attribute": "Attribute",
315
316
  "structure.type.File.icon": "file",
@@ -360,6 +361,7 @@ export default {
360
361
  "structureSelector.union.criteria": "Union criteria",
361
362
  "structureTagForm.props.domains": "Domains",
362
363
  "structureTagForm.props.name": "Name",
364
+ "structureTagForm.props.description": "Description",
363
365
  "structureTags.actions.create": "Create Structure Tag",
364
366
  "structureTags.actions.delete.confirmation.content":
365
367
  "This tag has {count} linked structures. Are you sure that you want to delete this Struture Tag?",
@@ -317,8 +317,9 @@ export default {
317
317
  "structure.tag.dropdown.label": "Seleccionar etiqueta",
318
318
  "structure.tag.dropdown.placeholder": "Clave de etiqueta",
319
319
  "structure.tag.edit": "Editar",
320
- "structure.tag.textArea.label": "Descripción de etiqueta",
321
- "structure.tag.textArea.placeholder": "Introducir una descripción",
320
+ "structure.tag.textArea.label": "Comentarios de etiqueta",
321
+ "structure.tag.textArea.placeholder": "Introducir un comentario",
322
+ "structure.tag.tooltip.commentTitle": "Comentario",
322
323
  "structure.type": "Tipo",
323
324
  "structure.type.Attribute": "Atributo",
324
325
  "structure.type.File.icon": "file",
@@ -369,6 +370,7 @@ export default {
369
370
  "structureSelector.union.criteria": "Criterio de unión",
370
371
  "structureTagForm.props.domains": "Dominios",
371
372
  "structureTagForm.props.name": "Nombre",
373
+ "structureTagForm.props.description": "Descripción",
372
374
  "structureTags.actions.create": "Crear Etiqueta de Estructura",
373
375
  "structureTags.actions.delete.confirmation.content":
374
376
  "Esta etiqueta tiene {count} estructuras asociadas. ¿Desea eliminar la Etiqueta de Estructura {name}?",
@@ -15,7 +15,7 @@ const tags = [
15
15
  updated_at: "foo",
16
16
  _embedded: {
17
17
  data_structure: { id: 1, external_id: "baz" },
18
- data_structure_tag: { id: 1, name: "bar" },
18
+ data_structure_tag: { id: 1, name: "bar", description: "qux" },
19
19
  },
20
20
  },
21
21
  ];