development-project.spec.ts 4.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'node:fs'
  2. import { tmpdir } from 'node:os'
  3. import { join } from 'node:path'
  4. import { afterEach, describe, expect, it } from 'vitest'
  5. import { prepareDevelopmentProject } from '../scripts/development-project.ts'
  6. import { DESKTOP_HOST_PROTOCOL_VERSION } from '../src/host-protocol.ts'
  7. import type { DesktopRelease } from '../src/release.ts'
  8. const roots: string[] = []
  9. function temporaryRoot(): string {
  10. const root = mkdtempSync(join(tmpdir(), 'dsh-desktop-development-test-'))
  11. roots.push(root)
  12. return root
  13. }
  14. function release(version = '1.2.3'): DesktopRelease {
  15. return {
  16. schemaVersion: 1,
  17. version,
  18. hostProtocolVersion: DESKTOP_HOST_PROTOCOL_VERSION,
  19. nodeVersion: '24.17.0',
  20. pnpmVersion: '11.7.0',
  21. }
  22. }
  23. afterEach(() => {
  24. for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true })
  25. })
  26. describe('desktop development project', () => {
  27. it('projects the built dsh and Desktop Host applications with their dependency graph', () => {
  28. const root = temporaryRoot()
  29. const cli = join(root, 'apps', 'cli')
  30. const host = join(root, 'apps', 'desktop-host')
  31. const dependencies = join(root, 'workspace-dependencies')
  32. mkdirSync(join(cli, 'lib'), { recursive: true })
  33. mkdirSync(join(host, 'lib'), { recursive: true })
  34. mkdirSync(join(dependencies, '@scope'), { recursive: true })
  35. mkdirSync(join(dependencies, '@deepseek-ai', 'dsh'), { recursive: true })
  36. writeFileSync(join(cli, 'package.json'), '{"name":"@deepseek-ai/dsh","version":"1.2.3"}\n')
  37. writeFileSync(join(host, 'package.json'), '{"name":"@deepseek-ai/dsh-desktop-host","version":"1.2.3"}\n')
  38. writeFileSync(join(host, 'lib', 'index.js'), '')
  39. writeFileSync(join(dependencies, '@deepseek-ai', 'dsh', 'package.json'), '{}\n')
  40. mkdirSync(join(dependencies, 'plain-dependency'))
  41. writeFileSync(join(dependencies, 'plain-dependency', 'package.json'), '{}\n')
  42. mkdirSync(join(dependencies, '@scope', 'dependency'))
  43. writeFileSync(join(dependencies, '@scope', 'dependency', 'package.json'), '{}\n')
  44. const project = prepareDevelopmentProject({
  45. projectDir: join(root, 'development'),
  46. cliDir: cli,
  47. hostDir: host,
  48. dependencyDir: dependencies,
  49. release: release(),
  50. })
  51. expect(realpathSync(join(project, 'node_modules', '@deepseek-ai', 'dsh'))).toBe(realpathSync(cli))
  52. expect(realpathSync(join(project, 'node_modules', '@deepseek-ai', 'dsh-desktop-host'))).toBe(realpathSync(host))
  53. expect(realpathSync(join(project, 'node_modules', 'plain-dependency')))
  54. .toBe(realpathSync(join(dependencies, 'plain-dependency')))
  55. expect(realpathSync(join(project, 'node_modules', '@scope', 'dependency')))
  56. .toBe(realpathSync(join(dependencies, '@scope', 'dependency')))
  57. const manifest = JSON.parse(readFileSync(join(project, 'package.json'), 'utf8')) as {
  58. dependencies: Record<string, string>
  59. }
  60. expect(manifest.dependencies['@deepseek-ai/dsh']).toBe('1.2.3')
  61. expect(manifest.dependencies['@deepseek-ai/dsh-desktop-host']).toBe('1.2.3')
  62. })
  63. it('rejects a CLI package from another release', () => {
  64. const root = temporaryRoot()
  65. const cli = join(root, 'apps', 'cli')
  66. const host = join(root, 'apps', 'desktop-host')
  67. const dependencies = join(root, 'workspace-dependencies')
  68. mkdirSync(join(cli, 'lib'), { recursive: true })
  69. mkdirSync(join(host, 'lib'), { recursive: true })
  70. mkdirSync(dependencies, { recursive: true })
  71. writeFileSync(join(cli, 'package.json'), '{"name":"@deepseek-ai/dsh","version":"2.0.0"}\n')
  72. writeFileSync(join(host, 'package.json'), '{"name":"@deepseek-ai/dsh-desktop-host","version":"1.2.3"}\n')
  73. writeFileSync(join(host, 'lib', 'index.js'), '')
  74. expect(() => prepareDevelopmentProject({
  75. projectDir: join(root, 'development'),
  76. cliDir: cli,
  77. hostDir: host,
  78. dependencyDir: dependencies,
  79. release: release(),
  80. })).toThrow(/must be @deepseek-ai\/dsh@1\.2\.3/u)
  81. })
  82. })