|
| 1 | +import { Types } from 'mongoose'; |
| 2 | +import { filterAccessibleIdsBySharedLogic } from './format'; |
| 3 | + |
| 4 | +const id = () => new Types.ObjectId(); |
| 5 | + |
| 6 | +describe('filterAccessibleIdsBySharedLogic', () => { |
| 7 | + const ownedA = id(); |
| 8 | + const ownedB = id(); |
| 9 | + const sharedC = id(); |
| 10 | + const sharedD = id(); |
| 11 | + const publicE = id(); |
| 12 | + const publicF = id(); |
| 13 | + |
| 14 | + // accessible = everything the ACL resolver says this user can see |
| 15 | + const accessibleIds = [ownedA, ownedB, sharedC, sharedD]; |
| 16 | + const ownedPromptGroupIds = [ownedA, ownedB]; |
| 17 | + const publicPromptGroupIds = [publicE, publicF]; |
| 18 | + |
| 19 | + function toStrings(ids: Types.ObjectId[]) { |
| 20 | + return ids.map((i) => i.toString()).sort(); |
| 21 | + } |
| 22 | + |
| 23 | + describe('MY_PROMPTS (searchShared=false)', () => { |
| 24 | + it('returns only owned IDs when ownedPromptGroupIds provided', async () => { |
| 25 | + const result = await filterAccessibleIdsBySharedLogic({ |
| 26 | + accessibleIds, |
| 27 | + searchShared: false, |
| 28 | + searchSharedOnly: false, |
| 29 | + publicPromptGroupIds, |
| 30 | + ownedPromptGroupIds, |
| 31 | + }); |
| 32 | + expect(toStrings(result)).toEqual(toStrings([ownedA, ownedB])); |
| 33 | + }); |
| 34 | + |
| 35 | + it('legacy fallback: excludes public IDs when ownedPromptGroupIds omitted', async () => { |
| 36 | + // accessible includes a public ID for this test |
| 37 | + const accessible = [ownedA, ownedB, publicE]; |
| 38 | + const result = await filterAccessibleIdsBySharedLogic({ |
| 39 | + accessibleIds: accessible, |
| 40 | + searchShared: false, |
| 41 | + searchSharedOnly: false, |
| 42 | + publicPromptGroupIds, |
| 43 | + }); |
| 44 | + // Should exclude publicE, keep ownedA and ownedB |
| 45 | + expect(toStrings(result)).toEqual(toStrings([ownedA, ownedB])); |
| 46 | + }); |
| 47 | + }); |
| 48 | + |
| 49 | + describe('SHARED_PROMPTS (searchSharedOnly=true)', () => { |
| 50 | + it('returns accessible + public minus owned when ownedPromptGroupIds provided', async () => { |
| 51 | + const result = await filterAccessibleIdsBySharedLogic({ |
| 52 | + accessibleIds, |
| 53 | + searchShared: true, |
| 54 | + searchSharedOnly: true, |
| 55 | + publicPromptGroupIds, |
| 56 | + ownedPromptGroupIds, |
| 57 | + }); |
| 58 | + // Should include sharedC, sharedD, publicE, publicF (not ownedA, ownedB) |
| 59 | + expect(toStrings(result)).toEqual(toStrings([sharedC, sharedD, publicE, publicF])); |
| 60 | + }); |
| 61 | + |
| 62 | + it('deduplicates when an ID appears in both accessible and public', async () => { |
| 63 | + const overlap = id(); |
| 64 | + const result = await filterAccessibleIdsBySharedLogic({ |
| 65 | + accessibleIds: [ownedA, overlap], |
| 66 | + searchShared: true, |
| 67 | + searchSharedOnly: true, |
| 68 | + publicPromptGroupIds: [overlap, publicE], |
| 69 | + ownedPromptGroupIds: [ownedA], |
| 70 | + }); |
| 71 | + // overlap should appear once, not twice |
| 72 | + expect(toStrings(result)).toEqual(toStrings([overlap, publicE])); |
| 73 | + }); |
| 74 | + |
| 75 | + it('legacy fallback: returns intersection of public and accessible when ownedPromptGroupIds omitted', async () => { |
| 76 | + // publicE is also accessible |
| 77 | + const accessible = [ownedA, publicE]; |
| 78 | + const result = await filterAccessibleIdsBySharedLogic({ |
| 79 | + accessibleIds: accessible, |
| 80 | + searchShared: true, |
| 81 | + searchSharedOnly: true, |
| 82 | + publicPromptGroupIds: [publicE, publicF], |
| 83 | + }); |
| 84 | + // Only publicE is in both accessible and public |
| 85 | + expect(toStrings(result)).toEqual(toStrings([publicE])); |
| 86 | + }); |
| 87 | + |
| 88 | + it('legacy fallback: returns empty when no public IDs', async () => { |
| 89 | + const result = await filterAccessibleIdsBySharedLogic({ |
| 90 | + accessibleIds, |
| 91 | + searchShared: true, |
| 92 | + searchSharedOnly: true, |
| 93 | + publicPromptGroupIds: [], |
| 94 | + }); |
| 95 | + expect(result).toEqual([]); |
| 96 | + }); |
| 97 | + }); |
| 98 | + |
| 99 | + describe('ALL (searchShared=true, searchSharedOnly=false)', () => { |
| 100 | + it('returns union of accessible + public, deduplicated', async () => { |
| 101 | + const result = await filterAccessibleIdsBySharedLogic({ |
| 102 | + accessibleIds, |
| 103 | + searchShared: true, |
| 104 | + searchSharedOnly: false, |
| 105 | + publicPromptGroupIds, |
| 106 | + ownedPromptGroupIds, |
| 107 | + }); |
| 108 | + expect(toStrings(result)).toEqual( |
| 109 | + toStrings([ownedA, ownedB, sharedC, sharedD, publicE, publicF]), |
| 110 | + ); |
| 111 | + }); |
| 112 | + |
| 113 | + it('deduplicates overlapping IDs', async () => { |
| 114 | + const overlap = id(); |
| 115 | + const result = await filterAccessibleIdsBySharedLogic({ |
| 116 | + accessibleIds: [ownedA, overlap], |
| 117 | + searchShared: true, |
| 118 | + searchSharedOnly: false, |
| 119 | + publicPromptGroupIds: [overlap, publicE], |
| 120 | + ownedPromptGroupIds, |
| 121 | + }); |
| 122 | + expect(toStrings(result)).toEqual(toStrings([ownedA, overlap, publicE])); |
| 123 | + }); |
| 124 | + }); |
| 125 | +}); |
0 commit comments