diff --git a/server/models/PilotProfile.test.ts b/server/models/PilotProfile.test.ts new file mode 100644 index 0000000..42341c5 --- /dev/null +++ b/server/models/PilotProfile.test.ts @@ -0,0 +1,32 @@ +import { describe, it } from 'node:test' +import assert from 'node:assert/strict' +import { PilotProfile } from '~~/server/models/PilotProfile' + +describe('PilotProfile model', () => { + it('is importable without a DB connection', () => { + assert.ok(PilotProfile, 'PilotProfile model must be importable') + }) + + it('schema defines the expected fields', () => { + const paths = PilotProfile.schema.paths + for (const field of [ + 'user', 'simulator', 'os', 'hardware', 'radioConfidence', 'radioPainPoint', + 'networkExperience', 'toolkit', 'toolkitDuration', 'topFeatures', + 'pricingPreference', 'resultCallsign', 'completedAt', 'skippedAt', + ]) { + assert.ok(field in paths, `schema must have ${field}`) + } + }) + + it('user reference is required and unique', () => { + const userPath = PilotProfile.schema.path('user') as any + assert.equal(userPath?.options?.required, true) + assert.equal(userPath?.options?.unique, true) + }) + + it('radioConfidence is bounded 1-5', () => { + const path = PilotProfile.schema.path('radioConfidence') as any + assert.equal(path?.options?.min, 1) + assert.equal(path?.options?.max, 5) + }) +}) diff --git a/server/models/PilotProfile.ts b/server/models/PilotProfile.ts new file mode 100644 index 0000000..8d5912b --- /dev/null +++ b/server/models/PilotProfile.ts @@ -0,0 +1,48 @@ +import mongoose from 'mongoose' +import type { + FeatureWish, HardwareItem, NetworkExperience, OperatingSystem, PricingPreference, + RadioPainPoint, Simulator, ToolkitDuration, ToolkitItem, +} from '~~/shared/onboarding/config' + +export interface PilotProfileDocument extends mongoose.Document { + user: mongoose.Types.ObjectId + simulator?: Simulator + os?: OperatingSystem + hardware: HardwareItem[] + radioConfidence?: number + radioPainPoint?: RadioPainPoint + networkExperience: NetworkExperience[] + toolkit: ToolkitItem[] + toolkitDuration: Partial> + topFeatures: FeatureWish[] + pricingPreference?: PricingPreference + resultCallsign?: string + completedAt?: Date + skippedAt?: Date + createdAt: Date + updatedAt: Date +} + +const pilotProfileSchema = new mongoose.Schema( + { + user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true, unique: true }, + simulator: { type: String }, + os: { type: String }, + hardware: { type: [String], default: () => [] }, + radioConfidence: { type: Number, min: 1, max: 5 }, + radioPainPoint: { type: String }, + networkExperience: { type: [String], default: () => [] }, + toolkit: { type: [String], default: () => [] }, + toolkitDuration: { type: mongoose.Schema.Types.Mixed, default: () => ({}) }, + topFeatures: { type: [String], default: () => [] }, + pricingPreference: { type: String }, + resultCallsign: { type: String, trim: true }, + completedAt: { type: Date }, + skippedAt: { type: Date }, + }, + { timestamps: true }, +) + +export const PilotProfile = + (mongoose.models.PilotProfile as mongoose.Model | undefined) || + mongoose.model('PilotProfile', pilotProfileSchema)