Files
ai-dimension/backend/wdkj-server/tests/unit/user.test.js
T
Yuzhiran Dev 24cd9cef53 🎉 feat: initialize 宇之然AI维度 project
- uni-app Vue3 frontend with dark glassmorphism theme
- 5 AI dimensions: Origin / Development / Current / Learning / Trend
- AI Chat system prompt updated from geometry to AI
- 23 AI knowledge articles initialized in DB
- Trend API + cron job for daily news
- Product pricing (Pro ¥19.9, VIP ¥39.9)
- Pinia stores + API utilities
- AGENTS.md documentation
2026-07-10 13:26:04 +08:00

167 lines
4.5 KiB
JavaScript
Executable File

/**
* 用户模型单元测试
*/
const mongoose = require('mongoose')
const User = require('../../src/models/User')
describe('User Model', () => {
beforeAll(async () => {
// 连接测试数据库
const mongoURI = process.env.MONGODB_URI || 'mongodb://localhost:27017/wdkj'
await mongoose.connect(mongoURI)
})
afterAll(async () => {
// 清理并关闭连接
await mongoose.connection.dropDatabase()
await mongoose.connection.close()
})
beforeEach(async () => {
// 每个测试前清空users集合
await User.deleteMany({})
})
describe('用户创建', () => {
test('应该成功创建新用户', async () => {
const userData = {
openid: 'test_openid_123',
nickName: '测试用户',
avatarUrl: 'https://example.com/avatar.jpg'
}
const user = new User(userData)
const savedUser = await user.save()
expect(savedUser._id).toBeDefined()
expect(savedUser.openid).toBe(userData.openid)
expect(savedUser.nickName).toBe(userData.nickName)
expect(savedUser.avatarUrl).toBe(userData.avatarUrl)
expect(savedUser.unlockedDims).toContain(1)
expect(savedUser.totalScore).toBe(0)
})
test('openid 是必需的', async () => {
const user = new User({
nickName: '测试用户'
})
await expect(user.save()).rejects.toThrow()
})
test('openid 必须唯一', async () => {
const userData = {
openid: 'unique_openid',
nickName: '用户1'
}
await new User(userData).save()
const duplicateUser = new User({
openid: 'unique_openid',
nickName: '用户2'
})
await expect(duplicateUser.save()).rejects.toThrow()
})
test('默认昵称应该是"星辰旅行者"', async () => {
const user = new User({ openid: 'test_openid' })
await user.save()
expect(user.nickName).toBe('星辰旅行者')
})
})
describe('探索数据', () => {
test('应该正确计算总分', async () => {
const user = new User({
openid: 'test_openid',
exploreData: {
dim1: { bestScore: 100 },
dim2: { bestArea: 200 },
dim3: { bestScore: 150 }
}
})
await user.save()
expect(user.totalScore).toBe(450)
expect(user.dim1Score).toBe(100)
expect(user.dim2Score).toBe(200)
expect(user.dim3Score).toBe(150)
})
test('未解锁维度分数应为0', async () => {
const user = new User({
openid: 'test_openid',
exploreData: {
dim1: { bestScore: 100 }
}
})
await user.save()
expect(user.dim2Score).toBe(0)
expect(user.dim3Score).toBe(0)
expect(user.dim4Score).toBe(0)
expect(user.dim5Score).toBe(0)
})
})
describe('虚拟字段', () => {
test('isNew 应该对新用户返回 true', async () => {
const user = new User({ openid: 'test_openid' })
await user.save()
expect(user.isNew).toBe(true)
})
test('isNew 应该对老用户返回 false', async () => {
const yesterday = new Date()
yesterday.setDate(yesterday.getDate() - 2)
const user = new User({
openid: 'test_openid',
createdAt: yesterday
})
await user.save()
expect(user.isNew).toBe(false)
})
})
describe('静态方法', () => {
test('getLeaderboard 应该返回排行榜', async () => {
// 创建测试用户
await User.create([
{ openid: 'user1', totalScore: 300, dim1Score: 100 },
{ openid: 'user2', totalScore: 500, dim1Score: 200 },
{ openid: 'user3', totalScore: 400, dim1Score: 150 }
])
const leaderboard = await User.getLeaderboard(null, 10)
expect(leaderboard).toHaveLength(3)
expect(leaderboard[0].totalScore).toBe(500)
expect(leaderboard[1].totalScore).toBe(400)
expect(leaderboard[2].totalScore).toBe(300)
})
test('getLeaderboard 应该支持按维度排序', async () => {
await User.create([
{ openid: 'user1', dim1Score: 100, totalScore: 100 },
{ openid: 'user2', dim1Score: 200, totalScore: 200 },
{ openid: 'user3', dim1Score: 150, totalScore: 150 }
])
const leaderboard = await User.getLeaderboard(1, 10)
expect(leaderboard[0].dim1Score).toBe(200)
expect(leaderboard[1].dim1Score).toBe(150)
expect(leaderboard[2].dim1Score).toBe(100)
})
})
})