import * as httpMock from '~test/http-mock.ts'; import { EXTERNAL_HOST_ERROR } from '../../../constants/error-messages.ts'; import * as hostRules from '../../../util/host-rules.ts'; import * as rubyVersioning from '../../versioning/ruby/index.ts'; import { getPkgReleases } from '../index.ts'; import { PodDatasource } from './index.ts'; const config = { versioning: rubyVersioning.id, datasource: PodDatasource.id, packageName: 'foo', registryUrls: [], }; const githubApiHost = 'https://api.github.com'; const githubEntApiHost = 'https://github.foo.com'; const githubEntApiHost2 = 'https://ghe.foo.com'; const cocoapodsHost = 'https://cdn.cocoapods.org'; describe('modules/datasource/pod/index', () => { describe('getReleases', () => { beforeEach(() => { hostRules.clear(); }); it('returns null for invalid inputs', async () => { // FIXME: why get request? httpMock .scope(cocoapodsHost) .get('/all_pods_versions_3_8_5.txt') .reply(404); await expect( getPkgReleases({ datasource: PodDatasource.id, packageName: 'foobar', registryUrls: [], }), ).resolves.toBeNull(); }); it('returns null disabled host', async () => { hostRules.add({ matchHost: cocoapodsHost, enabled: false }); await expect( getPkgReleases({ datasource: PodDatasource.id, packageName: 'foobar', }), ).resolves.toBeNull(); }); it('returns null for empty result', async () => { // FIXME: why get request? httpMock .scope(cocoapodsHost) .get('/all_pods_versions_a_c_b.txt') .reply(404); await expect(getPkgReleases(config)).resolves.toBeNull(); }); it('returns null for 404', async () => { httpMock .scope(githubApiHost) .get('/repos/foo/bar/contents/Specs/a/c/b/foo') .reply(404) .get('/repos/foo/bar/contents/a/c/b/foo') .reply(404) .get('/repos/foo/bar/contents/Specs/foo') .reply(404) .get('/repos/foo/bar/contents/foo') .reply(404); const res = await getPkgReleases({ ...config, registryUrls: [...config.registryUrls, 'https://github.com/foo/bar'], }); expect(res).toBeNull(); }); it('returns null for 404 Github enterprise', async () => { httpMock .scope(githubEntApiHost) .get('/api/v3/repos/foo/bar/contents/Specs/a/c/b/foo') .reply(404) .get('/api/v3/repos/foo/bar/contents/a/c/b/foo') .reply(404) .get('/api/v3/repos/foo/bar/contents/Specs/foo') .reply(404) .get('/api/v3/repos/foo/bar/contents/foo') .reply(404); const res = await getPkgReleases({ ...config, registryUrls: [ ...config.registryUrls, 'https://github.foo.com/foo/bar', ], }); expect(res).toBeNull(); }); it('returns null for 404 Github enterprise with different url style', async () => { httpMock .scope(githubEntApiHost2) .get('/api/v3/repos/foo/bar/contents/Specs/a/c/b/foo') .reply(404) .get('/api/v3/repos/foo/bar/contents/a/c/b/foo') .reply(404) .get('/api/v3/repos/foo/bar/contents/Specs/foo') .reply(404) .get('/api/v3/repos/foo/bar/contents/foo') .reply(404); const res = await getPkgReleases({ ...config, registryUrls: [...config.registryUrls, 'https://ghe.foo.com/foo/bar'], }); expect(res).toBeNull(); }); it('returns null for 401', async () => { httpMock .scope(cocoapodsHost) .get('/all_pods_versions_a_c_b.txt') .reply(401); await expect(getPkgReleases(config)).resolves.toBeNull(); }); it('throws for 429', async () => { httpMock .scope(cocoapodsHost) .get('/all_pods_versions_a_c_b.txt') .reply(429); await expect(getPkgReleases(config)).rejects.toThrow(EXTERNAL_HOST_ERROR); }); it('throws for 500', async () => { httpMock .scope(cocoapodsHost) .get('/all_pods_versions_a_c_b.txt') .reply(500); await expect(getPkgReleases(config)).rejects.toThrow(EXTERNAL_HOST_ERROR); }); it('returns null for unknown error', async () => { httpMock .scope(cocoapodsHost) .get('/all_pods_versions_a_c_b.txt') .replyWithError('foobar'); await expect(getPkgReleases(config)).resolves.toBeNull(); }); it('processes real data from CDN', async () => { httpMock .scope(cocoapodsHost) .get('/all_pods_versions_a_c_b.txt') .reply(200, 'foo/1.2.3'); await expect( getPkgReleases({ ...config, registryUrls: ['https://github.com/CocoaPods/Specs'], }), ).resolves.toEqual({ registryUrl: 'https://github.com/CocoaPods/Specs', releases: [ { version: '1.2.3', }, ], }); }); it('processes real data from Github with shard with specs', async () => { httpMock .scope(githubApiHost) .get('/repos/Artsy/Specs/contents/Specs/a/c/b/foo') .reply(200, [{ name: '1.2.3' }]); const res = await getPkgReleases({ ...config, registryUrls: ['https://github.com/Artsy/Specs'], }); expect(res).toEqual({ registryUrl: 'https://github.com/Artsy/Specs', releases: [ { version: '1.2.3', }, ], }); }); it('processes real data from Github with shard without specs', async () => { httpMock .scope(githubApiHost) .get('/repos/Artsy/Specs/contents/Specs/a/c/b/foo') .reply(404) .get('/repos/Artsy/Specs/contents/a/c/b/foo') .reply(200, [{ name: '1.2.3' }]); const res = await getPkgReleases({ ...config, registryUrls: ['https://github.com/Artsy/Specs'], }); expect(res).toEqual({ registryUrl: 'https://github.com/Artsy/Specs', releases: [ { version: '1.2.3', }, ], }); }); it('processes real data from Github with specs without shard', async () => { httpMock .scope(githubApiHost) .get('/repos/Artsy/Specs/contents/Specs/a/c/b/foo') .reply(404) .get('/repos/Artsy/Specs/contents/a/c/b/foo') .reply(404) .get('/repos/Artsy/Specs/contents/Specs/foo') .reply(200, [{ name: '1.2.3' }]); const res = await getPkgReleases({ ...config, registryUrls: ['https://github.com/Artsy/Specs'], }); expect(res).toEqual({ registryUrl: 'https://github.com/Artsy/Specs', releases: [ { version: '1.2.3', }, ], }); }); it('processes real data from Github without specs without shard', async () => { httpMock .scope(githubApiHost) .get('/repos/Artsy/Specs/contents/Specs/a/c/b/foo') .reply(404) .get('/repos/Artsy/Specs/contents/a/c/b/foo') .reply(404) .get('/repos/Artsy/Specs/contents/Specs/foo') .reply(404) .get('/repos/Artsy/Specs/contents/foo') .reply(200, [{ name: '1.2.3' }]); const res = await getPkgReleases({ ...config, registryUrls: ['https://github.com/Artsy/Specs'], }); expect(res).toEqual({ registryUrl: 'https://github.com/Artsy/Specs', releases: [ { version: '1.2.3', }, ], }); }); it('processes real data from Github Enterprise with shard with specs', async () => { httpMock .scope(githubEntApiHost) .get('/api/v3/repos/foo/bar/contents/Specs/a/c/b/foo') .reply(200, [{ name: '1.2.3' }]); const res = await getPkgReleases({ ...config, registryUrls: ['https://github.foo.com/foo/bar'], }); expect(res).toEqual({ registryUrl: 'https://github.foo.com/foo/bar', releases: [ { version: '1.2.3', }, ], }); }); it('processes real data from Github Enterprise with shard without specs', async () => { httpMock .scope(githubEntApiHost) .get('/api/v3/repos/foo/bar/contents/Specs/a/c/b/foo') .reply(404) .get('/api/v3/repos/foo/bar/contents/a/c/b/foo') .reply(200, [{ name: '1.2.3' }]); const res = await getPkgReleases({ ...config, registryUrls: ['https://github.foo.com/foo/bar'], }); expect(res).toEqual({ registryUrl: 'https://github.foo.com/foo/bar', releases: [ { version: '1.2.3', }, ], }); }); it('processes real data from Github Enterprise with specs without shard', async () => { httpMock .scope(githubEntApiHost) .get('/api/v3/repos/foo/bar/contents/Specs/a/c/b/foo') .reply(404) .get('/api/v3/repos/foo/bar/contents/a/c/b/foo') .reply(404) .get('/api/v3/repos/foo/bar/contents/Specs/foo') .reply(200, [{ name: '1.2.3' }]); const res = await getPkgReleases({ ...config, registryUrls: ['https://github.foo.com/foo/bar'], }); expect(res).toEqual({ registryUrl: 'https://github.foo.com/foo/bar', releases: [ { version: '1.2.3', }, ], }); }); it('processes real data from Github Enterprise without specs without shard', async () => { httpMock .scope(githubEntApiHost) .get('/api/v3/repos/foo/bar/contents/Specs/a/c/b/foo') .reply(404) .get('/api/v3/repos/foo/bar/contents/a/c/b/foo') .reply(404) .get('/api/v3/repos/foo/bar/contents/Specs/foo') .reply(404) .get('/api/v3/repos/foo/bar/contents/foo') .reply(200, [{ name: '1.2.3' }]); const res = await getPkgReleases({ ...config, registryUrls: ['https://github.foo.com/foo/bar'], }); expect(res).toEqual({ registryUrl: 'https://github.foo.com/foo/bar', releases: [ { version: '1.2.3', }, ], }); }); }); });