Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 115 additions & 20 deletions src/targets/__tests__/maven.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { homedir } from 'os';
import { join } from 'path';
import { NoneArtifactProvider } from '../../artifact_providers/none';
import {
GRADLE_PROPERTIES_FILENAME,
MavenTarget,
POM_DEFAULT_FILENAME,
targetOptions,
targetSecrets,
} from '../maven';
import { retrySpawnProcess } from '../../utils/async';
import { withTempDir } from '../../utils/files';
import { promises as fsPromises } from 'fs';

jest.mock('../../utils/files');

Expand All @@ -19,6 +21,8 @@ jest.mock('fs', () => ({
readFile: jest.fn((file: string) => file),
readdir: async () => Promise.resolve([]), // empty dir
unlink: jest.fn(),
access: jest.fn(),
copyFile: jest.fn(),
},
}));

Expand Down Expand Up @@ -188,16 +192,22 @@ describe('publish', () => {
beforeEach(() => jest.resetAllMocks());

test('main flow', async () => {
(withTempDir as jest.MockedFunction<
typeof withTempDir
>).mockImplementationOnce(async cb => {
return await cb(tmpDirName);
});

const callOrder: string[] = [];
const mvnTarget = createMavenTarget();
const createGradlePropsMock = jest.fn(
async () => void callOrder.push('createGradleProps')
const makeSnapshotMock = jest.fn(
async () => void callOrder.push('makeSnapshot')
);
mvnTarget.createUserGradlePropsFile = createGradlePropsMock;
const deleteGradlePropsMock = jest.fn(
async () => void callOrder.push('deleteGradleProps')
mvnTarget.createUserGradlePropsFile = makeSnapshotMock;
const restoreGradleProps = jest.fn(
async () => void callOrder.push('restoreSnapshot')
);
mvnTarget.deleteUserGradlePropsFile = deleteGradlePropsMock;
mvnTarget.restoreGradleProps = restoreGradleProps;
const uploadMock = jest.fn(async () => void callOrder.push('upload'));
mvnTarget.upload = uploadMock;
(retrySpawnProcess as jest.MockedFunction<
Expand All @@ -208,30 +218,30 @@ describe('publish', () => {

const revision = 'r3v1s10n';
await mvnTarget.publish('1.0.0', revision);
expect(createGradlePropsMock).toHaveBeenCalledTimes(1);
expect(makeSnapshotMock).toHaveBeenCalledTimes(1);
expect(uploadMock).toHaveBeenCalledTimes(1);
expect(uploadMock).toHaveBeenLastCalledWith(revision);
expect(deleteGradlePropsMock).toHaveBeenCalledTimes(1);
expect(restoreGradleProps).toHaveBeenCalledTimes(1);
expect(retrySpawnProcess).toHaveBeenCalledTimes(1);
expect(retrySpawnProcess).toHaveBeenCalledWith(DEFAULT_OPTION_VALUE, [
'closeAndReleaseRepository',
]);
expect(callOrder).toStrictEqual([
'createGradleProps',
'makeSnapshot',
'upload',
'closeAndRelease',
'deleteGradleProps',
'restoreSnapshot',
]);
});

test('upload POM', async () => {
// simple mock to always use the same temporary directory,
// instead of creating a new one
(withTempDir as jest.MockedFunction<typeof withTempDir>).mockImplementation(
async cb => {
return await cb(tmpDirName);
}
);
(withTempDir as jest.MockedFunction<
typeof withTempDir
>).mockImplementationOnce(async cb => {
return await cb(tmpDirName);
});

const mvnTarget = createMavenTarget();
mvnTarget.getArtifactsForRevision = jest
Expand Down Expand Up @@ -275,11 +285,11 @@ describe('publish', () => {
test('upload BOM', async () => {
// simple mock to always use the same temporary directory,
// instead of creating a new one
(withTempDir as jest.MockedFunction<typeof withTempDir>).mockImplementation(
async cb => {
return await cb(tmpDirName);
}
);
(withTempDir as jest.MockedFunction<
typeof withTempDir
>).mockImplementationOnce(async cb => {
return await cb(tmpDirName);
});

const mvnTarget = createMavenTarget();
mvnTarget.getArtifactsForRevision = jest
Expand Down Expand Up @@ -338,3 +348,88 @@ describe('get gradle home directory', () => {
expect(actual).toEqual(expected);
});
});

describe('withGradleProps', () => {
beforeAll(() => {
setTargetSecretsInEnv();
});

afterAll(() => {
removeTargetSecretsFromEnv();
});

beforeEach(() => {
delete process.env.GRADLE_USER_HOME;
});

/**
* Checks whether the properties file is correct.
* @param path Path to the properties file.
*/
async function testCorrectPropsFile(path: string): Promise<void> {
try {
const content = (await fsPromises.readFile(path)).toString();
Comment thread
iker-barriocanal marked this conversation as resolved.
expect(content).toMatch(`mavenCentralUsername=${DEFAULT_OPTION_VALUE}`);
Comment thread
iker-barriocanal marked this conversation as resolved.
expect(content).toMatch(`mavenCentralPassword=${DEFAULT_OPTION_VALUE}`);
} catch (error) {
throw new Error(`Cannot read the contents of the props file: ${error}`);
}
}

test('non-existent props file', async () => {
await withTempDir(async dir => {
process.env.GRADLE_USER_HOME = dir;
const expectedPropsPath = `${dir}/${GRADLE_PROPERTIES_FILENAME}`;

/**
* Expect 3 assertions:
* 2 testing whether the correct file in execution is created.
* 1 testing whether the user's file has been deleted.
*/
expect.assertions(3);

const mvnTarget = createMavenTarget(getRequiredTargetConfig());
mvnTarget.upload = jest
.fn()
.mockImplementationOnce(
async () => await testCorrectPropsFile(expectedPropsPath)
);

await mvnTarget.publish('v3rs10n', 'r3v1s10n');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expected you to test withGradleProps directly here, instead of mocking upload with your test method and then invoking publish. This would be the correct way to write a unit test for your helper.

await expect(fsPromises.access(expectedPropsPath)).rejects.toThrowError(
/ENOENT: no such file/
Comment on lines +399 to +400

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just expect(fs.exists(expectedPropsPath)).to.not.be.true()?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because to and be don't exist. Moving to accessSync since it's cleaner, but if you know an even cleaner way I can update it.

);
});
});

test('existent props file', async () => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missing some test cases:

  1. What if the callback function throws an error? You should test that we still restore the snapshot/delete our own props file
  2. What if we simply cannot backup an existing snapshot file? Where's the test case for that?
  3. What if we cannot restore a snapshot file for some reason?

await withTempDir(async dir => {
process.env.GRADLE_USER_HOME = dir;
const expectedPropsPath = `${dir}/${GRADLE_PROPERTIES_FILENAME}`;
const testProps = 'some random data to test prop snapshotting';

/**
* Expect 3 assertions:
* 2 testing whether the correct file in execution is created.
* 1 testing whether the file user's props file has correctly been restored.
*/
expect.assertions(3);

// If we can't create the props file this test doesn't test anything
// new, so stop it (don't catch the error).
await fsPromises.writeFile(expectedPropsPath, testProps);

const mvnTarget = createMavenTarget(getRequiredTargetConfig());
mvnTarget.upload = jest
.fn()
.mockImplementationOnce(
async () => await testCorrectPropsFile(expectedPropsPath)
);
await mvnTarget.publish('v3rs10n', 'r3v1s10n');

expect(
(await fsPromises.readFile(expectedPropsPath)).toString()
).toStrictEqual(testProps);
});
});
});
Loading