diff --git a/.github/workflows/lf-production-deploy-new.yaml b/.github/workflows/lf-production-deploy-new.yaml
index 1cf3a537bf..bdd5915e55 100644
--- a/.github/workflows/lf-production-deploy-new.yaml
+++ b/.github/workflows/lf-production-deploy-new.yaml
@@ -27,6 +27,10 @@ on:
description: Deploy emails-worker service?
required: true
type: boolean
+ deploy_profiles_worker:
+ description: Deploy profiles-worker service?
+ required: true
+ type: boolean
deploy_members_enrichment_worker:
description: Deploy members-enrichment-worker service?
required: true
@@ -182,6 +186,27 @@ jobs:
id: image
run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT
+ build-and-push-profiles-worker:
+ runs-on: ubuntu-latest
+ if: ${{ inputs.deploy_profiles_worker }}
+ outputs:
+ image: ${{ steps.image.outputs.IMAGE }}
+ defaults:
+ run:
+ shell: bash
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@v2
+
+ - uses: ./.github/actions/build-docker-image
+ id: image-builder
+ with:
+ image: profiles-worker
+
+ - name: Set docker image output
+ id: image
+ run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT
+
build-and-push-members-enrichment-worker:
runs-on: ubuntu-latest
if: ${{ inputs.deploy_members_enrichment_worker }}
@@ -378,6 +403,24 @@ jobs:
image: ${{ needs.build-and-push-emails-worker.outputs.image }}
cluster: ${{ env.CROWD_CLUSTER }}
+ deploy-profiles-worker:
+ needs: build-and-push-profiles-worker
+ runs-on: ubuntu-latest
+ if: ${{ inputs.deploy_profiles_worker }}
+ defaults:
+ run:
+ shell: bash
+
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@v2
+
+ - uses: ./.github/actions/deploy-service
+ with:
+ service: profiles-worker
+ image: ${{ needs.build-and-push-profiles-worker.outputs.image }}
+ cluster: ${{ env.CROWD_CLUSTER }}
+
deploy-members-enrichment-worker:
needs: build-and-push-members-enrichment-worker
runs-on: ubuntu-latest
diff --git a/.github/workflows/lf-staging-deploy-profiles-worker.yaml b/.github/workflows/lf-staging-deploy-profiles-worker.yaml
new file mode 100644
index 0000000000..71840b25f6
--- /dev/null
+++ b/.github/workflows/lf-staging-deploy-profiles-worker.yaml
@@ -0,0 +1,60 @@
+name: LF Staging Deploy Profiles Worker
+
+on:
+ push:
+ branches:
+ - 'lf-staging/**'
+ - 'lf-staging-**'
+ paths:
+ - 'services/libs/**'
+ - 'services/apps/profiles_worker/**'
+
+env:
+ DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
+ DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
+ CROWD_CLUSTER: ${{ secrets.LF_STAGING_CLUSTER_NAME }}
+ CROWD_ROLE_ARN: ${{ secrets.LF_STAGING_CLUSTER_ROLE_ARN }}
+ AWS_ACCESS_KEY_ID: ${{ secrets.LF_AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.LF_AWS_SECRET_ACCESS_KEY }}
+ AWS_REGION: ${{ secrets.LF_AWS_REGION }}
+ SLACK_CHANNEL: deploys-lf-staging
+ SLACK_WEBHOOK: ${{ secrets.LF_STAGING_SLACK_CHANNEL_HOOK }}
+
+jobs:
+ build-and-push:
+ runs-on: ubuntu-latest
+ outputs:
+ image: ${{ steps.image.outputs.IMAGE }}
+ defaults:
+ run:
+ shell: bash
+
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@v2
+
+ - uses: ./.github/actions/build-docker-image
+ id: image-builder
+ with:
+ image: profiles-worker
+
+ - name: Set docker image output
+ id: image
+ run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT
+
+ deploy-profiles-worker:
+ needs: build-and-push
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ shell: bash
+
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@v2
+
+ - uses: ./.github/actions/deploy-service
+ with:
+ service: profiles-worker
+ image: ${{ needs.build-and-push.outputs.image }}
+ cluster: ${{ env.CROWD_CLUSTER }}
diff --git a/.github/workflows/production-deploy-new.yaml b/.github/workflows/production-deploy-new.yaml
index 1ac79b1bcd..1f420bf5eb 100644
--- a/.github/workflows/production-deploy-new.yaml
+++ b/.github/workflows/production-deploy-new.yaml
@@ -27,6 +27,10 @@ on:
description: Deploy emails-worker service?
required: true
type: boolean
+ deploy_profiles_worker:
+ description: Deploy profiles-worker service?
+ required: true
+ type: boolean
deploy_members_enrichment_worker:
description: Deploy members-enrichment-worker service?
required: true
@@ -182,6 +186,27 @@ jobs:
id: image
run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT
+ build-and-push-profiles-worker:
+ runs-on: ubuntu-latest
+ if: ${{ inputs.deploy_profiles_worker }}
+ outputs:
+ image: ${{ steps.image.outputs.IMAGE }}
+ defaults:
+ run:
+ shell: bash
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@v2
+
+ - uses: ./.github/actions/build-docker-image
+ id: image-builder
+ with:
+ image: profiles-worker
+
+ - name: Set docker image output
+ id: image
+ run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT
+
build-and-push-members-enrichment-worker:
runs-on: ubuntu-latest
if: ${{ inputs.deploy_members_enrichment_worker }}
@@ -378,6 +403,24 @@ jobs:
image: ${{ needs.build-and-push-emails-worker.outputs.image }}
cluster: ${{ env.CROWD_CLUSTER }}
+ deploy-profiles-worker:
+ needs: build-and-push-profiles-worker
+ runs-on: ubuntu-latest
+ if: ${{ inputs.deploy_profiles_worker }}
+ defaults:
+ run:
+ shell: bash
+
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@v2
+
+ - uses: ./.github/actions/deploy-service
+ with:
+ service: profiles-worker
+ image: ${{ needs.build-and-push-profiles-worker.outputs.image }}
+ cluster: ${{ env.CROWD_CLUSTER }}
+
deploy-members-enrichment-worker:
needs: build-and-push-members-enrichment-worker
runs-on: ubuntu-latest
diff --git a/.github/workflows/staging-deploy-profiles-worker.yaml b/.github/workflows/staging-deploy-profiles-worker.yaml
new file mode 100644
index 0000000000..871289b851
--- /dev/null
+++ b/.github/workflows/staging-deploy-profiles-worker.yaml
@@ -0,0 +1,60 @@
+name: Staging Deploy Profiles Worker
+
+on:
+ push:
+ branches:
+ - 'staging/**'
+ - 'staging-**'
+ paths:
+ - 'services/libs/**'
+ - 'services/apps/profiles_worker/**'
+
+env:
+ DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
+ DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
+ CROWD_CLUSTER: ${{ secrets.STAGING_CLUSTER_NAME }}
+ CROWD_ROLE_ARN: ${{ secrets.STAGING_CLUSTER_ROLE_ARN }}
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ AWS_REGION: ${{ secrets.AWS_REGION }}
+ SLACK_CHANNEL: deploys-staging
+ SLACK_WEBHOOK: ${{ secrets.STAGING_SLACK_CHANNEL_HOOK }}
+
+jobs:
+ build-and-push:
+ runs-on: ubuntu-latest
+ outputs:
+ image: ${{ steps.image.outputs.IMAGE }}
+ defaults:
+ run:
+ shell: bash
+
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@v2
+
+ - uses: ./.github/actions/build-docker-image
+ id: image-builder
+ with:
+ image: profiles-worker
+
+ - name: Set docker image output
+ id: image
+ run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT
+
+ deploy-profiles-worker:
+ needs: build-and-push
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ shell: bash
+
+ steps:
+ - name: Check out repository code
+ uses: actions/checkout@v2
+
+ - uses: ./.github/actions/deploy-service
+ with:
+ service: profiles-worker
+ image: ${{ needs.build-and-push.outputs.image }}
+ cluster: ${{ env.CROWD_CLUSTER }}
diff --git a/backend/src/database/repositories/__tests__/activityRepository.test.ts b/backend/src/database/repositories/__tests__/activityRepository.test.ts
deleted file mode 100644
index 1dc727737f..0000000000
--- a/backend/src/database/repositories/__tests__/activityRepository.test.ts
+++ /dev/null
@@ -1,1765 +0,0 @@
-import { Error404 } from '@crowd/common'
-import MemberRepository from '../memberRepository'
-import SequelizeTestUtils from '../../utils/sequelizeTestUtils'
-import ActivityRepository from '../activityRepository'
-import { MemberAttributeName, PlatformType } from '@crowd/types'
-import TaskRepository from '../taskRepository'
-import MemberAttributeSettingsRepository from '../memberAttributeSettingsRepository'
-import MemberAttributeSettingsService from '../../../services/memberAttributeSettingsService'
-import { DEFAULT_MEMBER_ATTRIBUTES, UNKNOWN_ACTIVITY_TYPE_DISPLAY } from '@crowd/integrations'
-import OrganizationRepository from '../organizationRepository'
-
-const db = null
-
-describe('ActivityRepository tests', () => {
- beforeEach(async () => {
- await SequelizeTestUtils.wipeDatabase(db)
- })
-
- afterAll((done) => {
- // Closing the DB connection allows Jest to exit successfully.
- SequelizeTestUtils.closeConnection(db)
- done()
- })
-
- describe('create method', () => {
- it('Should create the given activity succesfully', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- attributes: {
- replies: 12,
- },
- title: 'Title',
- body: 'Here',
- url: 'https://github.com',
- channel: 'channel',
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- }
-
- const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions)
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- activityCreated.createdAt = activityCreated.createdAt.toISOString().split('T')[0]
- activityCreated.updatedAt = activityCreated.updatedAt.toISOString().split('T')[0]
- delete activityCreated.member
- delete activityCreated.objectMember
-
- const expectedActivityCreated = {
- id: activityCreated.id,
- attributes: activity.attributes,
- body: 'Here',
- type: 'activity',
- title: 'Title',
- url: 'https://github.com',
- channel: 'channel',
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- timestamp: new Date('2020-05-27T15:13:30Z'),
- platform: PlatformType.GITHUB,
- isContribution: true,
- score: 1,
- username: 'test',
- objectMemberUsername: null,
- memberId: memberCreated.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- tasks: [],
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parent: null,
- parentId: null,
- sourceId: activity.sourceId,
- sourceParentId: null,
- conversationId: null,
- display: UNKNOWN_ACTIVITY_TYPE_DISPLAY,
- organizationId: null,
- organization: null,
- }
-
- expect(activityCreated).toStrictEqual(expectedActivityCreated)
- })
-
- it('Should create a bare-bones activity succesfully', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- member: memberCreated.id,
- username: 'test',
- sourceId: '#sourceId1',
- }
-
- const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions)
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- activityCreated.createdAt = activityCreated.createdAt.toISOString().split('T')[0]
- activityCreated.updatedAt = activityCreated.updatedAt.toISOString().split('T')[0]
- delete activityCreated.member
- delete activityCreated.objectMember
-
- const expectedActivityCreated = {
- id: activityCreated.id,
- attributes: {},
- body: null,
- title: null,
- url: null,
- channel: null,
- sentiment: {},
- type: 'activity',
- timestamp: new Date('2020-05-27T15:13:30Z'),
- platform: PlatformType.GITHUB,
- isContribution: false,
- score: 2,
- username: 'test',
- objectMemberUsername: null,
- memberId: memberCreated.id,
- objectMemberId: null,
- tasks: [],
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parent: null,
- parentId: null,
- sourceId: activityCreated.sourceId,
- sourceParentId: null,
- conversationId: null,
- display: UNKNOWN_ACTIVITY_TYPE_DISPLAY,
- organizationId: null,
- organization: null,
- }
-
- expect(activityCreated).toStrictEqual(expectedActivityCreated)
- })
-
- it('Should throw error when no platform given', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- attributes: {
- replies: 12,
- },
- body: 'Here',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- }
-
- await expect(() =>
- ActivityRepository.create(activity, mockIRepositoryOptions),
- ).rejects.toThrow()
- })
-
- it('Should throw error when no type given', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity = {
- platform: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- attributes: {
- replies: 12,
- },
- username: 'test',
- body: 'Here',
- isContribution: true,
- member: memberCreated.id,
- score: 1,
- }
-
- await expect(() =>
- ActivityRepository.create(activity, mockIRepositoryOptions),
- ).rejects.toThrow()
- })
-
- it('Should throw error when no timestamp given', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity = {
- platform: PlatformType.GITHUB,
- type: 'activity',
- attributes: {
- replies: 12,
- },
- username: 'test',
- body: 'Here',
- isContribution: true,
- member: memberCreated.id,
- score: 1,
- }
-
- await expect(() =>
- ActivityRepository.create(activity, mockIRepositoryOptions),
- ).rejects.toThrow()
- })
-
- it('Should throw error when sentiment is incorrect', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- // Incomplete Object
- await expect(() =>
- ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- sentiment: {
- positive: 1,
- sentiment: 'positive',
- score: 1,
- },
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- ),
- ).rejects.toThrow()
-
- // No score
- await expect(() =>
- ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- sentiment: {
- positive: 0.8,
- negative: 0.2,
- mixed: 0,
- neutral: 0,
- sentiment: 'positive',
- },
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- ),
- ).rejects.toThrow()
-
- // Wrong Sentiment field
- await expect(() =>
- ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- sentiment: {
- positive: 0.3,
- negative: 0.2,
- neutral: 0.5,
- mixed: 0,
- score: 0.1,
- sentiment: 'smth',
- },
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- ),
- ).rejects.toThrow()
-
- // Works with empty object
- const created = await ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- sentiment: {},
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- )
- expect(created.sentiment).toStrictEqual({})
- })
-
- it('Should leave allowed HTML tags in body and title', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- body: '
This is some HTML
',
- title: ' This is some Title HTML
',
- url: 'https://github.com',
- channel: 'channel',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- }
-
- const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions)
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- activityCreated.createdAt = activityCreated.createdAt.toISOString().split('T')[0]
- activityCreated.updatedAt = activityCreated.updatedAt.toISOString().split('T')[0]
- delete activityCreated.member
- delete activityCreated.objectMember
-
- const expectedActivityCreated = {
- id: activityCreated.id,
- attributes: {},
- body: ' This is some HTML
',
- type: 'activity',
- title: ' This is some Title HTML
',
- url: 'https://github.com',
- channel: 'channel',
- sentiment: {},
- timestamp: new Date('2020-05-27T15:13:30Z'),
- platform: PlatformType.GITHUB,
- isContribution: true,
- score: 1,
- tasks: [],
- username: 'test',
- objectMemberUsername: null,
- memberId: memberCreated.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parent: null,
- parentId: null,
- sourceId: activity.sourceId,
- sourceParentId: null,
- conversationId: null,
- display: UNKNOWN_ACTIVITY_TYPE_DISPLAY,
- organizationId: null,
- organization: null,
- }
-
- expect(activityCreated).toStrictEqual(expectedActivityCreated)
- })
-
- it('Should remove script tags in body and title', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- body: " Malicious
",
- title: " Malicious title
",
- url: 'https://github.com',
- channel: 'channel',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- }
-
- const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions)
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- activityCreated.createdAt = activityCreated.createdAt.toISOString().split('T')[0]
- activityCreated.updatedAt = activityCreated.updatedAt.toISOString().split('T')[0]
- delete activityCreated.member
- delete activityCreated.objectMember
-
- const expectedActivityCreated = {
- id: activityCreated.id,
- attributes: {},
- body: ' Malicious
',
- type: 'activity',
- title: ' Malicious title
',
- url: 'https://github.com',
- channel: 'channel',
- sentiment: {},
- tasks: [],
- timestamp: new Date('2020-05-27T15:13:30Z'),
- platform: PlatformType.GITHUB,
- isContribution: true,
- score: 1,
- username: 'test',
- objectMemberUsername: null,
- memberId: memberCreated.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parent: null,
- parentId: null,
- sourceId: activity.sourceId,
- sourceParentId: null,
- conversationId: null,
- display: UNKNOWN_ACTIVITY_TYPE_DISPLAY,
- organizationId: null,
- organization: null,
- }
-
- expect(activityCreated).toStrictEqual(expectedActivityCreated)
- })
-
- it('Should create an activity with tasks succesfully', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const tasks1 = await TaskRepository.create(
- {
- name: 'task1',
- },
- mockIRepositoryOptions,
- )
-
- const task2 = await TaskRepository.create(
- {
- name: 'task2',
- },
- mockIRepositoryOptions,
- )
-
- const activity = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- attributes: {
- replies: 12,
- },
- title: 'Title',
- body: 'Here',
- url: 'https://github.com',
- channel: 'channel',
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- tasks: [tasks1.id, task2.id],
- sourceId: '#sourceId1',
- }
-
- const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions)
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- expect(activityCreated.tasks.length).toBe(2)
- })
-
- it('Should create an activity with an organization succesfully', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const org1 = await OrganizationRepository.create(
- {
- displayName: 'crowd.dev',
- },
- mockIRepositoryOptions,
- )
-
- const activity = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- attributes: {
- replies: 12,
- },
- title: 'Title',
- body: 'Here',
- url: 'https://github.com',
- channel: 'channel',
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- organizationId: org1.id,
- sourceId: '#sourceId1',
- }
-
- const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions)
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- expect(activityCreated.organizationId).toEqual(org1.id)
- })
- })
-
- describe('findById method', () => {
- it('Should successfully find created activity by id', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- }
-
- const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions)
-
- const expectedActivityFound = {
- id: activityCreated.id,
- attributes: {},
- body: null,
- title: null,
- url: null,
- channel: null,
- sentiment: {},
- type: 'activity',
- timestamp: new Date('2020-05-27T15:13:30Z'),
- platform: PlatformType.GITHUB,
- isContribution: true,
- score: 1,
- username: 'test',
- objectMemberUsername: null,
- memberId: memberCreated.id,
- objectMemberId: null,
- tasks: [],
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parent: null,
- parentId: null,
- sourceId: activity.sourceId,
- sourceParentId: null,
- conversationId: null,
- display: UNKNOWN_ACTIVITY_TYPE_DISPLAY,
- organizationId: null,
- organization: null,
- }
-
- const activityFound = await ActivityRepository.findById(
- activityCreated.id,
- mockIRepositoryOptions,
- )
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- activityFound.createdAt = activityFound.createdAt.toISOString().split('T')[0]
- activityFound.updatedAt = activityFound.updatedAt.toISOString().split('T')[0]
- delete activityFound.member
- delete activityFound.objectMember
-
- expect(activityFound).toStrictEqual(expectedActivityFound)
- })
-
- it('Should throw 404 error when no user found with given id', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const { randomUUID } = require('crypto')
-
- await expect(() =>
- ActivityRepository.findById(randomUUID(), mockIRepositoryOptions),
- ).rejects.toThrowError(new Error404())
- })
- })
-
- describe('filterIdsInTenant method', () => {
- it('Should return the given ids of previously created activity entities', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity1Returned = await ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- )
-
- const activity2Returned = await ActivityRepository.create(
- {
- type: 'activity-2',
- timestamp: '2020-06-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId2',
- },
- mockIRepositoryOptions,
- )
-
- const filterIdsReturned = await ActivityRepository.filterIdsInTenant(
- [activity1Returned.id, activity2Returned.id],
- mockIRepositoryOptions,
- )
-
- expect(filterIdsReturned).toStrictEqual([activity1Returned.id, activity2Returned.id])
- })
-
- it('Should only return the ids of previously created activities and filter random uuids out', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity3Returned = await ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- )
-
- const { randomUUID } = require('crypto')
-
- const filterIdsReturned = await ActivityRepository.filterIdsInTenant(
- [activity3Returned.id, randomUUID(), randomUUID()],
- mockIRepositoryOptions,
- )
-
- expect(filterIdsReturned).toStrictEqual([activity3Returned.id])
- })
-
- it('Should return an empty array for an irrelevant tenant', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity4Returned = await ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- )
-
- // create a new tenant and bind options to it
- const mockIRepositoryOptionsIr = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const filterIdsReturned = await ActivityRepository.filterIdsInTenant(
- [activity4Returned.id],
- mockIRepositoryOptionsIr,
- )
-
- expect(filterIdsReturned).toStrictEqual([])
- })
- })
-
- describe('Activities findOne method', () => {
- it('Should return the created activity for a simple query', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activityReturned = await ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- )
-
- const found = await ActivityRepository.findOne({ type: 'activity' }, mockIRepositoryOptions)
-
- expect(found.id).toStrictEqual(activityReturned.id)
- })
-
- it('Should return the activity for a complex query', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activityReturned = await ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- attributes: {
- thread: true,
- },
- body: 'Here',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- )
-
- const found = await ActivityRepository.findOne(
- { 'attributes.thread': true },
- mockIRepositoryOptions,
- )
-
- expect(found.id).toStrictEqual(activityReturned.id)
- })
-
- it('Should return null when non-existent', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- await ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- attributes: {
- replies: 12,
- },
- body: 'Here',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- )
-
- expect(
- await ActivityRepository.findOne({ type: 'notype' }, mockIRepositoryOptions),
- ).toBeNull()
- })
- })
-
- describe('update method', () => {
- it('Should succesfully update previously created activity - simple', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activityReturned = await ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- attributes: {
- replies: 12,
- },
- body: 'Here',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- )
-
- const updateFields = {
- type: 'activity-new',
- platform: PlatformType.GITHUB,
- }
-
- const updatedActivity = await ActivityRepository.update(
- activityReturned.id,
- updateFields,
- mockIRepositoryOptions,
- )
-
- // check updatedAt field looks ok or not. Should be greater than createdAt
- expect(updatedActivity.updatedAt.getTime()).toBeGreaterThan(
- updatedActivity.createdAt.getTime(),
- )
-
- updatedActivity.createdAt = updatedActivity.createdAt.toISOString().split('T')[0]
- updatedActivity.updatedAt = updatedActivity.updatedAt.toISOString().split('T')[0]
- delete updatedActivity.member
- delete updatedActivity.objectMember
-
- const expectedActivityUpdated = {
- id: activityReturned.id,
- body: activityReturned.body,
- channel: null,
- title: null,
- sentiment: {},
- url: null,
- attributes: activityReturned.attributes,
- type: 'activity-new',
- timestamp: new Date('2020-05-27T15:13:30Z'),
- platform: PlatformType.GITHUB,
- isContribution: true,
- score: 1,
- username: 'test',
- objectMemberUsername: null,
- memberId: memberCreated.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- tasks: [],
- parent: null,
- parentId: null,
- sourceId: activityReturned.sourceId,
- sourceParentId: null,
- conversationId: null,
- display: UNKNOWN_ACTIVITY_TYPE_DISPLAY,
- organizationId: null,
- organization: null,
- }
-
- expect(updatedActivity).toStrictEqual(expectedActivityUpdated)
- })
-
- it('Should succesfully update previously created activity - with member relation', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const memberCreated2 = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test2',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activityReturned = await ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- attributes: {
- replies: 12,
- },
- body: 'Here',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- )
-
- const updateFields = {
- type: 'activity-new',
- platform: PlatformType.GITHUB,
- body: 'There',
- title: 'Title',
- channel: 'Channel',
- url: 'https://www.google.com',
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- username: 'test2',
- member: memberCreated2.id,
- }
-
- const updatedActivity = await ActivityRepository.update(
- activityReturned.id,
- updateFields,
- mockIRepositoryOptions,
- )
-
- // check updatedAt field looks ok or not. Should be greater than createdAt
- expect(updatedActivity.updatedAt.getTime()).toBeGreaterThan(
- updatedActivity.createdAt.getTime(),
- )
-
- updatedActivity.createdAt = updatedActivity.createdAt.toISOString().split('T')[0]
- updatedActivity.updatedAt = updatedActivity.updatedAt.toISOString().split('T')[0]
- delete updatedActivity.member
- delete updatedActivity.objectMember
-
- const expectedActivityUpdated = {
- id: activityReturned.id,
- attributes: activityReturned.attributes,
- body: updateFields.body,
- channel: updateFields.channel,
- title: updateFields.title,
- sentiment: updateFields.sentiment,
- url: updateFields.url,
- type: 'activity-new',
- timestamp: new Date('2020-05-27T15:13:30Z'),
- tasks: [],
- platform: PlatformType.GITHUB,
- isContribution: true,
- score: 1,
- username: 'test2',
- objectMemberUsername: null,
- memberId: memberCreated2.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parent: null,
- parentId: null,
- sourceId: activityReturned.sourceId,
- sourceParentId: null,
- conversationId: null,
- display: UNKNOWN_ACTIVITY_TYPE_DISPLAY,
- organizationId: null,
- organization: null,
- }
-
- expect(updatedActivity).toStrictEqual(expectedActivityUpdated)
- })
-
- it('Should succesfully update tasks of an activity', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activityReturned = await ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- attributes: {
- replies: 12,
- },
- body: 'Here',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- )
-
- const tasks1 = await TaskRepository.create(
- {
- name: 'task1',
- },
- mockIRepositoryOptions,
- )
-
- const task2 = await TaskRepository.create(
- {
- name: 'task2',
- },
- mockIRepositoryOptions,
- )
-
- const updateFields = {
- tasks: [tasks1.id, task2.id],
- }
-
- const updatedActivity = await ActivityRepository.update(
- activityReturned.id,
- updateFields,
- mockIRepositoryOptions,
- )
-
- expect(updatedActivity.tasks).toHaveLength(2)
- expect(updatedActivity.tasks[0].id).toBe(tasks1.id)
- expect(updatedActivity.tasks[1].id).toBe(task2.id)
- })
-
- it('Should update body and title with allowed HTML tags', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activityReturned = await ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- attributes: {
- replies: 12,
- },
- body: 'Here',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- )
-
- const updateFields = {
- body: ' This is some HTML
',
- title: ' This is some Title HTML
',
- }
-
- const updatedActivity = await ActivityRepository.update(
- activityReturned.id,
- updateFields,
- mockIRepositoryOptions,
- )
-
- expect(updatedActivity.body).toBe(' This is some HTML
')
- expect(updatedActivity.title).toBe(' This is some Title HTML
')
- })
-
- it('Should sanitize body and title from non-allowed HTML tags', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activityReturned = await ActivityRepository.create(
- {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- attributes: {
- replies: 12,
- },
- body: 'Here',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- },
- mockIRepositoryOptions,
- )
-
- const updateFields = {
- body: " Malicious
",
- title: " Malicious title
",
- }
-
- const updatedActivity = await ActivityRepository.update(
- activityReturned.id,
- updateFields,
- mockIRepositoryOptions,
- )
-
- expect(updatedActivity.body).toBe(' Malicious
')
- expect(updatedActivity.title).toBe(' Malicious title
')
- })
-
- it('Should update an activity with an organization succesfully', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const org1 = await OrganizationRepository.create(
- {
- displayName: 'crowd.dev',
- },
- mockIRepositoryOptions,
- )
-
- const org2 = await OrganizationRepository.create(
- {
- displayName: 'tesla',
- },
- mockIRepositoryOptions,
- )
-
- const activity = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- attributes: {
- replies: 12,
- },
- title: 'Title',
- body: 'Here',
- url: 'https://github.com',
- channel: 'channel',
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- organizationId: org1.id,
- sourceId: '#sourceId1',
- }
-
- const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions)
-
- const activityUpdated = await ActivityRepository.update(
- activityCreated.id,
- { organizationId: org2.id },
- mockIRepositoryOptions,
- )
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- expect(activityUpdated.organizationId).toEqual(org2.id)
- })
- })
-
- describe('filter tests', () => {
- it('Positive sentiment filter and sort', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity1 = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId1',
- }
-
- const activity2 = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- sentiment: {
- positive: 0.55,
- negative: 0.0,
- neutral: 0.45,
- mixed: 0.0,
- label: 'neutral',
- sentiment: 0.55,
- },
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId2',
- }
-
- const activityCreated1 = await ActivityRepository.create(activity1, mockIRepositoryOptions)
- await ActivityRepository.create(activity2, mockIRepositoryOptions)
-
- // Control
- expect(
- (await ActivityRepository.findAndCountAll({ filter: {} }, mockIRepositoryOptions)).count,
- ).toBe(2)
-
- // Filter by how positive activities are
- const filteredActivities = await ActivityRepository.findAndCountAll(
- { filter: { positiveSentimentRange: [0.6, 1] } },
- mockIRepositoryOptions,
- )
-
- expect(filteredActivities.count).toBe(1)
- expect(filteredActivities.rows[0].id).toBe(activityCreated1.id)
-
- // Filter by whether activities are positive or not
- const filteredActivities2 = await ActivityRepository.findAndCountAll(
- { filter: { sentimentLabel: 'positive' } },
- mockIRepositoryOptions,
- )
-
- expect(filteredActivities2.count).toBe(1)
- expect(filteredActivities2.rows[0].id).toBe(activityCreated1.id)
-
- // No filter, but sorting
- const filteredActivities3 = await ActivityRepository.findAndCountAll(
- { filter: {}, orderBy: 'sentiment.positive_DESC' },
- mockIRepositoryOptions,
- )
- expect(filteredActivities3.count).toBe(2)
- expect(filteredActivities3.rows[0].sentiment.positive).toBeGreaterThan(
- filteredActivities3.rows[1].sentiment.positive,
- )
- })
- it('Negative sentiment filter and sort', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const memberCreated = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity1 = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId1',
- }
-
- const activity2 = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- sentiment: {
- positive: 0.01,
- negative: 0.55,
- neutral: 0.55,
- mixed: 0.0,
- label: 'negative',
- sentiment: -0.54,
- },
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId2',
- }
-
- await ActivityRepository.create(activity1, mockIRepositoryOptions)
- const activityCreated2 = await ActivityRepository.create(activity2, mockIRepositoryOptions)
-
- // Control
- expect(
- (await ActivityRepository.findAndCountAll({ filter: {} }, mockIRepositoryOptions)).count,
- ).toBe(2)
-
- // Filter by how positive activities are
- const filteredActivities = await ActivityRepository.findAndCountAll(
- { filter: { negativeSentimentRange: [0.5, 1] } },
- mockIRepositoryOptions,
- )
-
- expect(filteredActivities.count).toBe(1)
- expect(filteredActivities.rows[0].id).toBe(activityCreated2.id)
-
- // Filter by whether activities are positive or not
- const filteredActivities2 = await ActivityRepository.findAndCountAll(
- { filter: { sentimentLabel: 'negative' } },
- mockIRepositoryOptions,
- )
-
- expect(filteredActivities2.count).toBe(1)
- expect(filteredActivities2.rows[0].id).toBe(activityCreated2.id)
-
- // No filter, but sorting
- const filteredActivities3 = await ActivityRepository.findAndCountAll(
- { filter: {}, orderBy: 'sentiment.negative_DESC' },
- mockIRepositoryOptions,
- )
- expect(filteredActivities3.count).toBe(2)
- expect(filteredActivities3.rows[0].sentiment.negative).toBeGreaterThan(
- filteredActivities3.rows[1].sentiment.negative,
- )
- })
-
- it('Overall sentiment filter and sort', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const memberCreated = await MemberRepository.create(
- {
- username: {
- github: 'test',
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity1 = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId1',
- }
-
- const activity2 = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- sentiment: {
- positive: 0.55,
- negative: 0.0,
- neutral: 0.45,
- mixed: 0.0,
- label: 'neutral',
- sentiment: 0.55,
- },
- username: 'test',
- member: memberCreated.id,
- sourceId: '#sourceId2',
- }
-
- const activityCreated1 = await ActivityRepository.create(activity1, mockIRepositoryOptions)
- await ActivityRepository.create(activity2, mockIRepositoryOptions)
-
- // Control
- expect(
- (await ActivityRepository.findAndCountAll({ filter: {} }, mockIRepositoryOptions)).count,
- ).toBe(2)
-
- // Filter by how positive activities are
- const filteredActivities = await ActivityRepository.findAndCountAll(
- { filter: { sentimentRange: [0.6, 1] } },
- mockIRepositoryOptions,
- )
-
- expect(filteredActivities.count).toBe(1)
- expect(filteredActivities.rows[0].id).toBe(activityCreated1.id)
-
- // No filter, but sorting
- const filteredActivities3 = await ActivityRepository.findAndCountAll(
- { filter: {}, orderBy: 'sentiment_DESC' },
- mockIRepositoryOptions,
- )
- expect(filteredActivities3.count).toBe(2)
- expect(filteredActivities3.rows[0].sentiment.positive).toBeGreaterThan(
- filteredActivities3.rows[1].sentiment.positive,
- )
- })
-
- it('Member related attributes filters', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const mas = new MemberAttributeSettingsService(mockIRepositoryOptions)
-
- await mas.createPredefined(DEFAULT_MEMBER_ATTRIBUTES)
-
- const memberAttributeSettings = (
- await MemberAttributeSettingsRepository.findAndCountAll({}, mockIRepositoryOptions)
- ).rows
-
- const memberCreated1 = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- displayName: 'Anil',
- attributes: {
- [MemberAttributeName.IS_TEAM_MEMBER]: {
- default: true,
- [PlatformType.CROWD]: true,
- },
- [MemberAttributeName.LOCATION]: {
- default: 'Berlin',
- [PlatformType.GITHUB]: 'Berlin',
- [PlatformType.SLACK]: 'Turkey',
- },
- },
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const memberCreated2 = await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: 'Michael',
- },
- displayName: 'Michael',
- attributes: {
- [MemberAttributeName.IS_TEAM_MEMBER]: {
- default: false,
- [PlatformType.CROWD]: false,
- },
- [MemberAttributeName.LOCATION]: {
- default: 'Scranton',
- [PlatformType.GITHUB]: 'Scranton',
- [PlatformType.SLACK]: 'New York',
- },
- },
- joinedAt: '2020-05-27T15:13:30Z',
- },
- mockIRepositoryOptions,
- )
-
- const activity1 = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- username: 'test',
- member: memberCreated1.id,
- sourceId: '#sourceId1',
- }
-
- const activity2 = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- sentiment: {
- positive: 0.55,
- negative: 0.0,
- neutral: 0.45,
- mixed: 0.0,
- label: 'neutral',
- sentiment: 0.55,
- },
- username: 'Michael',
- member: memberCreated2.id,
- sourceId: '#sourceId2',
- }
-
- const activityCreated1 = await ActivityRepository.create(activity1, mockIRepositoryOptions)
- const activityCreated2 = await ActivityRepository.create(activity2, mockIRepositoryOptions)
-
- // Control
- expect(
- (await ActivityRepository.findAndCountAll({ filter: {} }, mockIRepositoryOptions)).count,
- ).toBe(2)
-
- // Filter by member.isTeamMember
- let filteredActivities = await ActivityRepository.findAndCountAll(
- {
- advancedFilter: {
- member: {
- isTeamMember: {
- not: false,
- },
- },
- },
- attributesSettings: memberAttributeSettings,
- },
- mockIRepositoryOptions,
- )
-
- expect(filteredActivities.count).toBe(1)
- expect(filteredActivities.rows[0].id).toBe(activityCreated1.id)
-
- filteredActivities = await ActivityRepository.findAndCountAll(
- {
- advancedFilter: {
- member: {
- 'attributes.location.slack': 'New York',
- },
- },
- attributesSettings: memberAttributeSettings,
- },
- mockIRepositoryOptions,
- )
-
- expect(filteredActivities.count).toBe(1)
- expect(filteredActivities.rows[0].id).toBe(activityCreated2.id)
- })
- })
-})
diff --git a/backend/src/database/repositories/__tests__/memberEnrichmentCacheRepository.test.ts b/backend/src/database/repositories/__tests__/memberEnrichmentCacheRepository.test.ts
deleted file mode 100644
index 8b2438a340..0000000000
--- a/backend/src/database/repositories/__tests__/memberEnrichmentCacheRepository.test.ts
+++ /dev/null
@@ -1,161 +0,0 @@
-import { randomUUID } from 'crypto'
-
-import MemberRepository from '../memberRepository'
-import SequelizeTestUtils from '../../utils/sequelizeTestUtils'
-import { PlatformType } from '@crowd/types'
-import MemberEnrichmentCacheRepository from '../memberEnrichmentCacheRepository'
-import { generateUUIDv1 } from '@crowd/common'
-
-const db = null
-
-describe('MemberEnrichmentCacheRepository tests', () => {
- beforeEach(async () => {
- await SequelizeTestUtils.wipeDatabase(db)
- })
-
- afterAll((done) => {
- // Closing the DB connection allows Jest to exit successfully.
- SequelizeTestUtils.closeConnection(db)
- done()
- })
-
- describe('upsert method', () => {
- it('Should create non existing item successfully', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member2add = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'michael_scott',
- },
- },
- displayName: 'Member 1',
- email: 'michael@dd.com',
- score: 10,
- attributes: {},
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const member = await MemberRepository.create(member2add, mockIRepositoryOptions)
-
- const enrichmentData = {
- enrichmentField1: 'string',
- enrichmentField2: 24,
- arrayEnrichmentField: [1, 2, 3],
- }
-
- const cache = await MemberEnrichmentCacheRepository.upsert(
- member.id,
- enrichmentData,
- mockIRepositoryOptions,
- )
-
- expect(cache.memberId).toEqual(member.id)
- expect(cache.data).toStrictEqual(enrichmentData)
- })
-
- it('Should update the data of existing cache item with incoming data', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member2add = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'michael_scott',
- },
- },
- displayName: 'Member 1',
- email: 'michael@dd.com',
- score: 10,
- attributes: {},
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const member = await MemberRepository.create(member2add, mockIRepositoryOptions)
-
- const enrichmentData = {
- enrichmentField1: 'string',
- enrichmentField2: 24,
- arrayEnrichmentField: [1, 2, 3],
- }
-
- let cache = await MemberEnrichmentCacheRepository.upsert(
- member.id,
- enrichmentData,
- mockIRepositoryOptions,
- )
-
- const newerEnrichmentData = {
- enrichmentField1: 'anotherString',
- enrichmentField2: 99,
- arrayEnrichmentField: ['a', 'b', 'c'],
- }
-
- // should overwrite with new cache data
- cache = await MemberEnrichmentCacheRepository.upsert(
- member.id,
- newerEnrichmentData,
- mockIRepositoryOptions,
- )
-
- expect(cache.memberId).toEqual(member.id)
- expect(cache.data).toStrictEqual(newerEnrichmentData)
-
- // when we send an empty object, it shouldn't overwrite
- cache = await MemberEnrichmentCacheRepository.upsert(member.id, {}, mockIRepositoryOptions)
-
- expect(cache.memberId).toEqual(member.id)
- expect(cache.data).toStrictEqual(newerEnrichmentData)
- })
- })
-
- describe('findByMemberId method', () => {
- it('Should find enrichment cache by memberId', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member2add = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'michael_scott',
- },
- },
- displayName: 'Member 1',
- email: 'michael@dd.com',
- score: 10,
- attributes: {},
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const member = await MemberRepository.create(member2add, mockIRepositoryOptions)
-
- const enrichmentData = {
- enrichmentField1: 'string',
- enrichmentField2: 24,
- arrayEnrichmentField: [1, 2, 3],
- }
-
- await MemberEnrichmentCacheRepository.upsert(
- member.id,
- enrichmentData,
- mockIRepositoryOptions,
- )
-
- const cache = await MemberEnrichmentCacheRepository.findByMemberId(
- member.id,
- mockIRepositoryOptions,
- )
-
- expect(cache.memberId).toEqual(member.id)
- expect(cache.data).toEqual(enrichmentData)
- })
-
- it('Should return null for non-existing cache entry', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const cache = await MemberEnrichmentCacheRepository.findByMemberId(
- randomUUID(),
- mockIRepositoryOptions,
- )
- expect(cache).toBeNull()
- })
- })
-})
diff --git a/backend/src/database/repositories/__tests__/memberRepository.test.ts b/backend/src/database/repositories/__tests__/memberRepository.test.ts
deleted file mode 100644
index 13945324b8..0000000000
--- a/backend/src/database/repositories/__tests__/memberRepository.test.ts
+++ /dev/null
@@ -1,3959 +0,0 @@
-import { v4 as uuid } from 'uuid'
-import moment from 'moment'
-
-import { Error404 } from '@crowd/common'
-import { PlatformType, SegmentStatus } from '@crowd/types'
-import { generateUUIDv1 } from '@crowd/common'
-import SequelizeTestUtils from '../../utils/sequelizeTestUtils'
-import MemberRepository from '../memberRepository'
-import NoteRepository from '../noteRepository'
-import OrganizationRepository from '../organizationRepository'
-import TagRepository from '../tagRepository'
-import TaskRepository from '../taskRepository'
-import lodash from 'lodash'
-import SegmentRepository from '../segmentRepository'
-import { populateSegments } from '../../utils/segmentTestUtils'
-import MemberService from '../../../services/memberService'
-import OrganizationService from '../../../services/organizationService'
-
-const db = null
-
-function mapUsername(data: any): any {
- const username = {}
- Object.keys(data).forEach((platform) => {
- const usernameData = data[platform]
-
- if (Array.isArray(usernameData)) {
- username[platform] = []
- if (usernameData.length > 0) {
- for (const entry of usernameData) {
- if (typeof entry === 'string') {
- username[platform].push(entry)
- } else if (typeof entry === 'object') {
- username[platform].push((entry as any).username)
- } else {
- throw new Error('Invalid username type')
- }
- }
- }
- } else if (typeof usernameData === 'object') {
- username[platform] = [usernameData.username]
- } else if (typeof usernameData === 'string') {
- username[platform] = [usernameData]
- } else {
- throw new Error('Invalid username type')
- }
- })
- return username
-}
-
-describe('MemberRepository tests', () => {
- beforeEach(async () => {
- await SequelizeTestUtils.wipeDatabase(db)
- })
-
- afterAll((done) => {
- // Closing the DB connection allows Jest to exit successfully.
- SequelizeTestUtils.closeConnection(db)
- done()
- })
-
- describe('create method', () => {
- it('Should create the given member succesfully', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member2add = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'anil_github',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- emails: ['lala@l.com'],
- score: 10,
- attributes: {
- [PlatformType.GITHUB]: {
- name: 'Quoc-Anh Nguyen',
- isHireable: true,
- url: 'https://github.com/imcvampire',
- websiteUrl: 'https://imcvampire.js.org/',
- bio: 'Lazy geek',
- location: 'Helsinki, Finland',
- actions: [
- {
- score: 2,
- timestamp: '2021-05-27T15:13:30Z',
- },
- ],
- },
- [PlatformType.TWITTER]: {
- profile_url: 'https://twitter.com/imcvampire',
- url: 'https://twitter.com/imcvampire',
- },
- },
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const cloned = lodash.cloneDeep(member2add)
- const memberCreated = await MemberRepository.create(cloned, mockIRepositoryOptions)
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const expectedMemberCreated = {
- id: memberCreated.id,
- username: mapUsername(member2add.username),
- attributes: member2add.attributes,
- displayName: member2add.displayName,
- emails: member2add.emails,
- score: member2add.score,
- identities: ['github'],
- lastEnriched: null,
- enrichedBy: [],
- contributions: null,
- organizations: [],
- notes: [],
- tasks: [],
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segments: mockIRepositoryOptions.currentSegments,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- activeOn: [],
- activityTypes: [],
- reach: { total: -1 },
- joinedAt: new Date('2020-05-27T15:13:30Z'),
- tags: [],
- noMerge: [],
- toMerge: [],
- activityCount: 0,
- activeDaysCount: 0,
- lastActive: null,
- averageSentiment: 0,
- numberOfOpenSourceContributions: 0,
- lastActivity: null,
- affiliations: [],
- manuallyCreated: false,
- }
- expect(memberCreated).toStrictEqual(expectedMemberCreated)
- })
-
- it('Should create succesfully but return without relations when doPopulateRelations=false', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member2add = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'anil_github',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- emails: ['lala@l.com'],
- score: 10,
- attributes: {
- [PlatformType.GITHUB]: {
- name: 'Quoc-Anh Nguyen',
- isHireable: true,
- url: 'https://github.com/imcvampire',
- websiteUrl: 'https://imcvampire.js.org/',
- bio: 'Lazy geek',
- location: 'Helsinki, Finland',
- actions: [
- {
- score: 2,
- timestamp: '2021-05-27T15:13:30Z',
- },
- ],
- },
- [PlatformType.TWITTER]: {
- profile_url: 'https://twitter.com/imcvampire',
- url: 'https://twitter.com/imcvampire',
- },
- },
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const cloned = lodash.cloneDeep(member2add)
- const memberCreated = await MemberRepository.create(cloned, mockIRepositoryOptions, false)
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const expectedMemberCreated = {
- id: memberCreated.id,
- username: mapUsername(member2add.username),
- displayName: member2add.displayName,
- attributes: member2add.attributes,
- emails: member2add.emails,
- lastEnriched: null,
- enrichedBy: [],
- contributions: null,
- score: member2add.score,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segments: mockIRepositoryOptions.currentSegments,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- reach: { total: -1 },
- organizations: [],
- joinedAt: new Date('2020-05-27T15:13:30Z'),
- affiliations: [],
- manuallyCreated: false,
- }
- expect(memberCreated).toStrictEqual(expectedMemberCreated)
- })
-
- it('Should succesfully create member with only mandatory username and joinedAt fields', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member2add = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const cloned = lodash.cloneDeep(member2add)
- const memberCreated = await MemberRepository.create(cloned, mockIRepositoryOptions)
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const expectedMemberCreated = {
- id: memberCreated.id,
- username: mapUsername(member2add.username),
- displayName: member2add.displayName,
- organizations: [],
- attributes: {},
- identities: ['github'],
- emails: [],
- lastEnriched: null,
- enrichedBy: [],
- contributions: null,
- score: -1,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segments: mockIRepositoryOptions.currentSegments,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- activeOn: [],
- activityTypes: [],
- reach: { total: -1 },
- joinedAt: new Date('2020-05-27T15:13:30Z'),
- notes: [],
- tasks: [],
- tags: [],
- noMerge: [],
- toMerge: [],
- activityCount: 0,
- activeDaysCount: 0,
- averageSentiment: 0,
- numberOfOpenSourceContributions: 0,
- lastActive: null,
- lastActivity: null,
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberCreated).toStrictEqual(expectedMemberCreated)
- })
-
- it('Should throw error when no username given', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- // no username field, should reject the promise with
- // sequelize unique constraint
- const member2add = {
- joinedAt: '2020-05-27T15:13:30Z',
- emails: ['test@crowd.dev'],
- }
-
- await expect(() =>
- MemberRepository.create(member2add, mockIRepositoryOptions),
- ).rejects.toThrow()
- })
-
- it('Should throw error when no joinedAt given', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- // no username field, should reject the promise with
- // sequelize unique constraint
- const member2add = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- emails: ['test@crowd.dev'],
- }
-
- await expect(() =>
- MemberRepository.create(member2add, mockIRepositoryOptions),
- ).rejects.toThrow()
- })
-
- it('Should succesfully create member with notes', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const notes1 = await NoteRepository.create(
- {
- body: 'note1',
- },
- mockIRepositoryOptions,
- )
-
- const notes2 = await NoteRepository.create(
- {
- body: 'note2',
- },
- mockIRepositoryOptions,
- )
-
- const member2add = {
- username: {
- [PlatformType.SLACK]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- notes: [notes1.id, notes2.id],
- }
-
- const memberCreated = await MemberRepository.create(member2add, mockIRepositoryOptions)
- expect(memberCreated.notes).toHaveLength(2)
- expect(memberCreated.notes[0].id).toEqual(notes1.id)
- expect(memberCreated.notes[1].id).toEqual(notes2.id)
- })
-
- it('Should succesfully create member with tasks', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const tasks1 = await TaskRepository.create(
- {
- name: 'task1',
- },
- mockIRepositoryOptions,
- )
-
- const task2 = await TaskRepository.create(
- {
- name: 'task2',
- },
- mockIRepositoryOptions,
- )
-
- const member2add = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- tasks: [tasks1.id, task2.id],
- }
-
- const memberCreated = await MemberRepository.create(member2add, mockIRepositoryOptions)
- expect(memberCreated.tasks).toHaveLength(2)
- expect(memberCreated.tasks.find((t) => t.id === tasks1.id)).not.toBeUndefined()
- expect(memberCreated.tasks.find((t) => t.id === task2.id)).not.toBeUndefined()
- })
-
- it('Should succesfully create member with organization affiliations', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const segmentRepo = new SegmentRepository(mockIRepositoryOptions)
-
- const segment1 = await segmentRepo.create({
- name: 'Crowd.dev - Segment1',
- url: '',
- parentName: 'Crowd.dev - Segment1',
- grandparentName: 'Crowd.dev - Segment1',
- slug: 'crowd.dev-1',
- parentSlug: 'crowd.dev-1',
- grandparentSlug: 'crowd.dev-1',
- status: SegmentStatus.ACTIVE,
- sourceId: null,
- sourceParentId: null,
- })
-
- const segment2 = await segmentRepo.create({
- name: 'Crowd.dev - Segment2',
- url: '',
- parentName: 'Crowd.dev - Segment2',
- grandparentName: 'Crowd.dev - Segment2',
- slug: 'crowd.dev-2',
- parentSlug: 'crowd.dev-2',
- grandparentSlug: 'crowd.dev-2',
- status: SegmentStatus.ACTIVE,
- sourceId: null,
- sourceParentId: null,
- })
-
- const org1 = await OrganizationRepository.create(
- {
- displayName: 'crowd.dev',
- },
- mockIRepositoryOptions,
- )
-
- const member2add = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- affiliations: [
- {
- segmentId: segment1.id,
- organizationId: org1.id,
- },
- {
- segmentId: segment2.id,
- organizationId: null,
- },
- ],
- }
-
- const memberCreated = await MemberRepository.create(member2add, mockIRepositoryOptions)
- expect(memberCreated.affiliations).toHaveLength(2)
- expect(
- memberCreated.affiliations.filter((a) => a.segmentId === segment1.id)[0].organizationId,
- ).toEqual(org1.id)
- expect(
- memberCreated.affiliations.filter((a) => a.segmentId === segment2.id)[0].organizationId,
- ).toBeNull()
- })
- })
-
- describe('findById method', () => {
- it('Should successfully find created member by id', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member2add = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const cloned = lodash.cloneDeep(member2add)
- const memberCreated = await MemberRepository.create(cloned, mockIRepositoryOptions)
-
- const expectedMemberFound = {
- id: memberCreated.id,
- username: mapUsername(member2add.username),
- displayName: member2add.displayName,
- identities: ['github'],
- attributes: {},
- emails: [],
- lastEnriched: null,
- enrichedBy: [],
- contributions: null,
- score: -1,
- importHash: null,
- organizations: [],
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segments: mockIRepositoryOptions.currentSegments,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- activeOn: [],
- activityTypes: [],
- reach: { total: -1 },
- notes: [],
- tasks: [],
- joinedAt: new Date('2020-05-27T15:13:30Z'),
- tags: [],
- noMerge: [],
- toMerge: [],
- activityCount: 0,
- activeDaysCount: 0,
- averageSentiment: 0,
- numberOfOpenSourceContributions: 0,
- lastActive: null,
- lastActivity: null,
- affiliations: [],
- manuallyCreated: false,
- }
-
- const memberById = await MemberRepository.findById(memberCreated.id, mockIRepositoryOptions)
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- memberById.createdAt = memberById.createdAt.toISOString().split('T')[0]
- memberById.updatedAt = memberById.updatedAt.toISOString().split('T')[0]
-
- expect(memberById).toStrictEqual(expectedMemberFound)
- })
-
- it('Should return a plain object when called with doPopulateRelations false', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member2add = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const cloned = lodash.cloneDeep(member2add)
- const memberCreated = await MemberRepository.create(cloned, mockIRepositoryOptions)
-
- const expectedMemberFound = {
- id: memberCreated.id,
- username: mapUsername(member2add.username),
- displayName: member2add.displayName,
- lastEnriched: null,
- enrichedBy: [],
- contributions: null,
- attributes: {},
- emails: [],
- score: -1,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segments: mockIRepositoryOptions.currentSegments,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- reach: { total: -1 },
- organizations: [],
- joinedAt: new Date('2020-05-27T15:13:30Z'),
- affiliations: [],
- manuallyCreated: false,
- }
-
- const memberById = await MemberRepository.findById(
- memberCreated.id,
- mockIRepositoryOptions,
- true,
- false,
- )
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- memberById.createdAt = memberById.createdAt.toISOString().split('T')[0]
- memberById.updatedAt = memberById.updatedAt.toISOString().split('T')[0]
-
- expect(memberById).toStrictEqual(expectedMemberFound)
- })
-
- it('Should throw 404 error when no member found with given id', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const { randomUUID } = require('crypto')
-
- await expect(() =>
- MemberRepository.findById(randomUUID(), mockIRepositoryOptions),
- ).rejects.toThrowError(new Error404())
- })
- })
-
- describe('filterIdsInTenant method', () => {
- it('Should return the given ids of previously created member entities', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const member1 = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- }
- const member2 = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'some-other-name',
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- const member1Returned = await MemberRepository.create(member1, mockIRepositoryOptions)
- const member2Returned = await MemberRepository.create(member2, mockIRepositoryOptions)
-
- const filterIdsReturned = await MemberRepository.filterIdsInTenant(
- [member1Returned.id, member2Returned.id],
- mockIRepositoryOptions,
- )
-
- expect(filterIdsReturned).toStrictEqual([member1Returned.id, member2Returned.id])
- })
-
- it('Should only return the ids of previously created members and filter random uuids out', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-29T15:14:30Z',
- }
-
- const member1Returned = await MemberRepository.create(member1, mockIRepositoryOptions)
-
- const { randomUUID } = require('crypto')
-
- const filterIdsReturned = await MemberRepository.filterIdsInTenant(
- [member1Returned.id, randomUUID(), randomUUID()],
- mockIRepositoryOptions,
- )
-
- expect(filterIdsReturned).toStrictEqual([member1Returned.id])
- })
-
- it('Should return an empty array for an irrelevant tenant', async () => {
- let mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-04-29T15:14:30Z',
- }
-
- const member1Returned = await MemberRepository.create(member1, mockIRepositoryOptions)
-
- // create a new tenant and bind options to it
- mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const filterIdsReturned = await MemberRepository.filterIdsInTenant(
- [member1Returned.id],
- mockIRepositoryOptions,
- )
-
- expect(filterIdsReturned).toStrictEqual([])
- })
- })
-
- describe('memberExists method', () => {
- it('Should return the created member for a simple query', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const member1 = {
- username: {
- [PlatformType.TWITTER]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- emails: ['joan@crowd.dev'],
- }
- const member1Returned = await MemberRepository.create(member1, mockIRepositoryOptions)
-
- const found = await MemberRepository.memberExists(
- 'test1',
- PlatformType.TWITTER,
- mockIRepositoryOptions,
- )
-
- expect(found).toStrictEqual(member1Returned)
- })
-
- it('Should a plain object when called with doPopulateRelations false', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const member1 = {
- username: {
- [PlatformType.TWITTER]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- emails: ['joan@crowd.dev'],
- }
- const member1Returned = await MemberRepository.create(member1, mockIRepositoryOptions)
- delete member1Returned.toMerge
- delete member1Returned.noMerge
- delete member1Returned.tags
- delete member1Returned.activities
- delete member1Returned.notes
- delete member1Returned.tasks
- delete member1Returned.lastActive
- delete member1Returned.activityCount
- delete member1Returned.averageSentiment
- delete member1Returned.lastActivity
- delete member1Returned.activeOn
- delete member1Returned.identities
- delete member1Returned.activityTypes
- delete member1Returned.activeDaysCount
- delete member1Returned.numberOfOpenSourceContributions
- delete member1Returned.affiliations
- delete member1Returned.manuallyCreated
- member1Returned.segments = member1Returned.segments.map((s) => s.id)
-
- const found = await MemberRepository.memberExists(
- 'test1',
- PlatformType.TWITTER,
- mockIRepositoryOptions,
- false,
- )
-
- expect(found).toStrictEqual(member1Returned)
- })
-
- it('Should return null when non-existent at platform level', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member1 = {
- username: {
- [PlatformType.TWITTER]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- emails: ['joan@crowd.dev'],
- }
- await MemberRepository.create(member1, mockIRepositoryOptions)
-
- await expect(() =>
- MemberRepository.memberExists('test1', PlatformType.GITHUB, mockIRepositoryOptions),
- )
- })
-
- it('Should return null when non-existent at username level', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member1 = {
- username: {
- [PlatformType.TWITTER]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- emails: ['joan@crowd.dev'],
- }
- await MemberRepository.create(member1, mockIRepositoryOptions)
-
- const memberExists = await MemberRepository.memberExists(
- 'test2',
- PlatformType.TWITTER,
- mockIRepositoryOptions,
- )
-
- expect(memberExists).toBeNull()
- })
- })
-
- describe('findAndCountAll method', () => {
- it('is successfully finding and counting all members, sortedBy activitiesCount DESC', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member1 = await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
- const member2 = await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
- const member3 = await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await mockIRepositoryOptions.database.activity.bulkCreate([
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date(),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member1.id,
- username: member1.username[PlatformType.SLACK],
- sourceId: '#sourceId1',
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date(),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member2.id,
- username: member2.username[PlatformType.SLACK],
- sourceId: '#sourceId2',
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date(),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member2.id,
- username: member2.username[PlatformType.SLACK],
- sourceId: '#sourceId3',
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date(),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member3.id,
- username: member3.username[PlatformType.SLACK],
- sourceId: '#sourceId4',
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date(),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member3.id,
- username: member3.username[PlatformType.SLACK],
- sourceId: '#sourceId5',
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date(),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member3.id,
- username: member3.username[PlatformType.SLACK],
- sourceId: '#sourceId6',
- },
- ])
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAll(
- { filter: {}, orderBy: 'activityCount_DESC' },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(3)
- expect(members.rows[0].activityCount).toEqual('3')
- expect(members.rows[1].activityCount).toEqual('2')
- expect(members.rows[2].activityCount).toEqual('1')
- })
-
- it('is successfully finding and counting all members, sortedBy numberOfOpenSourceContributions DESC', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test1' },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- contributions: [
- {
- id: 112529472,
- url: 'https://github.com/bachman/pied-piper',
- topics: ['compression', 'data', 'middle-out', 'Java'],
- summary: 'Pied Piper: 10 commits in 1 day',
- numberCommits: 10,
- lastCommitDate: '2023-03-10',
- firstCommitDate: '2023-03-01',
- },
- {
- id: 112529473,
- url: 'https://github.com/bachman/aviato',
- topics: ['Python', 'Django'],
- summary: 'Aviato: 5 commits in 1 day',
- numberCommits: 5,
- lastCommitDate: '2023-02-25',
- firstCommitDate: '2023-02-20',
- },
- {
- id: 112529476,
- url: 'https://github.com/bachman/erlichbot',
- topics: ['Python', 'Slack API'],
- summary: 'ErlichBot: 2 commits in 1 day',
- numberCommits: 2,
- lastCommitDate: '2023-01-25',
- firstCommitDate: '2023-01-24',
- },
- ],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test2' },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- contributions: [
- {
- id: 112529473,
- url: 'https://github.com/bighead/silicon-valley',
- topics: ['TV Shows', 'Comedy', 'Startups'],
- summary: 'Silicon Valley: 50 commits in 2 weeks',
- numberCommits: 50,
- lastCommitDate: '02/01/2023',
- firstCommitDate: '01/17/2023',
- },
- {
- id: 112529474,
- url: 'https://github.com/bighead/startup-ideas',
- topics: ['Ideas', 'Startups'],
- summary: 'Startup Ideas: 20 commits in 1 week',
- numberCommits: 20,
- lastCommitDate: '03/01/2023',
- firstCommitDate: '02/22/2023',
- },
- ],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test3' },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAll(
- { filter: {}, orderBy: 'numberOfOpenSourceContributions_DESC' },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(3)
- expect(members.rows[0].numberOfOpenSourceContributions).toEqual(3)
- expect(members.rows[1].numberOfOpenSourceContributions).toEqual(2)
- expect(members.rows[2].numberOfOpenSourceContributions).toEqual(0)
- })
-
- it('is successfully finding and counting all members, numberOfOpenSourceContributions range gte than 3 and less or equal to 6', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test1' },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- contributions: [
- {
- id: 112529472,
- url: 'https://github.com/bachman/pied-piper',
- topics: ['compression', 'data', 'middle-out', 'Java'],
- summary: 'Pied Piper: 10 commits in 1 day',
- numberCommits: 10,
- lastCommitDate: '2023-03-10',
- firstCommitDate: '2023-03-01',
- },
- {
- id: 112529473,
- url: 'https://github.com/bachman/aviato',
- topics: ['Python', 'Django'],
- summary: 'Aviato: 5 commits in 1 day',
- numberCommits: 5,
- lastCommitDate: '2023-02-25',
- firstCommitDate: '2023-02-20',
- },
- {
- id: 112529476,
- url: 'https://github.com/bachman/erlichbot',
- topics: ['Python', 'Slack API'],
- summary: 'ErlichBot: 2 commits in 1 day',
- numberCommits: 2,
- lastCommitDate: '2023-01-25',
- firstCommitDate: '2023-01-24',
- },
- {
- id: 112529473,
- url: 'https://github.com/bighead/silicon-valley',
- topics: ['TV Shows', 'Comedy', 'Startups'],
- summary: 'Silicon Valley: 50 commits in 2 weeks',
- numberCommits: 50,
- lastCommitDate: '02/01/2023',
- firstCommitDate: '01/17/2023',
- },
- ],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test2' },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- contributions: [
- {
- id: 112529473,
- url: 'https://github.com/bighead/silicon-valley',
- topics: ['TV Shows', 'Comedy', 'Startups'],
- summary: 'Silicon Valley: 50 commits in 2 weeks',
- numberCommits: 50,
- lastCommitDate: '02/01/2023',
- firstCommitDate: '01/17/2023',
- },
- {
- id: 112529474,
- url: 'https://github.com/bighead/startup-ideas',
- topics: ['Ideas', 'Startups'],
- summary: 'Startup Ideas: 20 commits in 1 week',
- numberCommits: 20,
- lastCommitDate: '03/01/2023',
- firstCommitDate: '02/22/2023',
- },
- ],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test3' },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAll(
- { filter: { numberOfOpenSourceContributionsRange: [3, 6] } },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(1)
- expect(members.rows[0].numberOfOpenSourceContributions).toEqual(4)
- })
-
- it('is successfully finding and counting all members, numberOfOpenSourceContributions range gte 2', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test1' },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- contributions: [
- {
- id: 112529472,
- url: 'https://github.com/bachman/pied-piper',
- topics: ['compression', 'data', 'middle-out', 'Java'],
- summary: 'Pied Piper: 10 commits in 1 day',
- numberCommits: 10,
- lastCommitDate: '2023-03-10',
- firstCommitDate: '2023-03-01',
- },
- {
- id: 112529473,
- url: 'https://github.com/bachman/aviato',
- topics: ['Python', 'Django'],
- summary: 'Aviato: 5 commits in 1 day',
- numberCommits: 5,
- lastCommitDate: '2023-02-25',
- firstCommitDate: '2023-02-20',
- },
- {
- id: 112529476,
- url: 'https://github.com/bachman/erlichbot',
- topics: ['Python', 'Slack API'],
- summary: 'ErlichBot: 2 commits in 1 day',
- numberCommits: 2,
- lastCommitDate: '2023-01-25',
- firstCommitDate: '2023-01-24',
- },
- {
- id: 112529473,
- url: 'https://github.com/bighead/silicon-valley',
- topics: ['TV Shows', 'Comedy', 'Startups'],
- summary: 'Silicon Valley: 50 commits in 2 weeks',
- numberCommits: 50,
- lastCommitDate: '02/01/2023',
- firstCommitDate: '01/17/2023',
- },
- ],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test2' },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- contributions: [
- {
- id: 112529473,
- url: 'https://github.com/bighead/silicon-valley',
- topics: ['TV Shows', 'Comedy', 'Startups'],
- summary: 'Silicon Valley: 50 commits in 2 weeks',
- numberCommits: 50,
- lastCommitDate: '02/01/2023',
- firstCommitDate: '01/17/2023',
- },
- {
- id: 112529474,
- url: 'https://github.com/bighead/startup-ideas',
- topics: ['Ideas', 'Startups'],
- summary: 'Startup Ideas: 20 commits in 1 week',
- numberCommits: 20,
- lastCommitDate: '03/01/2023',
- firstCommitDate: '02/22/2023',
- },
- ],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test3' },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAll(
- {
- filter: { numberOfOpenSourceContributionsRange: [2] },
- orderBy: 'numberOfOpenSourceContributions_DESC',
- },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(2)
- expect(members.rows[0].numberOfOpenSourceContributions).toEqual(4)
- expect(members.rows[1].numberOfOpenSourceContributions).toEqual(2)
- })
-
- it('is successfully finding and counting all members, and tags [nodejs, vuejs]', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const nodeTag = await mockIRepositoryOptions.database.tag.create({
- name: 'nodejs',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
- const vueTag = await mockIRepositoryOptions.database.tag.create({
- name: 'vuejs',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
-
- await MemberRepository.create(
- {
- username: {
- [PlatformType.TWITTER]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.TWITTER]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- tags: [nodeTag.id, vueTag.id],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAll(
- { filter: { tags: [nodeTag.id, vueTag.id] } },
- mockIRepositoryOptions,
- )
- const member2 = members.rows.find((m) => m.username[PlatformType.TWITTER][0] === 'test2')
- expect(members.rows.length).toEqual(1)
- expect(member2.tags[0].name).toEqual('nodejs')
- expect(member2.tags[1].name).toEqual('vuejs')
- })
-
- it('is successfully finding and counting all members, and tags [nodejs]', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const nodeTag = await mockIRepositoryOptions.database.tag.create({
- name: 'nodejs',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
- const vueTag = await mockIRepositoryOptions.database.tag.create({
- name: 'vuejs',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
-
- await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- tags: [nodeTag.id],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- tags: [nodeTag.id, vueTag.id],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAll(
- { filter: { tags: [nodeTag.id] } },
- mockIRepositoryOptions,
- )
- const member1 = members.rows.find((m) => m.username[PlatformType.GITHUB][0] === 'test1')
- const member2 = members.rows.find((m) => m.username[PlatformType.GITHUB][0] === 'test2')
-
- expect(members.rows.length).toEqual(2)
- expect(member1.tags[0].name).toEqual('nodejs')
- expect(member1.tags[0].name).toEqual('nodejs')
- expect(member2.tags[1].name).toEqual('vuejs')
- })
-
- it('is successfully finding and counting all members, and organisations [crowd.dev, pied piper]', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const crowd = await mockIRepositoryOptions.database.organization.create({
- displayName: 'crowd.dev',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
- await OrganizationRepository.addIdentity(
- crowd.id,
- {
- name: 'crowd.dev',
- url: 'https://crowd.dev',
- platform: 'crowd',
- },
- mockIRepositoryOptions,
- )
-
- const pp = await mockIRepositoryOptions.database.organization.create({
- displayName: 'pied piper',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
-
- await OrganizationRepository.addIdentity(
- pp.id,
- {
- name: 'pied piper',
- url: 'https://piedpiper.com',
- platform: 'crowd',
- },
- mockIRepositoryOptions,
- )
-
- await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- organizations: [crowd.id, pp.id],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAll(
- { filter: { organizations: [crowd.id, pp.id] } },
- mockIRepositoryOptions,
- )
- const member2 = members.rows.find((m) => m.username[PlatformType.SLACK][0] === 'test2')
- expect(members.rows.length).toEqual(1)
- expect(member2.organizations[0].displayName).toEqual('crowd.dev')
- expect(member2.organizations[1].displayName).toEqual('pied piper')
- })
-
- it('is successfully finding and counting all members, and scoreRange is gte than 1 and less or equal to 6', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const user1 = {
- username: {
- [PlatformType.SLACK]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- }
- const user2 = {
- username: {
- [PlatformType.SLACK]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- }
- const user3 = {
- username: {
- [PlatformType.SLACK]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '7',
- joinedAt: new Date(),
- }
- await MemberRepository.create(user1, mockIRepositoryOptions)
- await MemberRepository.create(user2, mockIRepositoryOptions)
- await MemberRepository.create(user3, mockIRepositoryOptions)
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAll(
- { filter: { scoreRange: [1, 6] } },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(2)
- expect(members.rows.find((m) => m.username[PlatformType.SLACK][0] === 'test1').score).toEqual(
- 1,
- )
- expect(members.rows.find((m) => m.username[PlatformType.SLACK][0] === 'test2').score).toEqual(
- 6,
- )
- })
-
- it('is successfully finding and counting all members, and scoreRange is gte than 7', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const user1 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- }
- const user2 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- }
- const user3 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- }
- await MemberRepository.create(user1, mockIRepositoryOptions)
- await MemberRepository.create(user2, mockIRepositoryOptions)
- await MemberRepository.create(user3, mockIRepositoryOptions)
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAll(
- { filter: { scoreRange: [7] } },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(1)
- for (const member of members.rows) {
- expect(member.score).toBeGreaterThanOrEqual(7)
- }
- })
-
- it('is successfully find and counting members with various filters, computed attributes, and full options (filter, limit, offset and orderBy)', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const nodeTag = await mockIRepositoryOptions.database.tag.create({
- name: 'nodejs',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
- const vueTag = await mockIRepositoryOptions.database.tag.create({
- name: 'vuejs',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
-
- const member1 = await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- tags: [nodeTag.id],
- reach: {
- total: 15,
- },
- },
- mockIRepositoryOptions,
- )
- const member2 = await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- tags: [nodeTag.id, vueTag.id],
- reach: {
- total: 55,
- },
- },
- mockIRepositoryOptions,
- )
- const member3 = await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- tags: [vueTag.id],
- reach: {
- total: 124,
- },
- },
- mockIRepositoryOptions,
- )
-
- await mockIRepositoryOptions.database.activity.bulkCreate([
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date('2022-09-10'),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member1.id,
- username: member1.username[PlatformType.SLACK],
- sourceId: '#sourceId1',
- sentiment: {
- positive: 0.55,
- negative: 0.0,
- neutral: 0.45,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.1,
- },
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date('2022-09-11'),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member2.id,
- username: member2.username[PlatformType.SLACK],
- sourceId: '#sourceId2',
- sentiment: {
- positive: 0.01,
- negative: 0.55,
- neutral: 0.55,
- mixed: 0.0,
- label: 'negative',
- sentiment: -0.54,
- },
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date('2022-09-12'),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member2.id,
- username: member2.username[PlatformType.SLACK],
- sourceId: '#sourceId3',
- sentiment: {
- positive: 0.94,
- negative: 0.0,
- neutral: 0.06,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.94,
- },
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date('2022-09-13'),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member3.id,
- username: member3.username[PlatformType.SLACK],
- sourceId: '#sourceId4',
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.42,
- },
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date('2022-09-14'),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member3.id,
- username: member3.username[PlatformType.SLACK],
- sourceId: '#sourceId5',
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.41,
- },
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date('2022-09-15'),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member3.id,
- username: member3.username[PlatformType.SLACK],
- sourceId: '#sourceId6',
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.18,
- },
- },
- ])
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- let members = await MemberRepository.findAndCountAll(
- {
- filter: {},
- limit: 15,
- offset: 0,
- orderBy: 'activityCount_DESC',
- },
- mockIRepositoryOptions,
- )
- expect(members.rows.length).toEqual(3)
- expect(members.rows[0].activityCount).toEqual('3')
- expect(members.rows[0].lastActive.toISOString()).toEqual('2022-09-15T00:00:00.000Z')
-
- expect(members.rows[1].activityCount).toEqual('2')
- expect(members.rows[1].lastActive.toISOString()).toEqual('2022-09-12T00:00:00.000Z')
-
- expect(members.rows[2].activityCount).toEqual('1')
- expect(members.rows[2].tags[0].name).toEqual('nodejs')
- expect(members.rows[2].lastActive.toISOString()).toEqual('2022-09-10T00:00:00.000Z')
-
- expect(members.rows[1].tags.map((i) => i.name).sort()).toEqual(['nodejs', 'vuejs'])
- expect(members.rows[0].tags[0].name).toEqual('vuejs')
-
- // filter and order by reach
- members = await MemberRepository.findAndCountAll(
- {
- filter: {
- reachRange: [55],
- },
- limit: 15,
- offset: 0,
- orderBy: 'reach_DESC',
- },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(2)
- expect(members.rows[0].id).toEqual(member3.id)
- expect(members.rows[1].id).toEqual(member2.id)
-
- // filter and sort by activity count
- members = await MemberRepository.findAndCountAll(
- {
- filter: {
- activityCountRange: [2],
- },
- limit: 15,
- offset: 0,
- orderBy: 'activityCount_DESC',
- },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(2)
- expect(members.rows.map((i) => i.id)).toEqual([member3.id, member2.id])
-
- // filter and sort by lastActive
- members = await MemberRepository.findAndCountAll(
- {
- filter: {
- lastActiveRange: ['2022-09-11'],
- },
- limit: 15,
- offset: 0,
- orderBy: 'lastActive_DESC',
- },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(2)
- expect(members.rows.map((i) => i.id)).toEqual([member3.id, member2.id])
-
- // filter and sort by averageSentiment (member1.avgSentiment = 0.1, member2.avgSentiment = 0.2, member3.avgSentiment = 0.34)
- members = await MemberRepository.findAndCountAll(
- {
- filter: {
- averageSentimentRange: [0.2],
- },
- limit: 15,
- offset: 0,
- orderBy: 'averageSentiment_ASC',
- },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(2)
- expect(members.rows.map((i) => i.id)).toEqual([member2.id, member3.id])
- })
- })
-
- describe('findAndCountAllv2 method', () => {
- it('is successfully finding and counting all members, sortedBy activitiesCount DESC', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member1 = await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test1' },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
- const member2 = await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test2' },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
- const member3 = await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test3' },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await mockIRepositoryOptions.database.activity.bulkCreate([
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date(),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- username: 'test1',
- memberId: member1.id,
- sourceId: '#sourceId1',
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date(),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- username: 'test2',
- memberId: member2.id,
- sourceId: '#sourceId2',
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date(),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- username: 'test2',
- memberId: member2.id,
- sourceId: '#sourceId3',
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date(),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- username: 'test3',
- memberId: member3.id,
- sourceId: '#sourceId4',
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date(),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- username: 'test3',
- memberId: member3.id,
- sourceId: '#sourceId5',
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date(),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- username: 'test3',
- memberId: member3.id,
- sourceId: '#sourceId6',
- },
- ])
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAllv2(
- { filter: {}, orderBy: 'activityCount_DESC' },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(3)
- expect(members.rows[0].activityCount).toEqual('3')
- expect(members.rows[1].activityCount).toEqual('2')
- expect(members.rows[2].activityCount).toEqual('1')
- })
-
- it('is successfully finding and counting all members, sortedBy numberOfOpenSourceContributions DESC', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test1' },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- contributions: [
- {
- id: 112529472,
- url: 'https://github.com/bachman/pied-piper',
- topics: ['compression', 'data', 'middle-out', 'Java'],
- summary: 'Pied Piper: 10 commits in 1 day',
- numberCommits: 10,
- lastCommitDate: '2023-03-10',
- firstCommitDate: '2023-03-01',
- },
- {
- id: 112529473,
- url: 'https://github.com/bachman/aviato',
- topics: ['Python', 'Django'],
- summary: 'Aviato: 5 commits in 1 day',
- numberCommits: 5,
- lastCommitDate: '2023-02-25',
- firstCommitDate: '2023-02-20',
- },
- {
- id: 112529476,
- url: 'https://github.com/bachman/erlichbot',
- topics: ['Python', 'Slack API'],
- summary: 'ErlichBot: 2 commits in 1 day',
- numberCommits: 2,
- lastCommitDate: '2023-01-25',
- firstCommitDate: '2023-01-24',
- },
- ],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test2' },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- contributions: [
- {
- id: 112529473,
- url: 'https://github.com/bighead/silicon-valley',
- topics: ['TV Shows', 'Comedy', 'Startups'],
- summary: 'Silicon Valley: 50 commits in 2 weeks',
- numberCommits: 50,
- lastCommitDate: '02/01/2023',
- firstCommitDate: '01/17/2023',
- },
- {
- id: 112529474,
- url: 'https://github.com/bighead/startup-ideas',
- topics: ['Ideas', 'Startups'],
- summary: 'Startup Ideas: 20 commits in 1 week',
- numberCommits: 20,
- lastCommitDate: '03/01/2023',
- firstCommitDate: '02/22/2023',
- },
- ],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test3' },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAllv2(
- { filter: {}, orderBy: 'numberOfOpenSourceContributions_DESC' },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(3)
- expect(members.rows[0].numberOfOpenSourceContributions).toEqual(3)
- expect(members.rows[1].numberOfOpenSourceContributions).toEqual(2)
- expect(members.rows[2].numberOfOpenSourceContributions).toEqual(0)
- })
-
- it('is successfully finding and counting all members, numberOfOpenSourceContributions range gte 3', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- await MemberRepository.create(
- {
- username: {
- [PlatformType.TWITTER]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- contributions: [
- {
- id: 112529472,
- url: 'https://github.com/bachman/pied-piper',
- topics: ['compression', 'data', 'middle-out', 'Java'],
- summary: 'Pied Piper: 10 commits in 1 day',
- numberCommits: 10,
- lastCommitDate: '2023-03-10',
- firstCommitDate: '2023-03-01',
- },
- {
- id: 112529473,
- url: 'https://github.com/bachman/aviato',
- topics: ['Python', 'Django'],
- summary: 'Aviato: 5 commits in 1 day',
- numberCommits: 5,
- lastCommitDate: '2023-02-25',
- firstCommitDate: '2023-02-20',
- },
- {
- id: 112529476,
- url: 'https://github.com/bachman/erlichbot',
- topics: ['Python', 'Slack API'],
- summary: 'ErlichBot: 2 commits in 1 day',
- numberCommits: 2,
- lastCommitDate: '2023-01-25',
- firstCommitDate: '2023-01-24',
- },
- {
- id: 112529473,
- url: 'https://github.com/bighead/silicon-valley',
- topics: ['TV Shows', 'Comedy', 'Startups'],
- summary: 'Silicon Valley: 50 commits in 2 weeks',
- numberCommits: 50,
- lastCommitDate: '02/01/2023',
- firstCommitDate: '01/17/2023',
- },
- ],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.TWITTER]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- contributions: [
- {
- id: 112529473,
- url: 'https://github.com/bighead/silicon-valley',
- topics: ['TV Shows', 'Comedy', 'Startups'],
- summary: 'Silicon Valley: 50 commits in 2 weeks',
- numberCommits: 50,
- lastCommitDate: '02/01/2023',
- firstCommitDate: '01/17/2023',
- },
- {
- id: 112529474,
- url: 'https://github.com/bighead/startup-ideas',
- topics: ['Ideas', 'Startups'],
- summary: 'Startup Ideas: 20 commits in 1 week',
- numberCommits: 20,
- lastCommitDate: '03/01/2023',
- firstCommitDate: '02/22/2023',
- },
- ],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.TWITTER]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAllv2(
- {
- filter: {
- and: [
- {
- and: [
- {
- numberOfOpenSourceContributions: {
- gte: 3,
- },
- },
- ],
- },
- ],
- },
- },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(1)
- expect(members.rows[0].numberOfOpenSourceContributions).toEqual(4)
- })
-
- it('is successfully finding and counting all members, numberOfOpenSourceContributions range gte 2 and sort by asc', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test1' },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- contributions: [
- {
- id: 112529472,
- url: 'https://github.com/bachman/pied-piper',
- topics: ['compression', 'data', 'middle-out', 'Java'],
- summary: 'Pied Piper: 10 commits in 1 day',
- numberCommits: 10,
- lastCommitDate: '2023-03-10',
- firstCommitDate: '2023-03-01',
- },
- {
- id: 112529473,
- url: 'https://github.com/bachman/aviato',
- topics: ['Python', 'Django'],
- summary: 'Aviato: 5 commits in 1 day',
- numberCommits: 5,
- lastCommitDate: '2023-02-25',
- firstCommitDate: '2023-02-20',
- },
- {
- id: 112529476,
- url: 'https://github.com/bachman/erlichbot',
- topics: ['Python', 'Slack API'],
- summary: 'ErlichBot: 2 commits in 1 day',
- numberCommits: 2,
- lastCommitDate: '2023-01-25',
- firstCommitDate: '2023-01-24',
- },
- {
- id: 112529473,
- url: 'https://github.com/bighead/silicon-valley',
- topics: ['TV Shows', 'Comedy', 'Startups'],
- summary: 'Silicon Valley: 50 commits in 2 weeks',
- numberCommits: 50,
- lastCommitDate: '02/01/2023',
- firstCommitDate: '01/17/2023',
- },
- ],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test2' },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- contributions: [
- {
- id: 112529473,
- url: 'https://github.com/bighead/silicon-valley',
- topics: ['TV Shows', 'Comedy', 'Startups'],
- summary: 'Silicon Valley: 50 commits in 2 weeks',
- numberCommits: 50,
- lastCommitDate: '02/01/2023',
- firstCommitDate: '01/17/2023',
- },
- {
- id: 112529474,
- url: 'https://github.com/bighead/startup-ideas',
- topics: ['Ideas', 'Startups'],
- summary: 'Startup Ideas: 20 commits in 1 week',
- numberCommits: 20,
- lastCommitDate: '03/01/2023',
- firstCommitDate: '02/22/2023',
- },
- ],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: { [PlatformType.TWITTER]: 'test3' },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
- const members = await MemberRepository.findAndCountAllv2(
- {
- filter: {
- and: [
- {
- and: [
- {
- numberOfOpenSourceContributions: {
- gte: 2,
- },
- },
- ],
- },
- ],
- },
- orderBy: 'numberOfOpenSourceContributions_ASC',
- },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(2)
- expect(members.rows[0].numberOfOpenSourceContributions).toEqual(2)
- expect(members.rows[1].numberOfOpenSourceContributions).toEqual(4)
- })
-
- it('is successfully finding and counting all members, and tags [nodejs, vuejs]', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const nodeTag = await mockIRepositoryOptions.database.tag.create({
- name: 'nodejs',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
- const vueTag = await mockIRepositoryOptions.database.tag.create({
- name: 'vuejs',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
-
- await MemberRepository.create(
- {
- username: {
- [PlatformType.TWITTER]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.TWITTER]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- tags: [nodeTag.id, vueTag.id],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAllv2(
- {
- filter: {
- and: [
- {
- tags: {
- contains: [nodeTag.id, vueTag.id],
- },
- },
- ],
- },
- },
- mockIRepositoryOptions,
- )
- const member2 = members.rows.find((m) => m.username[PlatformType.TWITTER].includes('test2'))
- expect(members.rows.length).toEqual(1)
- expect(member2.tags.map((t) => t.name)).toEqual(expect.arrayContaining(['nodejs', 'vuejs']))
- })
-
- it('is successfully finding and counting all members, and tags [nodejs]', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const nodeTag = await mockIRepositoryOptions.database.tag.create({
- name: 'nodejs',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
- const vueTag = await mockIRepositoryOptions.database.tag.create({
- name: 'vuejs',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
-
- await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- tags: [nodeTag.id],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- tags: [nodeTag.id, vueTag.id],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.GITHUB]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAllv2(
- {
- filter: {
- and: [
- {
- tags: {
- contains: [nodeTag.id],
- },
- },
- ],
- },
- },
- mockIRepositoryOptions,
- )
- const member1 = members.rows.find((m) => m.username[PlatformType.GITHUB].includes('test1'))
- const member2 = members.rows.find((m) => m.username[PlatformType.GITHUB].includes('test2'))
-
- expect(members.rows.length).toEqual(2)
- expect(member1.tags[0].name).toEqual('nodejs')
- expect(member2.tags.map((t) => t.name)).toEqual(expect.arrayContaining(['nodejs', 'vuejs']))
- })
-
- it('is successfully finding and counting all members, and organisations [crowd.dev, pied piper]', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const crowd = await OrganizationRepository.create(
- {
- identities: [
- {
- name: 'crowd.dev',
- url: 'https://crowd.dev',
- platform: 'crowd',
- },
- ],
- displayName: 'crowd.dev',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- },
- mockIRepositoryOptions,
- )
- const pp = await OrganizationRepository.create(
- {
- identities: [
- {
- name: 'pied piper',
- url: 'https://piedpiper.com',
- platform: 'crowd',
- },
- ],
- displayName: 'pied piper',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- },
- mockIRepositoryOptions,
- )
-
- await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- organizations: [crowd.id, pp.id],
- },
- mockIRepositoryOptions,
- )
- await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAllv2(
- {
- filter: {
- and: [
- {
- organizations: {
- contains: [crowd.id, pp.id],
- },
- },
- ],
- },
- },
- mockIRepositoryOptions,
- )
- const member2 = members.rows.find((m) => m.username[PlatformType.SLACK].includes('test2'))
- expect(members.rows.length).toEqual(1)
- expect(member2.organizations.map((o) => o.displayName)).toEqual(
- expect.arrayContaining(['crowd.dev', 'pied piper']),
- )
- })
-
- it('is successfully finding and counting all members, and scoreRange is gte than 7', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const user1 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- }
- const user2 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- }
- const user3 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- }
- await MemberRepository.create(user1, mockIRepositoryOptions)
- await MemberRepository.create(user2, mockIRepositoryOptions)
- await MemberRepository.create(user3, mockIRepositoryOptions)
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- const members = await MemberRepository.findAndCountAllv2(
- {
- filter: {
- and: [
- {
- and: [
- {
- score: {
- gte: 7,
- },
- },
- ],
- },
- ],
- },
- },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(1)
- for (const member of members.rows) {
- expect(member.score).toBeGreaterThanOrEqual(7)
- }
- })
-
- it('is successfully find and counting members with various filters, computed attributes, and full options (filter, limit, offset and orderBy)', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const nodeTag = await mockIRepositoryOptions.database.tag.create({
- name: 'nodejs',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
- const vueTag = await mockIRepositoryOptions.database.tag.create({
- name: 'vuejs',
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- })
-
- const member1 = await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- tags: [nodeTag.id],
- reach: {
- total: 15,
- },
- },
- mockIRepositoryOptions,
- )
- const member2 = await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- score: '6',
- joinedAt: new Date(),
- tags: [nodeTag.id, vueTag.id],
- reach: {
- total: 55,
- },
- },
- mockIRepositoryOptions,
- )
- const member3 = await MemberRepository.create(
- {
- username: {
- [PlatformType.SLACK]: {
- username: 'test3',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 3',
- score: '7',
- joinedAt: new Date(),
- tags: [vueTag.id],
- reach: {
- total: 124,
- },
- },
- mockIRepositoryOptions,
- )
-
- await mockIRepositoryOptions.database.activity.bulkCreate([
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date('2022-09-10'),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member1.id,
- username: member1.username[PlatformType.SLACK],
- sourceId: '#sourceId1',
- sentiment: {
- positive: 0.55,
- negative: 0.0,
- neutral: 0.45,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.1,
- },
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date('2022-09-11'),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member2.id,
- username: member2.username[PlatformType.SLACK],
- sourceId: '#sourceId2',
- sentiment: {
- positive: 0.01,
- negative: 0.55,
- neutral: 0.55,
- mixed: 0.0,
- label: 'negative',
- sentiment: -0.54,
- },
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date('2022-09-12'),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member2.id,
- username: member2.username[PlatformType.SLACK],
- sourceId: '#sourceId3',
- sentiment: {
- positive: 0.94,
- negative: 0.0,
- neutral: 0.06,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.94,
- },
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date('2022-09-13'),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member3.id,
- username: member3.username[PlatformType.SLACK],
- sourceId: '#sourceId4',
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.42,
- },
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date('2022-09-14'),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member3.id,
- username: member3.username[PlatformType.SLACK],
- sourceId: '#sourceId5',
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.41,
- },
- },
- {
- type: 'message',
- platform: PlatformType.SLACK,
- timestamp: new Date('2022-09-15'),
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- memberId: member3.id,
- username: member3.username[PlatformType.SLACK],
- sourceId: '#sourceId6',
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.18,
- },
- },
- ])
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- let members = await MemberRepository.findAndCountAllv2(
- {
- filter: {},
- limit: 15,
- offset: 0,
- orderBy: 'activityCount_DESC',
- },
- mockIRepositoryOptions,
- )
- expect(members.rows.length).toEqual(3)
- expect(members.rows[0].activityCount).toEqual('3')
- expect(members.rows[0].lastActive.toISOString()).toEqual('2022-09-15T00:00:00.000Z')
-
- expect(members.rows[1].activityCount).toEqual('2')
- expect(members.rows[1].lastActive.toISOString()).toEqual('2022-09-12T00:00:00.000Z')
-
- expect(members.rows[2].activityCount).toEqual('1')
- expect(members.rows[2].tags[0].name).toEqual('nodejs')
- expect(members.rows[2].lastActive.toISOString()).toEqual('2022-09-10T00:00:00.000Z')
-
- expect(members.rows[1].tags.map((i) => i.name).sort()).toEqual(['nodejs', 'vuejs'])
- expect(members.rows[0].tags[0].name).toEqual('vuejs')
-
- // filter and order by reach
- members = await MemberRepository.findAndCountAllv2(
- {
- filter: {
- and: [
- {
- and: [
- {
- reach: {
- gte: 55,
- },
- },
- ],
- },
- ],
- },
- limit: 15,
- offset: 0,
- orderBy: 'reach_DESC',
- },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(2)
- expect(members.rows[0].id).toEqual(member3.id)
- expect(members.rows[1].id).toEqual(member2.id)
-
- // filter and sort by activity count
- members = await MemberRepository.findAndCountAllv2(
- {
- filter: {
- and: [
- {
- and: [
- {
- activityCount: {
- gte: 2,
- },
- },
- ],
- },
- ],
- },
- limit: 15,
- offset: 0,
- orderBy: 'activityCount_DESC',
- },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(2)
- expect(members.rows.map((i) => i.id)).toEqual([member3.id, member2.id])
-
- // filter and sort by lastActive
- members = await MemberRepository.findAndCountAllv2(
- {
- filter: {
- and: [
- {
- and: [
- {
- lastActive: {
- gte: '2022-09-11',
- },
- },
- ],
- },
- ],
- },
- limit: 15,
- offset: 0,
- orderBy: 'lastActive_DESC',
- },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(2)
- expect(members.rows.map((i) => i.id)).toEqual([member3.id, member2.id])
-
- // filter and sort by averageSentiment (member1.avgSentiment = 0.1, member2.avgSentiment = 0.2, member3.avgSentiment = 0.34)
- members = await MemberRepository.findAndCountAllv2(
- {
- filter: {
- and: [
- {
- and: [
- {
- averageSentiment: {
- gte: 0.2,
- },
- },
- ],
- },
- ],
- },
- limit: 15,
- offset: 0,
- orderBy: 'averageSentiment_ASC',
- },
- mockIRepositoryOptions,
- )
-
- expect(members.rows.length).toEqual(2)
- expect(members.rows.map((i) => i.id)).toEqual([member2.id, member3.id])
- })
- })
-
- describe('update method', () => {
- it('Should succesfully update previously created member', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member1 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: '2021-05-27T15:14:30Z',
- }
- let cloned = lodash.cloneDeep(member1)
- const returnedMember = await MemberRepository.create(cloned, mockIRepositoryOptions)
-
- const updateFields = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'anil_github',
- integrationId: generateUUIDv1(),
- },
- },
- emails: ['lala@l.com'],
- score: 10,
- attributes: {
- [PlatformType.GITHUB]: {
- name: 'Quoc-Anh Nguyen',
- isHireable: true,
- url: 'https://github.com/imcvampire',
- websiteUrl: 'https://imcvampire.js.org/',
- bio: 'Lazy geek',
- location: 'Helsinki, Finland',
- actions: [
- {
- score: 2,
- timestamp: '2021-05-27T15:13:30Z',
- },
- ],
- },
- [PlatformType.TWITTER]: {
- profile_url: 'https://twitter.com/imcvampire',
- url: 'https://twitter.com/imcvampire',
- },
- },
- joinedAt: '2021-06-27T15:14:30Z',
- location: 'Istanbul',
- }
-
- cloned = lodash.cloneDeep(updateFields)
- const updatedMember = await MemberRepository.update(
- returnedMember.id,
- cloned,
- mockIRepositoryOptions,
- )
-
- // check updatedAt field looks ok or not. Should be greater than createdAt
- expect(updatedMember.updatedAt.getTime()).toBeGreaterThan(updatedMember.createdAt.getTime())
-
- updatedMember.createdAt = updatedMember.createdAt.toISOString().split('T')[0]
- updatedMember.updatedAt = updatedMember.updatedAt.toISOString().split('T')[0]
-
- const expectedMemberCreated = {
- id: returnedMember.id,
- username: mapUsername({
- ...updateFields.username,
- ...member1.username,
- }),
- identities: ['discord', 'github'],
- displayName: returnedMember.displayName,
- attributes: updateFields.attributes,
- emails: updateFields.emails,
- score: updateFields.score,
- lastEnriched: null,
- enrichedBy: [],
- contributions: null,
- organizations: [],
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segments: mockIRepositoryOptions.currentSegments,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- reach: { total: -1 },
- notes: [],
- tasks: [],
- activeOn: [],
- activityTypes: [],
- joinedAt: new Date(updateFields.joinedAt),
- tags: [],
- noMerge: [],
- toMerge: [],
- activityCount: 0,
- activeDaysCount: 0,
- averageSentiment: 0,
- numberOfOpenSourceContributions: 0,
- lastActive: null,
- lastActivity: null,
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(updatedMember).toStrictEqual(expectedMemberCreated)
- })
-
- it('Should update successfuly but return without relations when doPopulateRelations=false', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member1 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: '2021-05-27T15:14:30Z',
- }
- const returnedMember = await MemberRepository.create(member1, mockIRepositoryOptions)
-
- const updateFields = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'anil_github',
- integrationId: generateUUIDv1(),
- },
- },
- emails: ['lala@l.com'],
- score: 10,
- attributes: {
- [PlatformType.GITHUB]: {
- name: 'Quoc-Anh Nguyen',
- isHireable: true,
- url: 'https://github.com/imcvampire',
- websiteUrl: 'https://imcvampire.js.org/',
- bio: 'Lazy geek',
- location: 'Helsinki, Finland',
- actions: [
- {
- score: 2,
- timestamp: '2021-05-27T15:13:30Z',
- },
- ],
- },
- [PlatformType.TWITTER]: {
- profile_url: 'https://twitter.com/imcvampire',
- url: 'https://twitter.com/imcvampire',
- },
- },
- joinedAt: '2021-06-27T15:14:30Z',
- location: 'Istanbul',
- }
-
- const updatedMember = await MemberRepository.update(
- returnedMember.id,
- updateFields,
- mockIRepositoryOptions,
- false,
- )
-
- // check updatedAt field looks ok or not. Should be greater than createdAt
- expect(updatedMember.updatedAt.getTime()).toBeGreaterThan(updatedMember.createdAt.getTime())
-
- updatedMember.createdAt = updatedMember.createdAt.toISOString().split('T')[0]
- updatedMember.updatedAt = updatedMember.updatedAt.toISOString().split('T')[0]
-
- const expectedMemberCreated = {
- id: returnedMember.id,
- username: mapUsername({
- [PlatformType.DISCORD]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- [PlatformType.GITHUB]: {
- username: 'anil_github',
- integrationId: generateUUIDv1(),
- },
- }),
- displayName: returnedMember.displayName,
- attributes: updateFields.attributes,
- lastEnriched: null,
- enrichedBy: [],
- organizations: [],
- contributions: null,
- emails: updateFields.emails,
- score: updateFields.score,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segments: mockIRepositoryOptions.currentSegments,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- reach: { total: -1 },
- joinedAt: new Date(updateFields.joinedAt),
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(updatedMember).toStrictEqual(expectedMemberCreated)
- })
-
- it('Should successfully update member with given tags', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const tag1 = await TagRepository.create({ name: 'tag1' }, mockIRepositoryOptions)
- const tag2 = await TagRepository.create({ name: 'tag2' }, mockIRepositoryOptions)
- const tag3 = await TagRepository.create({ name: 'tag3' }, mockIRepositoryOptions)
-
- // Create member with tag3
- let member1 = await MemberRepository.create(
- {
- username: {
- [PlatformType.DISCORD]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- tags: [tag3.id],
- },
- mockIRepositoryOptions,
- )
-
- // When feeding tags attribute to update, update method will overwrite the member's tags with new given tags
- // member1 is expected to have [tag1,tag2] after update
- member1 = await MemberRepository.update(
- member1.id,
- { tags: [tag1.id, tag2.id] },
- mockIRepositoryOptions,
- )
-
- member1.createdAt = member1.createdAt.toISOString().split('T')[0]
- member1.updatedAt = member1.updatedAt.toISOString().split('T')[0]
-
- member1.tags = member1.tags.map((i) => i.get({ plain: true }))
-
- // strip members field from tags created to expect.
- // we won't be returning second level relationships.
- const { members: _tag1Members, ...tag1Plain } = tag1
- const { members: _tag2Members, ...tag2Plain } = tag2
-
- const expectedMemberCreated = {
- id: member1.id,
- username: member1.username,
- displayName: member1.displayName,
- identities: ['discord'],
- attributes: {},
- emails: member1.emails,
- score: member1.score,
- organizations: [],
- lastEnriched: null,
- enrichedBy: [],
- contributions: null,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segments: mockIRepositoryOptions.currentSegments,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- reach: { total: -1 },
- notes: [],
- tasks: [],
- activeOn: [],
- activityTypes: [],
- joinedAt: new Date(member1.joinedAt),
- tags: [tag1Plain, tag2Plain],
- noMerge: [],
- toMerge: [],
- activityCount: 0,
- activeDaysCount: 0,
- averageSentiment: 0,
- numberOfOpenSourceContributions: 0,
- lastActive: null,
- lastActivity: null,
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(member1).toStrictEqual(expectedMemberCreated)
- })
-
- it('Should successfully update member with given organizations', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const org1 = await OrganizationRepository.create(
- {
- displayName: 'crowd.dev',
- identities: [{ name: 'crowd.dev', url: 'https://crowd.dev', platform: 'crowd' }],
- },
- mockIRepositoryOptions,
- )
- const org2 = await OrganizationRepository.create(
- {
- displayName: 'pied piper',
- identities: [{ name: 'pied piper', url: 'https://piedpiper.com', platform: 'crowd' }],
- },
- mockIRepositoryOptions,
- )
- const org3 = await OrganizationRepository.create(
- {
- displayName: 'hooli',
- identities: [{ name: 'hooli', url: 'https://hooli.com', platform: 'crowd' }],
- },
- mockIRepositoryOptions,
- )
-
- // Create member with tag3
- let member1 = await MemberRepository.create(
- {
- username: {
- [PlatformType.DISCORD]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: new Date(),
- organizations: [org3.id],
- },
- mockIRepositoryOptions,
- )
-
- // When feeding organizations attribute to update, update method will overwrite the member's organizations with new given orgs
- // member1 is expected to have [org1,org2] after update
- member1 = await MemberRepository.update(
- member1.id,
- { organizations: [org1.id, org2.id], organizationsReplace: true },
- mockIRepositoryOptions,
- )
-
- member1.createdAt = member1.createdAt.toISOString().split('T')[0]
- member1.updatedAt = member1.updatedAt.toISOString().split('T')[0]
-
- member1.organizations = member1.organizations.map((i) =>
- SequelizeTestUtils.objectWithoutKey(i.get({ plain: true }), ['memberOrganizations']),
- )
-
- // // sort member organizations by createdAt
- // member1.organizations.sort((a, b) => {
- // return a.createdAt < b.createdAt ? -1 : 1
- // })
-
- // strip members field from tags created to expect.
- // we won't be returning second level relationships.
- const { memberCount: _tag1Members, ...org1Plain } = org1
- const { memberCount: _tag2Members, ...org2Plain } = org2
-
- const expectedMemberCreated = {
- id: member1.id,
- username: member1.username,
- displayName: member1.displayName,
- identities: ['discord'],
- attributes: {},
- emails: member1.emails,
- score: member1.score,
- tags: [],
- lastEnriched: null,
- enrichedBy: [],
- contributions: null,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segments: mockIRepositoryOptions.currentSegments,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- activeOn: [],
- activityTypes: [],
- reach: { total: -1 },
- joinedAt: new Date(member1.joinedAt),
- organizations: [
- SequelizeTestUtils.objectWithoutKey(org1Plain, [
- 'lastActive',
- 'identities',
- 'activeOn',
- 'joinedAt',
- 'activityCount',
- 'segments',
- 'weakIdentities',
- ]),
- SequelizeTestUtils.objectWithoutKey(org2Plain, [
- 'lastActive',
- 'identities',
- 'activeOn',
- 'joinedAt',
- 'activityCount',
- 'segments',
- 'weakIdentities',
- ]),
- ],
- noMerge: [],
- toMerge: [],
- notes: [],
- tasks: [],
- activityCount: 0,
- activeDaysCount: 0,
- averageSentiment: 0,
- numberOfOpenSourceContributions: 0,
- lastActive: null,
- lastActivity: null,
- affiliations: [],
- manuallyCreated: false,
- }
-
- member1.organizations = member1.organizations.sort((a, b) => {
- if (a.displayName < b.displayName) {
- return -1
- }
- if (a.displayName > b.displayName) {
- return 1
- }
- return 0
- })
-
- expect(member1).toStrictEqual(expectedMemberCreated)
- })
-
- it('Should succesfully update member with notes', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const notes1 = await NoteRepository.create(
- {
- body: 'note1',
- },
- mockIRepositoryOptions,
- )
-
- const notes2 = await NoteRepository.create(
- {
- body: 'note2',
- },
- mockIRepositoryOptions,
- )
-
- const member2add = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const memberCreated = await MemberRepository.create(member2add, mockIRepositoryOptions)
- const memberUpdated = await MemberRepository.update(
- memberCreated.id,
- { notes: [notes1.id, notes2.id] },
- mockIRepositoryOptions,
- )
- expect(memberCreated.notes).toHaveLength(0)
- expect(memberUpdated.notes).toHaveLength(2)
- expect(memberUpdated.notes[0].id).toEqual(notes1.id)
- expect(memberUpdated.notes[1].id).toEqual(notes2.id)
- })
-
- it('Should succesfully update member with tasks', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const tasks1 = await TaskRepository.create(
- {
- name: 'task1',
- },
- mockIRepositoryOptions,
- )
-
- const task2 = await TaskRepository.create(
- {
- name: 'task2',
- },
- mockIRepositoryOptions,
- )
-
- const member2add = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const memberCreated = await MemberRepository.create(member2add, mockIRepositoryOptions)
- expect(memberCreated.tasks).toHaveLength(0)
-
- const memberUpdated = await MemberRepository.update(
- memberCreated.id,
- { tasks: [tasks1.id, task2.id] },
- mockIRepositoryOptions,
- )
- expect(memberUpdated.tasks).toHaveLength(2)
- expect(memberUpdated.tasks.find((t) => t.id === tasks1.id)).not.toBeUndefined()
- expect(memberUpdated.tasks.find((t) => t.id === task2.id)).not.toBeUndefined()
- })
-
- it('Should throw 404 error when trying to update non existent member', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const { randomUUID } = require('crypto')
-
- await expect(() =>
- MemberRepository.update(randomUUID(), { location: 'test' }, mockIRepositoryOptions),
- ).rejects.toThrowError(new Error404())
- })
-
- it('Should throw a sequelize foreign key error when trying to update a member with a non existing tag', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const { randomUUID } = require('crypto')
-
- const member1 = await MemberRepository.create(
- {
- username: {
- [PlatformType.DISCORD]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: new Date(),
- },
- mockIRepositoryOptions,
- )
-
- await expect(() =>
- MemberRepository.update(member1.id, { tags: [randomUUID()] }, mockIRepositoryOptions),
- ).rejects.toThrow()
- })
-
- it('Should succesfully update member organization affiliations', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const segmentRepo = new SegmentRepository(mockIRepositoryOptions)
-
- const segment1 = await segmentRepo.create({
- name: 'Crowd.dev - Segment1',
- url: '',
- parentName: 'Crowd.dev - Segment1',
- grandparentName: 'Crowd.dev - Segment1',
- slug: 'crowd.dev-1',
- parentSlug: 'crowd.dev-1',
- grandparentSlug: 'crowd.dev-1',
- status: SegmentStatus.ACTIVE,
- sourceId: null,
- sourceParentId: null,
- })
-
- const segment2 = await segmentRepo.create({
- name: 'Crowd.dev - Segment2',
- url: '',
- parentName: 'Crowd.dev - Segment2',
- grandparentName: 'Crowd.dev - Segment2',
- slug: 'crowd.dev-2',
- parentSlug: 'crowd.dev-2',
- grandparentSlug: 'crowd.dev-2',
- status: SegmentStatus.ACTIVE,
- sourceId: null,
- sourceParentId: null,
- })
-
- const org1 = await OrganizationRepository.create(
- {
- displayName: 'crowd.dev',
- },
- mockIRepositoryOptions,
- )
-
- const member2add = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- affiliations: [
- {
- segmentId: segment1.id,
- organizationId: org1.id,
- },
- {
- segmentId: segment2.id,
- organizationId: null,
- },
- ],
- }
-
- const memberCreated = await MemberRepository.create(member2add, mockIRepositoryOptions)
- expect(memberCreated.affiliations).toHaveLength(2)
-
- // removes segment1 affiliation, and set segment2 affilition to org1
- const memberUpdated = await MemberRepository.update(
- memberCreated.id,
- {
- affiliations: [
- {
- segmentId: segment2.id,
- organizationId: org1.id,
- },
- ],
- },
- mockIRepositoryOptions,
- )
-
- expect(memberUpdated.affiliations.filter((a) => a.segmentId === segment1.id)).toHaveLength(0)
- expect(
- memberUpdated.affiliations.filter((a) => a.segmentId === segment2.id)[0].organizationId,
- ).toEqual(org1.id)
- })
- })
-
- describe('destroy method', () => {
- it('Should succesfully destroy previously created member', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member1 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'test1',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- score: '1',
- joinedAt: '2021-05-27T15:14:30Z',
- }
- const returnedMember = await MemberRepository.create(member1, mockIRepositoryOptions)
-
- await MemberRepository.destroy(returnedMember.id, mockIRepositoryOptions, true)
-
- // Try selecting it after destroy, should throw 404
- await expect(() =>
- MemberRepository.findById(returnedMember.id, mockIRepositoryOptions),
- ).rejects.toThrowError(new Error404())
- })
-
- it('Should throw 404 when trying to destroy a non existent member', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const { randomUUID } = require('crypto')
-
- await expect(() =>
- MemberRepository.destroy(randomUUID(), mockIRepositoryOptions),
- ).rejects.toThrowError(new Error404())
- })
- })
-
- describe('removeToMerge method', () => {
- it('Should remove a member from other members toMerge list', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member1 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const member2 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'anil2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const memberCreated1 = await MemberRepository.create(member1, mockIRepositoryOptions)
- const memberCreated2 = await MemberRepository.create(member2, mockIRepositoryOptions)
-
- await MemberRepository.addToMerge(
- [{ members: [memberCreated1.id, memberCreated2.id], similarity: null }],
- mockIRepositoryOptions,
- )
- await MemberRepository.addToMerge(
- [{ members: [memberCreated2.id, memberCreated1.id], similarity: null }],
- mockIRepositoryOptions,
- )
-
- let m1 = await MemberRepository.findById(memberCreated1.id, mockIRepositoryOptions)
- const m2 = await MemberRepository.findById(memberCreated2.id, mockIRepositoryOptions)
- m1 = await MemberRepository.removeToMerge(
- memberCreated1.id,
- memberCreated2.id,
- mockIRepositoryOptions,
- )
-
- // Member2 should be removed from Member1.toMerge
- expect(m1.toMerge.length).toBe(0)
-
- // Member1 is still in member2.toMerge list
- expect(m2.toMerge[0]).toBe(m1.id)
- })
- })
-
- describe('addNoMerge method', () => {
- it('Should add a member to other members noMerge list', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member1 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const member2 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'anil2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const memberCreated1 = await MemberRepository.create(member1, mockIRepositoryOptions)
- const memberCreated2 = await MemberRepository.create(member2, mockIRepositoryOptions)
-
- let memberUpdated1 = await MemberRepository.addNoMerge(
- memberCreated1.id,
- memberCreated2.id,
- mockIRepositoryOptions,
- )
- const memberUpdated2 = await MemberRepository.addNoMerge(
- memberCreated2.id,
- memberCreated1.id,
- mockIRepositoryOptions,
- )
-
- memberUpdated1 = await MemberRepository.removeToMerge(
- memberCreated1.id,
- memberCreated2.id,
- mockIRepositoryOptions,
- )
-
- expect(memberUpdated1.noMerge[0]).toBe(memberUpdated2.id)
- expect(memberUpdated2.noMerge[0]).toBe(memberUpdated1.id)
- })
- })
-
- describe('removeNoMerge method', () => {
- let options
- let memberService
-
- let defaultMember
-
- beforeEach(async () => {
- options = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(options)
-
- memberService = new MemberService(options)
-
- defaultMember = {
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- }
- })
- it('Should remove a member from other members noMerge list', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const member1 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 1',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const member2 = {
- username: {
- [PlatformType.DISCORD]: {
- username: 'anil2',
- integrationId: generateUUIDv1(),
- },
- },
- displayName: 'Member 2',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const memberCreated1 = await MemberRepository.create(member1, mockIRepositoryOptions)
- const memberCreated2 = await MemberRepository.create(member2, mockIRepositoryOptions)
-
- let memberUpdated1 = await MemberRepository.addNoMerge(
- memberCreated1.id,
- memberCreated2.id,
- mockIRepositoryOptions,
- )
- const memberUpdated2 = await MemberRepository.addNoMerge(
- memberCreated2.id,
- memberCreated1.id,
- mockIRepositoryOptions,
- )
-
- memberUpdated1 = await MemberRepository.removeNoMerge(
- memberCreated1.id,
- memberCreated2.id,
- mockIRepositoryOptions,
- )
-
- // Member2 should be removed from Member1.noMerge
- expect(memberUpdated1.noMerge.length).toBe(0)
-
- // Member1 is still in member2.noMerge list
- expect(memberUpdated2.noMerge[0]).toBe(memberUpdated1.id)
- })
- })
-
- describe('work experiences', () => {
- let options
- let memberService
- let organizationService
-
- let defaultMember
-
- beforeEach(async () => {
- options = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(options)
-
- memberService = new MemberService(options)
- organizationService = new OrganizationService(options)
-
- defaultMember = {
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- }
- })
-
- async function createMember(data = {}) {
- return await memberService.upsert({
- ...defaultMember,
- username: {
- [PlatformType.GITHUB]: uuid(),
- },
- ...data,
- })
- }
-
- async function createOrg(name, data = {}) {
- return await organizationService.createOrUpdate({
- identities: [
- {
- name,
- platform: 'crowd',
- },
- ],
- ...data,
- })
- }
-
- async function addWorkExperience(memberId, orgId, data = {}) {
- return await MemberRepository.createOrUpdateWorkExperience(
- {
- memberId,
- organizationId: orgId,
- source: 'test',
- ...data,
- },
- options,
- )
- }
-
- async function findMember(id) {
- return await memberService.findById(id)
- }
-
- function formatDate(value) {
- if (!value) {
- return null
- }
- return moment(value).format('YYYY-MM-DD')
- }
-
- it('Should not create multiple work experiences for same org without dates', async () => {
- let member = await createMember()
-
- const org = await createOrg('org')
-
- await addWorkExperience(member.id, org.id)
- await addWorkExperience(member.id, org.id)
-
- member = await findMember(member.id)
-
- expect(member.organizations.length).toBe(1)
- })
-
- it('Should not create multiple work experiences for same org with same start dates', async () => {
- let member = await createMember()
-
- const org = await createOrg('org')
-
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-01',
- })
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-01',
- })
-
- member = await findMember(member.id)
-
- expect(member.organizations.length).toBe(1)
- })
-
- it('Should not create multiple work experiences for same org with same dates', async () => {
- let member = await createMember()
-
- const org = await createOrg('org')
-
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-01',
- dateEnd: '2020-01-05',
- })
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-01',
- dateEnd: '2020-01-05',
- })
-
- member = await findMember(member.id)
-
- expect(member.organizations.length).toBe(1)
- })
-
- it('Should create multiple work experiences for same org with different dates', async () => {
- let member = await createMember()
-
- const org = await createOrg('org')
-
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-01',
- })
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-08',
- })
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-01',
- dateEnd: '2020-01-05',
- })
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-06',
- dateEnd: '2020-01-07',
- })
-
- member = await findMember(member.id)
-
- expect(member.organizations.length).toBe(4)
- })
-
- it('Should clean up work experiences without dates once we get start dates', async () => {
- let member = await createMember()
-
- const org = await createOrg('org')
-
- await addWorkExperience(member.id, org.id)
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-01',
- })
-
- member = await findMember(member.id)
-
- expect(member.organizations.length).toBe(1)
- const dates = member.organizations[0].memberOrganizations.dataValues
- expect(formatDate(dates.dateStart)).toBe('2020-01-01')
- expect(formatDate(dates.dateEnd)).toBeNull()
- })
- it('Should clean up work experiences without dates once we get both dates', async () => {
- let member = await createMember()
-
- const org = await createOrg('org')
-
- await addWorkExperience(member.id, org.id)
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-01',
- dateEnd: '2020-07-01',
- })
-
- member = await findMember(member.id)
-
- expect(member.organizations.length).toBe(1)
- const dates = member.organizations[0].memberOrganizations.dataValues
- expect(formatDate(dates.dateStart)).toBe('2020-01-01')
- expect(formatDate(dates.dateEnd)).toBe('2020-07-01')
- })
- it('Should not add new work experiences without dates if we have start dates', async () => {
- let member = await createMember()
-
- const org = await createOrg('org')
-
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-01',
- })
- await addWorkExperience(member.id, org.id)
-
- member = await findMember(member.id)
-
- expect(member.organizations.length).toBe(1)
- const dates = member.organizations[0].memberOrganizations.dataValues
- expect(formatDate(dates.dateStart)).toBe('2020-01-01')
- expect(formatDate(dates.dateEnd)).toBeNull()
- })
- it('Should not add new work experiences without dates if we have both dates', async () => {
- let member = await createMember()
-
- const org = await createOrg('org')
-
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-01',
- dateEnd: '2020-07-01',
- })
- await addWorkExperience(member.id, org.id)
-
- member = await findMember(member.id)
-
- expect(member.organizations.length).toBe(1)
- const dates = member.organizations[0].memberOrganizations.dataValues
- expect(formatDate(dates.dateStart)).toBe('2020-01-01')
- expect(formatDate(dates.dateEnd)).toBe('2020-07-01')
- })
- })
-})
diff --git a/backend/src/database/repositories/memberRepository.ts b/backend/src/database/repositories/memberRepository.ts
index 4f34f05f66..ba00a843c4 100644
--- a/backend/src/database/repositories/memberRepository.ts
+++ b/backend/src/database/repositories/memberRepository.ts
@@ -47,7 +47,6 @@ import {
} from './types/memberTypes'
import OrganizationRepository from './organizationRepository'
import MemberSyncRemoteRepository from './memberSyncRemoteRepository'
-import MemberAffiliationRepository from './memberAffiliationRepository'
import MemberAttributeSettingsRepository from './memberAttributeSettingsRepository'
const { Op } = Sequelize
@@ -950,7 +949,6 @@ class MemberRepository {
): Promise {
const affiliationRepository = new MemberSegmentAffiliationRepository(options)
await affiliationRepository.setForMember(memberId, data)
- await MemberAffiliationRepository.update(memberId, options)
}
static async getAffiliations(
@@ -3457,15 +3455,7 @@ class MemberRepository {
}
static async createOrUpdateWorkExperience(
- {
- memberId,
- organizationId,
- source,
- title = null,
- dateStart = null,
- dateEnd = null,
- updateAffiliation = true,
- },
+ { memberId, organizationId, source, title = null, dateStart = null, dateEnd = null },
options: IRepositoryOptions,
) {
const seq = SequelizeRepository.getSequelize(options)
@@ -3548,10 +3538,6 @@ class MemberRepository {
transaction,
},
)
-
- if (updateAffiliation) {
- await MemberAffiliationRepository.update(memberId, options)
- }
}
static async deleteWorkExperience(id, options: IRepositoryOptions) {
diff --git a/backend/src/services/__tests__/activityService.test.ts b/backend/src/services/__tests__/activityService.test.ts
deleted file mode 100644
index 72edf61759..0000000000
--- a/backend/src/services/__tests__/activityService.test.ts
+++ /dev/null
@@ -1,3193 +0,0 @@
-import { v4 as uuid } from 'uuid'
-
-import SequelizeTestUtils from '../../database/utils/sequelizeTestUtils'
-import MemberService from '../memberService'
-import ActivityService from '../activityService'
-import MemberRepository from '../../database/repositories/memberRepository'
-import ActivityRepository from '../../database/repositories/activityRepository'
-import ConversationService from '../conversationService'
-import SequelizeRepository from '../../database/repositories/sequelizeRepository'
-import { MemberAttributeName, PlatformType, SegmentStatus } from '@crowd/types'
-import SettingsRepository from '../../database/repositories/settingsRepository'
-import ConversationSettingsRepository from '../../database/repositories/conversationSettingsRepository'
-import MemberAttributeSettingsService from '../memberAttributeSettingsService'
-import { IServiceOptions } from '../../services/IServiceOptions'
-import { GITHUB_MEMBER_ATTRIBUTES, TWITTER_MEMBER_ATTRIBUTES } from '@crowd/integrations'
-import { populateSegments, switchSegments } from '../../database/utils/segmentTestUtils'
-import SegmentRepository from '../../database/repositories/segmentRepository'
-import OrganizationRepository from '../../database/repositories/organizationRepository'
-import OrganizationService from '../organizationService'
-import MemberSegmentAffiliationRepository from '../../database/repositories/memberSegmentAffiliationRepository'
-import SegmentService from '../segmentService'
-import MemberAffiliationService from '../memberAffiliationService'
-
-const db = null
-const searchEngine = null
-
-describe('ActivityService tests', () => {
- beforeEach(async () => {
- await SequelizeTestUtils.wipeDatabase(db)
- })
-
- afterAll(async () => {
- // Closing the DB connection allows Jest to exit successfully.
- await SequelizeTestUtils.closeConnection(db)
- })
-
- describe('upsert method', () => {
- it('Should create non existent activity with no parent', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
-
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- const activity = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Body',
- title: 'Title',
- url: 'URL',
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- attributes: {
- replies: 12,
- },
- sourceId: '#sourceId',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- }
-
- const activityCreated = await new ActivityService(mockIRepositoryOptions).upsert(activity)
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- activityCreated.createdAt = activityCreated.createdAt.toISOString().split('T')[0]
- activityCreated.updatedAt = activityCreated.updatedAt.toISOString().split('T')[0]
- delete activityCreated.member
- delete activityCreated.objectMember
-
- const expectedActivityCreated = {
- id: activityCreated.id,
- attributes: activity.attributes,
- type: 'activity',
- timestamp: new Date('2020-05-27T15:13:30Z'),
- platform: PlatformType.GITHUB,
- isContribution: true,
- score: 1,
- username: 'test',
- objectMemberUsername: null,
- memberId: memberCreated.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- channel: null,
- body: 'Body',
- title: 'Title',
- url: 'URL',
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- tasks: [],
- parent: null,
- parentId: null,
- conversationId: null,
- sourceId: activity.sourceId,
- sourceParentId: null,
- display: {
- default: activityCreated.type,
- short: activityCreated.type,
- channel: '',
- },
- organizationId: null,
- organization: null,
- }
-
- expect(activityCreated).toStrictEqual(expectedActivityCreated)
- })
-
- it('Should create non existent activity with parent', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- const activity1 = {
- type: 'question',
- timestamp: '2020-05-27T15:13:30Z',
- username: 'test',
- member: memberCreated.id,
- platform: 'non-existing-platform',
- body: 'What is love?',
- isContribution: true,
- score: 1,
- sourceId: 'sourceId#1',
- }
-
- const activityCreated1 = await new ActivityService(mockIRepositoryOptions).upsert(activity1)
-
- const activity2 = {
- type: 'answer',
- timestamp: '2020-05-28T15:13:30Z',
- platform: 'non-existing-platform',
- body: 'Baby dont hurt me',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 2,
- sourceId: 'sourceId#2',
- sourceParentId: activityCreated1.sourceId,
- }
-
- const activityCreated2 = await new ActivityService(mockIRepositoryOptions).upsert(activity2)
-
- // Since an activity with a parent is created, a Conversation entity should be created at this point
- // with both parent and the child activities. Try finding it using the slug
-
- const conversationCreated = await new ConversationService(
- mockIRepositoryOptions,
- ).findAndCountAll({ slug: 'what-is-love' })
-
- delete activityCreated2.member
- delete activityCreated2.parent
- delete activityCreated2.objectMember
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- activityCreated2.createdAt = activityCreated2.createdAt.toISOString().split('T')[0]
- activityCreated2.updatedAt = activityCreated2.updatedAt.toISOString().split('T')[0]
-
- const expectedActivityCreated = {
- id: activityCreated2.id,
- body: activity2.body,
- type: activity2.type,
- channel: null,
- attributes: {},
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.42,
- },
- url: null,
- title: null,
- timestamp: new Date(activity2.timestamp),
- platform: activity2.platform,
- isContribution: activity2.isContribution,
- score: activity2.score,
- username: 'test',
- objectMemberUsername: null,
- memberId: memberCreated.id,
- objectMemberId: null,
- tasks: [],
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parentId: activityCreated1.id,
- sourceParentId: activity1.sourceId,
- sourceId: activity2.sourceId,
- conversationId: conversationCreated.rows[0].id,
- display: {
- default: activity2.type,
- short: activity2.type,
- channel: '',
- },
- organizationId: null,
- organization: null,
- }
-
- expect(activityCreated2).toStrictEqual(expectedActivityCreated)
- })
-
- it('Should update already existing activity succesfully', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- const activity1 = {
- type: 'question',
- timestamp: '2020-05-27T15:13:30Z',
- username: 'test',
- member: memberCreated.id,
- body: 'What is love?',
- title: 'Song',
- platform: 'non-existing-platform',
- attributes: {
- nested_1: {
- attribute_1: '1',
- nested_2: {
- attribute_2: '2',
- attribute_array: [1, 2, 3],
- },
- },
- },
- isContribution: true,
- score: 1,
- sourceId: '#sourceId1',
- }
-
- const activityCreated1 = await new ActivityService(mockIRepositoryOptions).upsert(activity1)
-
- const activity2 = {
- type: 'question',
- timestamp: '2020-05-27T15:13:30Z',
- username: 'test',
- member: memberCreated.id,
- platform: 'non-existing-platform',
- body: 'Test',
- attributes: {
- nested_1: {
- attribute_1: '1',
- nested_2: {
- attribute_2: '5',
- attribute_3: 'test',
- attribute_array: [3, 4, 5],
- },
- },
- one: 'Baby dont hurt me',
- two: 'Dont hurt me',
- three: 'No more',
- },
- isContribution: false,
- score: 2,
- sourceId: '#sourceId1',
- }
-
- const activityUpserted = await new ActivityService(mockIRepositoryOptions).upsert(activity2)
-
- // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt
- activityUpserted.createdAt = activityUpserted.createdAt.toISOString().split('T')[0]
- activityUpserted.updatedAt = activityUpserted.updatedAt.toISOString().split('T')[0]
-
- // delete models before expect because we already have ids (memberId, parentId)
- delete activityUpserted.member
- delete activityUpserted.parent
- delete activityUpserted.objectMember
-
- const attributesExpected = {
- ...activity1.attributes,
- ...activity2.attributes,
- }
-
- attributesExpected.nested_1.nested_2.attribute_array = [1, 2, 3, 4, 5]
-
- const expectedActivityCreated = {
- id: activityCreated1.id,
- attributes: attributesExpected,
- type: activity2.type,
- timestamp: new Date(activity2.timestamp),
- platform: activity2.platform,
- isContribution: activity2.isContribution,
- score: activity2.score,
- title: activity1.title,
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.42,
- },
- url: null,
- body: activity2.body,
- channel: null,
- username: 'test',
- objectMemberUsername: null,
- memberId: memberCreated.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- tasks: [],
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parentId: null,
- sourceParentId: null,
- sourceId: activity1.sourceId,
- conversationId: null,
- display: {
- default: activity2.type,
- short: activity2.type,
- channel: '',
- },
- organizationId: null,
- organization: null,
- }
-
- expect(activityUpserted).toStrictEqual(expectedActivityCreated)
- })
-
- it('Should create various conversations successfully with given parent-child relationships of activities [ascending timestamp order]', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberService = new MemberService(mockIRepositoryOptions)
- const activityService = new ActivityService(mockIRepositoryOptions)
-
- const member1Created = await memberService.upsert({
- username: {
- [PlatformType.DISCORD]: 'test',
- },
- platform: PlatformType.DISCORD,
- joinedAt: '2020-05-27T15:13:30Z',
- })
- const member2Created = await memberService.upsert({
- username: {
- [PlatformType.DISCORD]: 'test2',
- },
- platform: PlatformType.DISCORD,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- // Simulate a reply chain in discord
-
- const activity1 = {
- type: 'message',
- timestamp: '2020-05-27T15:13:30Z',
- username: 'test',
- member: member1Created.id,
- platform: PlatformType.DISCORD,
- body: 'What is love?',
- isContribution: true,
- score: 1,
- sourceId: 'sourceId#1',
- }
-
- let activityCreated1 = await activityService.upsert(activity1)
-
- const activity2 = {
- type: 'message',
- timestamp: '2020-05-28T15:14:30Z',
- platform: PlatformType.DISCORD,
- body: 'Baby dont hurt me',
- isContribution: true,
- username: 'test2',
- member: member2Created.id,
- score: 2,
- sourceId: 'sourceId#2',
- sourceParentId: activityCreated1.sourceId,
- }
-
- const activityCreated2 = await activityService.upsert(activity2)
-
- const activity3 = {
- type: 'message',
- timestamp: '2020-05-28T15:15:30Z',
- platform: PlatformType.DISCORD,
- body: 'Dont hurt me',
- isContribution: true,
- username: 'test',
- member: member1Created.id,
- score: 2,
- sourceId: 'sourceId#3',
- sourceParentId: activityCreated2.sourceId,
- }
-
- const activityCreated3 = await activityService.upsert(activity3)
-
- const activity4 = {
- type: 'message',
- timestamp: '2020-05-28T15:16:30Z',
- platform: PlatformType.DISCORD,
- body: 'No more',
- isContribution: true,
- username: 'test2',
- member: member2Created.id,
- score: 2,
- sourceId: 'sourceId#4',
- sourceParentId: activityCreated3.sourceId,
- }
-
- const activityCreated4 = await activityService.upsert(activity4)
-
- // Get the conversation using slug (generated using the chain starter activity attributes.body)
- const conversationCreated = (
- await new ConversationService(mockIRepositoryOptions).findAndCountAll({
- slug: 'what-is-love',
- })
- ).rows[0]
-
- // We have to get activity1 again because conversation creation happens
- // after creation of the first activity that has a parent (activity2)
- activityCreated1 = await activityService.findById(activityCreated1.id)
-
- // All activities (including chain starter) should belong to the same conversation
- expect(activityCreated1.conversationId).toStrictEqual(conversationCreated.id)
- expect(activityCreated2.conversationId).toStrictEqual(conversationCreated.id)
- expect(activityCreated3.conversationId).toStrictEqual(conversationCreated.id)
- expect(activityCreated4.conversationId).toStrictEqual(conversationCreated.id)
-
- // Emulate a thread in discord
-
- const activity5 = {
- type: 'message',
- timestamp: '2020-05-28T15:17:30Z',
- platform: PlatformType.DISCORD,
- body: 'Never gonna give you up',
- isContribution: true,
- username: 'test',
- member: member1Created.id,
- score: 2,
- sourceId: 'sourceId#5',
- }
- let activityCreated5 = await activityService.upsert(activity5)
-
- const activity6 = {
- type: 'message',
- timestamp: '2020-05-28T15:18:30Z',
- platform: PlatformType.DISCORD,
- body: 'Never gonna let you down',
- isContribution: true,
- username: 'test2',
- member: member2Created.id,
- score: 2,
- sourceId: 'sourceId#6',
- sourceParentId: activityCreated5.sourceId,
- }
- const activityCreated6 = await activityService.upsert(activity6)
-
- const activity7 = {
- type: 'message',
- timestamp: '2020-05-28T15:19:30Z',
- platform: PlatformType.DISCORD,
- body: 'Never gonna run around and desert you',
- isContribution: true,
- username: 'test',
- member: member1Created.id,
- score: 2,
- sourceId: 'sourceId#7',
- sourceParentId: activityCreated5.sourceId,
- }
- const activityCreated7 = await activityService.upsert(activity7)
-
- const conversationCreated2 = (
- await new ConversationService(mockIRepositoryOptions).findAndCountAll({
- slug: 'never-gonna-give-you-up',
- })
- ).rows[0]
-
- activityCreated5 = await activityService.findById(activityCreated5.id)
-
- // All activities (including thread starter) should belong to the same conversation
- expect(activityCreated5.conversationId).toStrictEqual(conversationCreated2.id)
- expect(activityCreated6.conversationId).toStrictEqual(conversationCreated2.id)
- expect(activityCreated7.conversationId).toStrictEqual(conversationCreated2.id)
- })
-
- it('Should keep old timestamp', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberService = new MemberService(mockIRepositoryOptions)
- const activityService = new ActivityService(mockIRepositoryOptions)
-
- const cm = await memberService.upsert({
- username: {
- [PlatformType.DISCORD]: 'test',
- },
- platform: PlatformType.DISCORD,
- })
-
- const activity1 = {
- type: 'message',
- timestamp: '2020-05-27T15:13:30Z',
- username: 'test',
- member: cm.id,
- platform: PlatformType.DISCORD,
- sourceId: 'sourceId#1',
- }
-
- const activityCreated1 = await activityService.upsert(activity1)
-
- const activity2 = {
- type: 'message',
- timestamp: '2022-05-27T15:13:30Z',
- username: 'test',
- member: cm.id,
- platform: PlatformType.DISCORD,
- sourceId: 'sourceId#1',
- body: 'What is love?',
- }
-
- const activityCreated2 = await activityService.upsert(activity2)
-
- expect(activityCreated2.timestamp).toStrictEqual(activityCreated1.timestamp)
- expect(activityCreated2.body).toBe(activity2.body)
- })
-
- it('Should keep isMainBranch as true', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberService = new MemberService(mockIRepositoryOptions)
- const activityService = new ActivityService(mockIRepositoryOptions)
-
- const cm = await memberService.upsert({
- username: {
- [PlatformType.DISCORD]: 'test',
- },
- platform: PlatformType.DISCORD,
- })
-
- const activity1 = {
- type: 'message',
- timestamp: '2020-05-27T15:13:30Z',
- username: 'test',
- member: cm.id,
- platform: PlatformType.DISCORD,
- sourceId: 'sourceId#1',
- attributes: {
- isMainBranch: true,
- other: 'other',
- },
- }
-
- await activityService.upsert(activity1)
-
- const activity2 = {
- type: 'message',
- timestamp: '2022-05-27T15:13:30Z',
- username: 'test',
- member: cm.id,
- platform: PlatformType.DISCORD,
- sourceId: 'sourceId#1',
- body: 'What is love?',
- attributes: {
- isMainBranch: false,
- other2: 'other2',
- },
- }
-
- const activityCreated2 = await activityService.upsert(activity2)
-
- expect(activityCreated2.attributes).toStrictEqual({
- isMainBranch: true,
- other: 'other',
- other2: 'other2',
- })
- })
-
- it('Should create various conversations successfully with given parent-child relationships of activities [descending timestamp order]', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberService = new MemberService(mockIRepositoryOptions)
- const activityService = new ActivityService(mockIRepositoryOptions)
-
- const member1Created = await memberService.upsert({
- username: {
- [PlatformType.DISCORD]: 'test',
- },
- platform: PlatformType.DISCORD,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- const member2Created = await memberService.upsert({
- username: {
- [PlatformType.DISCORD]: 'test2',
- },
- platform: PlatformType.DISCORD,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- // Simulate a reply chain in discord in reverse order (child activities come first)
-
- const activity4 = {
- type: 'message',
- timestamp: '2020-05-28T15:16:30Z',
- platform: PlatformType.DISCORD,
- body: 'No more',
- isContribution: true,
- username: 'test2',
- member: member2Created.id,
- score: 2,
- sourceId: 'sourceId#4',
- sourceParentId: 'sourceId#3',
- }
-
- let activityCreated4 = await activityService.upsert(activity4)
-
- const activity3 = {
- type: 'message',
- timestamp: '2020-05-28T15:15:30Z',
- platform: PlatformType.DISCORD,
- body: 'Dont hurt me',
- isContribution: true,
- username: 'test',
- member: member1Created.id,
- score: 2,
- sourceId: 'sourceId#3',
- sourceParentId: 'sourceId#2',
- }
-
- let activityCreated3 = await activityService.upsert(activity3)
-
- const activity2 = {
- type: 'message',
- timestamp: '2020-05-28T15:14:30Z',
- platform: PlatformType.DISCORD,
- body: 'Baby dont hurt me',
- isContribution: true,
- username: 'test2',
- member: member2Created.id,
- score: 2,
- sourceId: 'sourceId#2',
- sourceParentId: 'sourceId#1',
- }
-
- let activityCreated2 = await activityService.upsert(activity2)
-
- const activity1 = {
- type: 'message',
- timestamp: '2020-05-27T15:13:30Z',
- username: 'test',
- member: member1Created.id,
- platform: PlatformType.DISCORD,
- body: 'What is love?',
- isContribution: true,
- score: 1,
- sourceId: 'sourceId#1',
- }
-
- // main parent activity that starts the reply chain
- let activityCreated1 = await activityService.upsert(activity1)
-
- // get activities again
- activityCreated1 = await activityService.findById(activityCreated1.id)
- activityCreated2 = await activityService.findById(activityCreated2.id)
- activityCreated3 = await activityService.findById(activityCreated3.id)
- activityCreated4 = await activityService.findById(activityCreated4.id)
-
- // expect parentIds
- expect(activityCreated4.parentId).toBe(activityCreated3.id)
- expect(activityCreated3.parentId).toBe(activityCreated2.id)
- expect(activityCreated2.parentId).toBe(activityCreated1.id)
-
- // Get the conversation using slug (generated using the chain starter activity attributes.body -last added activityCreated1-)
- const conversationCreated = (
- await new ConversationService(mockIRepositoryOptions).findAndCountAll({
- slug: 'what-is-love',
- })
- ).rows[0]
-
- // All activities (including chain starter) should belong to the same conversation
- expect(activityCreated1.conversationId).toStrictEqual(conversationCreated.id)
- expect(activityCreated2.conversationId).toStrictEqual(conversationCreated.id)
- expect(activityCreated3.conversationId).toStrictEqual(conversationCreated.id)
- expect(activityCreated4.conversationId).toStrictEqual(conversationCreated.id)
-
- // Simulate a thread in reverse order
-
- const activity6 = {
- type: 'message',
- timestamp: '2020-05-28T15:18:30Z',
- platform: PlatformType.DISCORD,
- body: 'Never gonna let you down',
- isContribution: true,
- username: 'test2',
- member: member2Created.id,
- score: 2,
- sourceId: 'sourceId#6',
- sourceParentId: 'sourceId#5',
- }
- let activityCreated6 = await activityService.upsert(activity6)
-
- const activity7 = {
- type: 'message',
- timestamp: '2020-05-28T15:19:30Z',
- platform: PlatformType.DISCORD,
- body: 'Never gonna run around and desert you',
-
- isContribution: true,
- username: 'test',
- member: member1Created.id,
- score: 2,
- sourceId: 'sourceId#7',
- sourceParentId: 'sourceId#5',
- }
- let activityCreated7 = await activityService.upsert(activity7)
-
- const activity5 = {
- type: 'message',
- timestamp: '2020-05-28T15:17:30Z',
- platform: PlatformType.DISCORD,
- body: 'Never gonna give you up',
- isContribution: true,
- username: 'test',
- member: member1Created.id,
- score: 2,
- sourceId: 'sourceId#5',
- }
- let activityCreated5 = await activityService.upsert(activity5)
-
- const conversationCreated2 = (
- await new ConversationService(mockIRepositoryOptions).findAndCountAll({
- slug: 'never-gonna-give-you-up',
- })
- ).rows[0]
-
- // get activities again
- activityCreated5 = await activityService.findById(activityCreated5.id)
- activityCreated6 = await activityService.findById(activityCreated6.id)
- activityCreated7 = await activityService.findById(activityCreated7.id)
-
- // expect parentIds
- expect(activityCreated6.parentId).toBe(activityCreated5.id)
- expect(activityCreated7.parentId).toBe(activityCreated5.id)
-
- expect(activityCreated5.conversationId).toStrictEqual(conversationCreated2.id)
- expect(activityCreated6.conversationId).toStrictEqual(conversationCreated2.id)
- expect(activityCreated7.conversationId).toStrictEqual(conversationCreated2.id)
-
- // Add some more childs to the conversation1 and conversation2
- // After setting child-parent in reverse order, we're now adding
- // some more childiren in normal order
-
- // add a new reply to the chain-starter activity
- const activity8 = {
- type: 'message',
- timestamp: '2020-05-28T15:21:30Z',
- platform: PlatformType.DISCORD,
- body: 'additional reply to the reply chain',
- isContribution: true,
- username: 'test2',
- member: member2Created.id,
- score: 2,
- sourceId: 'sourceId#8',
- sourceParentId: 'sourceId#1',
- }
-
- const activityCreated8 = await activityService.upsert(activity8)
-
- expect(activityCreated8.parentId).toBe(activityCreated1.id)
- expect(activityCreated8.conversationId).toStrictEqual(conversationCreated.id)
-
- // add a new activity to the thread
- const activity9 = {
- type: 'message',
- timestamp: '2020-05-28T15:35:30Z',
- platform: PlatformType.DISCORD,
- body: 'additional message to the thread',
- isContribution: true,
- username: 'test2',
- member: member2Created.id,
- score: 2,
- sourceId: 'sourceId#9',
- sourceParentId: 'sourceId#5',
- }
-
- const activityCreated9 = await activityService.upsert(activity9)
-
- expect(activityCreated9.parentId).toBe(activityCreated5.id)
- expect(activityCreated9.conversationId).toStrictEqual(conversationCreated2.id)
- })
-
- // Tests for checking channel logic when creating activity
- // Settings should get updated only when a new channel is sent alog while creating activity.
- it('Should create an activity with a channel which is not present in settings and add it to settings', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test1',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- const activity = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Body',
- title: 'Title',
- url: 'URL',
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- channel: 'TestChannel',
- attributes: {
- replies: 12,
- },
- sourceId: '#sourceId',
- isContribution: true,
- username: 'test1',
- member: memberCreated.id,
- score: 1,
- }
-
- await new ActivityService(mockIRepositoryOptions).upsert(activity)
- const segmentRepository = new SegmentRepository(mockIRepositoryOptions)
- const subprojectIds = (await segmentRepository.querySubprojects({})).rows.map((s) => s.id)
- const activityChannels = await segmentRepository.fetchTenantActivityChannels(subprojectIds)
- expect(activityChannels[activity.platform].includes(activity.channel)).toBe(true)
- })
-
- it('Should not create a duplicate channel when a channel is present in settings', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test1',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
- const activity = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Body',
- title: 'Title',
- url: 'URL',
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- channel: 'TestChannel',
- attributes: {
- replies: 12,
- },
- sourceId: '#sourceId',
- isContribution: true,
- username: 'test1',
- member: memberCreated.id,
- score: 1,
- }
-
- await new ActivityService(mockIRepositoryOptions).upsert(activity)
- let settings = await SettingsRepository.findOrCreateDefault({}, mockIRepositoryOptions)
- const activity1 = {
- type: 'activity1',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Body',
- title: 'Title',
- url: 'URL',
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- label: 'positive',
- sentiment: 0.98,
- },
- channel: 'TestChannel',
- attributes: {
- replies: 12,
- },
- sourceId: '#sourceId',
- isContribution: true,
- member: memberCreated.id,
- score: 1,
- }
-
- await new ActivityService(mockIRepositoryOptions).upsert(activity)
- const segmentRepository = new SegmentRepository(mockIRepositoryOptions)
- const subprojectIds = (await segmentRepository.querySubprojects({})).rows.map((s) => s.id)
- const activityChannels = await segmentRepository.fetchTenantActivityChannels(subprojectIds)
- expect(activityChannels[activity1.platform].length).toBe(1)
- })
- })
-
- describe('createWithMember method', () => {
- it('Create an activity with given member [no parent activity]', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(
- mockIRepositoryOptions,
- )
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
-
- const member = {
- username: {
- [PlatformType.GITHUB]: 'anil_github',
- },
- email: 'lala@l.com',
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- [PlatformType.TWITTER]: 'https://twitter.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- },
- organisation: 'Crowd',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const data = {
- member,
- body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots',
- title: 'Dashboard widgets and some other tweaks/adjustments',
- url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16',
- sentiment: {
- positive: 0.98,
- negative: 0.0,
- neutral: 0.02,
- mixed: 0.0,
- sentiment: 0.98,
- label: 'positive',
- },
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- timestamp: '2021-09-30T14:20:27.000Z',
- type: 'pull_request-closed',
- isContribution: true,
- platform: PlatformType.GITHUB,
- score: 4,
- sourceId: '#sourceId1',
- }
-
- const activityWithMember = await new ActivityService(mockIRepositoryOptions).createWithMember(
- data,
- )
-
- delete activityWithMember.member
- delete activityWithMember.display
- delete activityWithMember.objectMember
-
- activityWithMember.createdAt = activityWithMember.createdAt.toISOString().split('T')[0]
- activityWithMember.updatedAt = activityWithMember.updatedAt.toISOString().split('T')[0]
-
- const memberFound = await MemberRepository.findById(
- activityWithMember.memberId,
- mockIRepositoryOptions,
- )
-
- const expectedActivityCreated = {
- id: activityWithMember.id,
- type: data.type,
- body: data.body,
- title: data.title,
- url: data.url,
- channel: data.channel,
- sentiment: data.sentiment,
- attributes: {},
- timestamp: new Date(data.timestamp),
- platform: data.platform,
- isContribution: data.isContribution,
- score: data.score,
- username: 'anil_github',
- objectMemberUsername: null,
- memberId: memberFound.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- tasks: [],
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parentId: null,
- parent: null,
- sourceParentId: null,
- sourceId: data.sourceId,
- conversationId: null,
- organizationId: null,
- organization: null,
- }
-
- expect(activityWithMember).toStrictEqual(expectedActivityCreated)
- })
-
- it('Create an activity with given member [with parent activity, upsert member, new activity] [parent first, child later]', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(
- mockIRepositoryOptions,
- )
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
-
- const member = {
- username: 'anil_github',
- email: 'lala@l.com',
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- [PlatformType.TWITTER]: 'https://twitter.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- },
- organisation: 'Crowd',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const data = {
- member,
- body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots',
- title: 'Dashboard widgets and some other tweaks/adjustments',
- url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- timestamp: '2021-09-30T14:20:27.000Z',
- type: 'pull_request-closed',
- isContribution: true,
- platform: PlatformType.GITHUB,
- score: 4,
- sourceId: '#sourceId1',
- }
-
- const activityWithMember1 = await new ActivityService(
- mockIRepositoryOptions,
- ).createWithMember(data)
-
- const data2 = {
- member,
- body: 'Description\nMinor pull request that fixes the order by Score and # of activities in the members list page',
- title: 'Add order by score and # of activities',
- url: 'https://github.com/CrowdDevHQ/crowd-web/pull/30',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- timestamp: '2021-11-30T14:20:27.000Z',
- type: 'pull_request-open',
- isContribution: true,
- platform: PlatformType.GITHUB,
- score: 4,
- sourceId: '#sourceId2',
- sourceParentId: data.sourceId,
- }
-
- const activityWithMember2 = await new ActivityService(
- mockIRepositoryOptions,
- ).createWithMember(data2)
-
- // Since an activity with a parent is created, a Conversation entity should be created at this point
- // with both parent and the child activities. Try finding it using the slug (slug is generated using parent.attributes.body)
-
- const conversationCreated = await new ConversationService(
- mockIRepositoryOptions,
- ).findAndCountAll({ slug: 'description-this-pull-request-adds-a-new-dashboard-and-related' })
-
- // delete models before expect because we already have ids (memberId, parentId)
- delete activityWithMember2.member
- delete activityWithMember2.parent
- delete activityWithMember2.display
- delete activityWithMember2.objectMember
-
- activityWithMember2.createdAt = activityWithMember2.createdAt.toISOString().split('T')[0]
- activityWithMember2.updatedAt = activityWithMember2.updatedAt.toISOString().split('T')[0]
-
- const memberFound = await MemberRepository.findById(
- activityWithMember1.memberId,
- mockIRepositoryOptions,
- )
-
- const expectedActivityCreated = {
- id: activityWithMember2.id,
- body: data2.body,
- title: data2.title,
- url: data2.url,
- channel: data2.channel,
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.42,
- },
- attributes: {},
- type: data2.type,
- timestamp: new Date(data2.timestamp),
- platform: data2.platform,
- tasks: [],
- isContribution: data2.isContribution,
- score: data2.score,
- username: 'anil_github',
- objectMemberUsername: null,
- memberId: memberFound.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parentId: activityWithMember1.id,
- sourceParentId: data2.sourceParentId,
- sourceId: data2.sourceId,
- conversationId: conversationCreated.rows[0].id,
- organizationId: null,
- organization: null,
- }
-
- expect(activityWithMember2).toStrictEqual(expectedActivityCreated)
- })
-
- it('Create an activity with given member [with parent activity, upsert member, new activity] [child first, parent later]', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const activityService = new ActivityService(mockIRepositoryOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(
- mockIRepositoryOptions,
- )
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
-
- const member = {
- username: 'anil_github',
- email: 'lala@l.com',
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- [PlatformType.TWITTER]: 'https://twitter.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- },
- organisation: 'Crowd',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const dataChild = {
- member,
- body: 'Description\nMinor pull request that fixes the order by Score and # of activities in the members list page',
- title: 'Add order by score and # of activities',
- url: 'https://github.com/CrowdDevHQ/crowd-web/pull/30',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- timestamp: '2021-11-30T14:20:27.000Z',
- type: 'pull_request-open',
- isContribution: true,
- platform: PlatformType.GITHUB,
- score: 4,
- sourceParentId: '#sourceId1',
- sourceId: '#childSourceId',
- }
-
- let activityWithMemberChild = await activityService.createWithMember(dataChild)
-
- const dataParent = {
- member,
- body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots',
- title: 'Dashboard widgets and some other tweaks/adjustments',
- url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- timestamp: '2021-09-30T14:20:27.000Z',
- type: 'pull_request-closed',
- isContribution: true,
- platform: PlatformType.GITHUB,
- score: 4,
- sourceId: dataChild.sourceParentId,
- }
-
- let activityWithMemberParent = await activityService.createWithMember(dataParent)
-
- // after creating parent, conversation should be started
- const conversationCreated = await new ConversationService(
- mockIRepositoryOptions,
- ).findAndCountAll({ slug: 'description-this-pull-request-adds-a-new-dashboard-and-related' })
-
- // get child and parent activity again
- activityWithMemberChild = await activityService.findById(activityWithMemberChild.id)
- activityWithMemberParent = await activityService.findById(activityWithMemberParent.id)
-
- // delete models before expect because we already have ids (memberId, parentId)
- delete activityWithMemberChild.member
- delete activityWithMemberChild.parent
- delete activityWithMemberChild.display
- delete activityWithMemberChild.objectMember
- delete activityWithMemberParent.member
- delete activityWithMemberParent.parent
- delete activityWithMemberParent.display
- delete activityWithMemberParent.objectMember
-
- activityWithMemberChild.createdAt = activityWithMemberChild.createdAt
- .toISOString()
- .split('T')[0]
- activityWithMemberChild.updatedAt = activityWithMemberChild.updatedAt
- .toISOString()
- .split('T')[0]
- activityWithMemberParent.createdAt = activityWithMemberParent.createdAt
- .toISOString()
- .split('T')[0]
- activityWithMemberParent.updatedAt = activityWithMemberParent.updatedAt
- .toISOString()
- .split('T')[0]
-
- const memberFound = await MemberRepository.findById(
- activityWithMemberChild.memberId,
- mockIRepositoryOptions,
- )
-
- const expectedParentActivityCreated = {
- id: activityWithMemberParent.id,
- body: dataParent.body,
- title: dataParent.title,
- url: dataParent.url,
- channel: dataParent.channel,
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.42,
- },
- attributes: {},
- type: dataParent.type,
- timestamp: new Date(dataParent.timestamp),
- platform: dataParent.platform,
- isContribution: dataParent.isContribution,
- tasks: [],
- score: dataParent.score,
- username: 'anil_github',
- objectMemberUsername: null,
- memberId: memberFound.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parentId: null,
- sourceParentId: null,
- sourceId: dataParent.sourceId,
- conversationId: conversationCreated.rows[0].id,
- organizationId: null,
- organization: null,
- }
-
- expect(activityWithMemberParent).toStrictEqual(expectedParentActivityCreated)
-
- const expectedChildActivityCreated = {
- id: activityWithMemberChild.id,
- body: dataChild.body,
- title: dataChild.title,
- url: dataChild.url,
- channel: dataChild.channel,
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.42,
- },
- attributes: {},
- type: dataChild.type,
- timestamp: new Date(dataChild.timestamp),
- platform: dataChild.platform,
- isContribution: dataChild.isContribution,
- score: dataChild.score,
- username: 'anil_github',
- objectMemberUsername: null,
- memberId: memberFound.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- tasks: [],
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parentId: activityWithMemberParent.id,
- sourceParentId: dataChild.sourceParentId,
- sourceId: dataChild.sourceId,
- conversationId: conversationCreated.rows[0].id,
- organizationId: null,
- organization: null,
- }
-
- expect(activityWithMemberChild).toStrictEqual(expectedChildActivityCreated)
- })
-
- it(`Should respect the affiliation settings when setting an activity's organization with multiple member organizations`, async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const segmentRepo = new SegmentRepository(mockIRepositoryOptions)
-
- const segment1 = await segmentRepo.create({
- name: 'Crowd.dev - Segment1',
- url: '',
- parentName: 'Crowd.dev - Segment1',
- grandparentName: 'Crowd.dev - Segment1',
- slug: 'crowd.dev-1',
- parentSlug: 'crowd.dev-1',
- grandparentSlug: 'crowd.dev-1',
- status: SegmentStatus.ACTIVE,
- sourceId: null,
- sourceParentId: null,
- })
-
- const segment2 = await segmentRepo.create({
- name: 'Crowd.dev - Segment2',
- url: '',
- parentName: 'Crowd.dev - Segment2',
- grandparentName: 'Crowd.dev - Segment2',
- slug: 'crowd.dev-2',
- parentSlug: 'crowd.dev-2',
- grandparentSlug: 'crowd.dev-2',
- status: SegmentStatus.ACTIVE,
- sourceId: null,
- sourceParentId: null,
- })
-
- await populateSegments(mockIRepositoryOptions)
- const org1 = await OrganizationRepository.create(
- {
- displayName: 'tesla',
- },
- mockIRepositoryOptions,
- )
-
- const org2 = await OrganizationRepository.create(
- {
- displayName: 'crowd.dev',
- },
- mockIRepositoryOptions,
- )
-
- const member = {
- username: {
- [PlatformType.GITHUB]: 'anil_github',
- },
- organizations: [org1, org2],
- affiliations: [
- {
- segmentId: segment1.id,
- organizationId: org2.id,
- dateStart: '2021-09-01',
- },
- {
- segmentId: segment2.id,
- organizationId: null,
- dateStart: '2021-09-01',
- },
- ],
- }
-
- const data = {
- member,
- timestamp: '2021-09-30T14:20:27.000Z',
- type: 'pull_request-closed',
- platform: PlatformType.GITHUB,
- sourceId: '#sourceId1',
- }
-
- switchSegments(mockIRepositoryOptions, [segment1])
-
- let activityWithMember = await new ActivityService(mockIRepositoryOptions).createWithMember(
- data,
- )
-
- let activity = await ActivityRepository.findById(
- activityWithMember.id,
- mockIRepositoryOptions,
- )
-
- // org2 should be set as organization because it's in member's affiliated organizations
- expect(activity.organization.name).toEqual(org2.name)
-
- // add another activity to segment2 for the same member
- switchSegments(mockIRepositoryOptions, [segment2])
-
- data.sourceId = '#sourceId2'
- data.member = member // createWithMember modifies member, reset it
-
- activityWithMember = await new ActivityService(mockIRepositoryOptions).createWithMember(data)
-
- activity = await ActivityRepository.findById(activityWithMember.id, mockIRepositoryOptions)
-
- // this member had a null affiliation(meaning no organizations should be set) in segment 2
- expect(activity.organization).toBeNull()
- })
-
- describe('Member tests in createWithMember', () => {
- it('Should set the joinedAt to the time of the activity when the member does not exist', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(
- mockIRepositoryOptions,
- )
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
-
- const member = {
- username: {
- [PlatformType.GITHUB]: 'anil_github',
- },
- email: 'lala@l.com',
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- [PlatformType.TWITTER]: 'https://twitter.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- },
- organisation: 'Crowd',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- const data = {
- member,
- body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots',
- title: 'Dashboard widgets and some other tweaks/adjustments',
- url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- timestamp: '2021-09-30T14:20:27.000Z',
- type: 'pull_request-closed',
- isContribution: true,
- platform: PlatformType.GITHUB,
- score: 4,
- sourceId: '#sourceId1',
- }
-
- const activityWithMember = await new ActivityService(
- mockIRepositoryOptions,
- ).createWithMember(data)
-
- delete activityWithMember.member
- delete activityWithMember.display
- delete activityWithMember.objectMember
-
- activityWithMember.createdAt = activityWithMember.createdAt.toISOString().split('T')[0]
- activityWithMember.updatedAt = activityWithMember.updatedAt.toISOString().split('T')[0]
-
- const memberFound = await MemberRepository.findById(
- activityWithMember.memberId,
- mockIRepositoryOptions,
- )
-
- const expectedActivityCreated = {
- id: activityWithMember.id,
- body: data.body,
- title: data.title,
- url: data.url,
- channel: data.channel,
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.42,
- },
- attributes: {},
- type: data.type,
- timestamp: new Date(data.timestamp),
- platform: data.platform,
- isContribution: data.isContribution,
- score: data.score,
- username: 'anil_github',
- objectMemberUsername: null,
- memberId: memberFound.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- tasks: [],
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parentId: null,
- parent: null,
- sourceParentId: null,
- sourceId: data.sourceId,
- conversationId: null,
- organizationId: null,
- organization: null,
- }
-
- expect(activityWithMember).toStrictEqual(expectedActivityCreated)
- expect(memberFound.joinedAt).toStrictEqual(expectedActivityCreated.timestamp)
- expect(memberFound.username).toStrictEqual({
- [PlatformType.GITHUB]: ['anil_github'],
- })
- })
-
- it('Should replace joinedAt when activity ts is earlier than existing joinedAt', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(
- mockIRepositoryOptions,
- )
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
-
- const member = {
- username: {
- [PlatformType.GITHUB]: 'anil_github',
- },
- displayName: 'Anil',
- email: 'lala@l.com',
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- [PlatformType.TWITTER]: 'https://twitter.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- },
- organisation: 'Crowd',
- joinedAt: '2022-05-27T15:13:30Z',
- }
-
- await MemberRepository.create(member, mockIRepositoryOptions)
-
- const data = {
- member,
- body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots',
- title: 'Dashboard widgets and some other tweaks/adjustments',
- url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- timestamp: '2021-09-30T14:20:27.000Z',
- type: 'pull_request-closed',
- isContribution: true,
- platform: PlatformType.GITHUB,
- score: 4,
- sourceId: '#sourceId1',
- }
-
- const activityWithMember = await new ActivityService(
- mockIRepositoryOptions,
- ).createWithMember(data)
-
- delete activityWithMember.member
- delete activityWithMember.display
- delete activityWithMember.objectMember
-
- activityWithMember.createdAt = activityWithMember.createdAt.toISOString().split('T')[0]
- activityWithMember.updatedAt = activityWithMember.updatedAt.toISOString().split('T')[0]
-
- const memberFound = await MemberRepository.findById(
- activityWithMember.memberId,
- mockIRepositoryOptions,
- )
-
- const expectedActivityCreated = {
- id: activityWithMember.id,
- body: data.body,
- title: data.title,
- url: data.url,
- channel: data.channel,
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- sentiment: 0.42,
- mixed: 0.42,
- label: 'positive',
- },
- attributes: {},
- type: data.type,
- timestamp: new Date(data.timestamp),
- platform: data.platform,
- isContribution: data.isContribution,
- score: data.score,
- username: 'anil_github',
- objectMemberUsername: null,
- memberId: memberFound.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tasks: [],
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parentId: null,
- parent: null,
- sourceId: data.sourceId,
- sourceParentId: null,
- conversationId: null,
- organizationId: null,
- organization: null,
- }
-
- expect(activityWithMember).toStrictEqual(expectedActivityCreated)
- expect(memberFound.joinedAt).toStrictEqual(expectedActivityCreated.timestamp)
- expect(memberFound.username).toStrictEqual({
- [PlatformType.GITHUB]: ['anil_github'],
- })
- })
-
- it('Should not replace joinedAt when activity ts is later than existing joinedAt', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(
- mockIRepositoryOptions,
- )
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
-
- const member = {
- username: {
- [PlatformType.GITHUB]: 'anil_github',
- },
- displayName: 'Anil',
- email: 'lala@l.com',
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- [PlatformType.TWITTER]: 'https://twitter.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- },
- organisation: 'Crowd',
- joinedAt: '2020-05-27T15:13:30Z',
- }
-
- await MemberRepository.create(member, mockIRepositoryOptions)
-
- const data = {
- member,
- body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots',
- title: 'Dashboard widgets and some other tweaks/adjustments',
- url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- timestamp: '2021-09-30T14:20:27.000Z',
- type: 'pull_request-closed',
- isContribution: true,
- platform: PlatformType.GITHUB,
- score: 4,
- sourceId: '#sourceId1',
- }
-
- const activityWithMember = await new ActivityService(
- mockIRepositoryOptions,
- ).createWithMember(data)
-
- delete activityWithMember.member
- delete activityWithMember.display
- delete activityWithMember.objectMember
-
- activityWithMember.createdAt = activityWithMember.createdAt.toISOString().split('T')[0]
- activityWithMember.updatedAt = activityWithMember.updatedAt.toISOString().split('T')[0]
-
- const memberFound = await MemberRepository.findById(
- activityWithMember.memberId,
- mockIRepositoryOptions,
- )
-
- const expectedActivityCreated = {
- id: activityWithMember.id,
- body: data.body,
- title: data.title,
- url: data.url,
- channel: data.channel,
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.42,
- },
- attributes: {},
- type: data.type,
- timestamp: new Date(data.timestamp),
- platform: data.platform,
- isContribution: data.isContribution,
- score: data.score,
- username: 'anil_github',
- objectMemberUsername: null,
- memberId: memberFound.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- tasks: [],
- deletedAt: null,
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parentId: null,
- parent: null,
- sourceId: data.sourceId,
- sourceParentId: null,
- conversationId: null,
- organizationId: null,
- organization: null,
- }
-
- expect(activityWithMember).toStrictEqual(expectedActivityCreated)
- expect(memberFound.joinedAt).toStrictEqual(new Date('2020-05-27T15:13:30Z'))
- expect(memberFound.username).toStrictEqual({
- [PlatformType.GITHUB]: ['anil_github'],
- })
- })
-
- it('It should replace joinedAt if the original was in year 1970', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- await populateSegments(mockIRepositoryOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(
- mockIRepositoryOptions,
- )
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
-
- const member = {
- username: {
- [PlatformType.GITHUB]: 'anil_github',
- },
- displayName: 'Anil',
- email: 'lala@l.com',
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- [PlatformType.TWITTER]: 'https://twitter.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Computer Science',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Istanbul',
- },
- },
- organisation: 'Crowd',
- joinedAt: new Date('1970-01-01T00:00:00Z'),
- }
-
- await MemberRepository.create(member, mockIRepositoryOptions)
-
- const data = {
- member,
- body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots',
- title: 'Dashboard widgets and some other tweaks/adjustments',
- state: 'merged',
- url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- timestamp: '2021-09-30T14:20:27.000Z',
- type: 'pull_request-closed',
- isContribution: true,
- platform: PlatformType.GITHUB,
- score: 4,
- sourceId: '#sourceId1',
- }
-
- const activityWithMember = await new ActivityService(
- mockIRepositoryOptions,
- ).createWithMember(data)
-
- delete activityWithMember.member
- delete activityWithMember.display
- delete activityWithMember.objectMember
-
- activityWithMember.createdAt = activityWithMember.createdAt.toISOString().split('T')[0]
- activityWithMember.updatedAt = activityWithMember.updatedAt.toISOString().split('T')[0]
-
- const memberFound = await MemberRepository.findById(
- activityWithMember.memberId,
- mockIRepositoryOptions,
- )
-
- const expectedActivityCreated = {
- id: activityWithMember.id,
- body: data.body,
- title: data.title,
- url: data.url,
- channel: data.channel,
- sentiment: {
- positive: 0.42,
- negative: 0.42,
- neutral: 0.42,
- mixed: 0.42,
- label: 'positive',
- sentiment: 0.42,
- },
- attributes: {},
- type: data.type,
- timestamp: new Date(data.timestamp),
- platform: data.platform,
- isContribution: data.isContribution,
- score: data.score,
- username: 'anil_github',
- objectMemberUsername: null,
- memberId: memberFound.id,
- objectMemberId: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tasks: [],
- tenantId: mockIRepositoryOptions.currentTenant.id,
- segmentId: mockIRepositoryOptions.currentSegments[0].id,
- createdById: mockIRepositoryOptions.currentUser.id,
- updatedById: mockIRepositoryOptions.currentUser.id,
- importHash: null,
- parentId: null,
- parent: null,
- sourceId: data.sourceId,
- sourceParentId: null,
- conversationId: null,
- organizationId: null,
- organization: null,
- }
-
- expect(activityWithMember).toStrictEqual(expectedActivityCreated)
- expect(memberFound.joinedAt).toStrictEqual(expectedActivityCreated.timestamp)
- expect(memberFound.username).toStrictEqual({
- [PlatformType.GITHUB]: ['anil_github'],
- })
- })
-
- it('Should respect joinedAt when an existing activity comes in with a different timestamp', async () => {
- // This can happen in cases like the Twitter integration.
- // For follow activities, if we are onboarding we set the timestamp to 1970,
- // but if we are not onboarding, we set the timestamp to the current time.
- // This can cause having 2 activities with different timestamps, but the same sourceId.
- // The joinedAt should stay untouched in this case.
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(mockIRepositoryOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(
- mockIRepositoryOptions,
- )
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
-
- const data = {
- member: {
- username: 'anil',
- },
- timestamp: '1970-01-01T00:00:00.000Z',
- type: 'follow',
- platform: PlatformType.TWITTER,
- sourceId: '#sourceId1',
- }
-
- const activityWithMember = await new ActivityService(
- mockIRepositoryOptions,
- ).createWithMember(data)
-
- const data2 = {
- member: {
- username: 'anil',
- },
- timestamp: '2021-09-30T14:20:27.000Z',
- type: 'follow',
- platform: PlatformType.TWITTER,
- sourceId: '#sourceId1',
- }
- // Upsert the same activity with a different timestamp
- await new ActivityService(mockIRepositoryOptions).createWithMember(data2)
-
- const memberFound = await MemberRepository.findById(
- activityWithMember.memberId,
- mockIRepositoryOptions,
- )
- // The joinedAt should stay untouched
- expect(memberFound.joinedAt).toStrictEqual(new Date('1970-01-01T00:00:00.000Z'))
- })
- })
- })
-
- describe('addToConversation method', () => {
- it('Should create a new conversation and add the activities in, when parent and child has no conversation', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const activityService = new ActivityService(mockIRepositoryOptions)
-
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- const activityParent = {
- type: 'activity',
- timestamp: '2020-05-27T14:13:30Z',
- platform: PlatformType.GITHUB,
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- }
-
- let activityParentCreated = await ActivityRepository.create(
- activityParent,
- mockIRepositoryOptions,
- )
-
- const activityChild = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- parent: activityParentCreated.id,
- sourceId: '#sourceId2',
- }
-
- let activityChildCreated = await ActivityRepository.create(
- activityChild,
- mockIRepositoryOptions,
- )
-
- const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions)
-
- await activityService.addToConversation(
- activityChildCreated.id,
- activityParentCreated.id,
- transaction,
- )
-
- await SequelizeRepository.commitTransaction(transaction)
-
- const conversationCreated = (
- await new ConversationService(mockIRepositoryOptions).findAndCountAll({
- slug: 'some-parent-activity',
- })
- ).rows[0]
-
- // get activities again
- activityChildCreated = await activityService.findById(activityChildCreated.id)
- activityParentCreated = await activityService.findById(activityParentCreated.id)
-
- // activities should belong to the newly created conversation
- expect(activityChildCreated.conversationId).toBe(conversationCreated.id)
- expect(activityParentCreated.conversationId).toBe(conversationCreated.id)
- })
-
- it('Should add the child activity to parents conversation, when parent already has a conversation', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const activityService = new ActivityService(mockIRepositoryOptions)
- const conversationService = new ConversationService(mockIRepositoryOptions)
-
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- const conversation = await conversationService.create({
- slug: 'some-slug',
- title: 'some title',
- })
-
- const activityParent = {
- type: 'activity',
- timestamp: '2020-05-27T14:13:30Z',
- platform: PlatformType.GITHUB,
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- conversationId: conversation.id,
- sourceId: '#sourceId1',
- }
-
- const activityParentCreated = await ActivityRepository.create(
- activityParent,
- mockIRepositoryOptions,
- )
-
- const activityChild = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- parent: activityParentCreated.id,
- sourceId: '#sourceId2',
- }
-
- let activityChildCreated = await ActivityRepository.create(
- activityChild,
- mockIRepositoryOptions,
- )
-
- const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions)
-
- await activityService.addToConversation(
- activityChildCreated.id,
- activityParentCreated.id,
- transaction,
- )
-
- await SequelizeRepository.commitTransaction(transaction)
-
- // get child activity again
- activityChildCreated = await activityService.findById(activityChildCreated.id)
-
- // child should be added to already existing conservation
- expect(activityChildCreated.conversationId).toBe(conversation.id)
- expect(activityParentCreated.conversationId).toBe(conversation.id)
- })
-
- it('Should add the parent activity to childs conversation and update conversation [published=false] title&slug, when child already has a conversation', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const activityService = new ActivityService(mockIRepositoryOptions)
- const conversationService = new ConversationService(mockIRepositoryOptions)
-
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- let conversation = await conversationService.create({
- slug: 'some-slug',
- title: 'some title',
- })
-
- const activityParent = {
- type: 'activity',
- timestamp: '2020-05-27T14:13:30Z',
- platform: PlatformType.GITHUB,
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- body: 'Some Parent Activity',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- }
-
- let activityParentCreated = await ActivityRepository.create(
- activityParent,
- mockIRepositoryOptions,
- )
-
- const activityChild = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- parent: activityParentCreated.id,
- conversationId: conversation.id,
- sourceId: '#sourceId2',
- }
-
- const activityChildCreated = await ActivityRepository.create(
- activityChild,
- mockIRepositoryOptions,
- )
-
- const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions)
-
- await activityService.addToConversation(
- activityChildCreated.id,
- activityParentCreated.id,
- transaction,
- )
-
- await SequelizeRepository.commitTransaction(transaction)
-
- // get the conversation again
- conversation = await conversationService.findById(conversation.id)
-
- // conversation should be updated with newly added parents body
- expect(conversation.title).toBe('Some Parent Activity')
- expect(conversation.slug).toBe('some-parent-activity')
-
- // get parent activity again
- activityParentCreated = await activityService.findById(activityParentCreated.id)
-
- // parent should be added to the conversation
- expect(activityChildCreated.conversationId).toBe(conversation.id)
- expect(activityParentCreated.conversationId).toBe(conversation.id)
- })
-
- it('Should add the parent activity to childs conversation and NOT update conversation [published=true] title&slug, when child already has a conversation', async () => {
- let mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const activityService = new ActivityService(mockIRepositoryOptions)
- const conversationService = new ConversationService(mockIRepositoryOptions)
-
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- let conversation = await conversationService.create({
- slug: 'some-slug',
- title: 'some title',
- published: true,
- })
-
- const activityParent = {
- type: 'activity',
- timestamp: '2020-05-27T14:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Some Parent Activity',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- }
-
- let activityParentCreated = await ActivityRepository.create(
- activityParent,
- mockIRepositoryOptions,
- )
-
- const activityChild = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Here',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- parent: activityParentCreated.id,
- conversationId: conversation.id,
- sourceId: '#sourceId2',
- }
-
- const activityChildCreated = await ActivityRepository.create(
- activityChild,
- mockIRepositoryOptions,
- )
-
- const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions)
-
- await activityService.addToConversation(
- activityChildCreated.id,
- activityParentCreated.id,
- transaction,
- )
-
- await SequelizeRepository.commitTransaction(transaction)
-
- // get the conversation again
- conversation = await conversationService.findById(conversation.id)
-
- // conversation fields should NOT be updated because it's already published
- expect(conversation.title).toBe('some title')
- expect(conversation.slug).toBe('some-slug')
-
- // get parent activity again
- activityParentCreated = await activityService.findById(activityParentCreated.id)
-
- // parent should be added to the conversation
- expect(activityChildCreated.conversationId).toBe(conversation.id)
- expect(activityParentCreated.conversationId).toBe(conversation.id)
- })
-
- it('Should always auto-publish when conversationSettings.autoPublish.status is set to all', async () => {
- let mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const activityService = new ActivityService(mockIRepositoryOptions)
- await SettingsRepository.findOrCreateDefault(
- { website: 'https://some-website' },
- mockIRepositoryOptions,
- )
- await ConversationSettingsRepository.findOrCreateDefault(
- {
- autoPublish: {
- status: 'all',
- },
- },
- mockIRepositoryOptions,
- )
-
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- const activityParent = {
- type: 'activity',
- timestamp: '2020-05-27T14:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Some Parent Activity',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- }
-
- let activityParentCreated = await ActivityRepository.create(
- activityParent,
- mockIRepositoryOptions,
- )
-
- const activityChild = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Here',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- parent: activityParentCreated.id,
- sourceId: '#sourceId2',
- }
-
- let activityChildCreated = await ActivityRepository.create(
- activityChild,
- mockIRepositoryOptions,
- )
-
- const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions)
-
- await activityService.addToConversation(
- activityChildCreated.id,
- activityParentCreated.id,
- transaction,
- )
-
- const conversationCreated = (
- await new ConversationService({
- ...mockIRepositoryOptions,
- transaction,
- } as IServiceOptions).findAndCountAll({
- slug: 'some-parent-activity',
- })
- ).rows[0]
-
- await SequelizeRepository.commitTransaction(transaction)
-
- // get activities again
- activityChildCreated = await activityService.findById(activityChildCreated.id)
- activityParentCreated = await activityService.findById(activityParentCreated.id)
-
- // activities should belong to the newly created conversation
- expect(activityChildCreated.conversationId).toBe(conversationCreated.id)
- expect(activityParentCreated.conversationId).toBe(conversationCreated.id)
-
- expect(conversationCreated.published).toStrictEqual(true)
- })
-
- it('Should never auto-publish when conversationSettings.autoPublish.status is set to disabled', async () => {
- let mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const activityService = new ActivityService(mockIRepositoryOptions)
- await SettingsRepository.findOrCreateDefault(
- { website: 'https://some-website' },
- mockIRepositoryOptions,
- )
- await ConversationSettingsRepository.findOrCreateDefault(
- {
- autoPublish: {
- status: 'disabled',
- },
- },
- mockIRepositoryOptions,
- )
-
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- const activityParent = {
- type: 'activity',
- timestamp: '2020-05-27T14:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Some Parent Activity',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- }
-
- let activityParentCreated = await ActivityRepository.create(
- activityParent,
- mockIRepositoryOptions,
- )
-
- const activityChild = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Here',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- parent: activityParentCreated.id,
- sourceId: '#sourceId2',
- }
-
- let activityChildCreated = await ActivityRepository.create(
- activityChild,
- mockIRepositoryOptions,
- )
-
- const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions)
-
- await activityService.addToConversation(
- activityChildCreated.id,
- activityParentCreated.id,
- transaction,
- )
-
- const conversationCreated = (
- await new ConversationService({
- ...mockIRepositoryOptions,
- transaction,
- } as IServiceOptions).findAndCountAll({
- slug: 'some-parent-activity',
- })
- ).rows[0]
-
- await SequelizeRepository.commitTransaction(transaction)
-
- // get activities again
- activityChildCreated = await activityService.findById(activityChildCreated.id)
- activityParentCreated = await activityService.findById(activityParentCreated.id)
-
- // activities should belong to the newly created conversation
- expect(activityChildCreated.conversationId).toBe(conversationCreated.id)
- expect(activityParentCreated.conversationId).toBe(conversationCreated.id)
-
- expect(conversationCreated.published).toStrictEqual(false)
- })
-
- it('Should auto-publish when conversationSettings.autoPublish.status is set to custom and rules match', async () => {
- let mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const activityService = new ActivityService(mockIRepositoryOptions)
- await SettingsRepository.findOrCreateDefault(
- { website: 'https://some-website' },
- mockIRepositoryOptions,
- )
- await ConversationSettingsRepository.findOrCreateDefault(
- {
- autoPublish: {
- status: 'custom',
- channelsByPlatform: {
- [PlatformType.GITHUB]: ['crowd-web'],
- },
- },
- },
- mockIRepositoryOptions,
- )
-
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- const activityParent = {
- type: 'activity',
- timestamp: '2020-05-27T14:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Some Parent Activity',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- }
-
- let activityParentCreated = await ActivityRepository.create(
- activityParent,
- mockIRepositoryOptions,
- )
-
- const activityChild = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Here',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- parent: activityParentCreated.id,
- sourceId: '#sourceId2',
- }
-
- let activityChildCreated = await ActivityRepository.create(
- activityChild,
- mockIRepositoryOptions,
- )
-
- const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions)
-
- await activityService.addToConversation(
- activityChildCreated.id,
- activityParentCreated.id,
- transaction,
- )
-
- const conversationCreated = (
- await new ConversationService({
- ...mockIRepositoryOptions,
- transaction,
- } as IServiceOptions).findAndCountAll({
- slug: 'some-parent-activity',
- })
- ).rows[0]
-
- await SequelizeRepository.commitTransaction(transaction)
-
- // get activities again
- activityChildCreated = await activityService.findById(activityChildCreated.id)
- activityParentCreated = await activityService.findById(activityParentCreated.id)
-
- // activities should belong to the newly created conversation
- expect(activityChildCreated.conversationId).toBe(conversationCreated.id)
- expect(activityParentCreated.conversationId).toBe(conversationCreated.id)
-
- expect(conversationCreated.published).toStrictEqual(true)
- })
-
- it("Should not auto-publish when conversationSettings.autoPublish.status is set to custom and rules don't match", async () => {
- let mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
-
- const activityService = new ActivityService(mockIRepositoryOptions)
- await SettingsRepository.findOrCreateDefault(
- { website: 'https://some-website' },
- mockIRepositoryOptions,
- )
- await ConversationSettingsRepository.findOrCreateDefault(
- {
- autoPublish: {
- status: 'custom',
- channelsByPlatform: {
- [PlatformType.GITHUB]: ['a-different-test-channel'],
- },
- },
- },
- mockIRepositoryOptions,
- )
-
- const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({
- username: {
- [PlatformType.GITHUB]: 'test',
- },
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- })
-
- const activityParent = {
- type: 'activity',
- timestamp: '2020-05-27T14:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Some Parent Activity',
- channel: 'https://github.com/CrowdDevHQ/crowd-web',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- sourceId: '#sourceId1',
- }
-
- let activityParentCreated = await ActivityRepository.create(
- activityParent,
- mockIRepositoryOptions,
- )
-
- const activityChild = {
- type: 'activity',
- timestamp: '2020-05-27T15:13:30Z',
- platform: PlatformType.GITHUB,
- body: 'Here',
- isContribution: true,
- username: 'test',
- member: memberCreated.id,
- score: 1,
- parent: activityParentCreated.id,
- sourceId: '#sourceId2',
- }
-
- let activityChildCreated = await ActivityRepository.create(
- activityChild,
- mockIRepositoryOptions,
- )
-
- const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions)
-
- await activityService.addToConversation(
- activityChildCreated.id,
- activityParentCreated.id,
- transaction,
- )
-
- const conversations = await new ConversationService({
- ...mockIRepositoryOptions,
- transaction,
- } as IServiceOptions).findAndCountAll({
- slug: 'some-parent-activity',
- })
-
- const conversationCreated = conversations.rows[0]
-
- await SequelizeRepository.commitTransaction(transaction)
-
- // get activities again
- activityChildCreated = await activityService.findById(activityChildCreated.id)
- activityParentCreated = await activityService.findById(activityParentCreated.id)
-
- // activities should belong to the newly created conversation
- expect(activityChildCreated.conversationId).toBe(conversationCreated.id)
- expect(activityParentCreated.conversationId).toBe(conversationCreated.id)
-
- expect(conversationCreated.published).toStrictEqual(false)
- })
- })
-
- describe('affiliations', () => {
- let options
- let activityService: ActivityService
- let memberService
- let organizationService
- let segmentService: SegmentService
- let memberAffiliationService: MemberAffiliationService
- let memberSegmentAffiliationRepository: MemberSegmentAffiliationRepository
-
- let defaultActivity
- let defaultMember
-
- beforeEach(async () => {
- options = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- await populateSegments(options)
-
- activityService = new ActivityService(options)
- memberService = new MemberService(options)
- organizationService = new OrganizationService(options)
- segmentService = new SegmentService(options)
- memberAffiliationService = new MemberAffiliationService(options)
- memberSegmentAffiliationRepository = new MemberSegmentAffiliationRepository(options)
-
- defaultActivity = {
- type: 'question',
- timestamp: '2020-05-27T15:13:30Z',
- username: 'test',
- platform: PlatformType.GITHUB,
- }
- defaultMember = {
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-27T15:13:30Z',
- }
- })
-
- async function createMember(data = {}) {
- return await memberService.upsert({
- ...defaultMember,
- username: {
- [PlatformType.GITHUB]: uuid(),
- },
- ...data,
- })
- }
-
- async function createActivity(memberId, data: any = {}) {
- const activity = await activityService.upsert({
- ...defaultActivity,
- sourceId: uuid(),
- member: memberId,
- ...data,
- })
-
- if (data.organizationId) {
- await ActivityRepository.update(
- activity.id,
- {
- organizationId: data.organizationId,
- },
- options,
- )
- return await activityService.findById(activity.id)
- }
-
- return activity
- }
-
- async function findActivity(id) {
- return await activityService.findById(id)
- }
-
- async function createOrg(name, data = {}) {
- return await organizationService.createOrUpdate({
- identities: [
- {
- name,
- platform: 'crowd',
- },
- ],
- ...data,
- })
- }
-
- async function createSegment(slug, data = {}) {
- const db1 = await SequelizeTestUtils.getDatabase(db)
- const tenant = options.currentTenant
- try {
- const segment = (
- await db1.segment.create({
- url: tenant.url,
- name: slug,
- parentName: tenant.name,
- grandparentName: tenant.name,
- slug: slug,
- parentSlug: 'default',
- grandparentSlug: 'default',
- status: SegmentStatus.ACTIVE,
- description: null,
- sourceId: null,
- sourceParentId: null,
- tenantId: tenant.id,
- })
- ).get({ plain: true })
- return segment
- } catch (error) {
- console.log(error)
- throw error
- }
- }
-
- async function addWorkExperience(memberId, orgId, data = {}) {
- return await MemberRepository.createOrUpdateWorkExperience(
- {
- memberId,
- organizationId: orgId,
- updateAffiliation: false,
- source: 'test',
- ...data,
- },
- options,
- )
- }
-
- describe('new activities', () => {
- it('Should affiliate nothing if member has no organizations and no affiliations', async () => {
- const member = await createMember()
- const activity = await createActivity(member.id)
-
- expect(activity.organization).toBeNull()
- })
-
- it('Should affiliate work experience if member has organizations', async () => {
- const member = await createMember()
- const organization = await createOrg('hello')
- await addWorkExperience(member.id, organization.id, {
- dateStart: '2020-01-01',
- })
- const activity = await createActivity(member.id, {
- timestamp: '2023-01-01',
- })
-
- expect(activity.organization.id).toBe(organization.id)
- })
-
- it('Should affiliate with matching work experience if activity is from the past', async () => {
- const member = await createMember()
- const org1 = await createOrg('org1')
- const org2 = await createOrg('org2')
-
- await addWorkExperience(member.id, org1.id, {
- dateStart: '2020-01-01',
- dateEnd: '2020-02-01',
- })
- await addWorkExperience(member.id, org2.id, {
- dateStart: '2020-02-01',
- })
-
- const activity = await createActivity(member.id, {
- timestamp: '2020-01-15',
- })
-
- expect(activity.organization.id).toBe(org1.id)
- })
-
- it('Should affiliate with most recent open work experience if member has multiple organizations', async () => {
- const member = await createMember()
- const org1 = await createOrg('org1')
- const org2 = await createOrg('org2')
-
- await addWorkExperience(member.id, org1.id, {
- dateStart: '2020-01-01',
- })
- await addWorkExperience(member.id, org2.id, {
- dateStart: '2020-02-01',
- })
-
- const activity = await createActivity(member.id, {
- timestamp: '2020-03-01',
- })
-
- expect(activity.organization.id).toBe(org2.id)
- })
-
- it('Should affiliate with most recent open work experience, even if there is a more recent closed one', async () => {
- const member = await createMember()
- const org1 = await createOrg('org1')
- const org2 = await createOrg('org2')
-
- await addWorkExperience(member.id, org1.id, {
- dateStart: '2020-01-01',
- })
- await addWorkExperience(member.id, org2.id, {
- dateStart: '2020-02-01',
- dateEnd: '2020-03-01',
- })
-
- const activity = await createActivity(member.id)
-
- expect(activity.organization.id).toBe(org1.id)
- })
-
- it('Should affiliate with manual affiliation if member has organizations and affiliations', async () => {
- const member = await createMember()
- const org1 = await createOrg('org1')
- const org2 = await createOrg('org2')
-
- await addWorkExperience(member.id, org1.id, {
- dateStart: '2020-01-01',
- })
-
- await memberSegmentAffiliationRepository.createOrUpdate({
- memberId: member.id,
- segmentId: options.currentSegments[0].id,
- organizationId: org2.id,
- dateStart: '2020-02-01',
- })
-
- const activity = await createActivity(member.id)
-
- expect(activity.organization.id).toBe(org2.id)
- })
-
- it('Should affiliate to invidiual if member has organizations and affiliations', async () => {
- const member = await createMember()
- const org1 = await createOrg('org1')
-
- await addWorkExperience(member.id, org1.id, {
- dateStart: '2020-01-01',
- })
-
- await memberSegmentAffiliationRepository.createOrUpdate({
- memberId: member.id,
- segmentId: options.currentSegments[0].id,
- organizationId: null,
- dateStart: '2020-02-01',
- })
-
- const activity = await createActivity(member.id)
-
- expect(activity.organization).toBeNull()
- })
-
- it('Should not affiliate if there are no relevant manual affiliations', async () => {
- const member = await createMember()
- const org1 = await createOrg('org1')
- const segment1 = await createSegment('segment1')
-
- await memberSegmentAffiliationRepository.createOrUpdate({
- memberId: member.id,
- segmentId: segment1.id,
- organizationId: org1.id,
- })
-
- const activity = await createActivity(member.id)
-
- expect(activity.organization).toBeNull()
- })
- })
-
- describe('existing activities', () => {
- it('Should clear affiliation if there is a manual individual affiliation', async () => {
- const member = await createMember()
- const org1 = await createOrg('org1')
- const segment1 = await createSegment('segment1')
-
- await memberSegmentAffiliationRepository.createOrUpdate({
- memberId: member.id,
- segmentId: segment1.id,
- organizationId: null,
- })
-
- let activity = await createActivity(member.id, {
- organizationId: org1.id,
- })
-
- await memberAffiliationService.updateAffiliation(member.id)
-
- activity = await findActivity(activity.id)
-
- expect(activity.organization).toBeNull()
- })
-
- it('Should affiliate activities', async () => {
- const member = await createMember()
-
- let activity1 = await createActivity(member.id)
- let activity2 = await createActivity(member.id)
-
- const org = await createOrg('org')
- await addWorkExperience(member.id, org.id, {
- dateStart: '2020-01-01',
- })
-
- await memberAffiliationService.updateAffiliation(member.id)
-
- activity1 = await findActivity(activity1.id)
- activity2 = await findActivity(activity2.id)
-
- expect(activity1.organization.id).toBe(org.id)
- expect(activity2.organization.id).toBe(org.id)
- })
-
- it('Should only affiliate activities of specific member', async () => {
- const member1 = await createMember()
- const member2 = await createMember()
-
- let activity1 = await createActivity(member1.id)
- let activity2 = await createActivity(member2.id)
-
- const org1 = await createOrg('org1')
- await addWorkExperience(member1.id, org1.id, {
- dateStart: '2020-01-01',
- })
- const org2 = await createOrg('org2')
- await addWorkExperience(member2.id, org2.id, {
- dateStart: '2020-01-01',
- })
-
- await memberAffiliationService.updateAffiliation(member1.id)
-
- activity2 = await findActivity(activity2.id)
-
- expect(activity2.organization).toBeNull()
- })
-
- it('Should affiliate with matching recent work experience', async () => {
- const member = await createMember()
-
- let activity = await createActivity(member.id, {
- timestamp: '2020-01-01',
- })
-
- const org1 = await createOrg('org1')
- await addWorkExperience(member.id, org1.id)
- const org2 = await createOrg('org2')
- await addWorkExperience(member.id, org2.id, {
- dateStart: '2023-01-01',
- })
- const org3 = await createOrg('org2')
- await addWorkExperience(member.id, org3.id, {
- dateStart: '2019-01-01',
- dateEnd: '2022-01-01',
- })
-
- await memberAffiliationService.updateAffiliation(member.id)
-
- activity = await findActivity(activity.id)
-
- expect(activity.organization.id).toBe(org3.id)
- })
-
- it('Should affiliate first created org to past activities', async () => {
- const member = await createMember()
-
- let activity = await createActivity(member.id, {
- timestamp: '2022-05-01',
- })
-
- const org1 = await createOrg('org1')
- await addWorkExperience(member.id, org1.id)
- const org2 = await createOrg('org2')
- await addWorkExperience(member.id, org2.id, {
- dateStart: '2023-01-01',
- })
- const org3 = await createOrg('org2')
- await addWorkExperience(member.id, org3.id, {
- dateStart: '2019-01-01',
- dateEnd: '2022-01-01',
- })
-
- await memberAffiliationService.updateAffiliation(member.id)
-
- activity = await findActivity(activity.id)
-
- expect(activity.organization.id).toBe(org1.id)
- })
-
- it('Should prefer manual affiliation over work experience', async () => {
- const member = await createMember()
-
- let activity = await createActivity(member.id, {
- timestamp: '2020-05-01',
- })
-
- const org1 = await createOrg('org1')
- await addWorkExperience(member.id, org1.id, {
- dateStart: '2020-01-01',
- })
-
- const org2 = await createOrg('org2')
- await memberSegmentAffiliationRepository.createOrUpdate({
- memberId: member.id,
- segmentId: options.currentSegments[0].id,
- organizationId: org2.id,
- dateStart: '2020-01-01',
- })
-
- await memberAffiliationService.updateAffiliation(member.id)
-
- activity = await findActivity(activity.id)
-
- expect(activity.organization.id).toBe(org2.id)
- })
-
- it('Should prefer manual individual affiliation over work experience', async () => {
- const member = await createMember()
-
- let activity = await createActivity(member.id, {
- timestamp: '2020-05-01',
- })
-
- const org1 = await createOrg('org1')
- await addWorkExperience(member.id, org1.id, {
- dateStart: '2020-01-01',
- })
-
- await memberSegmentAffiliationRepository.createOrUpdate({
- memberId: member.id,
- segmentId: options.currentSegments[0].id,
- organizationId: null,
- dateStart: '2020-01-01',
- })
-
- await memberAffiliationService.updateAffiliation(member.id)
-
- activity = await findActivity(activity.id)
-
- expect(activity.organization).toBeNull()
- })
-
- it('Should trigger affiliation update when changing member organizations', async () => {
- const member = await createMember()
-
- let activity = await createActivity(member.id, {
- timestamp: '2020-05-01',
- })
-
- const org1 = await createOrg('org1')
- await addWorkExperience(member.id, org1.id, {
- dateStart: '2020-01-01',
- updateAffiliation: true,
- })
-
- activity = await findActivity(activity.id)
-
- expect(activity.organization.id).toBe(org1.id)
- })
-
- it('Should trigger affiliation update when changing member manual affiliations', async () => {
- const member = await createMember()
-
- let activity = await createActivity(member.id)
-
- const org1 = await createOrg('org1')
-
- await memberSegmentAffiliationRepository.createOrUpdate({
- memberId: member.id,
- segmentId: options.currentSegments[0].id,
- organizationId: org1.id,
- })
-
- activity = await findActivity(activity.id)
-
- expect(activity.organization.id).toBe(org1.id)
- })
- })
-
- it('Should filter by organization based on organizationId', async () => {
- const member = await createMember()
-
- const org1 = await createOrg('org1')
- await addWorkExperience(member.id, org1.id)
-
- const org2 = await createOrg('org2')
- await addWorkExperience(member.id, org2.id)
-
- let activity1 = await createActivity(member.id, {
- organizationId: org1.id,
- })
- let activity2 = await createActivity(member.id, {
- organizationId: org2.id,
- })
-
- const { rows } = await activityService.query({
- filter: {
- organizations: [org1.id],
- },
- })
-
- expect(rows.length).toBe(1)
- })
- })
-})
diff --git a/backend/src/services/__tests__/memberService.test.ts b/backend/src/services/__tests__/memberService.test.ts
deleted file mode 100644
index 505c7d6db3..0000000000
--- a/backend/src/services/__tests__/memberService.test.ts
+++ /dev/null
@@ -1,2834 +0,0 @@
-import { generateUUIDv1, Error400, Error404 } from '@crowd/common'
-import SequelizeTestUtils from '../../database/utils/sequelizeTestUtils'
-import MemberService from '../memberService'
-import MemberRepository from '../../database/repositories/memberRepository'
-import ActivityRepository from '../../database/repositories/activityRepository'
-import TagRepository from '../../database/repositories/tagRepository'
-import { MemberAttributeName, MemberAttributeType, PlatformType } from '@crowd/types'
-import OrganizationRepository from '../../database/repositories/organizationRepository'
-import TaskRepository from '../../database/repositories/taskRepository'
-import NoteRepository from '../../database/repositories/noteRepository'
-import MemberAttributeSettingsService from '../memberAttributeSettingsService'
-import SettingsRepository from '../../database/repositories/settingsRepository'
-import OrganizationService from '../organizationService'
-import Plans from '../../security/plans'
-import lodash from 'lodash'
-import {
- DEVTO_MEMBER_ATTRIBUTES,
- DISCORD_MEMBER_ATTRIBUTES,
- GITHUB_MEMBER_ATTRIBUTES,
- SLACK_MEMBER_ATTRIBUTES,
- TWITTER_MEMBER_ATTRIBUTES,
-} from '@crowd/integrations'
-
-const db = null
-
-describe('MemberService tests', () => {
- beforeEach(async () => {
- await SequelizeTestUtils.wipeDatabase(db)
- })
-
- afterAll(async () => {
- // Closing the DB connection allows Jest to exit successfully.
- await SequelizeTestUtils.closeConnection(db)
- })
-
- describe('upsert method', () => {
- it('Should throw 400 error when platform does not exist in member data', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const mas = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'anil',
- integrationId: generateUUIDv1(),
- },
- },
- emails: ['lala@l.com'],
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- },
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- await expect(() =>
- new MemberService(mockIServiceOptions).upsert(member1),
- ).rejects.toThrowError(new Error400())
- })
-
- it('Should create non existent member - attributes with matching platform', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const mas = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await mas.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
- await mas.createPredefined(DISCORD_MEMBER_ATTRIBUTES)
-
- const member1 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- emails: ['lala@l.com'],
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- [PlatformType.TWITTER]: 'https://some-twitter-url',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- [MemberAttributeName.SOURCE_ID]: {
- [PlatformType.TWITTER]: '#twitterId',
- [PlatformType.DISCORD]: '#discordId',
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: 'https://some-image-url',
- },
- },
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- // Save some attributes since they get modified in the upsert function
- const { platform, username, attributes } = member1
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- username: {
- [platform]: [username],
- },
- displayName: username,
- attributes: {
- [MemberAttributeName.SOURCE_ID]: {
- [PlatformType.DISCORD]: attributes[MemberAttributeName.SOURCE_ID][PlatformType.DISCORD],
- [PlatformType.TWITTER]: attributes[MemberAttributeName.SOURCE_ID][PlatformType.TWITTER],
- default: attributes[MemberAttributeName.SOURCE_ID][PlatformType.TWITTER],
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]:
- attributes[MemberAttributeName.AVATAR_URL][PlatformType.TWITTER],
- default: attributes[MemberAttributeName.AVATAR_URL][PlatformType.TWITTER],
- },
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB],
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.URL][PlatformType.GITHUB],
- [PlatformType.TWITTER]: attributes[MemberAttributeName.URL][PlatformType.TWITTER],
- default: attributes[MemberAttributeName.URL][PlatformType.TWITTER],
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB],
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.BIO][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.BIO][PlatformType.GITHUB],
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- },
- },
- emails: member1.emails,
- score: member1.score,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- organizations: [
- {
- displayName: 'l.com',
- id: memberCreated.organizations[0].id,
- memberOrganizations: {
- memberId: memberCreated.id,
- organizationId: memberCreated.organizations[0].id,
- dateEnd: null,
- dateStart: null,
- title: null,
- source: null,
- },
- },
- ],
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- reach: { total: -1 },
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- lastEnriched: null,
- enrichedBy: [],
- contributions: null,
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberCreated).toStrictEqual(memberExpected)
- })
-
- it('Should create non existent member - object type username', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
- const mas = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: 'anil',
- [PlatformType.TWITTER]: 'anil_twitter',
- },
- platform: PlatformType.GITHUB,
- emails: ['lala@l.com'],
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- },
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- // Save some attributes since they get modified in the upsert function
- const { username, attributes } = member1
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- username: {
- [PlatformType.GITHUB]: ['anil'],
- [PlatformType.TWITTER]: ['anil_twitter'],
- },
- displayName: 'anil',
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB],
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.URL][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.URL][PlatformType.GITHUB],
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB],
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.BIO][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.BIO][PlatformType.GITHUB],
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- },
- },
- emails: member1.emails,
- score: member1.score,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- lastEnriched: null,
- organizations: [
- {
- displayName: 'l.com',
- id: memberCreated.organizations[0].id,
- memberOrganizations: {
- memberId: memberCreated.id,
- organizationId: memberCreated.organizations[0].id,
- dateEnd: null,
- dateStart: null,
- title: null,
- source: null,
- },
- },
- ],
- enrichedBy: [],
- contributions: null,
- reach: { total: -1 },
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberCreated).toStrictEqual(memberExpected)
- })
-
- it('Should create non existent member - reach as number', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const member1 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- emails: ['lala@l.com'],
- score: 10,
- attributes: {},
- reach: 10,
- bio: 'Computer Science',
- joinedAt: '2020-05-28T15:13:30Z',
- location: 'Istanbul',
- }
-
- // Save some attributes since they get modified in the upsert function
- const { platform, username } = member1
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- username: {
- [platform]: [username],
- },
- displayName: username,
- attributes: {},
- emails: member1.emails,
- lastEnriched: null,
- organizations: [
- {
- displayName: 'l.com',
- id: memberCreated.organizations[0].id,
- memberOrganizations: {
- memberId: memberCreated.id,
- organizationId: memberCreated.organizations[0].id,
- dateEnd: null,
- dateStart: null,
- title: null,
- source: null,
- },
- },
- ],
- enrichedBy: [],
- contributions: null,
- score: member1.score,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- reach: { total: 10, [PlatformType.GITHUB]: 10 },
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberCreated).toStrictEqual(memberExpected)
- })
-
- it('Should create non existent member - reach as object, platform in object', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const member1 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- emails: ['lala@l.com'],
- score: 10,
- reach: { [PlatformType.GITHUB]: 10, [PlatformType.TWITTER]: 10 },
- bio: 'Computer Science',
- joinedAt: '2020-05-28T15:13:30Z',
- location: 'Istanbul',
- }
-
- // Save some attributes since they get modified in the upsert function
- const { platform, username } = member1
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- username: {
- [platform]: [username],
- },
- displayName: username,
- attributes: {},
- lastEnriched: null,
- organizations: [
- {
- displayName: 'l.com',
- id: memberCreated.organizations[0].id,
- memberOrganizations: {
- memberId: memberCreated.id,
- organizationId: memberCreated.organizations[0].id,
- dateEnd: null,
- dateStart: null,
- title: null,
- source: null,
- },
- },
- ],
- enrichedBy: [],
- contributions: null,
- emails: member1.emails,
- score: member1.score,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- reach: { total: 20, [PlatformType.GITHUB]: 10, [PlatformType.TWITTER]: 10 },
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberCreated).toStrictEqual(memberExpected)
- })
-
- it('Should create non existent member - reach as object, platform not in object', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const member1 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- emails: ['lala@l.com'],
- score: 10,
- reach: { [PlatformType.DISCORD]: 10, [PlatformType.TWITTER]: 10 },
- bio: 'Computer Science',
- joinedAt: '2020-05-28T15:13:30Z',
- location: 'Istanbul',
- }
-
- // Save some attributes since they get modified in the upsert function
- const { platform, username } = member1
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- username: {
- [platform]: [username],
- },
- displayName: username,
- attributes: {},
- emails: member1.emails,
- score: member1.score,
- lastEnriched: null,
- organizations: [
- {
- displayName: 'l.com',
- id: memberCreated.organizations[0].id,
- memberOrganizations: {
- memberId: memberCreated.id,
- organizationId: memberCreated.organizations[0].id,
- dateEnd: null,
- dateStart: null,
- title: null,
- source: null,
- },
- },
- ],
- enrichedBy: [],
- contributions: null,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- reach: { total: 20, [PlatformType.DISCORD]: 10, [PlatformType.TWITTER]: 10 },
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberCreated).toStrictEqual(memberExpected)
- })
-
- it('Should create non existent member - organization as name, no enrichment', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const member1 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- emails: ['lala@gmail.com'],
- score: 10,
- attributes: {},
- reach: 10,
- bio: 'Computer Science',
- organizations: ['crowd.dev'],
- joinedAt: '2020-05-28T15:13:30Z',
- location: 'Istanbul',
- }
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const organization = (await OrganizationRepository.findAndCountAll({}, mockIServiceOptions))
- .rows[0]
-
- const foundMember = await MemberRepository.findById(memberCreated.id, mockIServiceOptions)
-
- const o1 = foundMember.organizations[0].get({ plain: true })
- delete o1.createdAt
- delete o1.updatedAt
-
- expect(o1).toStrictEqual({
- id: organization.id,
- displayName: 'crowd.dev',
- github: null,
- location: null,
- website: null,
- description: null,
- emails: null,
- phoneNumbers: null,
- logo: null,
- memberOrganizations: {
- dateEnd: null,
- dateStart: null,
- title: null,
- source: null,
- },
- tags: null,
- twitter: null,
- linkedin: null,
- crunchbase: null,
- employees: null,
- revenueRange: null,
- importHash: null,
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- isTeamOrganization: false,
- type: null,
- ticker: null,
- size: null,
- naics: null,
- lastEnrichedAt: null,
- industry: null,
- headline: null,
- geoLocation: null,
- founded: null,
- employeeCountByCountry: null,
- address: null,
- profiles: null,
- attributes: {},
- manuallyCreated: false,
- affiliatedProfiles: null,
- allSubsidiaries: null,
- alternativeDomains: null,
- alternativeNames: null,
- averageEmployeeTenure: null,
- averageTenureByLevel: null,
- averageTenureByRole: null,
- directSubsidiaries: null,
- employeeChurnRate: null,
- employeeCountByMonth: null,
- employeeGrowthRate: null,
- employeeCountByMonthByLevel: null,
- employeeCountByMonthByRole: null,
- gicsSector: null,
- grossAdditionsByMonth: null,
- grossDeparturesByMonth: null,
- ultimateParent: null,
- immediateParent: null,
- manuallyChangedFields: null,
- })
- })
-
- it('Should create non existent member - organization as object, no enrichment', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const member1 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- emails: ['lala@gmail.com'],
- score: 10,
- attributes: {},
- reach: 10,
- bio: 'Computer Science',
- organizations: [{ name: 'crowd.dev', url: 'https://crowd.dev', description: 'Here' }],
- joinedAt: '2020-05-28T15:13:30Z',
- location: 'Istanbul',
- }
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const organization = (await OrganizationRepository.findAndCountAll({}, mockIServiceOptions))
- .rows[0]
-
- const foundMember = await MemberRepository.findById(memberCreated.id, mockIServiceOptions)
-
- const o1 = foundMember.organizations[0].get({ plain: true })
- delete o1.createdAt
- delete o1.updatedAt
-
- expect(o1).toStrictEqual({
- id: organization.id,
- displayName: 'crowd.dev',
- github: null,
- location: null,
- website: null,
- description: 'Here',
- emails: null,
- phoneNumbers: null,
- logo: null,
- memberOrganizations: {
- dateEnd: null,
- dateStart: null,
- title: null,
- source: null,
- },
- tags: null,
- twitter: null,
- linkedin: null,
- crunchbase: null,
- employees: null,
- revenueRange: null,
- importHash: null,
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- isTeamOrganization: false,
- type: null,
- ticker: null,
- size: null,
- naics: null,
- lastEnrichedAt: null,
- industry: null,
- headline: null,
- geoLocation: null,
- founded: null,
- employeeCountByCountry: null,
- address: null,
- profiles: null,
- attributes: {},
- manuallyCreated: false,
- affiliatedProfiles: null,
- allSubsidiaries: null,
- alternativeDomains: null,
- alternativeNames: null,
- averageEmployeeTenure: null,
- averageTenureByLevel: null,
- averageTenureByRole: null,
- directSubsidiaries: null,
- employeeChurnRate: null,
- employeeCountByMonth: null,
- employeeGrowthRate: null,
- employeeCountByMonthByLevel: null,
- employeeCountByMonthByRole: null,
- gicsSector: null,
- grossAdditionsByMonth: null,
- grossDeparturesByMonth: null,
- ultimateParent: null,
- immediateParent: null,
- manuallyChangedFields: null,
- })
- })
-
- it('Should create non existent member - organization as id', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const oCreated = await new OrganizationService(mockIServiceOptions).createOrUpdate({
- identities: [
- {
- name: 'crowd.dev',
- platform: 'crowd',
- },
- ],
- })
-
- const member1 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- emails: ['lala@gmail.com'],
- score: 10,
- attributes: {},
- reach: 10,
- bio: 'Computer Science',
- organizations: [oCreated.id],
- joinedAt: '2020-05-28T15:13:30Z',
- location: 'Istanbul',
- }
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const organization = (await OrganizationRepository.findAndCountAll({}, mockIServiceOptions))
- .rows[0]
-
- const foundMember = await MemberRepository.findById(memberCreated.id, mockIServiceOptions)
-
- const o1 = foundMember.organizations[0].get({ plain: true })
- delete o1.createdAt
- delete o1.updatedAt
-
- expect(o1).toStrictEqual({
- id: organization.id,
- displayName: 'crowd.dev',
- github: null,
- location: null,
- website: null,
- description: null,
- emails: null,
- phoneNumbers: null,
- logo: null,
- manuallyChangedFields: null,
- memberOrganizations: {
- dateEnd: null,
- dateStart: null,
- title: null,
- source: null,
- },
- tags: null,
- twitter: null,
- linkedin: null,
- crunchbase: null,
- employees: null,
- revenueRange: null,
- importHash: null,
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- isTeamOrganization: false,
- type: null,
- ticker: null,
- size: null,
- naics: null,
- lastEnrichedAt: null,
- industry: null,
- headline: null,
- geoLocation: null,
- founded: null,
- employeeCountByCountry: null,
- address: null,
- profiles: null,
- attributes: {},
- manuallyCreated: false,
- affiliatedProfiles: null,
- allSubsidiaries: null,
- alternativeDomains: null,
- alternativeNames: null,
- averageEmployeeTenure: null,
- averageTenureByLevel: null,
- averageTenureByRole: null,
- directSubsidiaries: null,
- employeeChurnRate: null,
- employeeCountByMonth: null,
- employeeGrowthRate: null,
- employeeCountByMonthByLevel: null,
- employeeCountByMonthByRole: null,
- gicsSector: null,
- grossAdditionsByMonth: null,
- grossDeparturesByMonth: null,
- ultimateParent: null,
- immediateParent: null,
- })
- })
-
- it('Should update existent member succesfully - simple', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const mas = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const member1 = {
- username: 'anil',
- emails: ['lala@l.com'],
- platform: PlatformType.GITHUB,
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- },
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- const member1Username = member1.username
- const attributes = member1.attributes
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const member2 = {
- username: 'anil',
- emails: ['test@gmail.com', 'test2@yahoo.com'],
- platform: PlatformType.GITHUB,
- location: 'Ankara',
- }
-
- const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2)
-
- memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0]
- memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- username: {
- [PlatformType.GITHUB]: [member1Username],
- },
- displayName: member1Username,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB],
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.URL][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.URL][PlatformType.GITHUB],
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB],
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.BIO][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.BIO][PlatformType.GITHUB],
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- },
- },
- lastEnriched: null,
- organizations: [
- {
- displayName: 'l.com',
- id: memberCreated.organizations[0].id,
- memberOrganizations: {
- memberId: memberCreated.id,
- organizationId: memberCreated.organizations[0].id,
- dateEnd: null,
- dateStart: null,
- title: null,
- source: null,
- },
- },
- ],
- enrichedBy: [],
- contributions: null,
- emails: ['lala@l.com', 'test@gmail.com', 'test2@yahoo.com'],
- score: member1.score,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- reach: { total: -1 },
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberUpdated).toStrictEqual(memberExpected)
- })
-
- it('Should update existent member successfully - attributes with matching platform', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const mas = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await mas.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
-
- const member1 = {
- username: 'anil',
- emails: ['lala@l.com'],
- platform: PlatformType.GITHUB,
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- },
- },
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- const member1Username = member1.username
- const attributes1 = member1.attributes
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const member2 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- attributes: {
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- [MemberAttributeName.URL]: {
- [PlatformType.TWITTER]: 'https://twitter-url',
- },
- },
- }
-
- const attributes2 = member2.attributes
-
- const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2)
-
- memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0]
- memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- username: {
- [PlatformType.GITHUB]: [member1Username],
- },
- displayName: member1Username,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]:
- attributes1[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB],
- default: attributes1[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB],
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: attributes1[MemberAttributeName.URL][PlatformType.GITHUB],
- [PlatformType.TWITTER]: attributes2[MemberAttributeName.URL][PlatformType.TWITTER],
- default: attributes2[MemberAttributeName.URL][PlatformType.TWITTER],
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]:
- attributes2[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB],
- default: attributes2[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB],
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: attributes2[MemberAttributeName.BIO][PlatformType.GITHUB],
- default: attributes2[MemberAttributeName.BIO][PlatformType.GITHUB],
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: attributes2[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- default: attributes2[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- },
- },
- lastEnriched: null,
- organizations: [
- {
- displayName: 'l.com',
- id: memberCreated.organizations[0].id,
- memberOrganizations: {
- memberId: memberCreated.id,
- organizationId: memberCreated.organizations[0].id,
- dateEnd: null,
- dateStart: null,
- title: null,
- source: null,
- },
- },
- ],
- enrichedBy: [],
- contributions: null,
- emails: member1.emails,
- score: member1.score,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- reach: { total: -1 },
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberUpdated).toStrictEqual(memberExpected)
- })
-
- it('Should update existent member succesfully - object type username', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const mas = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const member1 = {
- username: 'anil',
- emails: ['lala@l.com'],
- platform: PlatformType.GITHUB,
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- },
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- const member1Username = member1.username
- const attributes = member1.attributes
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const member2 = {
- username: {
- [PlatformType.GITHUB]: 'anil',
- [PlatformType.TWITTER]: 'anil_twitter',
- [PlatformType.DISCORD]: 'anil_discord',
- },
- platform: PlatformType.GITHUB,
- }
-
- const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2)
-
- memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0]
- memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- username: {
- [PlatformType.GITHUB]: ['anil'],
- [PlatformType.TWITTER]: ['anil_twitter'],
- [PlatformType.DISCORD]: ['anil_discord'],
- },
- displayName: 'anil',
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB],
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.URL][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.URL][PlatformType.GITHUB],
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB],
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.BIO][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.BIO][PlatformType.GITHUB],
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- default: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- },
- },
- emails: member1.emails,
- lastEnriched: null,
- organizations: [
- {
- displayName: 'l.com',
- id: memberCreated.organizations[0].id,
- memberOrganizations: {
- memberId: memberCreated.id,
- organizationId: memberCreated.organizations[0].id,
- dateEnd: null,
- dateStart: null,
- title: null,
- source: null,
- },
- },
- ],
- enrichedBy: [],
- contributions: null,
- score: member1.score,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- reach: { total: -1 },
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberUpdated).toStrictEqual(memberExpected)
- })
-
- it('Should throw 400 error when given platform does not match with username object ', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
- const mas = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const member1 = {
- username: 'anil',
- emails: ['lala@l.com'],
- platform: PlatformType.GITHUB,
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- },
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const member2 = {
- username: {
- [PlatformType.GITHUB]: 'anil',
- [PlatformType.TWITTER]: 'anil_twitter',
- [PlatformType.DISCORD]: 'anil_discord',
- },
- platform: PlatformType.SLACK,
- }
-
- await expect(() =>
- new MemberService(mockIServiceOptions).upsert(member2),
- ).rejects.toThrowError(new Error400())
- })
-
- it('Should update existent member succesfully - JSON fields', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
- const mas = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await mas.createPredefined(DEVTO_MEMBER_ATTRIBUTES)
-
- const member1 = {
- username: 'anil',
- platform: PlatformType.TWITTER,
- emails: ['lala@l.com'],
- score: 10,
- attributes: {
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/imcvampire',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- },
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- const member1Username = member1.username
- const attributes1 = member1.attributes
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const member2 = {
- username: 'anil',
- platform: PlatformType.TWITTER,
- joinedAt: '2020-05-28T15:13:30Z',
- location: 'Ankara',
- attributes: {
- [MemberAttributeName.SOURCE_ID]: {
- [PlatformType.DEVTO]: '#someDevtoId',
- [PlatformType.SLACK]: '#someSlackId',
- },
- [MemberAttributeName.NAME]: {
- [PlatformType.DEVTO]: 'Michael Scott',
- },
- [MemberAttributeName.URL]: {
- [PlatformType.DEVTO]: 'https://some-devto-url',
- },
- },
- }
-
- const attributes2 = member2.attributes
-
- const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2)
-
- memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0]
- memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- username: {
- [PlatformType.TWITTER]: [member1Username],
- },
- displayName: member1Username,
- attributes: {
- [MemberAttributeName.SOURCE_ID]: {
- [PlatformType.DEVTO]: attributes2[MemberAttributeName.SOURCE_ID][PlatformType.DEVTO],
- [PlatformType.SLACK]: attributes2[MemberAttributeName.SOURCE_ID][PlatformType.SLACK],
- default: attributes2[MemberAttributeName.SOURCE_ID][PlatformType.DEVTO],
- },
- [MemberAttributeName.NAME]: {
- [PlatformType.DEVTO]: attributes2[MemberAttributeName.NAME][PlatformType.DEVTO],
- default: attributes2[MemberAttributeName.NAME][PlatformType.DEVTO],
- },
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]:
- attributes1[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB],
- default: attributes1[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB],
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: attributes1[MemberAttributeName.URL][PlatformType.GITHUB],
- [PlatformType.DEVTO]: attributes2[MemberAttributeName.URL][PlatformType.DEVTO],
- default: attributes1[MemberAttributeName.URL][PlatformType.GITHUB],
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]:
- attributes1[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB],
- default: attributes1[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB],
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: attributes1[MemberAttributeName.BIO][PlatformType.GITHUB],
- default: attributes1[MemberAttributeName.BIO][PlatformType.GITHUB],
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: attributes1[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- default: attributes1[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- },
- },
- emails: member1.emails,
- lastEnriched: null,
- organizations: [
- {
- displayName: 'l.com',
- id: memberCreated.organizations[0].id,
- memberOrganizations: {
- memberId: memberCreated.id,
- organizationId: memberCreated.organizations[0].id,
- dateEnd: null,
- dateStart: null,
- title: null,
- source: null,
- },
- },
- ],
- enrichedBy: [],
- contributions: null,
- score: member1.score,
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- reach: { total: -1 },
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberUpdated).toStrictEqual(memberExpected)
- })
-
- it('Should update existent member succesfully - reach from default to complete - sending number', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const member1 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- const member1Username = member1.username
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const member2 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- reach: 10,
- }
-
- const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2)
-
- memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0]
- memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- username: {
- [PlatformType.GITHUB]: [member1Username],
- },
- displayName: member1Username,
- lastEnriched: null,
- organizations: [],
- enrichedBy: [],
- contributions: null,
- reach: { total: 10, [PlatformType.GITHUB]: 10 },
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- score: -1,
- emails: [],
- attributes: {},
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberUpdated).toStrictEqual(memberExpected)
- })
-
- it('Should update existent member succesfully - reach from default to complete - sending platform', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const member1 = {
- username: 'anil',
- type: 'member',
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- const member1Username = member1.username
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const member2 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- reach: { [PlatformType.GITHUB]: 10 },
- }
-
- const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2)
-
- memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0]
- memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- username: {
- [PlatformType.GITHUB]: [member1Username],
- },
- lastEnriched: null,
- organizations: [],
- enrichedBy: [],
- contributions: null,
- displayName: member1Username,
- reach: { total: 10, [PlatformType.GITHUB]: 10 },
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- score: -1,
- emails: [],
- attributes: {},
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberUpdated).toStrictEqual(memberExpected)
- })
-
- it('Should update existent member succesfully - complex reach update from object', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const member1 = {
- username: 'anil',
- type: 'member',
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-28T15:13:30Z',
- reach: { [PlatformType.TWITTER]: 10, linkedin: 10, total: 20 },
- }
-
- const member1Username = member1.username
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const member2 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- reach: { [PlatformType.GITHUB]: 15, linkedin: 11 },
- }
-
- const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2)
-
- memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0]
- memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- username: {
- [PlatformType.GITHUB]: [member1Username],
- },
- lastEnriched: null,
- organizations: [],
- enrichedBy: [],
- contributions: null,
- displayName: member1Username,
- reach: { total: 36, [PlatformType.GITHUB]: 15, linkedin: 11, [PlatformType.TWITTER]: 10 },
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- score: -1,
- emails: [],
- attributes: {},
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberUpdated).toStrictEqual(memberExpected)
- })
-
- it('Should update existent member succesfully - complex reach update from number', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const member1 = {
- username: 'anil',
- type: 'member',
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-28T15:13:30Z',
- reach: { [PlatformType.TWITTER]: 10, linkedin: 10, total: 20 },
- }
-
- const member1Username = member1.username
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0]
- memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0]
-
- const member2 = {
- username: 'anil',
- platform: PlatformType.GITHUB,
- reach: 30,
- }
-
- const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2)
-
- memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0]
- memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0]
-
- const memberExpected = {
- id: memberCreated.id,
- joinedAt: new Date('2020-05-28T15:13:30Z'),
- username: {
- [PlatformType.GITHUB]: [member1Username],
- },
- displayName: member1Username,
- lastEnriched: null,
- organizations: [],
- enrichedBy: [],
- contributions: null,
- reach: { total: 50, [PlatformType.GITHUB]: 30, linkedin: 10, [PlatformType.TWITTER]: 10 },
- importHash: null,
- createdAt: SequelizeTestUtils.getNowWithoutTime(),
- updatedAt: SequelizeTestUtils.getNowWithoutTime(),
- deletedAt: null,
- tenantId: mockIServiceOptions.currentTenant.id,
- segments: mockIServiceOptions.currentSegments,
- createdById: mockIServiceOptions.currentUser.id,
- updatedById: mockIServiceOptions.currentUser.id,
- score: -1,
- emails: [],
- attributes: {},
- affiliations: [],
- manuallyCreated: false,
- }
-
- expect(memberUpdated).toStrictEqual(memberExpected)
- })
- })
-
- describe('update method', () => {
- it('Should update existent member succesfully - removing identities with simple string format', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const member1 = {
- username: 'anil',
- type: 'member',
- platform: PlatformType.GITHUB,
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- const toUpdate = {
- username: 'anil_new',
- platform: PlatformType.GITHUB,
- }
-
- const memberUpdated = await new MemberService(mockIServiceOptions).update(
- memberCreated.id,
- toUpdate,
- )
-
- expect(memberUpdated.username[PlatformType.GITHUB]).toStrictEqual(['anil_new'])
- })
-
- it('Should update existent member succesfully - removing identities with simple identity format', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'anil',
- },
- },
- platform: PlatformType.GITHUB,
- type: 'member',
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- const toUpdate = {
- username: {
- [PlatformType.GITHUB]: {
- username: 'anil_new',
- },
- },
- platform: PlatformType.GITHUB,
- }
-
- const memberUpdated = await new MemberService(mockIServiceOptions).update(
- memberCreated.id,
- toUpdate,
- )
-
- expect(memberUpdated.username[PlatformType.GITHUB]).toStrictEqual(['anil_new'])
- })
-
- it('Should update existent member succesfully - removing identities with array identity format', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: [
- {
- username: 'anil',
- },
- ],
- },
- platform: PlatformType.GITHUB,
- type: 'member',
- joinedAt: '2020-05-28T15:13:30Z',
- }
-
- const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1)
-
- const toUpdate = {
- username: {
- [PlatformType.GITHUB]: [
- {
- username: 'anil_new',
- },
- {
- username: 'anil_new2',
- },
- ],
- },
- platform: PlatformType.GITHUB,
- }
-
- const memberUpdated = await new MemberService(mockIServiceOptions).update(
- memberCreated.id,
- toUpdate,
- )
-
- expect(memberUpdated.username[PlatformType.GITHUB]).toStrictEqual(['anil_new', 'anil_new2'])
- })
- })
-
- describe('merge method', () => {
- it('Should catch when two members are the same', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const mas = new MemberAttributeSettingsService(mockIRepositoryOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const memberService = new MemberService(mockIRepositoryOptions)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: 'anil',
- },
- displayName: 'Anil',
- joinedAt: '2021-05-27T15:14:30Z',
- attributes: {},
- }
-
- const memberCreated = await MemberRepository.create(member1, mockIRepositoryOptions)
- const mergeOutput = await memberService.merge(memberCreated.id, memberCreated.id)
-
- expect(mergeOutput).toStrictEqual({ status: 203, mergedId: memberCreated.id })
-
- const found = await memberService.findById(memberCreated.id)
- expect(found).toStrictEqual(memberCreated)
- })
- })
-
- describe('addToNoMerge method', () => {
- it('Should add two members to their respective noMerges, these members should be excluded from toMerges respectively', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const mas = new MemberAttributeSettingsService(mockIRepositoryOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await mas.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
- await mas.createPredefined(DISCORD_MEMBER_ATTRIBUTES)
-
- const memberService = new MemberService(mockIRepositoryOptions)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: 'anil',
- },
- displayName: 'Anil',
- joinedAt: '2021-05-27T15:14:30Z',
- attributes: {},
- }
-
- const member2 = {
- username: {
- [PlatformType.DISCORD]: 'anil',
- },
- displayName: 'Anil',
- joinedAt: '2021-05-30T15:14:30Z',
- attributes: {
- [MemberAttributeName.SOURCE_ID]: {
- [PlatformType.DISCORD]: '#discordId',
- default: '#discordId',
- },
- },
- }
-
- const member3 = {
- username: {
- [PlatformType.TWITTER]: 'anil',
- },
- displayName: 'Anil',
- joinedAt: '2021-05-30T15:14:30Z',
- attributes: {
- [MemberAttributeName.URL]: {
- [PlatformType.TWITTER]: 'https://a-twitter-url',
- default: 'https://a-twitter-url',
- },
- },
- }
-
- let returnedMember1 = await MemberRepository.create(member1, mockIRepositoryOptions)
- let returnedMember2 = await MemberRepository.create(member2, mockIRepositoryOptions)
- let returnedMember3 = await MemberRepository.create(member3, mockIRepositoryOptions)
-
- // toMerge[1] = [(1,2),(1,3)] toMerge[2] = [(2,1),(2,3)] toMerge[3] = [(3,1),(3,2)]
- await MemberRepository.addToMerge(
- [{ members: [returnedMember1.id, returnedMember2.id], similarity: null }],
- mockIRepositoryOptions,
- )
- await MemberRepository.addToMerge(
- [{ members: [returnedMember2.id, returnedMember1.id], similarity: null }],
- mockIRepositoryOptions,
- )
-
- await MemberRepository.addToMerge(
- [{ members: [returnedMember1.id, returnedMember3.id], similarity: null }],
- mockIRepositoryOptions,
- )
- await MemberRepository.addToMerge(
- [{ members: [returnedMember3.id, returnedMember1.id], similarity: null }],
- mockIRepositoryOptions,
- )
- await MemberRepository.addToMerge(
- [{ members: [returnedMember2.id, returnedMember3.id], similarity: null }],
- mockIRepositoryOptions,
- )
- await MemberRepository.addToMerge(
- [{ members: [returnedMember3.id, returnedMember2.id], similarity: null }],
- mockIRepositoryOptions,
- )
-
- await memberService.addToNoMerge(returnedMember1.id, returnedMember2.id)
-
- returnedMember1 = await MemberRepository.findById(returnedMember1.id, mockIRepositoryOptions)
-
- expect(returnedMember1.toMerge).toStrictEqual([returnedMember3.id])
- expect(returnedMember1.noMerge).toStrictEqual([returnedMember2.id])
-
- returnedMember2 = await MemberRepository.findById(returnedMember2.id, mockIRepositoryOptions)
-
- expect(returnedMember2.toMerge).toStrictEqual([returnedMember3.id])
- expect(returnedMember2.noMerge).toStrictEqual([returnedMember1.id])
-
- // call addToNoMerge once more, between member1 and member3
- await memberService.addToNoMerge(returnedMember1.id, returnedMember3.id)
-
- returnedMember1 = await MemberRepository.findById(returnedMember1.id, mockIRepositoryOptions)
-
- expect(returnedMember1.toMerge).toStrictEqual([])
- expect(returnedMember1.noMerge).toStrictEqual([returnedMember2.id, returnedMember3.id])
-
- returnedMember3 = await MemberRepository.findById(returnedMember3.id, mockIRepositoryOptions)
-
- expect(returnedMember3.toMerge).toStrictEqual([returnedMember2.id])
- expect(returnedMember3.noMerge).toStrictEqual([returnedMember1.id])
-
- // only toMerge relation (2,3) left. Testing addToNoMerge(2,3)
- await memberService.addToNoMerge(returnedMember3.id, returnedMember2.id)
-
- returnedMember2 = await MemberRepository.findById(returnedMember2.id, mockIRepositoryOptions)
-
- expect(returnedMember2.toMerge).toStrictEqual([])
- expect(returnedMember2.noMerge).toStrictEqual([returnedMember1.id, returnedMember3.id])
-
- returnedMember3 = await MemberRepository.findById(returnedMember3.id, mockIRepositoryOptions)
-
- expect(returnedMember3.toMerge).toStrictEqual([])
- expect(returnedMember3.noMerge).toStrictEqual([returnedMember1.id, returnedMember2.id])
- })
-
- it('Should throw 404 not found when trying to add non existent members to noMerge', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const mas = new MemberAttributeSettingsService(mockIRepositoryOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const memberService = new MemberService(mockIRepositoryOptions)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: 'anil',
- },
- displayName: 'Anil',
- joinedAt: '2021-05-27T15:14:30Z',
- attributes: {},
- }
-
- const returnedMember1 = await MemberRepository.create(member1, mockIRepositoryOptions)
-
- const { randomUUID } = require('crypto')
-
- await expect(() =>
- memberService.addToNoMerge(returnedMember1.id, randomUUID()),
- ).rejects.toThrowError(new Error404())
- })
- })
-
- describe('memberExists method', () => {
- it('Should find existing member with string username and default platform', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const mas = new MemberAttributeSettingsService(mockIRepositoryOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const memberService = new MemberService(mockIRepositoryOptions)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: 'anil',
- },
- displayName: 'Anil',
- joinedAt: '2021-05-27T15:14:30Z',
- attributes: {},
- }
-
- const cloned = lodash.cloneDeep(member1)
- const returnedMember1 = await MemberRepository.create(cloned, mockIRepositoryOptions)
- delete returnedMember1.toMerge
- delete returnedMember1.noMerge
- delete returnedMember1.tags
- delete returnedMember1.activities
- delete returnedMember1.tasks
- delete returnedMember1.notes
- delete returnedMember1.activityCount
- delete returnedMember1.averageSentiment
- delete returnedMember1.lastActive
- delete returnedMember1.lastActivity
- delete returnedMember1.activeOn
- delete returnedMember1.identities
- delete returnedMember1.activityTypes
- delete returnedMember1.activeDaysCount
- delete returnedMember1.numberOfOpenSourceContributions
- delete returnedMember1.affiliations
- delete returnedMember1.manuallyCreated
-
- returnedMember1.segments = returnedMember1.segments.map((s) => s.id)
-
- const existing = await memberService.memberExists(
- member1.username[PlatformType.GITHUB],
- PlatformType.GITHUB,
- )
-
- expect(existing).toStrictEqual(returnedMember1)
- })
-
- it('Should return null if member is not found - string type', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const mas = new MemberAttributeSettingsService(mockIRepositoryOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const memberService = new MemberService(mockIRepositoryOptions)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: 'anil',
- },
- displayName: 'Anil',
- joinedAt: '2021-05-27T15:14:30Z',
- attributes: {},
- }
-
- await MemberRepository.create(member1, mockIRepositoryOptions)
-
- const existing = await memberService.memberExists('some-random-username', PlatformType.GITHUB)
-
- expect(existing).toBeNull()
- })
-
- it('Should return null if member is not found - object type', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const mas = new MemberAttributeSettingsService(mockIRepositoryOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const memberService = new MemberService(mockIRepositoryOptions)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: 'anil',
- },
- displayName: 'Anil',
- joinedAt: '2021-05-27T15:14:30Z',
- attributes: {},
- }
-
- await MemberRepository.create(member1, mockIRepositoryOptions)
-
- const existing = await memberService.memberExists(
- {
- ...member1.username,
- [PlatformType.SLACK]: 'some-slack-username',
- },
- PlatformType.SLACK,
- )
-
- expect(existing).toBeNull()
- })
-
- it('Should find existing member with object username and given platform', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const mas = new MemberAttributeSettingsService(mockIRepositoryOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const memberService = new MemberService(mockIRepositoryOptions)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: 'anil',
- [PlatformType.DISCORD]: 'some-other-username',
- },
- displayName: 'Anil',
- joinedAt: '2021-05-27T15:14:30Z',
- attributes: {},
- }
-
- const returnedMember1 = await MemberRepository.create(member1, mockIRepositoryOptions)
- delete returnedMember1.toMerge
- delete returnedMember1.noMerge
- delete returnedMember1.tags
- delete returnedMember1.activities
- delete returnedMember1.tasks
- delete returnedMember1.notes
- delete returnedMember1.activityCount
- delete returnedMember1.averageSentiment
- delete returnedMember1.lastActive
- delete returnedMember1.lastActivity
- delete returnedMember1.activeOn
- delete returnedMember1.identities
- delete returnedMember1.activityTypes
- delete returnedMember1.activeDaysCount
- delete returnedMember1.numberOfOpenSourceContributions
- delete returnedMember1.affiliations
- delete returnedMember1.manuallyCreated
-
- returnedMember1.segments = returnedMember1.segments.map((s) => s.id)
-
- const existing = await memberService.memberExists(
- { [PlatformType.DISCORD]: 'some-other-username' },
- PlatformType.DISCORD,
- )
-
- expect(returnedMember1).toStrictEqual(existing)
- })
-
- it('Should throw 400 error when username is type of object and username[platform] is not present ', async () => {
- const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db)
- const mas = new MemberAttributeSettingsService(mockIRepositoryOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const memberService = new MemberService(mockIRepositoryOptions)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: 'anil',
- [PlatformType.DISCORD]: 'some-other-username',
- },
- displayName: 'Anil',
- joinedAt: '2021-05-27T15:14:30Z',
- attributes: {},
- }
-
- await MemberRepository.create(member1, mockIRepositoryOptions)
-
- await expect(() =>
- memberService.memberExists(
- { [PlatformType.DISCORD]: 'some-other-username' },
- PlatformType.SLACK,
- ),
- ).rejects.toThrowError(new Error400())
- })
- })
-
- describe('Update Reach method', () => {
- it('Should keep as total: -1 for an empty new reach and a default old reach', async () => {
- const oldReach = { total: -1 }
- const updatedReach = MemberService.calculateReach({}, oldReach)
- expect(updatedReach).toStrictEqual({
- total: -1,
- })
- })
- it('Should keep as total: -1 for a default new reach and a default old reach', async () => {
- const oldReach = { total: -1 }
- const updatedReach = MemberService.calculateReach({ total: -1 }, oldReach)
- expect(updatedReach).toStrictEqual({
- total: -1,
- })
- })
- it('Should update for a new reach and a default old reach', async () => {
- const oldReach = { total: -1 }
- const newReach = { [PlatformType.TWITTER]: 10 }
- const updatedReach = MemberService.calculateReach(oldReach, newReach)
- expect(updatedReach).toStrictEqual({
- total: 10,
- [PlatformType.TWITTER]: 10,
- })
- })
- it('Should update for a new reach and old reach in the same platform', async () => {
- const oldReach = { [PlatformType.TWITTER]: 5, total: 5 }
- const newReach = { [PlatformType.TWITTER]: 10 }
- const updatedReach = MemberService.calculateReach(oldReach, newReach)
- expect(updatedReach).toStrictEqual({
- total: 10,
- [PlatformType.TWITTER]: 10,
- })
- })
- it('Should update for a complex reach with different platforms', async () => {
- const oldReach = {
- [PlatformType.TWITTER]: 10,
- [PlatformType.GITHUB]: 20,
- [PlatformType.DISCORD]: 50,
- total: 10 + 20 + 50,
- }
- const newReach = {
- [PlatformType.TWITTER]: 20,
- [PlatformType.GITHUB]: 2,
- linkedin: 10,
- total: 20 + 2 + 10,
- }
- const updatedReach = MemberService.calculateReach(oldReach, newReach)
- expect(updatedReach).toStrictEqual({
- total: 10 + 20 + 2 + 50,
- [PlatformType.TWITTER]: 20,
- [PlatformType.GITHUB]: 2,
- linkedin: 10,
- [PlatformType.DISCORD]: 50,
- })
- })
- it('Should work with reach 0', async () => {
- const oldReach = { total: -1 }
- const newReach = { [PlatformType.TWITTER]: 0 }
- const updatedReach = MemberService.calculateReach(oldReach, newReach)
- expect(updatedReach).toStrictEqual({
- total: 0,
- [PlatformType.TWITTER]: 0,
- })
- })
- })
-
- describe('getHighestPriorityPlatformForAttributes method', () => {
- it('Should return the highest priority platform from a priority array, handling the exceptions', async () => {
- const priorityArray = [
- PlatformType.TWITTER,
- PlatformType.CROWD,
- PlatformType.SLACK,
- PlatformType.DEVTO,
- PlatformType.DISCORD,
- PlatformType.GITHUB,
- ]
-
- let inputPlatforms = [PlatformType.GITHUB, PlatformType.DEVTO]
- let highestPriorityPlatform = MemberService.getHighestPriorityPlatformForAttributes(
- inputPlatforms,
- priorityArray,
- )
-
- expect(highestPriorityPlatform).toBe(PlatformType.DEVTO)
-
- inputPlatforms = [PlatformType.GITHUB, 'someOtherPlatform'] as any
- highestPriorityPlatform = MemberService.getHighestPriorityPlatformForAttributes(
- inputPlatforms,
- priorityArray,
- )
-
- expect(highestPriorityPlatform).toBe(PlatformType.GITHUB)
-
- inputPlatforms = ['somePlatform1', 'somePlatform2'] as any
-
- // if no match in the priority array, it should return the first platform it finds
- highestPriorityPlatform = MemberService.getHighestPriorityPlatformForAttributes(
- inputPlatforms,
- priorityArray,
- )
-
- expect(highestPriorityPlatform).toBe('somePlatform1')
-
- inputPlatforms = []
-
- // if no platforms are sent to choose from, it should return undefined
- highestPriorityPlatform = MemberService.getHighestPriorityPlatformForAttributes(
- inputPlatforms,
- priorityArray,
- )
- expect(highestPriorityPlatform).not.toBeDefined()
- })
- })
-
- describe('validateAttributes method', () => {
- it('Should validate attributes object succesfully', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const memberService = new MemberService(mockIServiceOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(DEVTO_MEMBER_ATTRIBUTES)
-
- const attributes = {
- [MemberAttributeName.NAME]: {
- [PlatformType.DEVTO]: 'Dweet Srute',
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://some-github-url',
- [PlatformType.TWITTER]: 'https://some-twitter-url',
- [PlatformType.DEVTO]: 'https://some-devto-url',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Berlin',
- [PlatformType.DEVTO]: 'Istanbul',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Assistant to the Regional Manager',
- [PlatformType.DEVTO]: 'Assistant Regional Manager',
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: 'https://some-image-url',
- },
- }
-
- const validateAttributes = await memberService.validateAttributes(attributes)
-
- expect(validateAttributes).toEqual(attributes)
- })
-
- it(`Should accept custom attributes without 'custom' platform key`, async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const memberService = new MemberService(mockIServiceOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
-
- const attributes = {
- [MemberAttributeName.BIO]: 'Assistant to the Regional Manager',
- }
-
- const validateAttributes = await memberService.validateAttributes(attributes)
-
- const expectedValidatedAttributes = {
- [MemberAttributeName.BIO]: {
- custom: 'Assistant to the Regional Manager',
- },
- }
-
- expect(validateAttributes).toEqual(expectedValidatedAttributes)
- })
-
- it(`Should accept custom attributes both without and with 'custom' platform key`, async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const memberService = new MemberService(mockIServiceOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(DEVTO_MEMBER_ATTRIBUTES)
-
- const attributes = {
- [MemberAttributeName.NAME]: 'Dwight Schrute',
- [MemberAttributeName.URL]: 'https://some-url',
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Berlin',
- [PlatformType.DEVTO]: 'Istanbul',
- custom: 'a custom location',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Assistant to the Regional Manager',
- [PlatformType.DEVTO]: 'Assistant Regional Manager',
- custom: 'a custom bio',
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: 'https://some-image-url',
- custom: 'a custom image url',
- },
- }
-
- const validateAttributes = await memberService.validateAttributes(attributes)
-
- const expectedValidatedAttributes = {
- [MemberAttributeName.NAME]: {
- custom: 'Dwight Schrute',
- },
- [MemberAttributeName.URL]: {
- custom: 'https://some-url',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Berlin',
- [PlatformType.DEVTO]: 'Istanbul',
- custom: 'a custom location',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Assistant to the Regional Manager',
- [PlatformType.DEVTO]: 'Assistant Regional Manager',
- custom: 'a custom bio',
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: 'https://some-image-url',
- custom: 'a custom image url',
- },
- }
-
- expect(validateAttributes).toEqual(expectedValidatedAttributes)
- })
-
- it('Should throw a 400 Error when an attribute does not exist in member attribute settings', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const memberService = new MemberService(mockIServiceOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
-
- // in settings name has a string type, inserting an integer should throw an error
- const attributes = {
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://some-github-url',
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: 'https://some-image-url',
- },
- 'non-existing-attribute': {
- [PlatformType.TWITTER]: 'some value',
- },
- }
- const validateAttributes = await memberService.validateAttributes(attributes)
-
- // member attribute that is non existing in settings, should be omitted after validate
- const expectedValidatedAttributes = {
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://some-github-url',
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: 'https://some-image-url',
- },
- }
- expect(validateAttributes).toEqual(expectedValidatedAttributes)
- })
-
- it('Should throw a 400 Error when the type of an attribute does not match the type in member attribute settings', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const memberService = new MemberService(mockIServiceOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
-
- // in settings website_url has a url type, inserting an integer should throw an error
- const attributes = {
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 55,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://some-github-url',
- [PlatformType.TWITTER]: 'https://some-twitter-url',
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: 'https://some-image-url',
- },
- }
-
- await expect(() => memberService.validateAttributes(attributes)).rejects.toThrowError(
- new Error400('en', 'settings.memberAttributes.wrongType'),
- )
- })
- })
- describe('setAttributesDefaultValues method', () => {
- it('Should return the structured attributes object with default values succesfully', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const memberService = new MemberService(mockIServiceOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(DEVTO_MEMBER_ATTRIBUTES)
-
- const attributes = {
- [MemberAttributeName.NAME]: {
- [PlatformType.DEVTO]: 'Dweet Srute',
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://some-github-url',
- [PlatformType.TWITTER]: 'https://some-twitter-url',
- [PlatformType.DEVTO]: 'https://some-devto-url',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Berlin',
- [PlatformType.DEVTO]: 'Istanbul',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Assistant to the Regional Manager',
- [PlatformType.DEVTO]: 'Assistant Regional Manager',
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: 'https://some-image-url',
- },
- }
-
- const attributesWithDefaultValues = await memberService.setAttributesDefaultValues(attributes)
-
- // Default platform priority is: custom, twitter, github, devto, slack, discord, crowd
- const expectedAttributesWithDefaultValues = {
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.URL][PlatformType.GITHUB],
- [PlatformType.TWITTER]: attributes[MemberAttributeName.URL][PlatformType.TWITTER],
- [PlatformType.DEVTO]: attributes[MemberAttributeName.URL][PlatformType.DEVTO],
- default: attributes[MemberAttributeName.URL][PlatformType.TWITTER],
- },
- [MemberAttributeName.NAME]: {
- [PlatformType.DEVTO]: attributes[MemberAttributeName.NAME][PlatformType.DEVTO],
- default: attributes[MemberAttributeName.NAME][PlatformType.DEVTO],
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: attributes[MemberAttributeName.AVATAR_URL][PlatformType.TWITTER],
- default: attributes[MemberAttributeName.AVATAR_URL][PlatformType.TWITTER],
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.BIO][PlatformType.GITHUB],
- [PlatformType.DEVTO]: attributes[MemberAttributeName.BIO][PlatformType.DEVTO],
- default: attributes[MemberAttributeName.BIO][PlatformType.GITHUB],
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- [PlatformType.DEVTO]: attributes[MemberAttributeName.LOCATION][PlatformType.DEVTO],
- default: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB],
- },
- }
-
- expect(attributesWithDefaultValues).toEqual(expectedAttributesWithDefaultValues)
- })
-
- it('Should throw a 400 Error when priority array does not exist', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const memberService = new MemberService(mockIServiceOptions)
- const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
- await memberAttributeSettingsService.createPredefined(DEVTO_MEMBER_ATTRIBUTES)
-
- // Empty default priority array
- const settings = await SettingsRepository.findOrCreateDefault({}, mockIServiceOptions)
-
- await SettingsRepository.save(
- { ...settings, attributeSettings: { priorities: [] } },
- mockIServiceOptions,
- )
- const attributes = {
- [MemberAttributeName.NAME]: {
- [PlatformType.DEVTO]: 'Dweet Srute',
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://some-github-url',
- [PlatformType.TWITTER]: 'https://some-twitter-url',
- [PlatformType.DEVTO]: 'https://some-devto-url',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Berlin',
- [PlatformType.DEVTO]: 'Istanbul',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Assistant to the Regional Manager',
- [PlatformType.DEVTO]: 'Assistant Regional Manager',
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: 'https://some-image-url',
- },
- }
-
- await expect(() => memberService.setAttributesDefaultValues(attributes)).rejects.toThrowError(
- new Error400('en', 'settings.memberAttributes.priorityArrayNotFound'),
- )
- })
- })
-
- describe('findAndCountAll method', () => {
- it('Should filter and sort by dynamic attributes using advanced filters successfully', async () => {
- const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db)
-
- const ms = new MemberService(mockIServiceOptions)
-
- const mas = new MemberAttributeSettingsService(mockIServiceOptions)
-
- await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES)
- await mas.createPredefined(TWITTER_MEMBER_ATTRIBUTES)
- await mas.createPredefined(DISCORD_MEMBER_ATTRIBUTES)
-
- const attribute1 = {
- name: 'aNumberAttribute',
- label: 'A number Attribute',
- type: MemberAttributeType.NUMBER,
- canDelete: true,
- show: true,
- }
-
- const attribute2 = {
- name: 'aDateAttribute',
- label: 'A date Attribute',
- type: MemberAttributeType.DATE,
- canDelete: true,
- show: true,
- }
-
- const attribute3 = {
- name: 'aMultiSelectAttribute',
- label: 'A multi select Attribute',
- options: ['a', 'b', 'c'],
- type: MemberAttributeType.MULTI_SELECT,
- canDelete: true,
- show: true,
- }
-
- await mas.create(attribute1)
- await mas.create(attribute2)
- await mas.create(attribute3)
-
- const member1 = {
- username: {
- [PlatformType.GITHUB]: 'anil',
- [PlatformType.DISCORD]: 'anil',
- [PlatformType.TWITTER]: 'anil',
- },
- platform: PlatformType.GITHUB,
- emails: ['lala@l.com'],
- score: 10,
- attributes: {
- aDateAttribute: {
- custom: '2022-08-01T00:00:00',
- },
- aMultiSelectAttribute: {
- custom: ['a', 'b'],
- github: ['a'],
- },
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: false,
- [PlatformType.DISCORD]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/anil',
- [PlatformType.TWITTER]: 'https://twitter.com/anil',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://imcvampire.js.org/',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Lazy geek',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Helsinki, Finland',
- },
- [MemberAttributeName.SOURCE_ID]: {
- [PlatformType.TWITTER]: '#twitterId2',
- [PlatformType.DISCORD]: '#discordId1',
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: 'https://twitter.com/anil/image',
- },
- aNumberAttribute: {
- [PlatformType.GITHUB]: 1,
- [PlatformType.TWITTER]: 2,
- [PlatformType.DISCORD]: 300000,
- },
- },
- contributions: [
- {
- id: 112529473,
- url: 'https://github.com/bighead/silicon-valley',
- topics: ['TV Shows', 'Comedy', 'Startups'],
- summary: 'Silicon Valley: 50 commits in 2 weeks',
- numberCommits: 50,
- lastCommitDate: '02/01/2023',
- firstCommitDate: '01/17/2023',
- },
- {
- id: 112529474,
- url: 'https://github.com/bighead/startup-ideas',
- topics: ['Ideas', 'Startups'],
- summary: 'Startup Ideas: 20 commits in 1 week',
- numberCommits: 20,
- lastCommitDate: '03/01/2023',
- firstCommitDate: '02/22/2023',
- },
- ],
- joinedAt: '2022-05-28T15:13:30',
- }
-
- const member2 = {
- username: {
- [PlatformType.GITHUB]: 'michaelScott',
- [PlatformType.DISCORD]: 'michaelScott',
- [PlatformType.TWITTER]: 'michaelScott',
- },
- platform: PlatformType.GITHUB,
- emails: ['michael@mifflin.com'],
- score: 10,
- attributes: {
- aDateAttribute: {
- custom: '2022-08-06T00:00:00',
- },
- aMultiSelectAttribute: {
- custom: ['b', 'c'],
- github: ['b'],
- },
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: true,
- [PlatformType.DISCORD]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/michael-scott',
- [PlatformType.TWITTER]: 'https://twitter.com/michael',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://website/michael',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Dunder & Mifflin Regional Manager',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Berlin',
- },
- [MemberAttributeName.SOURCE_ID]: {
- [PlatformType.TWITTER]: '#twitterId2',
- [PlatformType.DISCORD]: '#discordId2',
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: 'https://twitter.com/michael/image',
- },
- aNumberAttribute: {
- [PlatformType.GITHUB]: 1500,
- [PlatformType.TWITTER]: 2500,
- [PlatformType.DISCORD]: 2,
- },
- },
- contributions: [
- {
- id: 112529472,
- url: 'https://github.com/bachman/pied-piper',
- topics: ['compression', 'data', 'middle-out', 'Java'],
- summary: 'Pied Piper: 10 commits in 1 day',
- numberCommits: 10,
- lastCommitDate: '2023-03-10',
- firstCommitDate: '2023-03-01',
- },
- {
- id: 112529473,
- url: 'https://github.com/bachman/aviato',
- topics: ['Python', 'Django'],
- summary: 'Aviato: 5 commits in 1 day',
- numberCommits: 5,
- lastCommitDate: '2023-02-25',
- firstCommitDate: '2023-02-20',
- },
- {
- id: 112529476,
- url: 'https://github.com/bachman/erlichbot',
- topics: ['Python', 'Slack API'],
- summary: 'ErlichBot: 2 commits in 1 day',
- numberCommits: 2,
- lastCommitDate: '2023-01-25',
- firstCommitDate: '2023-01-24',
- },
- ],
- joinedAt: '2022-09-15T15:13:30',
- }
-
- const member3 = {
- username: {
- [PlatformType.GITHUB]: 'jimHalpert',
- [PlatformType.DISCORD]: 'jimHalpert',
- [PlatformType.TWITTER]: 'jimHalpert',
- },
- platform: PlatformType.GITHUB,
- emails: ['jim@mifflin.com'],
- score: 10,
- attributes: {
- aDateAttribute: {
- custom: '2022-08-15T00:00:00',
- },
- aMultiSelectAttribute: {
- custom: ['a', 'c'],
- github: ['c'],
- },
- [MemberAttributeName.IS_HIREABLE]: {
- [PlatformType.GITHUB]: false,
- [PlatformType.DISCORD]: true,
- },
- [MemberAttributeName.URL]: {
- [PlatformType.GITHUB]: 'https://github.com/jim-halpert',
- [PlatformType.TWITTER]: 'https://twitter.com/jim',
- },
- [MemberAttributeName.WEBSITE_URL]: {
- [PlatformType.GITHUB]: 'https://website/jim',
- },
- [MemberAttributeName.BIO]: {
- [PlatformType.GITHUB]: 'Sales guy',
- },
- [MemberAttributeName.LOCATION]: {
- [PlatformType.GITHUB]: 'Scranton',
- },
- [MemberAttributeName.SOURCE_ID]: {
- [PlatformType.TWITTER]: '#twitterId3',
- [PlatformType.DISCORD]: '#discordId3',
- },
- [MemberAttributeName.AVATAR_URL]: {
- [PlatformType.TWITTER]: 'https://twitter.com/jim/image',
- },
- aNumberAttribute: {
- [PlatformType.GITHUB]: 15500,
- [PlatformType.TWITTER]: 25500,
- [PlatformType.DISCORD]: 200000,
- },
- },
- joinedAt: '2022-09-16T15:13:30Z',
- }
-
- const member1Created = await ms.upsert(member1)
- const member2Created = await ms.upsert(member2)
- const member3Created = await ms.upsert(member3)
-
- await SequelizeTestUtils.refreshMaterializedViews(db)
-
- // filter and sort by aNumberAttribute default values
- let members = await ms.findAndCountAll({
- advancedFilter: {
- aNumberAttribute: {
- gte: 1000,
- },
- },
- orderBy: 'aNumberAttribute_DESC',
- })
-
- expect(members.count).toBe(2)
- expect(members.rows.map((i) => i.id)).toStrictEqual([member3Created.id, member2Created.id])
-
- // filter and sort by aNumberAttribute platform specific values
- members = await ms.findAndCountAll({
- advancedFilter: {
- 'attributes.aNumberAttribute.discord': {
- gte: 100000,
- },
- },
- orderBy: 'attributes.aNumberAttribute.discord_DESC',
- })
-
- expect(members.count).toBe(2)
- expect(members.rows.map((i) => i.id)).toStrictEqual([member1Created.id, member3Created.id])
-
- // filter by isHireable default values
- members = await ms.findAndCountAll({
- advancedFilter: {
- isHireable: true,
- },
- })
-
- expect(members.count).toBe(1)
- expect(members.rows.map((i) => i.id)).toStrictEqual([member2Created.id])
-
- // filter by isHireable platform specific values
- members = await ms.findAndCountAll({
- advancedFilter: {
- 'attributes.isHireable.discord': true,
- },
- })
-
- expect(members.count).toBe(3)
- expect(members.rows.map((i) => i.id)).toStrictEqual([
- member3Created.id,
- member2Created.id,
- member1Created.id,
- ])
-
- // filter and sort by url default values
- members = await ms.findAndCountAll({
- advancedFilter: {
- url: {
- textContains: 'jim',
- },
- },
- orderBy: 'url_DESC',
- })
-
- expect(members.count).toBe(1)
- expect(members.rows.map((i) => i.id)).toStrictEqual([member3Created.id])
-
- // filter and sort by url platform specific values
- members = await ms.findAndCountAll({
- advancedFilter: {
- 'attributes.url.github': {
- textContains: 'github',
- },
- },
- orderBy: 'attributes.url.github_ASC',
- })
-
- expect(members.count).toBe(3)
-
- // results will be sorted by github.url anil -> jim -> michael
- expect(members.rows.map((i) => i.id)).toStrictEqual([
- member1Created.id,
- member3Created.id,
- member2Created.id,
- ])
-
- // filter and sort by custom aDateAttribute
- members = await ms.findAndCountAll({
- advancedFilter: {
- aDateAttribute: {
- lte: '2022-08-06T00:00:00',
- },
- },
- orderBy: 'aDateAttribute_DESC',
- })
-
- expect(members.count).toBe(2)
- expect(members.rows.map((i) => i.id)).toStrictEqual([member2Created.id, member1Created.id])
-
- // filter by custom aMultiSelectAttribute
- members = await ms.findAndCountAll({
- advancedFilter: {
- aMultiSelectAttribute: {
- overlap: ['a'],
- },
- },
- orderBy: 'createdAt_DESC',
- })
- expect(members.count).toBe(2)
- expect(members.rows.map((i) => i.id)).toStrictEqual([member3Created.id, member1Created.id])
-
- // filter by numberOfOpenSourceContributions
- members = await ms.findAndCountAll({
- filter: {
- numberOfOpenSourceContributionsRange: [2, 6],
- },
- })
- expect(members.count).toBe(2)
- expect(members.rows.map((i) => i.id)).toEqual([member2Created.id, member1Created.id])
-
- // filter by numberOfOpenSourceContributions only start
- members = await ms.findAndCountAll({
- filter: {
- numberOfOpenSourceContributionsRange: [3],
- },
- })
- expect(members.count).toBe(1)
- expect(members.rows.map((i) => i.id)).toStrictEqual([member2Created.id])
-
- // filter and sort by numberOfOpenSourceContributions
- members = await ms.findAndCountAll({
- filter: {
- numberOfOpenSourceContributionsRange: [2, 6],
- },
- orderBy: 'numberOfOpenSourceContributions_ASC',
- })
- expect(members.count).toBe(2)
- expect(members.rows.map((i) => i.id)).toStrictEqual([member1Created.id, member2Created.id])
-
- // sort by numberOfOpenSourceContributions
- members = await ms.findAndCountAll({
- orderBy: 'numberOfOpenSourceContributions_ASC',
- })
- expect(members.count).toBe(3)
- expect(members.rows.map((i) => i.id)).toStrictEqual([
- member3Created.id,
- member1Created.id,
- member2Created.id,
- ])
- })
- })
-})
diff --git a/backend/src/services/memberAffiliationService.ts b/backend/src/services/memberAffiliationService.ts
index 28f29b5127..e41484e924 100644
--- a/backend/src/services/memberAffiliationService.ts
+++ b/backend/src/services/memberAffiliationService.ts
@@ -1,8 +1,9 @@
import { LoggerBase } from '@crowd/logging'
+import { TemporalWorkflowId } from '@crowd/types'
+import { WorkflowIdReusePolicy } from '@crowd/temporal'
import { IServiceOptions } from './IServiceOptions'
import MemberSegmentAffiliationRepository from '../database/repositories/memberSegmentAffiliationRepository'
import MemberRepository from '../database/repositories/memberRepository'
-import MemberAffiliationRepository from '../database/repositories/memberAffiliationRepository'
export default class MemberAffiliationService extends LoggerBase {
options: IServiceOptions
@@ -53,6 +54,23 @@ export default class MemberAffiliationService extends LoggerBase {
}
async updateAffiliation(memberId: string) {
- await MemberAffiliationRepository.update(memberId, this.options)
+ await this.options.temporal.workflow.start('memberUpdate', {
+ taskQueue: 'profiles',
+ workflowId: `${TemporalWorkflowId.MEMBER_UPDATE}/${this.options.currentTenant.id}/${memberId}`,
+ workflowIdReusePolicy: WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_TERMINATE_IF_RUNNING,
+ retry: {
+ maximumAttempts: 10,
+ },
+ args: [
+ {
+ member: {
+ id: memberId,
+ },
+ },
+ ],
+ searchAttributes: {
+ TenantId: [this.options.currentTenant.id],
+ },
+ })
}
}
diff --git a/backend/src/services/memberService.ts b/backend/src/services/memberService.ts
index 615a056620..09b7ce508d 100644
--- a/backend/src/services/memberService.ts
+++ b/backend/src/services/memberService.ts
@@ -1000,6 +1000,24 @@ export default class MemberService extends LoggerBase {
const record = await MemberRepository.update(id, data, repoOptions)
await SequelizeRepository.commitTransaction(transaction)
+ await this.options.temporal.workflow.start('memberUpdate', {
+ taskQueue: 'profiles',
+ workflowId: `${TemporalWorkflowId.MEMBER_UPDATE}/${this.options.currentTenant.id}/${id}`,
+ workflowIdReusePolicy: WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_TERMINATE_IF_RUNNING,
+ retry: {
+ maximumAttempts: 10,
+ },
+ args: [
+ {
+ member: {
+ id,
+ },
+ },
+ ],
+ searchAttributes: {
+ TenantId: [this.options.currentTenant.id],
+ },
+ })
if (syncToOpensearch) {
try {
diff --git a/backend/src/services/premium/enrichment/memberEnrichmentService.ts b/backend/src/services/premium/enrichment/memberEnrichmentService.ts
index d59af509be..62f6e2a7b9 100644
--- a/backend/src/services/premium/enrichment/memberEnrichmentService.ts
+++ b/backend/src/services/premium/enrichment/memberEnrichmentService.ts
@@ -14,6 +14,7 @@ import {
OrganizationSource,
SyncMode,
IOrganizationIdentity,
+ TemporalWorkflowId,
} from '@crowd/types'
import {
EnrichmentAPICertification,
@@ -24,6 +25,7 @@ import {
EnrichmentAPISkills,
EnrichmentAPIWorkExperience,
} from '@crowd/types/premium'
+import { WorkflowIdReusePolicy } from '@crowd/temporal'
import { ENRICHMENT_CONFIG, REDIS_CONFIG } from '../../../conf'
import { AttributeData } from '../../../database/attributes/attribute'
import MemberEnrichmentCacheRepository from '../../../database/repositories/memberEnrichmentCacheRepository'
@@ -389,6 +391,28 @@ export default class MemberEnrichmentService extends LoggerBase {
}
await SequelizeRepository.commitTransaction(transaction)
+ if (enrichmentData.work_experiences) {
+ await this.options.temporal.workflow.start('memberUpdate', {
+ taskQueue: 'profiles',
+ workflowId: `${TemporalWorkflowId.MEMBER_UPDATE}/${this.options.currentTenant.id}/${result.id}`,
+ workflowIdReusePolicy:
+ WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_TERMINATE_IF_RUNNING,
+ retry: {
+ maximumAttempts: 10,
+ },
+ args: [
+ {
+ member: {
+ id: result.id,
+ },
+ },
+ ],
+ searchAttributes: {
+ TenantId: [this.options.currentTenant.id],
+ },
+ })
+ }
+
await searchSyncService.triggerMemberSync(this.options.currentTenant.id, result.id)
result = await MemberRepository.findByIdOpensearch(result.id, this.options)
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6b296b28a4..e0f56fac4b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1217,6 +1217,58 @@ importers:
specifier: ^3.0.3
version: 3.1.0
+ services/apps/profiles_worker:
+ dependencies:
+ '@crowd/archetype-standard':
+ specifier: file:../../archetypes/standard
+ version: file:services/archetypes/standard(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2)
+ '@crowd/archetype-worker':
+ specifier: file:../../archetypes/worker
+ version: file:services/archetypes/worker(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2)
+ '@crowd/types':
+ specifier: file:../../libs/types
+ version: file:services/libs/types
+ '@temporalio/workflow':
+ specifier: ~1.8.6
+ version: 1.8.6
+ ts-node:
+ specifier: ^10.9.1
+ version: 10.9.1(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2)
+ tsconfig-paths:
+ specifier: ^4.2.0
+ version: 4.2.0
+ typescript:
+ specifier: ^5.2.2
+ version: 5.3.2
+ devDependencies:
+ '@types/node':
+ specifier: ^20.8.2
+ version: 20.10.1
+ '@types/uuid':
+ specifier: ~9.0.6
+ version: 9.0.7
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^6.7.4
+ version: 6.13.1(@typescript-eslint/parser@6.13.1)(eslint@8.54.0)(typescript@5.3.2)
+ '@typescript-eslint/parser':
+ specifier: ^6.7.4
+ version: 6.13.1(eslint@8.54.0)(typescript@5.3.2)
+ eslint:
+ specifier: ^8.50.0
+ version: 8.54.0
+ eslint-config-prettier:
+ specifier: ^9.0.0
+ version: 9.0.0(eslint@8.54.0)
+ eslint-plugin-prettier:
+ specifier: ^5.0.0
+ version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.54.0)(prettier@3.1.0)
+ nodemon:
+ specifier: ^3.0.1
+ version: 3.0.1
+ prettier:
+ specifier: ^3.0.3
+ version: 3.1.0
+
services/apps/search_sync_api:
dependencies:
'@crowd/common':
diff --git a/scripts/builders/profiles-worker.sh b/scripts/builders/profiles-worker.sh
new file mode 100644
index 0000000000..83688bf071
--- /dev/null
+++ b/scripts/builders/profiles-worker.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+DOCKERFILE="./services/docker/Dockerfile.profiles_worker"
+CONTEXT="../"
+REPO="crowddotdev/profiles-worker"
\ No newline at end of file
diff --git a/scripts/services/docker/Dockerfile.profiles_worker b/scripts/services/docker/Dockerfile.profiles_worker
new file mode 100644
index 0000000000..ddcf8631f4
--- /dev/null
+++ b/scripts/services/docker/Dockerfile.profiles_worker
@@ -0,0 +1,18 @@
+FROM node:16-alpine as builder
+
+WORKDIR /usr/crowd/app
+RUN corepack enable && apk add --update --no-cache python3 build-base && ln -sf python3 /usr/bin/python && python3 -m ensurepip && pip3 install --no-cache --upgrade pip setuptools
+
+COPY ./pnpm-workspace.yaml ./pnpm-lock.yaml ./
+COPY ./services ./services
+RUN pnpm i --frozen-lockfile
+
+FROM node:16-bookworm-slim as runner
+
+WORKDIR /usr/crowd/app
+RUN corepack enable && apt update && apt install -y ca-certificates --no-install-recommends && rm -rf /var/lib/apt/lists/*
+
+COPY --from=builder /usr/crowd/app/node_modules ./node_modules
+COPY --from=builder /usr/crowd/app/services/libs ./services/libs
+COPY --from=builder /usr/crowd/app/services/archetypes/ ./services/archetypes
+COPY --from=builder /usr/crowd/app/services/apps/profiles_worker/ ./services/apps/profiles_worker
diff --git a/scripts/services/profiles-worker.yaml b/scripts/services/profiles-worker.yaml
new file mode 100644
index 0000000000..8410b1aec5
--- /dev/null
+++ b/scripts/services/profiles-worker.yaml
@@ -0,0 +1,64 @@
+version: '3.1'
+
+x-env-args: &env-args
+ DOCKER_BUILDKIT: 1
+ NODE_ENV: docker
+ SERVICE: profiles-worker
+ CROWD_TEMPORAL_TASKQUEUE: profiles
+ SHELL: /bin/sh
+
+services:
+ profiles-worker:
+ build:
+ context: ../../
+ dockerfile: ./scripts/services/docker/Dockerfile.profiles_worker
+ command: 'pnpm run start'
+ working_dir: /usr/crowd/app/services/apps/profiles_worker
+ env_file:
+ - ../../backend/.env.dist.local
+ - ../../backend/.env.dist.composed
+ - ../../backend/.env.override.local
+ - ../../backend/.env.override.composed
+ environment:
+ <<: *env-args
+ restart: always
+ networks:
+ - crowd-bridge
+
+ profiles-worker-dev:
+ build:
+ context: ../../
+ dockerfile: ./scripts/services/docker/Dockerfile.profiles_worker
+ command: 'pnpm run dev'
+ working_dir: /usr/crowd/app/services/apps/profiles_worker
+ # user: '${USER_ID}:${GROUP_ID}'
+ env_file:
+ - ../../backend/.env.dist.local
+ - ../../backend/.env.dist.composed
+ - ../../backend/.env.override.local
+ - ../../backend/.env.override.composed
+ environment:
+ <<: *env-args
+ hostname: profiles-worker
+ networks:
+ - crowd-bridge
+ volumes:
+ - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src
+ - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src
+ - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src
+ - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src
+ - ../../services/libs/cubejs/src:/usr/crowd/app/services/libs/cubejs/src
+ - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src
+ - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src
+ - ../../services/libs/ioc/src:/usr/crowd/app/services/libs/ioc/src
+ - ../../services/libs/logging/src:/usr/crowd/app/services/libs/logging/src
+ - ../../services/libs/opensearch/src:/usr/crowd/app/services/libs/opensearch/src
+ - ../../services/libs/redis/src:/usr/crowd/app/services/libs/redis/src
+ - ../../services/libs/sentiment/src:/usr/crowd/app/services/libs/sentiment/src
+ - ../../services/libs/sqs/src:/usr/crowd/app/services/libs/sqs/src
+ - ../../services/libs/types/src:/usr/crowd/app/services/libs/types/src
+ - ../../services/apps/profiles_worker/src:/usr/crowd/app/services/apps/profiles_worker/src
+
+networks:
+ crowd-bridge:
+ external: true
diff --git a/services/apps/profiles_worker/.eslintrc.cjs b/services/apps/profiles_worker/.eslintrc.cjs
new file mode 100644
index 0000000000..25ba4e0d66
--- /dev/null
+++ b/services/apps/profiles_worker/.eslintrc.cjs
@@ -0,0 +1,21 @@
+module.exports = {
+ parser: '@typescript-eslint/parser',
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:prettier/recommended',
+ ],
+ plugins: ['@typescript-eslint', 'prettier'],
+ parserOptions: {
+ ecmaVersion: 2022,
+ sourceType: 'module',
+ },
+ env: {
+ es6: true,
+ node: true,
+ },
+ rules: {
+ 'prettier/prettier': 'error',
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
+ },
+}
diff --git a/services/apps/profiles_worker/.prettierignore b/services/apps/profiles_worker/.prettierignore
new file mode 100644
index 0000000000..2b24877309
--- /dev/null
+++ b/services/apps/profiles_worker/.prettierignore
@@ -0,0 +1,3 @@
+dist/
+.eslintrc.cjs
+.prettierrc.cjs
diff --git a/services/apps/profiles_worker/.prettierrc.cjs b/services/apps/profiles_worker/.prettierrc.cjs
new file mode 100644
index 0000000000..a8ca459839
--- /dev/null
+++ b/services/apps/profiles_worker/.prettierrc.cjs
@@ -0,0 +1,7 @@
+module.exports = {
+ singleQuote: true,
+ arrowParens: 'always',
+ printWidth: 100,
+ trailingComma: 'all',
+ semi: false,
+}
diff --git a/services/apps/profiles_worker/package.json b/services/apps/profiles_worker/package.json
new file mode 100644
index 0000000000..f28772b071
--- /dev/null
+++ b/services/apps/profiles_worker/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "@crowd/profiles-worker",
+ "version": "1.0.0",
+ "private": true,
+ "scripts": {
+ "start": "CROWD_TEMPORAL_TASKQUEUE=profiles SERVICE=profiles-worker TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/main.ts",
+ "start:debug:local": "set -a && . ../../../backend/.env.dist.local && . ../../../backend/.env.override.local && set +a && CROWD_TEMPORAL_TASKQUEUE=profiles SERVICE=profiles-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts",
+ "start:debug": "CROWD_TEMPORAL_TASKQUEUE=profiles SERVICE=profiles-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts",
+ "dev:local": "./node_modules/.bin/nodemon --watch src --watch ../../libs --ext ts --exec pnpm run start:debug:local",
+ "dev": "./node_modules/.bin/nodemon --watch src --watch ../../libs --ext ts --exec pnpm run start:debug",
+ "lint": "./node_modules/.bin/eslint --ext .ts src --max-warnings=0",
+ "format": "./node_modules/.bin/prettier --write \"src/**/*.ts\"",
+ "format-check": "./node_modules/.bin/prettier --check .",
+ "tsc-check": "./node_modules/.bin/tsc --noEmit"
+ },
+ "dependencies": {
+ "@crowd/archetype-standard": "file:../../archetypes/standard",
+ "@crowd/archetype-worker": "file:../../archetypes/worker",
+ "@crowd/types": "file:../../libs/types",
+ "@temporalio/workflow": "~1.8.6",
+ "ts-node": "^10.9.1",
+ "tsconfig-paths": "^4.2.0",
+ "typescript": "^5.2.2"
+ },
+ "devDependencies": {
+ "@types/node": "^20.8.2",
+ "@types/uuid": "~9.0.6",
+ "@typescript-eslint/eslint-plugin": "^6.7.4",
+ "@typescript-eslint/parser": "^6.7.4",
+ "eslint": "^8.50.0",
+ "eslint-config-prettier": "^9.0.0",
+ "eslint-plugin-prettier": "^5.0.0",
+ "nodemon": "^3.0.1",
+ "prettier": "^3.0.3"
+ }
+}
diff --git a/services/apps/profiles_worker/src/activities.ts b/services/apps/profiles_worker/src/activities.ts
new file mode 100644
index 0000000000..be231964e8
--- /dev/null
+++ b/services/apps/profiles_worker/src/activities.ts
@@ -0,0 +1,3 @@
+import { updateMemberAffiliations } from './activities/member/memberUpdate'
+
+export { updateMemberAffiliations }
diff --git a/services/apps/profiles_worker/src/activities/member/memberUpdate.ts b/services/apps/profiles_worker/src/activities/member/memberUpdate.ts
new file mode 100644
index 0000000000..a9cf0aba47
--- /dev/null
+++ b/services/apps/profiles_worker/src/activities/member/memberUpdate.ts
@@ -0,0 +1,57 @@
+import { svc } from '../../main'
+import { MemberWithIDOnly } from '../../types/member'
+
+/*
+updateMemberAffiliations is a Temporal activity that updates all affiliations for
+a given member.
+*/
+export async function updateMemberAffiliations(input: MemberWithIDOnly): Promise {
+ try {
+ await svc.postgres.writer.connection().query(
+ `WITH new_activities_organizations AS (
+ SELECT
+ a.id,
+
+ -- this 000000 magic is to differentiate between nothing to LEFT JOIN with and real individial affiliation
+ -- we want to keep NULL in 'organizationId' if there is an affiliation configured,
+ -- but if there is no manual affiliation, we know this by 'msa.id' being NULL, and then using 000000 as a marker,
+ -- which we remove afterwards
+ (ARRAY_REMOVE(ARRAY_AGG(CASE WHEN msa.id IS NULL THEN '00000000-0000-0000-0000-000000000000' ELSE msa."organizationId" END), '00000000-0000-0000-0000-000000000000')
+ || ARRAY_REMOVE(ARRAY_AGG(mo."organizationId" ORDER BY mo."dateStart" DESC, mo.id), NULL)
+ || ARRAY_REMOVE(ARRAY_AGG(mo1."organizationId" ORDER BY mo1."createdAt" DESC, mo1.id), NULL)
+ || ARRAY_REMOVE(ARRAY_AGG(mo2."organizationId" ORDER BY mo2."createdAt", mo2.id), NULL)
+ )[1] AS new_org
+ FROM activities a
+ LEFT JOIN "memberSegmentAffiliations" msa ON msa."memberId" = a."memberId" AND a."segmentId" = msa."segmentId" AND (
+ a.timestamp BETWEEN msa."dateStart" AND msa."dateEnd"
+ OR (a.timestamp >= msa."dateStart" AND msa."dateEnd" IS NULL)
+ )
+ LEFT JOIN "memberOrganizations" mo ON mo."memberId" = a."memberId"
+ AND (
+ a.timestamp BETWEEN mo."dateStart" AND mo."dateEnd"
+ OR (a.timestamp >= mo."dateStart" AND mo."dateEnd" IS NULL)
+ )
+ AND mo."deletedAt" IS NULL
+ LEFT JOIN "memberOrganizations" mo1 ON mo1."memberId" = a."memberId"
+ AND mo1."dateStart" IS NULL AND mo1."dateEnd" IS NULL
+ AND mo1."createdAt" <= a.timestamp
+ AND mo1."deletedAt" IS NULL
+ LEFT JOIN "memberOrganizations" mo2 ON mo2."memberId" = a."memberId"
+ AND mo2."dateStart" IS NULL AND mo2."dateEnd" IS NULL
+ AND mo2."deletedAt" IS NULL
+ WHERE a."memberId" = $1
+ GROUP BY a.id
+ )
+ UPDATE activities a1
+ SET "organizationId" = nao.new_org
+ FROM new_activities_organizations nao
+ WHERE a1.id = nao.id
+ AND ("organizationId" != nao.new_org
+ OR ("organizationId" IS NULL AND nao.new_org IS NOT NULL)
+ OR ("organizationId" IS NOT NULL AND nao.new_org IS NULL));`,
+ [input.member.id],
+ )
+ } catch (err) {
+ throw new Error(err)
+ }
+}
diff --git a/services/apps/profiles_worker/src/main.ts b/services/apps/profiles_worker/src/main.ts
new file mode 100644
index 0000000000..27896e9f9a
--- /dev/null
+++ b/services/apps/profiles_worker/src/main.ts
@@ -0,0 +1,31 @@
+import { Config } from '@crowd/archetype-standard'
+import { ServiceWorker, Options } from '@crowd/archetype-worker'
+
+const config: Config = {
+ producer: {
+ enabled: false,
+ },
+ temporal: {
+ enabled: true,
+ },
+ redis: {
+ enabled: false,
+ },
+}
+
+const options: Options = {
+ postgres: {
+ enabled: true,
+ },
+ opensearch: {
+ enabled: false,
+ },
+}
+
+export const svc = new ServiceWorker(config, options)
+
+setImmediate(async () => {
+ await svc.init()
+
+ await svc.start()
+})
diff --git a/services/apps/profiles_worker/src/types/member.ts b/services/apps/profiles_worker/src/types/member.ts
new file mode 100644
index 0000000000..74e210924d
--- /dev/null
+++ b/services/apps/profiles_worker/src/types/member.ts
@@ -0,0 +1,5 @@
+export interface MemberWithIDOnly {
+ member: {
+ id: string
+ }
+}
diff --git a/services/apps/profiles_worker/src/workflows.ts b/services/apps/profiles_worker/src/workflows.ts
new file mode 100644
index 0000000000..233f128fb7
--- /dev/null
+++ b/services/apps/profiles_worker/src/workflows.ts
@@ -0,0 +1,3 @@
+import { memberUpdate } from './workflows/member/memberUpdate'
+
+export { memberUpdate }
diff --git a/services/apps/profiles_worker/src/workflows/member/memberUpdate.ts b/services/apps/profiles_worker/src/workflows/member/memberUpdate.ts
new file mode 100644
index 0000000000..3c022af415
--- /dev/null
+++ b/services/apps/profiles_worker/src/workflows/member/memberUpdate.ts
@@ -0,0 +1,21 @@
+import { proxyActivities } from '@temporalio/workflow'
+
+import * as activities from '../../activities'
+import { MemberWithIDOnly } from '../../types/member'
+
+// Configure timeouts and retry policies to update a member in the database.
+const { updateMemberAffiliations } = proxyActivities({
+ startToCloseTimeout: '60 seconds',
+})
+
+/*
+memberUpdate is a Temporal workflow that:
+ - [Activity]: Update all affiliations for a given member in the database.
+*/
+export async function memberUpdate(input: MemberWithIDOnly): Promise {
+ try {
+ await updateMemberAffiliations(input)
+ } catch (err) {
+ throw new Error(err)
+ }
+}
diff --git a/services/apps/profiles_worker/tsconfig.json b/services/apps/profiles_worker/tsconfig.json
new file mode 100644
index 0000000000..47a983b5d5
--- /dev/null
+++ b/services/apps/profiles_worker/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "compilerOptions": {
+ "target": "es2017",
+ "module": "Node16",
+ "lib": ["es6", "es7", "es2017", "es2017.object", "es2015.promise"],
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "moduleResolution": "node16",
+ "experimentalDecorators": true,
+ "esModuleInterop": true,
+ "baseUrl": "./src",
+ "paths": {
+ "@crowd/*": ["../../../libs/*/src"],
+ "@crowd/archetype-*": ["../../../archetypes/*/src"]
+ }
+ },
+ "include": ["src/**/*"]
+}
diff --git a/services/libs/types/src/enums/temporal.ts b/services/libs/types/src/enums/temporal.ts
index 3dda198445..529d0af6d1 100644
--- a/services/libs/types/src/enums/temporal.ts
+++ b/services/libs/types/src/enums/temporal.ts
@@ -4,4 +4,6 @@ export enum TemporalWorkflowId {
EMAIL_WEEKLY_ANALYTICS = 'email-weekly-analytics',
EMAIL_EAGLEEYE_DIGEST = 'email-eagleeye-digest',
+
+ MEMBER_UPDATE = 'member-update',
}