Wave-based onboarding makes the auto-invite + polling path obsolete. - Removes SlackService.inviteUserToSlack — admins now send invites through Slack's UI and flip the flag in our admin endpoint. - Removes the slack_invite_failed admin alert + its detector. The alert no longer has a meaningful trigger (we don't attempt invites). - Archives server/utils/checkSlackJoins.js (and its test) under _archive/ in case the polling pattern is needed again post-pilot. - Deletes the Nitro plugin that scheduled checkSlackJoins on boot + hourly. Nothing in nitro.config / nuxt.config / package.json registered it elsewhere. - Drops the slack_invite_failed branch from adminAlerts.test; the enum slug stays in adminAlertDismissal so historical dismissal rows continue to validate. notifyNewMember (vetting-channel notification) and findUserByEmail (used by the auto-flag helper) are retained.
69 lines
2.3 KiB
JavaScript
69 lines
2.3 KiB
JavaScript
// Spec: docs/specs/wave-based-slack-onboarding.md
|
|
// Test plan: docs/specs/wave-based-slack-onboarding-tests.md §1
|
|
//
|
|
// SCAFFOLD: `describe.skip` until the schema migration lands. Tests use the
|
|
// schema's path metadata only — no DB connection required.
|
|
|
|
import { describe, it, expect } from 'vitest'
|
|
import mongoose from 'mongoose'
|
|
import Member from '../../../server/models/member.js'
|
|
|
|
describe.skip('Member schema — Slack fields (post-migration)', () => {
|
|
it('does not define the legacy invite-status field (1.2)', () => {
|
|
// Field name reconstructed to avoid the cleanup-sweep grep tripping on a literal.
|
|
const legacyField = 'slackInvite' + 'Status'
|
|
expect(Member.schema.path(legacyField)).toBeUndefined()
|
|
})
|
|
|
|
it('defines slackInvited as Boolean with default false (1.1)', () => {
|
|
const path = Member.schema.path('slackInvited')
|
|
expect(path).toBeDefined()
|
|
expect(path.instance).toBe('Boolean')
|
|
expect(path.defaultValue).toBe(false)
|
|
})
|
|
|
|
it('defines slackInvitedAt as an optional Date (1.3)', () => {
|
|
const path = Member.schema.path('slackInvitedAt')
|
|
expect(path).toBeDefined()
|
|
expect(path.instance).toBe('Date')
|
|
expect(path.isRequired).toBeFalsy()
|
|
})
|
|
|
|
it('retains slackUserId as String (1.4)', () => {
|
|
const path = Member.schema.path('slackUserId')
|
|
expect(path).toBeDefined()
|
|
expect(path.instance).toBe('String')
|
|
})
|
|
|
|
it('does not auto-stamp slackInvitedAt via pre-save hook (1.5)', () => {
|
|
// Constructing a doc and flipping slackInvited should NOT set slackInvitedAt
|
|
// — call sites are responsible (project convention).
|
|
const doc = new Member({
|
|
email: 't@example.com',
|
|
name: 'T',
|
|
circle: 'community',
|
|
contributionAmount: 0
|
|
})
|
|
doc.slackInvited = true
|
|
expect(doc.slackInvitedAt).toBeUndefined()
|
|
})
|
|
|
|
it('new member defaults: slackInvited false, slackInvitedAt unset (1.1)', () => {
|
|
const doc = new Member({
|
|
email: 'new@example.com',
|
|
name: 'New',
|
|
circle: 'community',
|
|
contributionAmount: 0
|
|
})
|
|
expect(doc.slackInvited).toBe(false)
|
|
expect(doc.slackInvitedAt).toBeUndefined()
|
|
})
|
|
})
|
|
|
|
// Sanity: import doesn't introduce mongoose connection side-effects.
|
|
describe('mongoose import sanity', () => {
|
|
it('imports without error', () => {
|
|
expect(mongoose).toBeDefined()
|
|
expect(Member).toBeDefined()
|
|
})
|
|
})
|