From f860254c04e0d83f2d6cbdb96f21c848045a1a77 Mon Sep 17 00:00:00 2001 From: Jeffrey Horton Date: Mon, 20 May 2024 13:52:13 +0100 Subject: [PATCH] [ASL-4413] Snippets will continue falling back if non-string template is found --- package-lock.json | 4 ++-- package.json | 2 +- src/snippet/index.jsx | 25 ++++++++++++++++++------- src/snippet/index.spec.jsx | 31 ++++++++++++++++++++++++++++++- 4 files changed, 51 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 63828d0..2722d2c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@ukhomeoffice/asl-components", - "version": "13.4.0", + "version": "13.5.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@ukhomeoffice/asl-components", - "version": "13.4.0", + "version": "13.5.1", "license": "MIT", "dependencies": { "@ukhomeoffice/asl-constants": "^2.1.5", diff --git a/package.json b/package.json index 4523e2c..72608cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ukhomeoffice/asl-components", - "version": "13.5.0", + "version": "13.5.1", "description": "React components for ASL layouts and elements", "main": "src/index.jsx", "styles": "styles/index.scss", diff --git a/src/snippet/index.jsx b/src/snippet/index.jsx index 1aa8c9c..1bfb4cb 100644 --- a/src/snippet/index.jsx +++ b/src/snippet/index.jsx @@ -4,12 +4,24 @@ import { connect } from 'react-redux'; import Markdown from '../markdown'; import { render } from 'mustache'; +function getKeysToTry(primary, fallback) { + if (Array.isArray(fallback)) { + return [primary, ...fallback]; + } + + if(['string', 'number'].includes(typeof fallback)) { + return [primary, fallback]; + } + + return [primary]; +} + function getTemplate(content, primary, fallback) { - const keysToTry = [primary, ...(Array.isArray(fallback) ? fallback : [fallback])]; + const keysToTry = getKeysToTry(primary, fallback); for (let key of keysToTry) { const template = get(content, key); - if (template != undefined) { + if (typeof template === 'string') { return template; } } @@ -19,16 +31,15 @@ function getTemplate(content, primary, fallback) { export const Snippet = ({ content, children, optional, fallback, ...props }) => { const str = getTemplate(content, children, fallback); + if (str === undefined && optional) { return null; - } + if (str === undefined) { - throw new Error(`Failed to lookup content snippet: ${children}`); - } - if (typeof str !== 'string') { - throw new Error(`Invalid content snippet for key ${children}: ${JSON.stringify(str)}`); + throw new Error(`Failed to lookup content snippet. Tried keys: ${JSON.stringify(getKeysToTry(children, fallback))}`); } + const source = render(str, props); return ( diff --git a/src/snippet/index.spec.jsx b/src/snippet/index.spec.jsx index 04d2ff1..62e30a7 100644 --- a/src/snippet/index.spec.jsx +++ b/src/snippet/index.spec.jsx @@ -20,7 +20,11 @@ describe('', () => { * three`, paragraphs: `one -two` +two`, + nested: { + string: 'nested string', + template: 'Hello {{ name }}' + } }; test('does not include a wrapping element on single line input', () => { @@ -42,6 +46,11 @@ two` expect(wrapper.html()).toEqual(paragraphs); }); + test('will inject props as template variables', () => { + const wrapper = render(
nested.template
); + expect(wrapper.html()).toEqual('Hello world'); + }) + test('can accept single fallback', () => { const wrapper = render(
non.existent
); expect(wrapper.find('p').length).toEqual(2); @@ -54,4 +63,24 @@ two` expect(wrapper.html()).toEqual(paragraphs); }); + test('will error if no fallback matches content', () => { + expect(() => render(
non.existent
)) + .toThrow('Failed to lookup content snippet. Tried keys: ["non.existent","non.existent.2","missing"]'); + }); + + test('will return null if no content matches and the snippet is optional', () => { + const wrapper = render(
non.existent
); + expect(wrapper.html()).toEqual(''); + }); + + test('errors if content at the specified key is not a string', () => { + expect(() => render(
nested
)) + .toThrow('Failed to lookup content snippet. Tried keys: ["nested"]'); + }); + + test('renders a fallback if content at the specified key is not a string', () => { + const wrapper = render(
nested
); + expect(wrapper.html()).toEqual('nested string'); + }); + });