Repository: FHIR/sushi
Pull request #716 (2021-01-06 16:37:30)

FshQuantity toString updates
This PR updates `FshQuantity`'s `toString` method to include the unit display text. This was missing when the display text was added to the quantity syntax.

By adding tests for this method, I discovered that the `toString` method will not return an accurate string if the `system` on the `unit` FshCode is not UCUM. This isn't a problem for now for SUSHI because the only FshQuantities created by SUSHI use UCUM as the system. I talked with @cmoesel about this, and we realized that we will need to ensure that GoFSH is not creating FshQuantities with non-UCUM systems, and in the future, we may consider supporting regular codes on Quantities if the unit is not a UCUM unit. However, those changes are separate from this PR.

jafeltra: @mint-thompson your description above is correct. I found at least one spot in GoFSH where we create a `FSHQuantity` for a property that `endsWith('Quantity')` without checking if the system on that quantity is UCUM. However, in SUSHI, we only create a `FSHQuantity` in two places (as far as I can tell) and they either specify UCUM or don't include any unit. I believe @cmoesel said he was going to log an issue for GoFSH.

Patch:
diff --git a/src/fshtypes/FshQuantity.ts b/src/fshtypes/FshQuantity.ts
index 55c593d..a331af8 100644
--- a/src/fshtypes/FshQuantity.ts
+++ b/src/fshtypes/FshQuantity.ts
@@ -9,7 +9,10 @@ export class FshQuantity extends FshEntity {
 
   toString(): string {
     let str = this.value.toString();
-    if (this.unit?.code != null) str += ` '${this.unit.code}'`;
+    if (this.unit?.code != null) {
+      str += ` '${this.unit.code}'`;
+      if (this.unit.display != null) str += ` "${this.unit.display}"`;
+    }
     return str;
   }
 


Test patch:
diff --git a/test/fshtypes/FshQuantity.test.ts b/test/fshtypes/FshQuantity.test.ts
new file mode 100644
index 0000000..f652e80
--- /dev/null
+++ b/test/fshtypes/FshQuantity.test.ts
@@ -0,0 +1,77 @@
+import { FshCode, FshQuantity } from '../../src/fshtypes';
+
+describe('FshQuantity', () => {
+  describe('#constructor', () => {
+    it('should set the properties correctly', () => {
+      const quantity = new FshQuantity(
+        100,
+        new FshCode('mm', 'http://unitsofmeasure.org', 'millimeters')
+      );
+      expect(quantity.value).toBe(100);
+      expect(quantity.unit.code).toBe('mm');
+      expect(quantity.unit.system).toBe('http://unitsofmeasure.org');
+      expect(quantity.unit.display).toBe('millimeters');
+    });
+  });
+
+  describe('#toString', () => {
+    it('should return string for quantity without unit', () => {
+      const quantity = new FshQuantity(100);
+      const result = quantity.toString();
+      expect(result).toEqual('100');
+    });
+
+    it('should return string for basic unit code', () => {
+      const code = new FshCode('mm');
+      const quantity = new FshQuantity(100, code);
+      const result = quantity.toString();
+      expect(result).toEqual("100 'mm'");
+    });
+
+    it('should return string for unit code with UCUM system', () => {
+      const code = new FshCode('mm', 'http://unitsofmeasure.org');
+      const quantity = new FshQuantity(100, code);
+      const result = quantity.toString();
+      expect(result).toEqual("100 'mm'");
+    });
+
+    // NOTE: Technically this is invalid, but SUSHI never creates a FshQuantity with a non-UCUM system
+    // This is purely for testing purposes
+    it('should return string for unit code with non-UCUM system', () => {
+      const code = new FshCode('bar', 'http://foo.com');
+      const quantity = new FshQuantity(100, code);
+      const result = quantity.toString();
+      expect(result).toEqual("100 'bar'");
+    });
+
+    it('should return string for unit code with display', () => {
+      const code = new FshCode('mm', null, 'Display');
+      const quantity = new FshQuantity(100, code);
+      const result = quantity.toString();
+      expect(result).toEqual('100 \'mm\' "Display"');
+    });
+
+    it('should return string for unit code with UCUM system and display', () => {
+      const code = new FshCode('mm', 'http://unitsofmeasure.org', 'Display');
+      const quantity = new FshQuantity(100, code);
+      const result = quantity.toString();
+      expect(result).toEqual('100 \'mm\' "Display"');
+    });
+
+    // NOTE: Technically this is invalid, but SUSHI never creates a FshQuantity with a non-UCUM system
+    // This is purely for testing purposes
+    it('should return string for unit code with non-UCUM system and display', () => {
+      const code = new FshCode('bar', 'http://foo.com', 'Display');
+      const quantity = new FshQuantity(100, code);
+      const result = quantity.toString();
+      expect(result).toEqual('100 \'bar\' "Display"');
+    });
+
+    it('should return string for unit code with code with spaces', () => {
+      const code = new FshCode('milli meters');
+      const quantity = new FshQuantity(100, code);
+      const result = quantity.toString();
+      expect(result).toEqual("100 'milli meters'");
+    });
+  });
+});