diff --git a/package.json b/package.json index 3300f6131..52aa5a46e 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "netlify:dev": "bunx netlify dev --port 8881", "test:front": "playwright test", "test:all": "vitest --bail=1 --mode=test tests/*", + "test:all:local": "LOCAL_CLI_PATH=true vitest --bail=1 --mode=test tests/*", "test:backend": "vitest --bail=1 --mode=test --exclude=tests/cli*", "test:cli": "vitest --bail=1 --mode=test tests/cli*", "test:cli:local": "LOCAL_CLI_PATH=true vitest --bail=1 --mode=test tests/cli*", diff --git a/tests/cli-utils.ts b/tests/cli-utils.ts index cc7c76479..ec25900f8 100644 --- a/tests/cli-utils.ts +++ b/tests/cli-utils.ts @@ -1,6 +1,6 @@ import type { ExecSyncOptions } from 'node:child_process' import type { Readable } from 'node:stream' -import { execSync, spawn } from 'node:child_process' +import { execSync } from 'node:child_process' import { existsSync, mkdirSync, writeFileSync } from 'node:fs' import { join } from 'node:path' import { cwd, env } from 'node:process' diff --git a/tests/cli.test.ts b/tests/cli.test.ts index e7c6fb406..b47ee4b63 100644 --- a/tests/cli.test.ts +++ b/tests/cli.test.ts @@ -3,8 +3,8 @@ import { randomUUID } from 'node:crypto' import { rmSync, writeFileSync } from 'node:fs' import { join } from 'node:path' import AdmZip from 'adm-zip' -import { beforeAll, beforeEach, describe, expect, it } from 'vitest' -import { cleanupCli, getSemver, prepareCli, runCli, setDependencies, tempFileFolder } from './cli-utils' +import { beforeAll, describe, expect, it } from 'vitest' +import { getSemver, prepareCli, runCli, tempFileFolder } from './cli-utils' import { getSupabaseClient, getUpdate, getUpdateBaseData, resetAndSeedAppData, responseOk } from './test-utils' describe('tests CLI upload', () => { @@ -17,7 +17,7 @@ describe('tests CLI upload', () => { let semver = getSemver() it('should upload bundle successfully', async () => { - const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check'], id, false) + const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production'], id, false) expect(output).toContain('Bundle uploaded') }) it('should download and verify uploaded bundle', async () => { @@ -44,16 +44,8 @@ describe('tests CLI upload', () => { const indexJsContent = indexJsEntry!.getData().toString('utf8') expect(indexJsContent).toBe('import { CapacitorUpdater } from \'@capgo/capacitor-updater\';\nconsole.log(\"Hello world!!!\");\nCapacitorUpdater.notifyAppReady();') }) - it('should not upload same twice', async () => { - semver = getSemver(semver) - const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check'], id, false) - expect(output).toContain('Cannot upload the same bundle content') - }) it ('should not upload same hash twice', async () => { semver = getSemver(semver) - await runCli(['bundle', 'upload', '-b', semver, '-c', 'production'], id, false) - semver = getSemver(semver) - const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production'], id, false) expect(output).toContain('Cannot upload the same bundle content') }) @@ -74,26 +66,36 @@ describe('tests CLI upload', () => { expect(error).toBeNull() expect(data?.external_url).toBe('https://example.com') }) - it('test --iv-session-key with cloud upload', async () => { - semver = getSemver(semver) - const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check', '--iv-session-key', 'aaa:bbb'], id, false) - expect(output).toContain('Time to share your update to the world') - - const supabase = getSupabaseClient() - const { data, error } = await supabase - .from('app_versions') - .select('*') - .eq('name', semver) - .eq('app_id', APPNAME) - .single() - .throwOnError() - - expect(error).toBeNull() - expect(data?.session_key).toBeNull() +}) +describe('tests CLI upload options in parallel', () => { + const id_one = randomUUID() + const APPNAME_one = `com.demo.app.cli_${id_one}` + beforeAll(async () => { + await resetAndSeedAppData(APPNAME_one) + await prepareCli(APPNAME_one, id_one) }) - it('test --iv-session-key with external upload', async () => { - semver = getSemver(semver) - const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check', '--iv-session-key', 'aaa:bbb', '--external', 'https://example.com'], id, false) + const prepareApp = async () => { + const id = randomUUID() + const APPNAME = `com.demo.app.cli_${id}` + await resetAndSeedAppData(APPNAME) + await prepareCli(APPNAME, id) + return { id, APPNAME } + } + it.concurrent('test code check (missing notifyAppReady)', async () => { + const { id } = await prepareApp() + const semver = getSemver() + writeFileSync(join(tempFileFolder(id), 'dist', 'index.js'), 'import { CapacitorUpdater } from \'@capgo/capacitor-updater\';\nconsole.log("Hello world!!!");') + const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check'], id, false) + expect(output).toContain('notifyAppReady() is missing in') + }) + it.concurrent('test --iv-session-key with cloud upload', async () => { + const semver = getSemver() + const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check', '--iv-session-key', 'aaa:bbb'], id_one, false) + expect(output).toContain('You need to provide an external url if you want to use the --iv-session-key option') + }) + it.concurrent('test --iv-session-key with external upload', async () => { + const semver = getSemver() + const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check', '--iv-session-key', 'aaa:bbb', '--external', 'https://example.com'], id_one, false) expect(output).toContain('Time to share your update to the world') const supabase = getSupabaseClient() @@ -101,33 +103,21 @@ describe('tests CLI upload', () => { .from('app_versions') .select('*') .eq('name', semver) - .eq('app_id', APPNAME) + .eq('app_id', APPNAME_one) .single() .throwOnError() expect(error).toBeNull() expect(data?.session_key).toBe('aaa:bbb') }) - it('test --encrypted-checksum with cloud upload', async () => { - semver = getSemver(semver) - const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check', '--encrypted-checksum', 'aaaa'], id, false) - expect(output).toContain('Time to share your update to the world') - - const supabase = getSupabaseClient() - const { data, error } = await supabase - .from('app_versions') - .select('*') - .eq('name', semver) - .eq('app_id', APPNAME) - .single() - .throwOnError() - - expect(error).toBeNull() - expect(data?.checksum).not.toBe('aaaa') + it.concurrent('test --encrypted-checksum with cloud upload', async () => { + const semver = getSemver() + const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check', '--encrypted-checksum', 'aaaa'], id_one, false) + expect(output).toContain('You need to provide an external url if you want to use the --encrypted-checksum option') }) - it('test --min-update-version', async () => { - semver = getSemver(semver) - const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check', '--min-update-version', '1.0.0', '--ignore-checksum-check'], id, false) + it.concurrent('test --min-update-version', async () => { + const semver = getSemver() + const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check', '--min-update-version', '1.0.0', '--ignore-checksum-check'], id_one, false) expect(output).toContain('Time to share your update to the world') const supabase = getSupabaseClient() @@ -135,16 +125,16 @@ describe('tests CLI upload', () => { .from('app_versions') .select('*') .eq('name', semver) - .eq('app_id', APPNAME) + .eq('app_id', APPNAME_one) .single() .throwOnError() expect(error).toBeNull() expect(data?.minUpdateVersion).not.toBe('1.0.0') }) - it('test --encrypted-checksum with external upload', async () => { - semver = getSemver(semver) - const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check', '--encrypted-checksum', 'aaaa', '--external', 'https://example.com'], id, false) + it.concurrent('test --encrypted-checksum with external upload', async () => { + const semver = getSemver() + const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check', '--encrypted-checksum', 'aaaa', '--external', 'https://example.com'], id_one, false) expect(output).toContain('Time to share your update to the world') const supabase = getSupabaseClient() @@ -152,62 +142,40 @@ describe('tests CLI upload', () => { .from('app_versions') .select('*') .eq('name', semver) - .eq('app_id', APPNAME) + .eq('app_id', APPNAME_one) .single() .throwOnError() expect(error).toBeNull() expect(data?.checksum).toBe('aaaa') }) - it('test code check (missing notifyAppReady)', async () => { - writeFileSync(join(tempFileFolder(id), 'dist', 'index.js'), 'import { CapacitorUpdater } from \'@capgo/capacitor-updater\';\nconsole.log("Hello world!!!");') - const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check'], id, false) - expect(output).toContain('notifyAppReady() is missing in') - }) - cleanupCli(id) -}) - -describe('tests Code check', () => { - const id = randomUUID() - const APPNAME = `com.demo.app.cli_${id}` - let semver = getSemver() - beforeEach(async () => { - await resetAndSeedAppData(APPNAME) - await prepareCli(APPNAME, id) - }) - it('test code check (missing index.html)', async () => { + it.concurrent('test code check (missing index.html)', async () => { + const { id } = await prepareApp() + const semver = getSemver() rmSync(join(tempFileFolder(id), 'dist', 'index.html')) const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check'], id, false) expect(output).toContain('index.html is missing') }) - it('test --no-code-check', async () => { + it.concurrent('test --no-code-check', async () => { + const { id } = await prepareApp() + let semver = getSemver() rmSync(join(tempFileFolder(id), 'dist', 'index.html')) semver = getSemver(semver) const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check', '--no-code-check'], id, false) expect(output).toContain('Time to share your update to the world') }) - cleanupCli(id) -}) - -describe('tests Wrong cases', () => { - const id = randomUUID() - const APPNAME = `com.demo.app.cli_${id}` - let semver = getSemver() - beforeAll(async () => { - await resetAndSeedAppData(APPNAME) - await prepareCli(APPNAME, id) - }) - it('cannot upload with wrong api key', async () => { + it.concurrent('cannot upload with wrong api key', async () => { + const { id } = await prepareApp() const testApiKey = randomUUID() - - semver = getSemver(semver) + const semver = getSemver() const output = await runCli(['bundle', 'upload', '-b', semver, '-c', 'production', '--ignore-metadata-check'], id, false, testApiKey) expect(output).toContain('Invalid API key or insufficient permissions.') }) - it('should test selectable disallow upload', async () => { + it.concurrent('should test selectable disallow upload', async () => { + const { id, APPNAME } = await prepareApp() const supabase = getSupabaseClient() - semver = getSemver(semver) + const semver = getSemver() await supabase.from('channels').update({ disable_auto_update: 'version_number' }).eq('name', 'production').eq('app_id', APPNAME).throwOnError() // test if is set correctly @@ -225,18 +193,9 @@ describe('tests Wrong cases', () => { await supabase.from('channels').update({ disable_auto_update: 'major' }).eq('name', 'production').eq('app_id', APPNAME).throwOnError() } }) - cleanupCli(id) -}) - -describe('tests CLI for organization', () => { - const id = randomUUID() - const APPNAME = `com.demo.app.cli_${id}` - let semver = getSemver() - beforeAll(async () => { - await resetAndSeedAppData(APPNAME) - await prepareCli(APPNAME, id) - }) - it('should test upload with organization', async () => { + it.concurrent('should test upload with organization', async () => { + const { id } = await prepareApp() + let semver = getSemver() const testApiKey = randomUUID() const testUserId = '6f0d1a2e-59ed-4769-b9d7-4d9615b28fe5' const supabase = getSupabaseClient() @@ -282,5 +241,4 @@ describe('tests CLI for organization', () => { .throwOnError() } }) - cleanupCli(id) }) diff --git a/vitest.config.ts b/vitest.config.ts index 3570484d3..ac8a97895 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -8,6 +8,7 @@ export default defineConfig(({ mode }) => ({ environment: 'node', watch: false, testTimeout: 60_000, + maxConcurrency: 12, env: loadEnv(mode, process.cwd(), ''), }, }))