experiments in a post-browser web
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

test: add integration tests for tag-centric events

4 new tests in smoke.spec.ts:
- tag:created emitted when new tag created
- tag:item-added emitted when item tagged
- tag:item-removed emitted when item untagged
- tag:item-added NOT emitted for duplicate tag

+205
+205
tests/desktop/smoke.spec.ts
··· 921 921 }); 922 922 923 923 // ============================================================================ 924 + // Tag Events Tests (uses shared app) 925 + // ============================================================================ 926 + 927 + test.describe('Tag Events @desktop', () => { 928 + let bgWindow: Page; 929 + 930 + test.beforeAll(async () => { 931 + bgWindow = sharedBgWindow; 932 + }); 933 + 934 + test('tag:created is emitted when new tag is created', async () => { 935 + const timestamp = Date.now(); 936 + const tagName = `event-test-tag-${timestamp}`; 937 + 938 + const result = await bgWindow.evaluate(async (name: string) => { 939 + const api = (window as any).app; 940 + 941 + return new Promise((resolve) => { 942 + const timeout = setTimeout(() => { 943 + resolve({ received: false }); 944 + }, 5000); 945 + 946 + api.subscribe('tag:created', (msg: any) => { 947 + if (msg.tagName === name) { 948 + clearTimeout(timeout); 949 + resolve({ 950 + received: true, 951 + tagId: msg.tagId, 952 + tagName: msg.tagName 953 + }); 954 + } 955 + }, api.scopes.GLOBAL); 956 + 957 + // Create new tag to trigger the event 958 + api.datastore.getOrCreateTag(name); 959 + }); 960 + }, tagName); 961 + 962 + expect((result as any).received).toBe(true); 963 + expect((result as any).tagName).toBe(tagName); 964 + expect((result as any).tagId).toBeTruthy(); 965 + }); 966 + 967 + test('tag:item-added is emitted when item is tagged', async () => { 968 + const timestamp = Date.now(); 969 + const tagName = `item-added-event-tag-${timestamp}`; 970 + 971 + const result = await bgWindow.evaluate(async (name: string) => { 972 + const api = (window as any).app; 973 + 974 + // First create an item and a tag 975 + const itemResult = await api.datastore.addItem('url', { 976 + content: `https://tag-event-test-${Date.now()}.example.com`, 977 + metadata: JSON.stringify({ title: 'Tag Event Test Item' }) 978 + }); 979 + if (!itemResult.success) { 980 + return { received: false, error: 'failed to create item' }; 981 + } 982 + const itemId = itemResult.data.id; 983 + 984 + const tagResult = await api.datastore.getOrCreateTag(name); 985 + if (!tagResult.success) { 986 + return { received: false, error: 'failed to create tag' }; 987 + } 988 + const tagId = tagResult.data.tag.id; 989 + 990 + return new Promise((resolve) => { 991 + const timeout = setTimeout(() => { 992 + resolve({ received: false, error: 'timeout' }); 993 + }, 5000); 994 + 995 + api.subscribe('tag:item-added', (msg: any) => { 996 + if (msg.itemId === itemId && msg.tagId === tagId) { 997 + clearTimeout(timeout); 998 + resolve({ 999 + received: true, 1000 + tagId: msg.tagId, 1001 + tagName: msg.tagName, 1002 + itemId: msg.itemId, 1003 + itemType: msg.itemType 1004 + }); 1005 + } 1006 + }, api.scopes.GLOBAL); 1007 + 1008 + // Tag the item to trigger the event 1009 + api.datastore.tagItem(itemId, tagId); 1010 + }); 1011 + }, tagName); 1012 + 1013 + expect((result as any).received).toBe(true); 1014 + expect((result as any).tagName).toBe(tagName); 1015 + expect((result as any).tagId).toBeTruthy(); 1016 + expect((result as any).itemId).toBeTruthy(); 1017 + expect((result as any).itemType).toBe('url'); 1018 + }); 1019 + 1020 + test('tag:item-removed is emitted when item is untagged', async () => { 1021 + const timestamp = Date.now(); 1022 + const tagName = `item-removed-event-tag-${timestamp}`; 1023 + 1024 + const result = await bgWindow.evaluate(async (name: string) => { 1025 + const api = (window as any).app; 1026 + 1027 + // Create an item 1028 + const itemResult = await api.datastore.addItem('url', { 1029 + content: `https://untag-event-test-${Date.now()}.example.com`, 1030 + metadata: JSON.stringify({ title: 'Untag Event Test Item' }) 1031 + }); 1032 + if (!itemResult.success) { 1033 + return { received: false, error: 'failed to create item' }; 1034 + } 1035 + const itemId = itemResult.data.id; 1036 + 1037 + // Create a tag 1038 + const tagResult = await api.datastore.getOrCreateTag(name); 1039 + if (!tagResult.success) { 1040 + return { received: false, error: 'failed to create tag' }; 1041 + } 1042 + const tagId = tagResult.data.tag.id; 1043 + 1044 + // Tag the item first 1045 + await api.datastore.tagItem(itemId, tagId); 1046 + 1047 + return new Promise((resolve) => { 1048 + const timeout = setTimeout(() => { 1049 + resolve({ received: false, error: 'timeout' }); 1050 + }, 5000); 1051 + 1052 + api.subscribe('tag:item-removed', (msg: any) => { 1053 + if (msg.itemId === itemId && msg.tagId === tagId) { 1054 + clearTimeout(timeout); 1055 + resolve({ 1056 + received: true, 1057 + tagId: msg.tagId, 1058 + tagName: msg.tagName, 1059 + itemId: msg.itemId 1060 + }); 1061 + } 1062 + }, api.scopes.GLOBAL); 1063 + 1064 + // Untag the item to trigger the event 1065 + api.datastore.untagItem(itemId, tagId); 1066 + }); 1067 + }, tagName); 1068 + 1069 + expect((result as any).received).toBe(true); 1070 + expect((result as any).tagName).toBe(tagName); 1071 + expect((result as any).tagId).toBeTruthy(); 1072 + expect((result as any).itemId).toBeTruthy(); 1073 + }); 1074 + 1075 + test('tag:item-added is NOT emitted for duplicate tag', async () => { 1076 + const timestamp = Date.now(); 1077 + const tagName = `duplicate-tag-event-${timestamp}`; 1078 + 1079 + const result = await bgWindow.evaluate(async (name: string) => { 1080 + const api = (window as any).app; 1081 + 1082 + // Create an item 1083 + const itemResult = await api.datastore.addItem('url', { 1084 + content: `https://duplicate-tag-test-${Date.now()}.example.com`, 1085 + metadata: JSON.stringify({ title: 'Duplicate Tag Test Item' }) 1086 + }); 1087 + if (!itemResult.success) { 1088 + return { received: false, error: 'failed to create item' }; 1089 + } 1090 + const itemId = itemResult.data.id; 1091 + 1092 + // Create a tag 1093 + const tagResult = await api.datastore.getOrCreateTag(name); 1094 + if (!tagResult.success) { 1095 + return { received: false, error: 'failed to create tag' }; 1096 + } 1097 + const tagId = tagResult.data.tag.id; 1098 + 1099 + // Tag the item for the first time (this should emit an event but we don't care) 1100 + await api.datastore.tagItem(itemId, tagId); 1101 + 1102 + // Wait a bit to ensure the first event has been processed 1103 + await new Promise(r => setTimeout(r, 100)); 1104 + 1105 + return new Promise((resolve) => { 1106 + // Use a short timeout since we expect NO event 1107 + const timeout = setTimeout(() => { 1108 + resolve({ received: false }); // This is the expected outcome 1109 + }, 1000); 1110 + 1111 + api.subscribe('tag:item-added', (msg: any) => { 1112 + if (msg.itemId === itemId && msg.tagId === tagId) { 1113 + clearTimeout(timeout); 1114 + resolve({ received: true }); // This would be unexpected 1115 + } 1116 + }, api.scopes.GLOBAL); 1117 + 1118 + // Try to tag the same item with the same tag again 1119 + api.datastore.tagItem(itemId, tagId); 1120 + }); 1121 + }, tagName); 1122 + 1123 + // We expect NO event to be received for duplicate tagging 1124 + expect((result as any).received).toBe(false); 1125 + }); 1126 + }); 1127 + 1128 + // ============================================================================ 924 1129 // Groups View Tests (uses shared app) 925 1130 // ============================================================================ 926 1131