From 35951ed068a39e9d471cf191c73c02ecbeede7df Mon Sep 17 00:00:00 2001 From: Clara Youdale Date: Wed, 29 Nov 2023 13:08:43 -0300 Subject: [PATCH 01/15] Create 2023.11.29T14.56.25.delete-duplicated-subscriptions.js Migration that removes duplicates in subscriptions collection --- ...4.56.25.delete-duplicated-subscriptions.js | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js diff --git a/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js b/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js new file mode 100644 index 0000000000..35064fc693 --- /dev/null +++ b/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js @@ -0,0 +1,74 @@ +const config = require('../config'); + +/** @type {import('umzug').MigrationFn} */ +exports.up = async ({ context: { client } }) => { + const db = client.db(config.realm.production_db.db_custom_data); + + const subscriptions = db.collection('subscriptions'); + + // Remove duplicates of type "incident", "new-incidents" and "submission-promoted", based on type, incident_id and userId + subscriptions + .aggregate([ + { + $match: { + type: { $in: ['incident', 'new-incidents', 'submission-promoted'] }, + }, + }, + { + $group: { + _id: { incident_id: '$incident_id', type: '$type', userId: '$userId' }, + uniqueIds: { $addToSet: '$_id' }, + count: { $sum: 1 }, + }, + }, + { + $match: { + count: { $gt: 1 }, + }, + }, + ]) + .forEach(function (doc) { + if (doc._id.incident_id && doc._id.type && doc._id.userId) { + console.log( + `Removing ${doc.count - 1} duplicated subscriptions for incident ${ + doc._id.incident_id + } of type ${doc._id.type} for user ${doc._id.userId}` + ); + doc.uniqueIds.pop(); // Remove one from the array to keep + subscriptions.deleteOne({ _id: { $in: doc.uniqueIds } }); + } + }); + + // Remove duplicates of type "entity", based on type, entityId and userId + subscriptions + .aggregate([ + { + $match: { + type: { $in: ['entity'] }, + }, + }, + { + $group: { + _id: { entityId: '$entityId', type: '$type', userId: '$userId' }, + uniqueIds: { $addToSet: '$_id' }, + count: { $sum: 1 }, + }, + }, + { + $match: { + count: { $gt: 1 }, + }, + }, + ]) + .forEach(function (doc) { + if (doc._id.entityId && doc._id.type && doc._id.userId) { + console.log( + `Removing ${doc.count - 1} duplicated subscriptions for entity ${ + doc._id.entityId + } of type ${doc._id.type} for user ${doc._id.userId}` + ); + doc.uniqueIds.pop(); // Remove one from the array to keep + subscriptions.deleteOne({ _id: { $in: doc.uniqueIds } }); + } + }); +}; From 1deef8f1e2c597fed44532f77c62f3d421ce7d7d Mon Sep 17 00:00:00 2001 From: Luna McNulty Date: Tue, 5 Dec 2023 11:53:32 -0500 Subject: [PATCH 02/15] Factor common checklist test logic --- .../e2e/integration/apps/checklistsForm.cy.js | 126 +++++++----------- 1 file changed, 45 insertions(+), 81 deletions(-) diff --git a/site/gatsby-site/cypress/e2e/integration/apps/checklistsForm.cy.js b/site/gatsby-site/cypress/e2e/integration/apps/checklistsForm.cy.js index 89dee79b86..1875c438b9 100644 --- a/site/gatsby-site/cypress/e2e/integration/apps/checklistsForm.cy.js +++ b/site/gatsby-site/cypress/e2e/integration/apps/checklistsForm.cy.js @@ -4,6 +4,18 @@ const { gql } = require('@apollo/client'); describe('Checklists App Form', () => { const url = '/apps/checklists?id=testChecklist'; + const defaultChecklist = { + __typename: 'Checklist', + about: '', + id: 'testChecklist', + name: 'Test Checklist', + owner_id: 'a-fake-user-id-that-does-not-exist', + risks: [], + tags_goals: [], + tags_methods: [], + tags_other: [], + }; + const usersQuery = { query: gql` { @@ -19,27 +31,36 @@ describe('Checklists App Form', () => { timeout: 120000, // mongodb admin api is extremely slow }; - it('Should have read-only access for non-logged-in users', () => { + const withLogin = (callback) => { + cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword')); + + cy.query(usersQuery).then(({ data: { users } }) => { + const user = users.find((user) => user.adminData.email == Cypress.env('e2eUsername')); + + callback({ user }); + }); + }; + + const interceptFindChecklist = (checklist) => { cy.conditionalIntercept( '**/graphql', (req) => req.body.operationName == 'findChecklist', 'findChecklist', - { - data: { - checklist: { - __typename: 'Checklist', - about: '', - id: 'testChecklist', - name: 'Test Checklist', - owner_id: 'a-fake-user-id-that-does-not-exist', - risks: [], - tags_goals: [], - tags_methods: [], - tags_other: [], - }, - }, - } + { data: { checklist } } ); + }; + + const interceptUpsertChecklist = (checklist) => { + cy.conditionalIntercept( + '**/graphql', + (req) => req.body.operationName == 'upsertChecklist', + 'upsertChecklist', + { data: { checklist } } + ); + }; + + it('Should have read-only access for non-logged-in users', () => { + interceptFindChecklist(defaultChecklist); cy.visit(url); @@ -55,26 +76,7 @@ describe('Checklists App Form', () => { maybeIt('Should have read-only access for logged-in non-owners', () => { cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword')); - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'findChecklist', - 'findChecklist', - { - data: { - checklist: { - __typename: 'Checklist', - about: '', - id: 'testChecklist', - name: 'Test Checklist', - owner_id: 'a-fake-user-id-that-does-not-exist', - risks: [], - tags_goals: [], - tags_methods: [], - tags_other: [], - }, - }, - } - ); + interceptFindChecklist(defaultChecklist); cy.visit(url); @@ -88,51 +90,13 @@ describe('Checklists App Form', () => { }); maybeIt('Should allow editing for owner', () => { - cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword')); - - cy.query(usersQuery).then(({ data: { users } }) => { - const user = users.find((user) => user.adminData.email == Cypress.env('e2eUsername')); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'findChecklist', - 'findChecklist', - { - data: { - checklist: { - __typename: 'Checklist', - about: '', - id: 'testChecklist', - name: 'Test Checklist', - owner_id: user.userId, - risks: [], - tags_goals: [], - tags_methods: [], - tags_other: [], - }, - }, - } - ); - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'upsertChecklist', - 'upsertChecklist', - { - data: { - checklist: { - __typename: 'Checklist', - about: "It's a system that does something probably.", - id: 'testChecklist', - name: 'Test Checklist', - owner_id: user.userId, - risks: [], - tags_goals: [], - tags_methods: [], - tags_other: [], - }, - }, - } - ); + withLogin(({ user }) => { + interceptFindChecklist({ ...defaultChecklist, owner_id: user.userId }); + interceptUpsertChecklist({ + ...defaultChecklist, + owner_id: user.userId, + about: "It's a system that does something probably.", + }); cy.visit(url); From f158362579aabc0a2d54c3ee36956917a75ef9b3 Mon Sep 17 00:00:00 2001 From: Pablo Costa Date: Thu, 7 Dec 2023 17:53:02 -0300 Subject: [PATCH 03/15] Add migration to mark all pending notifications as processed --- ...09.mark-pending-notifications-as-processed.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 site/gatsby-site/migrations/2023.12.07T20.45.09.mark-pending-notifications-as-processed.js diff --git a/site/gatsby-site/migrations/2023.12.07T20.45.09.mark-pending-notifications-as-processed.js b/site/gatsby-site/migrations/2023.12.07T20.45.09.mark-pending-notifications-as-processed.js new file mode 100644 index 0000000000..59a6e9b0b9 --- /dev/null +++ b/site/gatsby-site/migrations/2023.12.07T20.45.09.mark-pending-notifications-as-processed.js @@ -0,0 +1,16 @@ +const config = require('../config'); + +/** @type {import('umzug').MigrationFn} */ +exports.up = async ({ context: { client } }) => { + const db = client.db(config.realm.production_db.db_custom_data); + + const notifications = db.collection('notifications'); + + // Mark all pending notifications as processed + const result = await notifications.updateMany( + { processed: false }, + { $set: { processed: true } } + ); + + console.log(`All pending notifications marked as processed. Total: ${result.modifiedCount}`); +}; From eb55422c317a823425f56d1ee657560f0b3a8e2d Mon Sep 17 00:00:00 2001 From: kepae Date: Thu, 7 Dec 2023 17:33:53 -0500 Subject: [PATCH 04/15] Add Slack badge to README To do: Create link to form for invites, rather than link to the slack workspace directly. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 40d13219c0..250833f1a8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Artificial Intelligence Incident Database (AIID) [![Netlify Status](https://api.netlify.com/api/v1/badges/9eb0dda2-916c-46f9-a0bd-9ddab3879c6e/deploy-status)](https://app.netlify.com/sites/aiid/deploys) +[![Slack Link](https://img.shields.io/badge/Join%20the%20RAIC%20Slack!-purple?logo=slack)](https://raicollab.slack.com) Information about the goals and organization of the AI Incident Database can be found on the [production website](https://incidentdatabase.ai/). This page concentrates on onboarding for the following types of contributions to the database, From 89d764d48a3830d120f2e75f1b3d7ee45f3f6ee5 Mon Sep 17 00:00:00 2001 From: Clara Youdale Date: Fri, 8 Dec 2023 09:37:21 -0300 Subject: [PATCH 05/15] Fix migration to delete all duplicates --- ...4.56.25.delete-duplicated-subscriptions.js | 65 ++++++++++++------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js b/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js index 35064fc693..b414f3c1a9 100644 --- a/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js +++ b/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js @@ -1,3 +1,5 @@ +const { ObjectID } = require('bson'); + const config = require('../config'); /** @type {import('umzug').MigrationFn} */ @@ -7,7 +9,8 @@ exports.up = async ({ context: { client } }) => { const subscriptions = db.collection('subscriptions'); // Remove duplicates of type "incident", "new-incidents" and "submission-promoted", based on type, incident_id and userId - subscriptions + + const result = await subscriptions .aggregate([ { $match: { @@ -27,20 +30,28 @@ exports.up = async ({ context: { client } }) => { }, }, ]) - .forEach(function (doc) { - if (doc._id.incident_id && doc._id.type && doc._id.userId) { - console.log( - `Removing ${doc.count - 1} duplicated subscriptions for incident ${ - doc._id.incident_id - } of type ${doc._id.type} for user ${doc._id.userId}` - ); - doc.uniqueIds.pop(); // Remove one from the array to keep - subscriptions.deleteOne({ _id: { $in: doc.uniqueIds } }); - } - }); + .toArray(); + + for (const doc of result) { + const uniqueIds = doc.uniqueIds.map((id) => new ObjectID(id)); + + if (doc._id.incident_id && doc._id.type && doc._id.userId) { + console.log( + `Removing ${doc.count - 1} duplicated subscriptions for incident ${ + doc._id.incident_id + } of type ${doc._id.type} for user ${doc._id.userId}` + ); + uniqueIds.pop(); // Remove one from the array to keep + const deleteResult = await subscriptions.deleteMany({ + _id: { $in: uniqueIds }, + }); + + console.log('Delete Result: ', deleteResult); + } + } // Remove duplicates of type "entity", based on type, entityId and userId - subscriptions + const resultEntities = await subscriptions .aggregate([ { $match: { @@ -60,15 +71,21 @@ exports.up = async ({ context: { client } }) => { }, }, ]) - .forEach(function (doc) { - if (doc._id.entityId && doc._id.type && doc._id.userId) { - console.log( - `Removing ${doc.count - 1} duplicated subscriptions for entity ${ - doc._id.entityId - } of type ${doc._id.type} for user ${doc._id.userId}` - ); - doc.uniqueIds.pop(); // Remove one from the array to keep - subscriptions.deleteOne({ _id: { $in: doc.uniqueIds } }); - } - }); + .toArray(); + + for (const doc of resultEntities) { + const uniqueIds = doc.uniqueIds.map((id) => new ObjectID(id)); + + if (doc._id.entityId && doc._id.type && doc._id.userId) { + console.log( + `Removing ${doc.count - 1} duplicated subscriptions for entity ${ + doc._id.entityId + } of type ${doc._id.type} for user ${doc._id.userId}` + ); + uniqueIds.pop(); // Remove one from the array to keep + const deleteResult = await subscriptions.deleteMany({ _id: { $in: uniqueIds } }); + + console.log('Delete Result: ', deleteResult); + } + } }; From 86d06eb94866bf4b45e78c76e4dc3895333a1ca5 Mon Sep 17 00:00:00 2001 From: Luna McNulty Date: Mon, 11 Dec 2023 01:37:03 -0500 Subject: [PATCH 06/15] Fix = vs == in find user --- site/gatsby-site/src/components/checklists/CheckListForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/gatsby-site/src/components/checklists/CheckListForm.js b/site/gatsby-site/src/components/checklists/CheckListForm.js index 554ecda6ba..4e77fde626 100644 --- a/site/gatsby-site/src/components/checklists/CheckListForm.js +++ b/site/gatsby-site/src/components/checklists/CheckListForm.js @@ -36,7 +36,7 @@ export default function CheckListForm({ const userIsOwner = values.owner_id == user.id; - const owner = users.find((u) => (u.userId = values.owner_id)); + const owner = users.find((u) => u.userId == values.owner_id); const [deleteChecklist] = useMutation(DELETE_CHECKLIST); From 63a9e31cc689cb62653bf32397ac84f9e2ee1915 Mon Sep 17 00:00:00 2001 From: Clara Youdale Date: Mon, 11 Dec 2023 10:04:47 -0300 Subject: [PATCH 07/15] Fix migration to remove duplicates of new-incidents --- ...4.56.25.delete-duplicated-subscriptions.js | 72 ++++++++++++------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js b/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js index b414f3c1a9..0ba731729d 100644 --- a/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js +++ b/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js @@ -14,7 +14,7 @@ exports.up = async ({ context: { client } }) => { .aggregate([ { $match: { - type: { $in: ['incident', 'new-incidents', 'submission-promoted'] }, + type: { $in: ['incident', 'submission-promoted'] }, }, }, { @@ -32,23 +32,7 @@ exports.up = async ({ context: { client } }) => { ]) .toArray(); - for (const doc of result) { - const uniqueIds = doc.uniqueIds.map((id) => new ObjectID(id)); - - if (doc._id.incident_id && doc._id.type && doc._id.userId) { - console.log( - `Removing ${doc.count - 1} duplicated subscriptions for incident ${ - doc._id.incident_id - } of type ${doc._id.type} for user ${doc._id.userId}` - ); - uniqueIds.pop(); // Remove one from the array to keep - const deleteResult = await subscriptions.deleteMany({ - _id: { $in: uniqueIds }, - }); - - console.log('Delete Result: ', deleteResult); - } - } + await removeDuplicates(subscriptions, result); // Remove duplicates of type "entity", based on type, entityId and userId const resultEntities = await subscriptions @@ -73,19 +57,57 @@ exports.up = async ({ context: { client } }) => { ]) .toArray(); - for (const doc of resultEntities) { + await removeDuplicates(subscriptions, resultEntities); + + // Remove duplicates of type "incident", "new-incidents" and "submission-promoted", based on type, incident_id and userId + + const resultNewIncidents = await subscriptions + .aggregate([ + { + $match: { + type: { $in: ['new-incidents'] }, + }, + }, + { + $group: { + _id: { incident_id: '$incident_id', type: '$type', userId: '$userId' }, + uniqueIds: { $addToSet: '$_id' }, + count: { $sum: 1 }, + }, + }, + { + $match: { + count: { $gt: 1 }, + }, + }, + ]) + .toArray(); + + await removeDuplicates(subscriptions, resultNewIncidents); +}; + +async function removeDuplicates(subscriptions, results) { + for (const doc of results) { const uniqueIds = doc.uniqueIds.map((id) => new ObjectID(id)); - if (doc._id.entityId && doc._id.type && doc._id.userId) { + if (doc._id.type && doc._id.userId) { console.log( - `Removing ${doc.count - 1} duplicated subscriptions for entity ${ - doc._id.entityId - } of type ${doc._id.type} for user ${doc._id.userId}` + `Removing ${doc.count - 1} duplicated subscriptions of type ${doc._id.type} for user ${ + doc._id.userId + } ${ + doc._id.incident_id + ? ' and for incident ' + doc._id.incident_id + : doc._id.entityId + ? ' and for entity ' + doc._id.entityId + : '' + }` ); uniqueIds.pop(); // Remove one from the array to keep - const deleteResult = await subscriptions.deleteMany({ _id: { $in: uniqueIds } }); + const deleteResult = await subscriptions.deleteMany({ + _id: { $in: uniqueIds }, + }); console.log('Delete Result: ', deleteResult); } } -}; +} From 535c48dcf19f62df05f92538881e5c900dc05c62 Mon Sep 17 00:00:00 2001 From: kepae Date: Mon, 11 Dec 2023 16:43:37 -0500 Subject: [PATCH 08/15] nit: update comments --- .../2023.11.29T14.56.25.delete-duplicated-subscriptions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js b/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js index 0ba731729d..2a29269487 100644 --- a/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js +++ b/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js @@ -8,7 +8,7 @@ exports.up = async ({ context: { client } }) => { const subscriptions = db.collection('subscriptions'); - // Remove duplicates of type "incident", "new-incidents" and "submission-promoted", based on type, incident_id and userId + // Remove duplicates of type "incident" and "submission-promoted", based on type, incident_id and userId const result = await subscriptions .aggregate([ From 32a55fa9866446b44bf13b675e1e4a03a7c2ba54 Mon Sep 17 00:00:00 2001 From: kepae Date: Mon, 11 Dec 2023 16:44:00 -0500 Subject: [PATCH 09/15] nit: update comments --- .../2023.11.29T14.56.25.delete-duplicated-subscriptions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js b/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js index 2a29269487..51b44f3d86 100644 --- a/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js +++ b/site/gatsby-site/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.js @@ -59,7 +59,7 @@ exports.up = async ({ context: { client } }) => { await removeDuplicates(subscriptions, resultEntities); - // Remove duplicates of type "incident", "new-incidents" and "submission-promoted", based on type, incident_id and userId + // Remove duplicates of type "new-incidents" based on type, incident_id and userId const resultNewIncidents = await subscriptions .aggregate([ From 9d4a2d4472b87f4cba789f3acc271b8fc3bc6a5f Mon Sep 17 00:00:00 2001 From: Clara Youdale Date: Tue, 12 Dec 2023 17:06:55 -0300 Subject: [PATCH 10/15] Add test for delete duplicate migration --- ...6.25.delete-duplicated-subscriptions.cy.js | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 site/gatsby-site/cypress/e2e/unit/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.cy.js diff --git a/site/gatsby-site/cypress/e2e/unit/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.cy.js b/site/gatsby-site/cypress/e2e/unit/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.cy.js new file mode 100644 index 0000000000..a64e9fc16e --- /dev/null +++ b/site/gatsby-site/cypress/e2e/unit/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.cy.js @@ -0,0 +1,144 @@ +const { ObjectID } = require('bson'); + +const { + up, +} = require('../../../../migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions'); + +describe('Migration Script - Remove Duplicated Subscriptions', () => { + it('Should remove duplicated subscriptions correctly', () => { + // Mocked data for all three cases + const testSubscriptions = { + incident: [ + { + _id: { + type: 'incident', + userId: '642188372947d07020c1319d', + incident_id: 600, + }, + uniqueIds: [ + new ObjectID('5f9f6b9b5f9c4c0001a3b3a3'), + new ObjectID('5f9f6b9b5f9c4c0001a3b3a4'), + ], + }, + { + _id: { + type: 'submission-promoted', + userId: '642188372947d07020c1319d', + incident_id: 600, + }, + uniqueIds: [ + new ObjectID('5f9f6b9b5f9c4c0001a3b3a0'), + new ObjectID('5f9f6b9b5f9c4c0001a3b3a1'), + new ObjectID('5f9f6b9b5f9c4c0001a3b3a2'), + ], + }, + ], + entity: [ + { + _id: { + type: 'entity', + userId: '642188372947d07020c1319d', + entity_id: 'trans-women', + }, + uniqueIds: ['5f9f6b9b5f9c4c0001a3b3a5', '5f9f6b9b5f9c4c0001a3b3a6'], + }, + ], + 'new-incidents': [ + { + _id: { + type: 'new-incidents', + userId: '642188372947d07020c1319d', + }, + uniqueIds: ['5f9f6b9b5f9c4c0001a3b3a7', '5f9f6b9b5f9c4c0001a3b3a8'], + }, + ], + }; + + // Mocked collection with stubbed methods + const subscriptionsCollection = { + aggregate: cy.stub().callsFake((query) => { + const type = query[0].$match.type.$in[0]; + + console.log(type); + return { + toArray: cy.stub().resolves(testSubscriptions[type]), + }; + }), + deleteMany: cy.stub().callsFake((query) => { + console.log('deleteMany called with:', query._id.$in[0].toString()); // Log the query + return Promise.resolve({ deletedCount: 1 }); + }), + }; + + // Mocked context with database client + const context = { + client: { + db: cy.stub().returns({ + collection: cy.stub().withArgs('subscriptions').returns(subscriptionsCollection), + }), + }, + }; + + // Execute the migration script + cy.wrap(up({ context })).then(() => { + // Assertions for each case + const args = subscriptionsCollection.deleteMany.getCall(0).args[0]; + + const argsSubmissionPromoted = subscriptionsCollection.deleteMany.getCall(1).args[0]; + + const argsEntity = subscriptionsCollection.deleteMany.getCall(2).args[0]; + + const argsNewIncidents = subscriptionsCollection.deleteMany.getCall(3).args[0]; + + let modifiedObjectIncident = { + _id: { + $in: args._id.$in.map((id) => id.toString()), + }, + }; + + let modifiedObjectSubmissionPromoted = { + _id: { + $in: argsSubmissionPromoted._id.$in.map((id) => id.toString()), + }, + }; + + let modifiedObjectEntity = { + _id: { + $in: argsEntity._id.$in.map((id) => id.toString()), + }, + }; + + let modifiedObjectNewIncidents = { + _id: { + $in: argsNewIncidents._id.$in.map((id) => id.toString()), + }, + }; + + expect(modifiedObjectIncident).to.be.deep.equal({ + _id: { + $in: testSubscriptions['incident'][0].uniqueIds.slice(0, 1).map((id) => id.toString()), + }, + }); + + expect(modifiedObjectSubmissionPromoted).to.be.deep.equal({ + _id: { + $in: testSubscriptions['incident'][1].uniqueIds.slice(0, 2).map((id) => id.toString()), + }, + }); + + expect(modifiedObjectEntity).to.be.deep.equal({ + _id: { + $in: testSubscriptions['entity'][0].uniqueIds.slice(0, 1).map((id) => id.toString()), + }, + }); + + expect(modifiedObjectNewIncidents).to.be.deep.equal({ + _id: { + $in: testSubscriptions['new-incidents'][0].uniqueIds + .slice(0, 1) + .map((id) => id.toString()), + }, + }); + }); + }); +}); From c85934d5c1097fc47d9d2c4568a3da39ab8d34c1 Mon Sep 17 00:00:00 2001 From: Clara Youdale Date: Wed, 13 Dec 2023 09:04:40 -0300 Subject: [PATCH 11/15] keep consistency in object IDs --- ....29T14.56.25.delete-duplicated-subscriptions.cy.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/site/gatsby-site/cypress/e2e/unit/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.cy.js b/site/gatsby-site/cypress/e2e/unit/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.cy.js index a64e9fc16e..956861ad3d 100644 --- a/site/gatsby-site/cypress/e2e/unit/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.cy.js +++ b/site/gatsby-site/cypress/e2e/unit/migrations/2023.11.29T14.56.25.delete-duplicated-subscriptions.cy.js @@ -40,7 +40,10 @@ describe('Migration Script - Remove Duplicated Subscriptions', () => { userId: '642188372947d07020c1319d', entity_id: 'trans-women', }, - uniqueIds: ['5f9f6b9b5f9c4c0001a3b3a5', '5f9f6b9b5f9c4c0001a3b3a6'], + uniqueIds: [ + new ObjectID('5f9f6b9b5f9c4c0001a3b3a5'), + new ObjectID('5f9f6b9b5f9c4c0001a3b3a6'), + ], }, ], 'new-incidents': [ @@ -49,7 +52,10 @@ describe('Migration Script - Remove Duplicated Subscriptions', () => { type: 'new-incidents', userId: '642188372947d07020c1319d', }, - uniqueIds: ['5f9f6b9b5f9c4c0001a3b3a7', '5f9f6b9b5f9c4c0001a3b3a8'], + uniqueIds: [ + new ObjectID('5f9f6b9b5f9c4c0001a3b3a7'), + new ObjectID('5f9f6b9b5f9c4c0001a3b3a8'), + ], }, ], }; @@ -59,7 +65,6 @@ describe('Migration Script - Remove Duplicated Subscriptions', () => { aggregate: cy.stub().callsFake((query) => { const type = query[0].$match.type.$in[0]; - console.log(type); return { toArray: cy.stub().resolves(testSubscriptions[type]), }; From fb32a52f076e4305cfc2eb9dd76e2090c74e1dae Mon Sep 17 00:00:00 2001 From: Luna McNulty Date: Mon, 18 Dec 2023 02:04:44 -0500 Subject: [PATCH 12/15] Add null check to className in string templates --- .../components/checklists/CheckListForm.js | 16 +++++++++------ .../components/checklists/EditableLabel.js | 2 +- .../src/components/checklists/RiskSection.js | 20 +++++++++---------- .../src/components/cite/SimilarIncidents.js | 2 +- .../src/components/discover/QuickAccess.js | 2 +- .../components/discover/hitTypes/shared.js | 2 +- .../components/forms/FlowbiteSearchInput.js | 2 +- .../forms/SubmissionWizard/StepContainer.js | 6 ++++-- site/gatsby-site/src/components/forms/Tags.js | 2 +- .../src/components/forms/TextInputGroup.js | 10 ++++++---- .../src/components/i18n/TranslationBadge.js | 2 +- .../src/components/incidents/IncidentCard.js | 4 +++- .../src/components/loginSignup/index.js | 2 +- .../src/components/reports/ReportCard.js | 6 +++--- .../src/components/sidebar/treeNode.js | 2 +- site/gatsby-site/src/components/ui/Header.js | 9 ++++++--- .../src/components/ui/SocialShareButtons.js | 2 +- site/gatsby-site/src/components/ui/Table.js | 2 +- .../src/components/ui/WebArchiveLink.js | 2 +- .../src/elements/ProgessCircle/index.js | 2 +- site/gatsby-site/src/elements/Select/index.js | 2 +- .../src/elements/Skeletons/Card/index.js | 4 +++- site/gatsby-site/src/utils/checklists.js | 4 +++- site/gatsby-site/src/utils/cloudinary.js | 4 ++-- 24 files changed, 64 insertions(+), 47 deletions(-) diff --git a/site/gatsby-site/src/components/checklists/CheckListForm.js b/site/gatsby-site/src/components/checklists/CheckListForm.js index f944aae79a..5943dc40f3 100644 --- a/site/gatsby-site/src/components/checklists/CheckListForm.js +++ b/site/gatsby-site/src/components/checklists/CheckListForm.js @@ -343,20 +343,22 @@ const Header = (props) => { lg:min-h-[5.5rem] flex justify-between flex-wrap gap-4 pb-2 -mt-2 - ${props.className} + ${props.className || ''} `; return
{props.children}
; }; const HeaderInfo = (props) => { - const className = `flex flex-col justify-center ${props.className}`; + const className = `flex flex-col justify-center ${props.className || ''}`; return
{props.children}
; }; const HeaderControls = (props) => { - const className = `flex flex-wrap md:flex-nowrap shrink-0 gap-2 items-center max-w-full ${props.className}`; + const className = `flex flex-wrap md:flex-nowrap shrink-0 gap-2 items-center max-w-full ${ + props.className || '' + }`; return
{props.children}
; }; @@ -366,14 +368,14 @@ const SideBySide = (props) => { flex flex-col md:flex-row gap-2 [&>*]:w-full [&>*]:md:w-1/2 [&>*]:h-full - ${props.className} + ${props.className || ''} `; return
{props.children}
; }; function SavingIndicator({ isSubmitting, submissionError, className }) { - className = `text-lg text-gray-500 inline-block ${className}`; + className = `text-lg text-gray-500 inline-block ${className || ''}`; if (isSubmitting) { return ( @@ -404,7 +406,9 @@ function Info({ children, className }) { if (hide) return <>; return (
diff --git a/site/gatsby-site/src/components/checklists/RiskSection.js b/site/gatsby-site/src/components/checklists/RiskSection.js index 97aef12607..83ce2680a2 100644 --- a/site/gatsby-site/src/components/checklists/RiskSection.js +++ b/site/gatsby-site/src/components/checklists/RiskSection.js @@ -282,7 +282,7 @@ const RiskBody = (props) => (
{props.children} @@ -306,7 +306,7 @@ const RiskDetails = (props) => ( [&>summary]:before:content-['⏵'] [&[open]>summary]:before:w-4 [&>summary]:before:w-4 - ${props.className} + ${props.className || ''} `, }} > @@ -329,7 +329,7 @@ const RiskHeaderSummary = (props) => ( before:text-lg ${props.generated ? 'before:text-gray-400' : 'before:text-red-700'} - ${props.className} + ${props.className || ''} `, }} > @@ -341,7 +341,7 @@ const HeaderItemsGroup = (props) => (
{props.children} @@ -356,7 +356,7 @@ const HeaderTextWithIcon = (props) => ( inline-flex flex gap-1 items-center inline-block bg-${props.color || 'gray'}-200 px-3 rounded-lg text-${props.color || 'gray'}-800 - ${props.className} + ${props.className || ''} `, }} > @@ -365,17 +365,17 @@ const HeaderTextWithIcon = (props) => ( ); const PrecedentsQuery = (props) => ( -
{props.children}
+
{props.children}
); const Precedents = (props) => ( -
+
{props.children}
); const RiskFields = (props) => ( -
+
{props.children}
); @@ -392,7 +392,7 @@ const PrecedentsList = (props) => ( border-1 border-gray-200 rounded shadow-inner - ${props.className} + ${props.className || ''} `, }} > @@ -424,7 +424,7 @@ function ProgressCircle({ progress, className }) { const clearLength = c - filledLength; return ( -
+
+
{(editor_similar_incidents.length > 0 || nlp_only_incidents.length > 0) && ( diff --git a/site/gatsby-site/src/components/discover/hitTypes/shared.js b/site/gatsby-site/src/components/discover/hitTypes/shared.js index f6c3e069a1..57260cbb95 100644 --- a/site/gatsby-site/src/components/discover/hitTypes/shared.js +++ b/site/gatsby-site/src/components/discover/hitTypes/shared.js @@ -42,7 +42,7 @@ export function HeaderTitle({ item, ...props }) { export function SourceDomainSubtitle({ item, className }) { return ( -
+
{item.source_domain} · {format(fromUnixTime(item.epoch_date_published), 'yyyy')} diff --git a/site/gatsby-site/src/components/forms/FlowbiteSearchInput.js b/site/gatsby-site/src/components/forms/FlowbiteSearchInput.js index 1bbef0d1f8..75cc402fbd 100644 --- a/site/gatsby-site/src/components/forms/FlowbiteSearchInput.js +++ b/site/gatsby-site/src/components/forms/FlowbiteSearchInput.js @@ -42,7 +42,7 @@ const FlowbiteSearchInput = ({ props.touched[name] && props.errors[name] ? 'border-red-600 focus:border-red-600 focus:ring-red-500' : 'border-gray-300 dark:border-gray-600 dark:focus:border-blue-500 focus:border-blue-500 focus:ring-blue-500 dark:focus:ring-blue-500' - } ${className}`} + } ${className || ''}`} placeholder={placeholder} onChange={handleChange} onBlur={handleBlur} diff --git a/site/gatsby-site/src/components/forms/SubmissionWizard/StepContainer.js b/site/gatsby-site/src/components/forms/SubmissionWizard/StepContainer.js index 2a172a993c..fb9207d2ab 100644 --- a/site/gatsby-site/src/components/forms/SubmissionWizard/StepContainer.js +++ b/site/gatsby-site/src/components/forms/SubmissionWizard/StepContainer.js @@ -4,9 +4,11 @@ import React from 'react'; const StepContainer = (props) => { return (
-
+
{props.children}
{props.name} diff --git a/site/gatsby-site/src/components/forms/Tags.js b/site/gatsby-site/src/components/forms/Tags.js index 87c324c4f1..ee16c98ae9 100644 --- a/site/gatsby-site/src/components/forms/Tags.js +++ b/site/gatsby-site/src/components/forms/Tags.js @@ -28,7 +28,7 @@ export default function Tags({ return ( { if (e.key === ',') { diff --git a/site/gatsby-site/src/components/forms/TextInputGroup.js b/site/gatsby-site/src/components/forms/TextInputGroup.js index 1eda7f11cb..f4665fb94e 100644 --- a/site/gatsby-site/src/components/forms/TextInputGroup.js +++ b/site/gatsby-site/src/components/forms/TextInputGroup.js @@ -31,7 +31,7 @@ const TextInputGroup = ({ }, []); return ( -
+
{icon && } {label && ( @@ -97,11 +97,13 @@ const TextAreaInput = ({ <>