From 56e2b607114765801459b75a972f0e0d1b13a05b Mon Sep 17 00:00:00 2001 From: illiakovalenko Date: Thu, 11 Jul 2024 10:45:37 +0300 Subject: [PATCH 1/3] [React][Next.js] DateField empty value is not treated as empty --- .../src/components/Date.test.tsx | 135 ++++++++++++------ .../withEmptyFieldEditingComponent.test.tsx | 60 ++++++++ packages/sitecore-jss/src/layout/index.ts | 7 +- .../sitecore-jss/src/layout/utils.test.ts | 25 +++- packages/sitecore-jss/src/layout/utils.ts | 9 +- 5 files changed, 191 insertions(+), 45 deletions(-) diff --git a/packages/sitecore-jss-react/src/components/Date.test.tsx b/packages/sitecore-jss-react/src/components/Date.test.tsx index d62d7f5e17..d2872c9360 100644 --- a/packages/sitecore-jss-react/src/components/Date.test.tsx +++ b/packages/sitecore-jss-react/src/components/Date.test.tsx @@ -4,6 +4,7 @@ import { mount, shallow } from 'enzyme'; import React from 'react'; import { DateField } from './Date'; import { describe } from 'node:test'; +import { EMPTY_DATE_FIELD_VALUE } from '@sitecore-jss/sitecore-jss/layout'; describe('', () => { it('should return null if no editable or value', () => { @@ -116,48 +117,98 @@ describe('', () => { ); }); - it('should render default empty field component when field value is empty', () => { - const field = { - value: '', - metadata: testMetadata, - }; - - const rendered = mount(); - - expect(rendered.html()).to.equal( - [ - `${JSON.stringify( - testMetadata - )}`, - '[No text in field]', - '', - ].join('') - ); - }); - - it('should render custom empty field component when provided, when field value is empty', () => { - const field = { - value: '', - metadata: testMetadata, - }; - - const EmptyFieldEditingComponent: React.FC = () => ( - Custom Empty field value - ); - - const rendered = mount( - - ); - - expect(rendered.html()).to.equal( - [ - `${JSON.stringify( - testMetadata - )}`, - 'Custom Empty field value', - '', - ].join('') - ); + describe('empty value', () => { + describe('Should render default component', () => { + it('field value is empty string', () => { + const field = { + value: '', + metadata: testMetadata, + }; + + const rendered = mount(); + + expect(rendered.html()).to.equal( + [ + `${JSON.stringify( + testMetadata + )}`, + '[No text in field]', + '', + ].join('') + ); + }); + + it('field value is default empty date value', () => { + const field = { + value: EMPTY_DATE_FIELD_VALUE, + metadata: testMetadata, + }; + + const rendered = mount(); + + expect(rendered.html()).to.equal( + [ + `${JSON.stringify( + testMetadata + )}`, + '[No text in field]', + '', + ].join('') + ); + }); + }); + + describe('Should render custom component', () => { + it('field value is empty string', () => { + const field = { + value: '', + metadata: testMetadata, + }; + + const EmptyFieldEditingComponent: React.FC = () => ( + Custom Empty field value + ); + + const rendered = mount( + + ); + + expect(rendered.html()).to.equal( + [ + `${JSON.stringify( + testMetadata + )}`, + 'Custom Empty field value', + '', + ].join('') + ); + }); + + it('field value is defaule empty date value', () => { + const field = { + value: EMPTY_DATE_FIELD_VALUE, + metadata: testMetadata, + }; + + const EmptyFieldEditingComponent: React.FC = () => ( + Custom Empty field value + ); + + const rendered = mount( + + ); + + expect(rendered.html()).to.equal( + [ + `${JSON.stringify( + testMetadata + )}`, + 'Custom Empty field value', + '', + ].join('') + ); + }); + }); }); it('should render nothing when field value is empty, when editing is explicitly disabled ', () => { diff --git a/packages/sitecore-jss-react/src/enhancers/withEmptyFieldEditingComponent.test.tsx b/packages/sitecore-jss-react/src/enhancers/withEmptyFieldEditingComponent.test.tsx index 2cd08c9c60..0c03c34c17 100644 --- a/packages/sitecore-jss-react/src/enhancers/withEmptyFieldEditingComponent.test.tsx +++ b/packages/sitecore-jss-react/src/enhancers/withEmptyFieldEditingComponent.test.tsx @@ -5,6 +5,7 @@ import { mount } from 'enzyme'; import { withEmptyFieldEditingComponent } from './withEmptyFieldEditingComponent'; import { DefaultEmptyFieldEditingComponentText } from '../components/DefaultEmptyFieldEditingComponents'; import { describe } from 'node:test'; +import { EMPTY_DATE_FIELD_VALUE } from '@sitecore-jss/sitecore-jss/layout'; describe('withEmptyFieldEditingComponent', () => { describe('Metadata', () => { @@ -165,6 +166,65 @@ describe('withEmptyFieldEditingComponent', () => { expect(rendered.html()).to.equal('

hi

foo

bar

'); }); + describe('Date', () => { + it('Should render component if field value is provided', () => { + const props = { + field: { + metadata: testMetadata, + value: '2024-01-01T00:00:00Z', + }, + }; + + const WrappedComponent = withEmptyFieldEditingComponent(TestComponent, { + defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentText, + }); + + const rendered = mount(); + expect(rendered.html()).to.equal('

hi

foo

bar

'); + }); + + it('Should render default empty component if field value is empty', () => { + const props = { + field: { + value: EMPTY_DATE_FIELD_VALUE, + metadata: testMetadata, + }, + }; + + const WrappedComponent = withEmptyFieldEditingComponent(TestComponent, { + defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentText, + }); + + const rendered = mount(); + const expected = mount(); + + expect(rendered.html()).to.equal(expected.html()); + }); + + it('Should render custom empty component if field value is empty', () => { + const EmptyFieldEditingComponent: React.FC = () => ( + Custom Empty field value + ); + + const props = { + field: { + value: EMPTY_DATE_FIELD_VALUE, + metadata: testMetadata, + }, + emptyFieldEditingComponent: EmptyFieldEditingComponent, + }; + + const WrappedComponent = withEmptyFieldEditingComponent(TestComponent, { + defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentText, + }); + + const rendered = mount(); + const expected = mount(); + + expect(rendered.html()).to.equal(expected.html()); + }); + }); + describe('Image', () => { it('Should render component if field src is provided', () => { const props = { diff --git a/packages/sitecore-jss/src/layout/index.ts b/packages/sitecore-jss/src/layout/index.ts index 17c2d61c3b..b601e6ed18 100644 --- a/packages/sitecore-jss/src/layout/index.ts +++ b/packages/sitecore-jss/src/layout/index.ts @@ -18,7 +18,12 @@ export { FieldMetadata, } from './models'; -export { getFieldValue, getChildPlaceholder, isFieldValueEmpty } from './utils'; +export { + getFieldValue, + getChildPlaceholder, + isFieldValueEmpty, + EMPTY_DATE_FIELD_VALUE, +} from './utils'; export { getContentStylesheetLink } from './content-styles'; diff --git a/packages/sitecore-jss/src/layout/utils.test.ts b/packages/sitecore-jss/src/layout/utils.test.ts index 7da3c77c1f..1861307c07 100644 --- a/packages/sitecore-jss/src/layout/utils.test.ts +++ b/packages/sitecore-jss/src/layout/utils.test.ts @@ -1,7 +1,7 @@ /* eslint-disable no-unused-expressions */ import { expect } from 'chai'; import { ComponentRendering } from '../../layout'; -import { getFieldValue, getChildPlaceholder, isFieldValueEmpty } from './utils'; +import { getFieldValue, getChildPlaceholder, isFieldValueEmpty, EMPTY_DATE_FIELD_VALUE } from './utils'; describe('sitecore-jss layout utils', () => { describe('getFieldValue', () => { @@ -153,6 +153,29 @@ describe('sitecore-jss layout utils', () => { }); }); + describe('Date', () => { + it('should return true if Date field is empty', () => { + expect( + isFieldValueEmpty({ + value: EMPTY_DATE_FIELD_VALUE, + }) + ).to.be.true; + expect( + isFieldValueEmpty({ + value: '', + }) + ).to.be.true; + }); + + it('should return false if Date field is not empty', () => { + const field = { + value: '2024-01-01T00:00:00Z', + }; + const result = isFieldValueEmpty(field); + expect(result).to.be.false; + }); + }); + describe('boolean', () => { it('should return false if field value is boolean false', () => { const field = { diff --git a/packages/sitecore-jss/src/layout/utils.ts b/packages/sitecore-jss/src/layout/utils.ts index 56811b092f..9d7521868c 100644 --- a/packages/sitecore-jss/src/layout/utils.ts +++ b/packages/sitecore-jss/src/layout/utils.ts @@ -79,6 +79,12 @@ export function getChildPlaceholder( return rendering.placeholders[placeholderName]; } +/** + * The default value for an empty Date field. + * This value is defined as a default one by .NET + */ +export const EMPTY_DATE_FIELD_VALUE = '0001-01-01T00:00:00Z'; + /** * Determines if the passed in field object's value is empty. * @param {GenericFieldValue | Partial} field the field object. @@ -91,6 +97,7 @@ export function isFieldValueEmpty(field: GenericFieldValue | Partial): bo !(fieldValue as { [key: string]: unknown }).src; const isLinkFieldEmpty = (fieldValue: GenericFieldValue) => !(fieldValue as { [key: string]: unknown }).href; + const isDateFieldEmpty = (fieldValue: GenericFieldValue) => fieldValue === EMPTY_DATE_FIELD_VALUE; const isEmpty = (fieldValue: GenericFieldValue) => { if (typeof fieldValue === 'object') { @@ -103,7 +110,7 @@ export function isFieldValueEmpty(field: GenericFieldValue | Partial): bo // Avoid returning true for 0 and false values return false; } else { - return !fieldValue; + return !fieldValue || isDateFieldEmpty(fieldValue); } }; From 11c245c312b25351249524e846a4d67c72a07909 Mon Sep 17 00:00:00 2001 From: illiakovalenko Date: Thu, 11 Jul 2024 10:47:41 +0300 Subject: [PATCH 2/3] Updated CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4307b6442..2fc4744b15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Our versioning strategy is as follows: * `[templates/nextjs]` `[templates/react]` `[templates/vue]` `[templates/angular]` Changed formatting in temp/config to prevent parse issues in Unix systems ([#1787](https://github.com/Sitecore/jss/pull/1787))([#1791](https://github.com/Sitecore/jss/pull/1791)) * `[templates/nextjs-sxa]` The banner variant of image component is fixed with supporting metadata mode. ([#1826](https://github.com/Sitecore/jss/pull/1826)) +* `[sitecore-jss]` `[sitecore-jss-react]` DateField empty value is not treated as empty ([#1836](https://github.com/Sitecore/jss/pull/1836)) ### 🎉 New Features & Improvements From 60a540eaafbb288368377f023c5bee5ed842ef4e Mon Sep 17 00:00:00 2001 From: illiakovalenko Date: Thu, 11 Jul 2024 11:44:01 +0300 Subject: [PATCH 3/3] Fixed lint step --- packages/sitecore-jss/src/layout/utils.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/sitecore-jss/src/layout/utils.test.ts b/packages/sitecore-jss/src/layout/utils.test.ts index 1861307c07..c72228eb21 100644 --- a/packages/sitecore-jss/src/layout/utils.test.ts +++ b/packages/sitecore-jss/src/layout/utils.test.ts @@ -1,7 +1,12 @@ /* eslint-disable no-unused-expressions */ import { expect } from 'chai'; import { ComponentRendering } from '../../layout'; -import { getFieldValue, getChildPlaceholder, isFieldValueEmpty, EMPTY_DATE_FIELD_VALUE } from './utils'; +import { + getFieldValue, + getChildPlaceholder, + isFieldValueEmpty, + EMPTY_DATE_FIELD_VALUE, +} from './utils'; describe('sitecore-jss layout utils', () => { describe('getFieldValue', () => {