381 lines
12 KiB
TypeScript
381 lines
12 KiB
TypeScript
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
|
import { SmartRegistry } from '../ts/index.js';
|
|
import {
|
|
createTestRegistry,
|
|
createTestTokens,
|
|
createTestPom,
|
|
createTestJar,
|
|
calculateMavenChecksums,
|
|
} from './helpers/registry.js';
|
|
|
|
let registry: SmartRegistry;
|
|
let mavenToken: string;
|
|
let userId: string;
|
|
|
|
// Test data
|
|
const testGroupId = 'com.example.test';
|
|
const testArtifactId = 'test-artifact';
|
|
const testVersion = '1.0.0';
|
|
const testJarData = createTestJar();
|
|
const testPomData = Buffer.from(
|
|
createTestPom(testGroupId, testArtifactId, testVersion),
|
|
'utf-8'
|
|
);
|
|
|
|
tap.test('Maven: should create registry instance', async () => {
|
|
registry = await createTestRegistry();
|
|
const tokens = await createTestTokens(registry);
|
|
mavenToken = tokens.mavenToken;
|
|
userId = tokens.userId;
|
|
|
|
expect(registry).toBeInstanceOf(SmartRegistry);
|
|
expect(mavenToken).toBeTypeOf('string');
|
|
|
|
// Clean up any existing metadata from previous test runs
|
|
const storage = registry.getStorage();
|
|
try {
|
|
await storage.deleteMavenMetadata(testGroupId, testArtifactId);
|
|
} catch (error) {
|
|
// Ignore error if metadata doesn't exist
|
|
}
|
|
});
|
|
|
|
tap.test('Maven: should upload POM file (PUT /{groupPath}/{artifactId}/{version}/*.pom)', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const pomFilename = `${testArtifactId}-${testVersion}.pom`;
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'PUT',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${pomFilename}`,
|
|
headers: {
|
|
Authorization: `Bearer ${mavenToken}`,
|
|
'Content-Type': 'application/xml',
|
|
},
|
|
query: {},
|
|
body: testPomData,
|
|
});
|
|
|
|
expect(response.status).toEqual(201);
|
|
});
|
|
|
|
tap.test('Maven: should upload JAR file (PUT /{groupPath}/{artifactId}/{version}/*.jar)', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'PUT',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}`,
|
|
headers: {
|
|
Authorization: `Bearer ${mavenToken}`,
|
|
'Content-Type': 'application/java-archive',
|
|
},
|
|
query: {},
|
|
body: testJarData,
|
|
});
|
|
|
|
expect(response.status).toEqual(201);
|
|
});
|
|
|
|
tap.test('Maven: should retrieve uploaded POM file (GET)', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const pomFilename = `${testArtifactId}-${testVersion}.pom`;
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'GET',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${pomFilename}`,
|
|
headers: {},
|
|
query: {},
|
|
});
|
|
|
|
expect(response.status).toEqual(200);
|
|
expect(response.body).toBeInstanceOf(Buffer);
|
|
expect((response.body as Buffer).toString('utf-8')).toContain(testGroupId);
|
|
expect((response.body as Buffer).toString('utf-8')).toContain(testArtifactId);
|
|
expect((response.body as Buffer).toString('utf-8')).toContain(testVersion);
|
|
expect(response.headers['Content-Type']).toEqual('application/xml');
|
|
});
|
|
|
|
tap.test('Maven: should retrieve uploaded JAR file (GET)', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'GET',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}`,
|
|
headers: {},
|
|
query: {},
|
|
});
|
|
|
|
expect(response.status).toEqual(200);
|
|
expect(response.body).toBeInstanceOf(Buffer);
|
|
expect(response.headers['Content-Type']).toEqual('application/java-archive');
|
|
});
|
|
|
|
tap.test('Maven: should retrieve MD5 checksum for JAR (GET *.jar.md5)', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
|
|
const checksums = calculateMavenChecksums(testJarData);
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'GET',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}.md5`,
|
|
headers: {},
|
|
query: {},
|
|
});
|
|
|
|
expect(response.status).toEqual(200);
|
|
expect(response.body).toBeInstanceOf(Buffer);
|
|
expect((response.body as Buffer).toString('utf-8')).toEqual(checksums.md5);
|
|
expect(response.headers['Content-Type']).toEqual('text/plain');
|
|
});
|
|
|
|
tap.test('Maven: should retrieve SHA1 checksum for JAR (GET *.jar.sha1)', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
|
|
const checksums = calculateMavenChecksums(testJarData);
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'GET',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}.sha1`,
|
|
headers: {},
|
|
query: {},
|
|
});
|
|
|
|
expect(response.status).toEqual(200);
|
|
expect(response.body).toBeInstanceOf(Buffer);
|
|
expect((response.body as Buffer).toString('utf-8')).toEqual(checksums.sha1);
|
|
expect(response.headers['Content-Type']).toEqual('text/plain');
|
|
});
|
|
|
|
tap.test('Maven: should retrieve SHA256 checksum for JAR (GET *.jar.sha256)', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
|
|
const checksums = calculateMavenChecksums(testJarData);
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'GET',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}.sha256`,
|
|
headers: {},
|
|
query: {},
|
|
});
|
|
|
|
expect(response.status).toEqual(200);
|
|
expect(response.body).toBeInstanceOf(Buffer);
|
|
expect((response.body as Buffer).toString('utf-8')).toEqual(checksums.sha256);
|
|
expect(response.headers['Content-Type']).toEqual('text/plain');
|
|
});
|
|
|
|
tap.test('Maven: should retrieve SHA512 checksum for JAR (GET *.jar.sha512)', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
|
|
const checksums = calculateMavenChecksums(testJarData);
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'GET',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}.sha512`,
|
|
headers: {},
|
|
query: {},
|
|
});
|
|
|
|
expect(response.status).toEqual(200);
|
|
expect(response.body).toBeInstanceOf(Buffer);
|
|
expect((response.body as Buffer).toString('utf-8')).toEqual(checksums.sha512);
|
|
expect(response.headers['Content-Type']).toEqual('text/plain');
|
|
});
|
|
|
|
tap.test('Maven: should retrieve maven-metadata.xml (GET)', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'GET',
|
|
path: `/maven/${groupPath}/${testArtifactId}/maven-metadata.xml`,
|
|
headers: {},
|
|
query: {},
|
|
});
|
|
|
|
expect(response.status).toEqual(200);
|
|
expect(response.body).toBeInstanceOf(Buffer);
|
|
const xml = (response.body as Buffer).toString('utf-8');
|
|
expect(xml).toContain('<groupId>');
|
|
expect(xml).toContain('<artifactId>');
|
|
expect(xml).toContain('<version>1.0.0</version>');
|
|
expect(xml).toContain('<latest>1.0.0</latest>');
|
|
expect(xml).toContain('<release>1.0.0</release>');
|
|
expect(response.headers['Content-Type']).toEqual('application/xml');
|
|
});
|
|
|
|
tap.test('Maven: should upload a second version and update metadata', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const newVersion = '2.0.0';
|
|
const pomFilename = `${testArtifactId}-${newVersion}.pom`;
|
|
const jarFilename = `${testArtifactId}-${newVersion}.jar`;
|
|
const newPomData = Buffer.from(
|
|
createTestPom(testGroupId, testArtifactId, newVersion),
|
|
'utf-8'
|
|
);
|
|
|
|
// Upload POM
|
|
await registry.handleRequest({
|
|
method: 'PUT',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${newVersion}/${pomFilename}`,
|
|
headers: {
|
|
Authorization: `Bearer ${mavenToken}`,
|
|
'Content-Type': 'application/xml',
|
|
},
|
|
query: {},
|
|
body: newPomData,
|
|
});
|
|
|
|
// Upload JAR
|
|
await registry.handleRequest({
|
|
method: 'PUT',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${newVersion}/${jarFilename}`,
|
|
headers: {
|
|
Authorization: `Bearer ${mavenToken}`,
|
|
'Content-Type': 'application/java-archive',
|
|
},
|
|
query: {},
|
|
body: testJarData,
|
|
});
|
|
|
|
// Retrieve metadata and verify both versions are present
|
|
const response = await registry.handleRequest({
|
|
method: 'GET',
|
|
path: `/maven/${groupPath}/${testArtifactId}/maven-metadata.xml`,
|
|
headers: {},
|
|
query: {},
|
|
});
|
|
|
|
expect(response.status).toEqual(200);
|
|
const xml = (response.body as Buffer).toString('utf-8');
|
|
expect(xml).toContain('<version>1.0.0</version>');
|
|
expect(xml).toContain('<version>2.0.0</version>');
|
|
expect(xml).toContain('<latest>2.0.0</latest>');
|
|
expect(xml).toContain('<release>2.0.0</release>');
|
|
});
|
|
|
|
tap.test('Maven: should upload WAR file with correct content type', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const warVersion = '1.0.0-war';
|
|
const warFilename = `${testArtifactId}-${warVersion}.war`;
|
|
const warData = Buffer.from('fake war content', 'utf-8');
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'PUT',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${warVersion}/${warFilename}`,
|
|
headers: {
|
|
Authorization: `Bearer ${mavenToken}`,
|
|
'Content-Type': 'application/x-webarchive',
|
|
},
|
|
query: {},
|
|
body: warData,
|
|
});
|
|
|
|
expect(response.status).toEqual(201);
|
|
});
|
|
|
|
tap.test('Maven: should return 404 for non-existent artifact', async () => {
|
|
const groupPath = 'com/example/nonexistent';
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'GET',
|
|
path: `/maven/${groupPath}/fake-artifact/1.0.0/fake-artifact-1.0.0.jar`,
|
|
headers: {},
|
|
query: {},
|
|
});
|
|
|
|
expect(response.status).toEqual(404);
|
|
expect(response.body).toHaveProperty('error');
|
|
});
|
|
|
|
tap.test('Maven: should return 401 for unauthorized upload', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const jarFilename = `${testArtifactId}-3.0.0.jar`;
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'PUT',
|
|
path: `/maven/${groupPath}/${testArtifactId}/3.0.0/${jarFilename}`,
|
|
headers: {
|
|
// No authorization header
|
|
'Content-Type': 'application/java-archive',
|
|
},
|
|
query: {},
|
|
body: testJarData,
|
|
});
|
|
|
|
expect(response.status).toEqual(401);
|
|
expect(response.body).toHaveProperty('error');
|
|
});
|
|
|
|
tap.test('Maven: should reject POM upload with mismatched GAV', async () => {
|
|
const groupPath = 'com/mismatch/test';
|
|
const pomFilename = `different-artifact-1.0.0.pom`;
|
|
// POM contains different GAV than the path
|
|
const mismatchedPom = Buffer.from(
|
|
createTestPom('com.other.group', 'other-artifact', '1.0.0'),
|
|
'utf-8'
|
|
);
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'PUT',
|
|
path: `/maven/${groupPath}/different-artifact/1.0.0/${pomFilename}`,
|
|
headers: {
|
|
Authorization: `Bearer ${mavenToken}`,
|
|
'Content-Type': 'application/xml',
|
|
},
|
|
query: {},
|
|
body: mismatchedPom,
|
|
});
|
|
|
|
expect(response.status).toEqual(400);
|
|
expect(response.body).toHaveProperty('error');
|
|
});
|
|
|
|
tap.test('Maven: should delete an artifact (DELETE)', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'DELETE',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}`,
|
|
headers: {
|
|
Authorization: `Bearer ${mavenToken}`,
|
|
},
|
|
query: {},
|
|
});
|
|
|
|
expect(response.status).toEqual(200);
|
|
|
|
// Verify artifact was deleted
|
|
const getResponse = await registry.handleRequest({
|
|
method: 'GET',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}`,
|
|
headers: {},
|
|
query: {},
|
|
});
|
|
|
|
expect(getResponse.status).toEqual(404);
|
|
});
|
|
|
|
tap.test('Maven: should return 404 for checksum of deleted artifact', async () => {
|
|
const groupPath = testGroupId.replace(/\./g, '/');
|
|
const jarFilename = `${testArtifactId}-${testVersion}.jar`;
|
|
|
|
const response = await registry.handleRequest({
|
|
method: 'GET',
|
|
path: `/maven/${groupPath}/${testArtifactId}/${testVersion}/${jarFilename}.md5`,
|
|
headers: {},
|
|
query: {},
|
|
});
|
|
|
|
expect(response.status).toEqual(404);
|
|
});
|
|
|
|
tap.postTask('cleanup registry', async () => {
|
|
if (registry) {
|
|
registry.destroy();
|
|
}
|
|
});
|
|
|
|
export default tap.start();
|