|
| 1 | +import { getVariantAliases, getVariantMetadataTags } from '../src/variant-aliases'; |
| 2 | +import { variantEntrySingle, variantEntries } from './mock/variant-fixtures'; |
| 3 | + |
| 4 | +function sortAliases(aliases: string[]): string[] { |
| 5 | + return [...aliases].sort((a, b) => a.localeCompare(b)); |
| 6 | +} |
| 7 | + |
| 8 | +describe('getVariantAliases', () => { |
| 9 | + const contentTypeUid = 'movie'; |
| 10 | + |
| 11 | + it('extracts variant aliases for a single entry with explicit contentTypeUid', () => { |
| 12 | + const result = getVariantAliases(variantEntrySingle, contentTypeUid); |
| 13 | + expect(result.entry_uid).toBe('entry_uid_single'); |
| 14 | + expect(result.contenttype_uid).toBe(contentTypeUid); |
| 15 | + expect(sortAliases(result.variants)).toEqual(sortAliases(['cs_personalize_0_0', 'cs_personalize_0_3'])); |
| 16 | + }); |
| 17 | + |
| 18 | + it('uses _content_type_uid from entry when present', () => { |
| 19 | + const entry = { |
| 20 | + ...variantEntrySingle, |
| 21 | + _content_type_uid: 'from_entry', |
| 22 | + }; |
| 23 | + const result = getVariantAliases(entry, 'ignored'); |
| 24 | + expect(result.contenttype_uid).toBe('from_entry'); |
| 25 | + }); |
| 26 | + |
| 27 | + it('returns empty contenttype_uid when missing from entry and not passed', () => { |
| 28 | + const result = getVariantAliases(variantEntrySingle); |
| 29 | + expect(result.contenttype_uid).toBe(''); |
| 30 | + }); |
| 31 | + |
| 32 | + it('maps multiple entries in order', () => { |
| 33 | + const results = getVariantAliases(variantEntries, contentTypeUid); |
| 34 | + expect(results).toHaveLength(3); |
| 35 | + expect(results[0].entry_uid).toBe('entry_uid_1'); |
| 36 | + expect(sortAliases(results[0].variants)).toEqual(sortAliases(['cs_personalize_0_0', 'cs_personalize_0_3'])); |
| 37 | + expect(results[1].entry_uid).toBe('entry_uid_2'); |
| 38 | + expect(results[1].variants).toEqual(['cs_personalize_0_0']); |
| 39 | + expect(results[2].entry_uid).toBe('entry_uid_3'); |
| 40 | + expect(results[2].variants).toEqual([]); |
| 41 | + }); |
| 42 | + |
| 43 | + it('returns empty variants when publish_details or variants is absent', () => { |
| 44 | + const entry = { uid: 'u1', _content_type_uid: 'ct' }; |
| 45 | + expect(getVariantAliases(entry).variants).toEqual([]); |
| 46 | + const entry2 = { uid: 'u1', publish_details: {} }; |
| 47 | + expect(getVariantAliases(entry2).variants).toEqual([]); |
| 48 | + const entry3 = { uid: 'u1', publish_details: { variants: {} } }; |
| 49 | + expect(getVariantAliases(entry3).variants).toEqual([]); |
| 50 | + }); |
| 51 | + |
| 52 | + it('skips variant objects with missing or empty alias', () => { |
| 53 | + const entry = { |
| 54 | + uid: 'u1', |
| 55 | + publish_details: { |
| 56 | + variants: { |
| 57 | + a: { alias: 'keep_me' }, |
| 58 | + b: { alias: '' }, |
| 59 | + c: {}, |
| 60 | + d: { alias: 'also_keep' }, |
| 61 | + }, |
| 62 | + }, |
| 63 | + }; |
| 64 | + const result = getVariantAliases(entry); |
| 65 | + expect(sortAliases(result.variants)).toEqual(sortAliases(['keep_me', 'also_keep'])); |
| 66 | + }); |
| 67 | + |
| 68 | + it('skips variant entries that are null, non-objects, or arrays', () => { |
| 69 | + const variants: Record<string, unknown> = { |
| 70 | + skip_null: null, |
| 71 | + skip_string: 'not-an-object', |
| 72 | + skip_array: [1, 2], |
| 73 | + keep: { alias: 'only_valid' }, |
| 74 | + }; |
| 75 | + const entry = { |
| 76 | + uid: 'u1', |
| 77 | + publish_details: { |
| 78 | + variants, |
| 79 | + }, |
| 80 | + }; |
| 81 | + const result = getVariantAliases(entry); |
| 82 | + expect(result.variants).toEqual(['only_valid']); |
| 83 | + }); |
| 84 | + |
| 85 | + it('throws when entry is null or undefined', () => { |
| 86 | + expect(() => getVariantAliases(null as unknown as Record<string, unknown>)).toThrow(); |
| 87 | + expect(() => getVariantAliases(undefined as unknown as Record<string, unknown>)).toThrow(); |
| 88 | + }); |
| 89 | + |
| 90 | + it('throws TypeError when single entry is a non-object (e.g. primitive)', () => { |
| 91 | + expect(() => getVariantAliases(42 as unknown as Record<string, unknown>)).toThrow(TypeError); |
| 92 | + expect(() => getVariantAliases('entry' as unknown as Record<string, unknown>)).toThrow(TypeError); |
| 93 | + }); |
| 94 | + |
| 95 | + it('throws TypeError when an array item is not a plain object', () => { |
| 96 | + expect(() => |
| 97 | + getVariantAliases([variantEntrySingle, [] as unknown as Record<string, unknown>]) |
| 98 | + ).toThrow(TypeError); |
| 99 | + }); |
| 100 | + |
| 101 | + it('throws when entry uid is missing or empty', () => { |
| 102 | + expect(() => getVariantAliases({})).toThrow(/uid/i); |
| 103 | + expect(() => getVariantAliases({ uid: '' })).toThrow(/uid/i); |
| 104 | + }); |
| 105 | + |
| 106 | + it('throws when entries array contains a non-object', () => { |
| 107 | + expect(() => getVariantAliases([variantEntrySingle, null as unknown as Record<string, unknown>])).toThrow(); |
| 108 | + }); |
| 109 | +}); |
| 110 | + |
| 111 | +describe('getVariantMetadataTags', () => { |
| 112 | + const contentTypeUid = 'movie'; |
| 113 | + |
| 114 | + it('serialises array results as JSON in data-csvariants', () => { |
| 115 | + const tag = getVariantMetadataTags(variantEntries, contentTypeUid); |
| 116 | + expect(tag).toHaveProperty('data-csvariants'); |
| 117 | + const parsed = JSON.parse(tag['data-csvariants']) as Array<{ |
| 118 | + entry_uid: string; |
| 119 | + contenttype_uid: string; |
| 120 | + variants: string[]; |
| 121 | + }>; |
| 122 | + expect(parsed).toHaveLength(3); |
| 123 | + expect(parsed[0].entry_uid).toBe('entry_uid_1'); |
| 124 | + expect(sortAliases(parsed[0].variants)).toEqual(sortAliases(['cs_personalize_0_0', 'cs_personalize_0_3'])); |
| 125 | + }); |
| 126 | + |
| 127 | + it('returns empty JSON array string for empty entries', () => { |
| 128 | + const tag = getVariantMetadataTags([]); |
| 129 | + expect(tag['data-csvariants']).toBe('[]'); |
| 130 | + }); |
| 131 | + |
| 132 | + it('throws when entries is null or not an array', () => { |
| 133 | + expect(() => getVariantMetadataTags(null as unknown as Record<string, unknown>[])).toThrow(); |
| 134 | + expect(() => getVariantMetadataTags({} as unknown as Record<string, unknown>[])).toThrow(); |
| 135 | + }); |
| 136 | +}); |
0 commit comments