mirror of
https://github.com/selfxyz/self.git
synced 2026-01-09 22:58:20 -05:00
* code rabbit feedback for staging auto deploy logic * fix jest test * cr feedback * workflow fixes * fix tests * restore cache
317 lines
9.7 KiB
JavaScript
317 lines
9.7 KiB
JavaScript
// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
|
|
|
/**
|
|
* @jest-environment node
|
|
*
|
|
* SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc.
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
* NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
|
*/
|
|
|
|
/**
|
|
* Unit tests for version-manager.cjs
|
|
*
|
|
* This file is only meant to be run with Jest.
|
|
*/
|
|
|
|
const path = require('path');
|
|
|
|
// Mock file system operations - data
|
|
const mockPackageJson = { version: '1.2.3' };
|
|
const mockVersionJson = {
|
|
ios: { build: 100, lastDeployed: '2024-01-01T00:00:00Z' },
|
|
android: { build: 200, lastDeployed: '2024-01-01T00:00:00Z' },
|
|
};
|
|
|
|
// Use manual mocking instead of jest.mock to avoid hoisting issues
|
|
const fs = require('fs');
|
|
|
|
// Store originals for restore
|
|
const originalReadFileSync = fs.readFileSync;
|
|
const originalWriteFileSync = fs.writeFileSync;
|
|
const originalExistsSync = fs.existsSync;
|
|
const originalAppendFileSync = fs.appendFileSync;
|
|
|
|
// Setup mocks before importing the module
|
|
function setupMocks() {
|
|
fs.readFileSync = function (filePath, encoding) {
|
|
if (filePath.includes('package.json')) {
|
|
return JSON.stringify(mockPackageJson);
|
|
}
|
|
if (filePath.includes('version.json')) {
|
|
return JSON.stringify(mockVersionJson);
|
|
}
|
|
return originalReadFileSync(filePath, encoding);
|
|
};
|
|
|
|
fs.writeFileSync = function () {};
|
|
fs.existsSync = function () {
|
|
return true;
|
|
};
|
|
fs.appendFileSync = function () {};
|
|
}
|
|
|
|
function restoreMocks() {
|
|
fs.readFileSync = originalReadFileSync;
|
|
fs.writeFileSync = originalWriteFileSync;
|
|
fs.existsSync = originalExistsSync;
|
|
fs.appendFileSync = originalAppendFileSync;
|
|
}
|
|
|
|
// Setup mocks before requiring the module
|
|
setupMocks();
|
|
|
|
// Import module after mocks are set up
|
|
const versionManager = require('./version-manager.cjs');
|
|
|
|
describe('version-manager', () => {
|
|
beforeEach(() => {
|
|
// Reset mock data
|
|
mockPackageJson.version = '1.2.3';
|
|
mockVersionJson.ios.build = 100;
|
|
mockVersionJson.android.build = 200;
|
|
});
|
|
|
|
afterAll(() => {
|
|
restoreMocks();
|
|
});
|
|
|
|
describe('getVersionInfo', () => {
|
|
it('should return current version information', () => {
|
|
const info = versionManager.getVersionInfo();
|
|
expect(info.version).toBe('1.2.3');
|
|
expect(info.iosBuild).toBe(100);
|
|
expect(info.androidBuild).toBe(200);
|
|
});
|
|
});
|
|
|
|
describe('bumpVersion', () => {
|
|
it('should bump major version correctly', () => {
|
|
const result = versionManager.bumpVersion('major', 'both');
|
|
expect(result.version).toBe('2.0.0');
|
|
expect(result.iosBuild).toBe(101);
|
|
expect(result.androidBuild).toBe(201);
|
|
});
|
|
|
|
it('should bump minor version correctly', () => {
|
|
const result = versionManager.bumpVersion('minor', 'both');
|
|
expect(result.version).toBe('1.3.0');
|
|
expect(result.iosBuild).toBe(101);
|
|
expect(result.androidBuild).toBe(201);
|
|
});
|
|
|
|
it('should bump patch version correctly', () => {
|
|
const result = versionManager.bumpVersion('patch', 'both');
|
|
expect(result.version).toBe('1.2.4');
|
|
expect(result.iosBuild).toBe(101);
|
|
expect(result.androidBuild).toBe(201);
|
|
});
|
|
|
|
it('should bump build numbers only', () => {
|
|
const result = versionManager.bumpVersion('build', 'both');
|
|
expect(result.version).toBe('1.2.3');
|
|
expect(result.iosBuild).toBe(101);
|
|
expect(result.androidBuild).toBe(201);
|
|
});
|
|
|
|
it('should respect platform parameter (ios only)', () => {
|
|
const result = versionManager.bumpVersion('build', 'ios');
|
|
expect(result.version).toBe('1.2.3');
|
|
expect(result.iosBuild).toBe(101);
|
|
expect(result.androidBuild).toBe(200); // unchanged
|
|
});
|
|
|
|
it('should respect platform parameter (android only)', () => {
|
|
const result = versionManager.bumpVersion('build', 'android');
|
|
expect(result.version).toBe('1.2.3');
|
|
expect(result.iosBuild).toBe(100); // unchanged
|
|
expect(result.androidBuild).toBe(201);
|
|
});
|
|
|
|
it('should throw on invalid bump type', () => {
|
|
expect(() => versionManager.bumpVersion('invalid', 'both')).toThrow(
|
|
/Invalid bump type/,
|
|
);
|
|
});
|
|
|
|
it('should throw on invalid platform', () => {
|
|
expect(() => versionManager.bumpVersion('build', 'invalid')).toThrow(
|
|
/Invalid platform/,
|
|
);
|
|
});
|
|
|
|
it('should handle version with major bump resetting minor and patch', () => {
|
|
mockPackageJson.version = '2.5.8';
|
|
const result = versionManager.bumpVersion('major', 'both');
|
|
expect(result.version).toBe('3.0.0');
|
|
});
|
|
|
|
it('should handle version with minor bump resetting patch', () => {
|
|
mockPackageJson.version = '2.5.8';
|
|
const result = versionManager.bumpVersion('minor', 'both');
|
|
expect(result.version).toBe('2.6.0');
|
|
});
|
|
});
|
|
|
|
describe('applyVersions', () => {
|
|
it('should reject invalid version format - not semver', () => {
|
|
expect(() => versionManager.applyVersions('invalid', 1, 1)).toThrow(
|
|
/Invalid version format/,
|
|
);
|
|
});
|
|
|
|
it('should reject invalid version format - two parts', () => {
|
|
expect(() => versionManager.applyVersions('1.2', 1, 1)).toThrow(
|
|
/Invalid version format/,
|
|
);
|
|
});
|
|
|
|
it('should reject invalid version format - four parts', () => {
|
|
expect(() => versionManager.applyVersions('1.2.3.4', 1, 1)).toThrow(
|
|
/Invalid version format/,
|
|
);
|
|
});
|
|
|
|
it('should reject invalid version format - empty string', () => {
|
|
expect(() => versionManager.applyVersions('', 1, 1)).toThrow(
|
|
/Invalid version format/,
|
|
);
|
|
});
|
|
|
|
it('should reject invalid version format - null', () => {
|
|
expect(() => versionManager.applyVersions(null, 1, 1)).toThrow(
|
|
/Invalid version format/,
|
|
);
|
|
});
|
|
|
|
it('should reject invalid iOS build number - zero', () => {
|
|
expect(() => versionManager.applyVersions('1.2.3', 0, 1)).toThrow(
|
|
/Invalid iOS build/,
|
|
);
|
|
});
|
|
|
|
it('should reject invalid iOS build number - negative', () => {
|
|
expect(() => versionManager.applyVersions('1.2.3', -1, 1)).toThrow(
|
|
/Invalid iOS build/,
|
|
);
|
|
});
|
|
|
|
it('should reject invalid iOS build number - non-numeric string', () => {
|
|
expect(() => versionManager.applyVersions('1.2.3', 'abc', 1)).toThrow(
|
|
/Invalid iOS build/,
|
|
);
|
|
});
|
|
|
|
it('should reject invalid iOS build number - float', () => {
|
|
expect(() => versionManager.applyVersions('1.2.3', 1.5, 1)).toThrow(
|
|
/Invalid iOS build/,
|
|
);
|
|
});
|
|
|
|
it('should reject invalid Android build number - zero', () => {
|
|
expect(() => versionManager.applyVersions('1.2.3', 1, 0)).toThrow(
|
|
/Invalid Android build/,
|
|
);
|
|
});
|
|
|
|
it('should reject invalid Android build number - negative', () => {
|
|
expect(() => versionManager.applyVersions('1.2.3', 1, -1)).toThrow(
|
|
/Invalid Android build/,
|
|
);
|
|
});
|
|
|
|
it('should reject invalid Android build number - non-numeric string', () => {
|
|
expect(() => versionManager.applyVersions('1.2.3', 1, 'xyz')).toThrow(
|
|
/Invalid Android build/,
|
|
);
|
|
});
|
|
|
|
it('should reject invalid Android build number - float', () => {
|
|
expect(() => versionManager.applyVersions('1.2.3', 1, 2.5)).toThrow(
|
|
/Invalid Android build/,
|
|
);
|
|
});
|
|
|
|
it('should accept string build numbers that parse to integers', () => {
|
|
expect(() =>
|
|
versionManager.applyVersions('1.2.3', '100', '200'),
|
|
).not.toThrow();
|
|
});
|
|
|
|
it('should accept large build numbers', () => {
|
|
expect(() =>
|
|
versionManager.applyVersions('1.2.3', 99999, 88888),
|
|
).not.toThrow();
|
|
});
|
|
|
|
it('should write correct values to files', () => {
|
|
// Track write calls
|
|
const writeCalls = [];
|
|
fs.writeFileSync = function (filePath, content) {
|
|
writeCalls.push({ filePath, content });
|
|
};
|
|
|
|
versionManager.applyVersions('2.0.0', 150, 250);
|
|
|
|
// Verify writes occurred
|
|
expect(writeCalls.length).toBe(2);
|
|
|
|
// Find and verify package.json write
|
|
const packageWrite = writeCalls.find(call =>
|
|
call.filePath.includes('package.json'),
|
|
);
|
|
expect(packageWrite).toBeDefined();
|
|
const updatedPackage = JSON.parse(packageWrite.content);
|
|
expect(updatedPackage.version).toBe('2.0.0');
|
|
|
|
// Find and verify version.json write
|
|
const versionWrite = writeCalls.find(call =>
|
|
call.filePath.includes('version.json'),
|
|
);
|
|
expect(versionWrite).toBeDefined();
|
|
const updatedVersion = JSON.parse(versionWrite.content);
|
|
expect(updatedVersion.ios.build).toBe(150);
|
|
expect(updatedVersion.android.build).toBe(250);
|
|
});
|
|
});
|
|
|
|
describe('readPackageJson', () => {
|
|
it('should read and parse package.json', () => {
|
|
const pkg = versionManager.readPackageJson();
|
|
expect(pkg.version).toBe('1.2.3');
|
|
});
|
|
|
|
it('should throw error if file does not exist', () => {
|
|
const originalExists = fs.existsSync;
|
|
fs.existsSync = function () {
|
|
return false;
|
|
};
|
|
expect(() => versionManager.readPackageJson()).toThrow(
|
|
/package.json not found/,
|
|
);
|
|
fs.existsSync = originalExists;
|
|
});
|
|
});
|
|
|
|
describe('readVersionJson', () => {
|
|
it('should read and parse version.json', () => {
|
|
const version = versionManager.readVersionJson();
|
|
expect(version.ios.build).toBe(100);
|
|
expect(version.android.build).toBe(200);
|
|
});
|
|
|
|
it('should throw error if file does not exist', () => {
|
|
const originalExists = fs.existsSync;
|
|
fs.existsSync = function () {
|
|
return false;
|
|
};
|
|
expect(() => versionManager.readVersionJson()).toThrow(
|
|
/version.json not found/,
|
|
);
|
|
fs.existsSync = originalExists;
|
|
});
|
|
});
|
|
});
|