Skip to content
Merged
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
12 changes: 5 additions & 7 deletions src/cli/command/install-tool.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ vi.mock('../prepare-tool', () => mocks);
describe('cli/command/install-tool', () => {
beforeEach(() => {
delete env.NODE_VERSION;
delete env.IGNORED_TOOLS;
env.IGNORED_TOOLS = 'pnpm,php';
});

test('install-tool', async () => {
Expand All @@ -42,9 +42,8 @@ describe('cli/command/install-tool', () => {
mocks.installTool.mockRejectedValueOnce(new Error('test'));
expect(await cli.run(['node'])).toBe(1);

env.IGNORED_TOOLS = 'node';
expect(await cli.run(['node'])).toBe(0);
expect(logger.info).toHaveBeenCalledWith({ tool: 'node' }, 'tool ignored');
expect(await cli.run(['php'])).toBe(0);
expect(logger.info).toHaveBeenCalledWith({ tool: 'php' }, 'tool ignored');
});

test('containerbase-cli install tool', async () => {
Expand All @@ -69,8 +68,7 @@ describe('cli/command/install-tool', () => {
mocks.installTool.mockRejectedValueOnce(new Error('test'));
expect(await cli.run(['install', 'tool', 'node'])).toBe(1);

env.IGNORED_TOOLS = 'node';
expect(await cli.run(['install', 'tool', 'node'])).toBe(0);
expect(logger.info).toHaveBeenCalledWith({ tool: 'node' }, 'tool ignored');
expect(await cli.run(['install', 'tool', 'php'])).toBe(0);
expect(logger.info).toHaveBeenCalledWith({ tool: 'php' }, 'tool ignored');
});
});
7 changes: 3 additions & 4 deletions src/cli/command/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('cli/command/utils', () => {
beforeEach(() => {
delete env.NODE_VERSION;
delete env.DEL_CLI_VERSION;
delete env.IGNORED_TOOLS;
env.IGNORED_TOOLS = 'php,pnpm';
});

test('getVersion', () => {
Expand All @@ -19,8 +19,7 @@ describe('cli/command/utils', () => {

test('isToolIgnored', async () => {
expect(await isToolIgnored('node')).toBe(false);
env.IGNORED_TOOLS = 'node,pnpm';
expect(await isToolIgnored('node')).toBe(true);
expect(await isToolIgnored('php')).toBe(false);
expect(await isToolIgnored('pnpm')).toBe(true);
expect(await isToolIgnored('php')).toBe(true);
});
});
2 changes: 1 addition & 1 deletion src/cli/install-tool/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import fs from 'node:fs/promises';
import { beforeAll, describe, expect, test, vi } from 'vitest';
import { rootPath } from '../../../test/path';
import { VersionService } from '../services';
import { NpmVersionResolver } from '../tools/node/resolver';
import { NpmBaseInstallService } from '../tools/node/utils';
Expand All @@ -11,6 +10,7 @@ import {
RubyGemVersionResolver,
} from '../tools/ruby/utils';
import { installTool, resolveVersion } from '.';
import { rootPath } from '~test/path';

vi.mock('del');
vi.mock('execa');
Expand Down
2 changes: 1 addition & 1 deletion src/cli/install-tool/install-tool.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import fs from 'node:fs/promises';
import type { Container } from 'inversify';
import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
import { rootPath } from '../../../test/path';
import { VersionService, createContainer } from '../services';
import { BunInstallService } from '../tools/bun';
import { LegacyToolInstallService } from './install-legacy-tool.service';
import { INSTALL_TOOL_TOKEN, InstallToolService } from './install-tool.service';
import { rootPath } from '~test/path';

vi.mock('del');
vi.mock('execa');
Expand Down
15 changes: 6 additions & 9 deletions src/cli/services/apt.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { env } from 'node:process';
import type { Container } from 'inversify';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { AptService, createContainer } from '.';
import { AptService } from '.';
import { testContainer } from '~test/path';

const mocks = vi.hoisted(() => ({
execa: vi.fn(),
Expand All @@ -17,15 +18,15 @@ vi.mock('node:fs/promises', async (importActual) => ({

describe('cli/services/apt.service', () => {
let child!: Container;
let svc!: AptService;

beforeEach(() => {
child = createContainer();
beforeEach(async () => {
child = await testContainer();
svc = await child.getAsync(AptService);
delete env.APT_HTTP_PROXY;
});

test('skips install', async () => {
const svc = await child.getAsync(AptService);

mocks.execa.mockResolvedValueOnce({
stdout: 'Status: install ok installed',
});
Expand All @@ -34,8 +35,6 @@ describe('cli/services/apt.service', () => {
});

test('works', async () => {
const svc = await child.getAsync(AptService);

mocks.execa.mockRejectedValueOnce(new Error('not installed'));
await svc.install('some-pkg');
expect(mocks.execa).toHaveBeenCalledTimes(3);
Expand All @@ -45,8 +44,6 @@ describe('cli/services/apt.service', () => {

test('uses proxy', async () => {
env.APT_HTTP_PROXY = 'http://proxy';
const svc = await child.getAsync(AptService);

mocks.execa.mockRejectedValueOnce(new Error('not installed'));
await svc.install('some-pkg', 'other-pkg');
expect(mocks.execa).toHaveBeenCalledTimes(4);
Expand Down
7 changes: 4 additions & 3 deletions src/cli/services/compression.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import type { Container } from 'inversify';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { CompressionService, createContainer } from '.';
import { CompressionService } from '.';
import { testContainer } from '~test/path';

vi.mock('execa');

describe('cli/services/compression.service', () => {
let child!: Container;

beforeEach(() => {
child = createContainer();
beforeEach(async () => {
child = await testContainer();
});

test('extracts with bstar', async () => {
Expand Down
27 changes: 15 additions & 12 deletions src/cli/services/env.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { sep } from 'node:path';
import { env } from 'node:process';
import type { Container } from 'inversify';
import { Container } from 'inversify';
import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
import { EnvService, createContainer } from '.';
import { rootPath } from '~test/path';
import { EnvService } from '.';
import { rootPath, testContainer } from '~test/path';

const mocks = vi.hoisted(() => ({ arch: vi.fn() }));

Expand All @@ -21,27 +21,30 @@ describe('cli/services/env.service', () => {
let rootDir: string | undefined;
let svc!: EnvService;

async function init() {
child = await testContainer();
svc = await child.getAsync(EnvService);
}

beforeAll(() => {
rootDir = globalThis.rootDir;
});

beforeEach(async () => {
child = createContainer();
globalThis.rootDir = rootDir;
mocks.arch.mockReturnValue('x64');
svc = await child.getAsync(EnvService);
await init();
});

test('arch', async () => {
expect(svc.arch).toBe('amd64');

mocks.arch.mockReturnValue('arm64');
expect((await child.getAsync(EnvService)).arch).toBe('arm64');
await init();
expect(svc.arch).toBe('arm64');

mocks.arch.mockReturnValue('invalid');
await expect(
async () => (await child.getAsync(EnvService)).arch,
).rejects.toThrow();
await expect(init()).rejects.toThrow();
});

test('isRoot', () => {
Expand Down Expand Up @@ -95,9 +98,9 @@ describe('cli/services/env.service', () => {
expect(svc.isToolIgnored('node')).toBe(false);

env.IGNORED_TOOLS = 'npm,yarn';
const e = await child.getAsync(EnvService);
expect(e.isToolIgnored('npm')).toBe(true);
expect(e.isToolIgnored('node')).toBe(false);
await init();
expect(svc.isToolIgnored('npm')).toBe(true);
expect(svc.isToolIgnored('node')).toBe(false);
});

test('replaceUrl', () => {
Expand Down
4 changes: 2 additions & 2 deletions src/cli/services/env.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { arch } from 'node:os';
import { join } from 'node:path';
import { env, geteuid } from 'node:process';
import { injectable } from 'inversify';
import { bindingScopeValues, injectable } from 'inversify';
import { type Arch, logger } from '../utils';

export type Replacements = [string, string][];
Expand All @@ -14,7 +14,7 @@ const compare = (() => {
return (a: string, b: string) => collator.compare(a, b);
})();

@injectable()
@injectable(bindingScopeValues.Singleton)
export class EnvService {
readonly arch: Arch;
private uid: number;
Expand Down
6 changes: 3 additions & 3 deletions src/cli/services/http.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ import { env } from 'node:process';
import type { Container } from 'inversify';
import { beforeEach, describe, expect, test } from 'vitest';
import { logger } from '../utils';
import { HttpService, createContainer } from '.';
import { HttpService } from '.';
import { scope } from '~test/http-mock';
import { cachePath } from '~test/path';
import { cachePath, testContainer } from '~test/path';

const baseUrl = 'https://example.com';
describe('cli/services/http.service', () => {
let child!: Container;
let http!: HttpService;

beforeEach(async () => {
child = createContainer();
child = await testContainer();
http = await child.getAsync(HttpService);

for (const key of Object.keys(env)) {
Expand Down
2 changes: 1 addition & 1 deletion src/cli/services/http.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class HttpService {
private readonly _opts: Pick<OptionsInit, 'headers'> = {};

@postConstruct()
protected init(): void {
protected [Symbol('construct')](): void {
Object.assign(this._opts, {
headers: {
'user-agent': `containerbase/${
Expand Down
21 changes: 13 additions & 8 deletions src/cli/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Container } from 'inversify';
import { type Bind, Container, ContainerModule } from 'inversify';
import { AptService } from './apt.service';
import { CompressionService } from './compression.service';
import { EnvService } from './env.service';
Expand All @@ -15,14 +15,19 @@ export {
VersionService,
};

export const rootContainer = new Container();
function init<T extends { bind: Bind }>(options: T): void {
options.bind(AptService).toSelf();
options.bind(CompressionService).toSelf();
options.bind(EnvService).toSelf();
options.bind(HttpService).toSelf();
options.bind(PathService).toSelf();
options.bind(VersionService).toSelf();
}

export const rootContainerModule = new ContainerModule(init);

rootContainer.bind(AptService).toSelf();
rootContainer.bind(CompressionService).toSelf();
rootContainer.bind(EnvService).toSelf();
rootContainer.bind(HttpService).toSelf();
rootContainer.bind(PathService).toSelf();
rootContainer.bind(VersionService).toSelf();
const rootContainer = new Container();
init(rootContainer);

export function createContainer(parent = rootContainer): Container {
return new Container({ parent });
Expand Down
8 changes: 4 additions & 4 deletions src/cli/services/path.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ import { mkdir, readFile, stat } from 'node:fs/promises';
import { platform } from 'node:os';
import { env } from 'node:process';
import { deleteAsync } from 'del';
import type { Container } from 'inversify';
import { Container } from 'inversify';
import { beforeEach, describe, expect, test } from 'vitest';
import { fileRights, pathExists } from '../utils';
import { PathService, createContainer } from '.';
import { rootPath } from '~test/path';
import { PathService } from '.';
import { rootPath, testContainer } from '~test/path';

describe('cli/services/path.service', () => {
const path = env.PATH;
let child!: Container;
let pathSvc!: PathService;

beforeEach(async () => {
child = createContainer();
child = await testContainer();
env.PATH = path;
delete env.NODE_VERSION;
pathSvc = await child.getAsync(PathService);
Expand Down
4 changes: 2 additions & 2 deletions src/cli/services/path.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import fs from 'node:fs/promises';
import { dirname, join } from 'node:path';
import { env } from 'node:process';
import { isNonEmptyStringAndNotWhitespace } from '@sindresorhus/is';
import { inject, injectable } from 'inversify';
import { bindingScopeValues, inject, injectable } from 'inversify';
import { fileRights, logger, pathExists, tool2path } from '../utils';
import { EnvService } from './env.service';

Expand All @@ -14,7 +14,7 @@ export interface FileOwnerConfig {
mode?: number;
}

@injectable()
@injectable(bindingScopeValues.Singleton)
export class PathService {
@inject(EnvService)
private readonly envSvc!: EnvService;
Expand Down
6 changes: 3 additions & 3 deletions src/cli/services/version.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { mkdir } from 'fs/promises';
import { Container } from 'inversify';
import { beforeEach, describe, expect, test } from 'vitest';
import { VersionService, createContainer } from '.';
import { rootPath } from '~test/path';
import { VersionService } from '.';
import { rootPath, testContainer } from '~test/path';

describe('cli/services/version.service', () => {
let child!: Container;
let svc!: VersionService;

beforeEach(async () => {
child = createContainer();
child = await testContainer();
svc = await child.getAsync(VersionService);
});

Expand Down
8 changes: 8 additions & 0 deletions test/path.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { join, sep } from 'node:path';
import { Container } from 'inversify';
import { createContainer, rootContainerModule } from '../src/cli/services';

export function cachePath(path: string): string {
return `${globalThis.cacheDir}/${path}`.replace(/\/+/g, sep);
Expand All @@ -10,3 +12,9 @@ export function rootPath(path?: string): string {
}
return join(globalThis.rootDir!, path).replace(/\/+/g, sep);
}

export async function testContainer() {
const parent = new Container();
await parent.load(rootContainerModule);
return createContainer(parent);
}