Ctrl K
ComunidadGuías…

tests/cli-meta.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { randomUUID } from 'node:crypto'
import { readFile, writeFile } from 'node:fs/promises'
import { join } from 'node:path'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import { createTestSDK, uploadBundleSDK } from './cli-sdk-utils'
import { BASE_PACKAGE_JSON, cleanupCli, getSemver, prepareCli, tempFileFolder } from './cli-utils'
import { createIsolatedSeedAppOptions, resetAndSeedAppData, resetAppData, resetAppDataStats } from './test-utils'

async function assertCompatibilityTableColumns(appId: string, packageName: string, localVersion: string, remoteVersion: string, customPackageJsonPath?: string) {
  const packageJsonPath = customPackageJsonPath || join(process.cwd(), 'temp_cli_test', appId, 'package.json')
  const result = await createTestSDK().checkBundleCompatibility({
    appId,
    channel: 'production',
    packageJson: packageJsonPath,
    nodeModules: join(process.cwd(), 'node_modules'),
  })

  expect(result.success, result.error).toBe(true)
  const packageEntry = result.data?.find((entry: any) => entry.name === packageName)
  expect(packageEntry).toBeDefined()
  expect(packageEntry!.localVersion).toContain(localVersion)
  expect(packageEntry!.remoteVersion).toContain(remoteVersion)
}

async function writeBundleContent(appId: string, marker: string) {
  const indexHtmlPath = join(tempFileFolder(appId), 'dist', 'index.html')
  await writeFile(indexHtmlPath, `<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>CLI Metadata Test</title>
</head>
<body>
  <h1>${marker}</h1>
  <script>
    if (window.CapacitorUpdater) {
      window.CapacitorUpdater.notifyAppReady();
    }
  </script>
</body>
</html>`)
}

async function getInstalledDependencyVersion(packageName: string): Promise<string> {
  const packageJsonPath = join(process.cwd(), 'node_modules', ...packageName.split('/'), 'package.json')
  const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8')) as { version: string }
  return packageJson.version
}

async function createCustomPackageJson(appId: string, testName: string, dependencies: Record<string, string>): Promise<string> {
  const customPath = join(tempFileFolder(appId), `package-${testName}.json`)
  const packageContent = BASE_PACKAGE_JSON
    .replace('%APPID%', appId)
    .replace('%DEPENDENCIES%', JSON.stringify(dependencies, null, 2))
  await writeFile(customPath, packageContent)
  return customPath
}

describe('tests CLI metadata', () => {
  const id = randomUUID()
  const APPNAME = `com.cli_meta_${id}`
  const seedOptions = createIsolatedSeedAppOptions()
  let installedAndroidVersion = ''
  let installedUpdaterVersion = ''

  beforeAll(async () => {
    const [androidVersion, updaterVersion] = await Promise.all([
      getInstalledDependencyVersion('@capacitor/android'),
      getInstalledDependencyVersion('@capgo/capacitor-updater'),
      resetAndSeedAppData(APPNAME, seedOptions),
      prepareCli(APPNAME, false, false), // Use main project dependencies instead
    ])

    installedAndroidVersion = androidVersion
    installedUpdaterVersion = updaterVersion
  })

  afterAll(async () => {
    await Promise.all([
      cleanupCli(APPNAME),
      resetAppData(APPNAME),
      resetAppDataStats(APPNAME),
    ])
  })

  it('should upload bundle with metadata check', async () => {
    const testSemver = getSemver()
    const packageJsonPath = join(process.cwd(), 'temp_cli_test', APPNAME, 'package.json')
    await writeBundleContent(APPNAME, `metadata-${testSemver}`)

    // First upload a bundle WITH metadata to establish baseline
    const result = await uploadBundleSDK(APPNAME, testSemver, 'production', {
      ignoreCompatibilityCheck: false,
      packageJsonPaths: packageJsonPath,
    })
    expect(result.success, result.error).toBe(true)

    // Now compatibility check should show remote versions from the uploaded bundle
    // The SDK reports the currently installed dependency version from node_modules.
    await assertCompatibilityTableColumns(APPNAME, '@capacitor/android', installedAndroidVersion, installedAndroidVersion)
  })

  // Each case writes its own package.json and compares against the uploaded baseline.
  // localVersion always comes from node_modules, not from the declared dependency.
  it.concurrent.each([
    ['matching versions', () => installedAndroidVersion],
    ['semver caret ranges', () => '^8.0.0'],
    ['semver tilde ranges', () => '~8.0.0'],
    ['major version mismatches', () => '7.0.0'],
    ['registry prefixes', () => 'npm:@capacitor/android@8.0.0'],
    ['file references', () => 'file:../capacitor-android'],
    ['git references', () => 'github:capacitorjs/capacitor#main'],
  ])('should resolve %s against the installed dependency', async (testName, declaredVersion) => {
    const customPkgPath = await createCustomPackageJson(APPNAME, testName.replaceAll(' ', '-'), { '@capacitor/android': declaredVersion() })
    await assertCompatibilityTableColumns(APPNAME, '@capacitor/android', installedAndroidVersion, installedAndroidVersion, customPkgPath)
  })

  it.concurrent('should handle additional local plugins', async () => {
    const customPkgPath = await createCustomPackageJson(APPNAME, 'plugins', {
      '@capacitor/android': installedAndroidVersion,
      '@capgo/capacitor-updater': installedUpdaterVersion,
    })
    await assertCompatibilityTableColumns(APPNAME, '@capacitor/android', installedAndroidVersion, installedAndroidVersion, customPkgPath)
    await assertCompatibilityTableColumns(APPNAME, '@capgo/capacitor-updater', installedUpdaterVersion, installedUpdaterVersion, customPkgPath)
  })
})