From 34c86561071feba60e01b8d57d537578be01479d Mon Sep 17 00:00:00 2001 From: Haixing Hu Date: Thu, 30 Nov 2023 15:22:08 +0800 Subject: [PATCH] fix: freeze the CaseFormat class and its class constants --- src/case-format.js | 45 ++++++++- test/case-format.immutable.test.js | 147 +++++++++++++++++++++++++++++ test/case-format.of.test.js | 79 ++++++++++++++++ 3 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 test/case-format.immutable.test.js create mode 100644 test/case-format.of.test.js diff --git a/src/case-format.js b/src/case-format.js index 179d1ea..e864adf 100644 --- a/src/case-format.js +++ b/src/case-format.js @@ -6,8 +6,8 @@ // All rights reserved. // //////////////////////////////////////////////////////////////////////////////// -import firstCharOnlyToUpper from './first-char-only-to-upper'; -import findFirst from './find-first'; +import firstCharOnlyToUpper from './impl/first-char-only-to-upper'; +import findFirst from './impl/find-first'; /** * A class that represents case formats. @@ -133,6 +133,39 @@ class CaseFormat { ]; } + /** + * Returns the case format constant of the specified name. + * + * @param {String|CaseFormat} name + * the name of the case format constant, or a `CaseFormat` instance. The + * name is compared case-insensitively and the characters '-' and '_' are + * treated as the same. + * @return {CaseFormat} + * the case format constant of the specified name, or the specified + * `CaseFormat` instance if the argument `name` is a `CaseFormat` instance. + * @throws {TypeError} + * if the argument `name` is not a string nor a `CaseFormat` instance. + * @throws {Error} + * if there is no case format constant of the specified name. + */ + static of(name) { + if (name instanceof CaseFormat) { + return name; + } + if (typeof name !== 'string') { + throw new TypeError('The argument of `CaseFormat.of()` must be a string or a `CaseFormat` instance.'); + } + const normalizedName = name.replace(/_/g, '-').toLowerCase(); + const values = CaseFormat.values(); + for (let i = 0; i < values.length; ++i) { + const value = values[i]; + if (value.name.toLowerCase() === normalizedName) { + return value; + } + } + throw new Error(`Unknown case format: '${name}'.`); + } + /** * Constructor a {@link CaseFormat} instance. * @@ -214,4 +247,12 @@ class CaseFormat { } } +// freeze the constants and the class +Object.freeze(CaseFormat.LOWER_HYPHEN); +Object.freeze(CaseFormat.LOWER_UNDERSCORE); +Object.freeze(CaseFormat.LOWER_CAMEL); +Object.freeze(CaseFormat.UPPER_CAMEL); +Object.freeze(CaseFormat.UPPER_UNDERSCORE); +Object.freeze(CaseFormat); + export default CaseFormat; diff --git a/test/case-format.immutable.test.js b/test/case-format.immutable.test.js new file mode 100644 index 0000000..3b5f86a --- /dev/null +++ b/test/case-format.immutable.test.js @@ -0,0 +1,147 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2022 - 2023. +// Haixing Hu, Qubit Co. Ltd. +// +// All rights reserved. +// +//////////////////////////////////////////////////////////////////////////////// +import { + LOWER_HYPHEN, + LOWER_UNDERSCORE, + LOWER_CAMEL, + UPPER_CAMEL, + UPPER_UNDERSCORE, + CaseFormat, +} from '../src'; + +/** + * Unit tests of the immutability of the {@link CaseFormat} class. + * + * @author Haixing Hu + */ +describe('Test the immutability of the CaseFormat class', () => { + test('Test the immutability of CaseFormat.LOWER_HYPHEN', () => { + expect(() => { + LOWER_HYPHEN.name = 'xxx'; + }).toThrow(Error); + expect(() => { + LOWER_HYPHEN.wordBoundaryFilter = null; + }).toThrow(Error); + expect(() => { + LOWER_HYPHEN.wordSeparator = 'xx'; + }).toThrow(Error); + expect(() => { + LOWER_HYPHEN.wordNormalizer = null; + }).toThrow(Error); + expect(() => { + LOWER_HYPHEN.firstWordNormalizer = null; + }).toThrow(Error); + expect(() => { + LOWER_HYPHEN.quickOptimizer = null; + }).toThrow(Error); + }); + test('Test the immutability of CaseFormat.LOWER_UNDERSCORE', () => { + expect(() => { + LOWER_UNDERSCORE.name = 'xxx'; + }).toThrow(Error); + expect(() => { + LOWER_UNDERSCORE.wordBoundaryFilter = null; + }).toThrow(Error); + expect(() => { + LOWER_UNDERSCORE.wordSeparator = 'xx'; + }).toThrow(Error); + expect(() => { + LOWER_UNDERSCORE.wordNormalizer = null; + }).toThrow(Error); + expect(() => { + LOWER_UNDERSCORE.firstWordNormalizer = null; + }).toThrow(Error); + expect(() => { + LOWER_UNDERSCORE.quickOptimizer = null; + }).toThrow(Error); + }); + test('Test the immutability of CaseFormat.LOWER_CAMEL', () => { + expect(() => { + LOWER_CAMEL.name = 'xxx'; + }).toThrow(Error); + expect(() => { + LOWER_CAMEL.wordBoundaryFilter = null; + }).toThrow(Error); + expect(() => { + LOWER_CAMEL.wordSeparator = 'xx'; + }).toThrow(Error); + expect(() => { + LOWER_CAMEL.wordNormalizer = null; + }).toThrow(Error); + expect(() => { + LOWER_CAMEL.firstWordNormalizer = null; + }).toThrow(Error); + expect(() => { + LOWER_CAMEL.quickOptimizer = null; + }).toThrow(Error); + }); + test('Test the immutability of CaseFormat.UPPER_CAMEL', () => { + expect(() => { + UPPER_CAMEL.name = 'xxx'; + }).toThrow(Error); + expect(() => { + UPPER_CAMEL.wordBoundaryFilter = null; + }).toThrow(Error); + expect(() => { + UPPER_CAMEL.wordSeparator = 'xx'; + }).toThrow(Error); + expect(() => { + UPPER_CAMEL.wordNormalizer = null; + }).toThrow(Error); + expect(() => { + UPPER_CAMEL.firstWordNormalizer = null; + }).toThrow(Error); + expect(() => { + UPPER_CAMEL.quickOptimizer = null; + }).toThrow(Error); + }); + test('Test the immutability of CaseFormat.UPPER_UNDERSCORE', () => { + expect(() => { + UPPER_UNDERSCORE.name = 'xxx'; + }).toThrow(Error); + expect(() => { + UPPER_UNDERSCORE.wordBoundaryFilter = null; + }).toThrow(Error); + expect(() => { + UPPER_UNDERSCORE.wordSeparator = 'xx'; + }).toThrow(Error); + expect(() => { + UPPER_UNDERSCORE.wordNormalizer = null; + }).toThrow(Error); + expect(() => { + UPPER_UNDERSCORE.firstWordNormalizer = null; + }).toThrow(Error); + expect(() => { + UPPER_UNDERSCORE.quickOptimizer = null; + }).toThrow(Error); + }); + test('Test the immutability of CaseFormat class', () => { + expect(() => { + CaseFormat.LOWER_HYPHEN = 'xxx'; + }).toThrow(Error); + expect(() => { + CaseFormat.LOWER_UNDERSCORE = null; + }).toThrow(Error); + expect(() => { + CaseFormat.LOWER_CAMEL = 'xx'; + }).toThrow(Error); + expect(() => { + CaseFormat.UPPER_CAMEL = null; + }).toThrow(Error); + expect(() => { + CaseFormat.UPPER_UNDERSCORE = null; + }).toThrow(Error); + expect(() => { + CaseFormat.values = null; + }).toThrow(Error); + expect(() => { + CaseFormat.of = null; + }).toThrow(Error); + }); +}); diff --git a/test/case-format.of.test.js b/test/case-format.of.test.js new file mode 100644 index 0000000..fd3d3f5 --- /dev/null +++ b/test/case-format.of.test.js @@ -0,0 +1,79 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2022 - 2023. +// Haixing Hu, Qubit Co. Ltd. +// +// All rights reserved. +// +//////////////////////////////////////////////////////////////////////////////// +import { + LOWER_HYPHEN, + LOWER_UNDERSCORE, + LOWER_CAMEL, + UPPER_CAMEL, + UPPER_UNDERSCORE, + CaseFormat, +} from '../src'; + +/** + * Unit tests of the {@link CaseFormat#of()} function. + * + * @author Haixing Hu + */ +describe('Test the CaseFormat.of()', () => { + test('Test CaseFormat.of(), with CaseFormat instances', () => { + expect(CaseFormat.of(CaseFormat.LOWER_HYPHEN)).toBe(LOWER_HYPHEN); + expect(CaseFormat.of(CaseFormat.LOWER_UNDERSCORE)).toBe(LOWER_UNDERSCORE); + expect(CaseFormat.of(CaseFormat.LOWER_CAMEL)).toBe(LOWER_CAMEL); + expect(CaseFormat.of(CaseFormat.UPPER_CAMEL)).toBe(UPPER_CAMEL); + expect(CaseFormat.of(CaseFormat.UPPER_UNDERSCORE)).toBe(UPPER_UNDERSCORE); + }); + test('Test CaseFormat.of(), with a argument of invalid type', () => { + expect(() => CaseFormat.of(undefined)).toThrow(TypeError); + expect(() => CaseFormat.of(null)).toThrow(TypeError); + expect(() => CaseFormat.of(123)).toThrow(TypeError); + }); + test('Test CaseFormat.of(), with a argument of invalid name', () => { + expect(() => CaseFormat.of('xxx')).toThrow(Error); + }); + test('Test CaseFormat.of(), with correct name of LOWER_HYPHEN', () => { + expect(CaseFormat.of('lower-hyphen')).toBe(LOWER_HYPHEN); + expect(CaseFormat.of('lower_hyphen')).toBe(LOWER_HYPHEN); + expect(CaseFormat.of('Lower-Hyphen')).toBe(LOWER_HYPHEN); + expect(CaseFormat.of('Lower_Hyphen')).toBe(LOWER_HYPHEN); + expect(CaseFormat.of('LOWER-HYPHEN')).toBe(LOWER_HYPHEN); + expect(CaseFormat.of('LOWER_HYPHEN')).toBe(LOWER_HYPHEN); + }); + test('Test CaseFormat.of(), with correct name of LOWER_UNDERSCORE', () => { + expect(CaseFormat.of('lower-underscore')).toBe(LOWER_UNDERSCORE); + expect(CaseFormat.of('lower_underscore')).toBe(LOWER_UNDERSCORE); + expect(CaseFormat.of('Lower-Underscore')).toBe(LOWER_UNDERSCORE); + expect(CaseFormat.of('Lower_Underscore')).toBe(LOWER_UNDERSCORE); + expect(CaseFormat.of('LOWER-UNDERSCORE')).toBe(LOWER_UNDERSCORE); + expect(CaseFormat.of('LOWER_UNDERSCORE')).toBe(LOWER_UNDERSCORE); + }); + test('Test CaseFormat.of(), with correct name of LOWER_CAMEL', () => { + expect(CaseFormat.of('lower-camel')).toBe(LOWER_CAMEL); + expect(CaseFormat.of('lower_camel')).toBe(LOWER_CAMEL); + expect(CaseFormat.of('Lower-Camel')).toBe(LOWER_CAMEL); + expect(CaseFormat.of('Lower_Camel')).toBe(LOWER_CAMEL); + expect(CaseFormat.of('LOWER-CAMEL')).toBe(LOWER_CAMEL); + expect(CaseFormat.of('LOWER_CAMEL')).toBe(LOWER_CAMEL); + }); + test('Test CaseFormat.of(), with correct name of UPPER_CAMEL', () => { + expect(CaseFormat.of('upper-camel')).toBe(UPPER_CAMEL); + expect(CaseFormat.of('upper_camel')).toBe(UPPER_CAMEL); + expect(CaseFormat.of('Upper-Camel')).toBe(UPPER_CAMEL); + expect(CaseFormat.of('Upper_Camel')).toBe(UPPER_CAMEL); + expect(CaseFormat.of('UPPER-CAMEL')).toBe(UPPER_CAMEL); + expect(CaseFormat.of('UPPER_CAMEL')).toBe(UPPER_CAMEL); + }); + test('Test CaseFormat.of(), with correct name of UPPER_UNDERSCORE', () => { + expect(CaseFormat.of('upper-underscore')).toBe(UPPER_UNDERSCORE); + expect(CaseFormat.of('upper_underscore')).toBe(UPPER_UNDERSCORE); + expect(CaseFormat.of('Upper-Underscore')).toBe(UPPER_UNDERSCORE); + expect(CaseFormat.of('Upper_Underscore')).toBe(UPPER_UNDERSCORE); + expect(CaseFormat.of('UPPER-UNDERSCORE')).toBe(UPPER_UNDERSCORE); + expect(CaseFormat.of('UPPER_UNDERSCORE')).toBe(UPPER_UNDERSCORE); + }); +});