Skip to content

Commit

Permalink
Merge pull request #172 from inversify/refactor/update-instance-resol…
Browse files Browse the repository at this point in the history
…ution-with-post-construct-checks

Update instance resolution with post construct checks
  • Loading branch information
notaphplover authored Dec 9, 2024
2 parents 1a7bd2f + ab54aff commit 04094c0
Show file tree
Hide file tree
Showing 6 changed files with 755 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
import { afterAll, beforeAll, describe, expect, it, jest } from '@jest/globals';

import { ServiceIdentifier } from '@inversifyjs/common';

import { BindingActivation } from '../../binding/models/BindingActivation';
import { ResolutionParams } from '../models/ResolutionParams';
import { resolveBindingActivations } from './resolveBindingActivations';

describe(resolveBindingActivations.name, () => {
describe('having a non promise value', () => {
let paramsMock: jest.Mocked<ResolutionParams>;
let serviceIdentifierFixture: ServiceIdentifier;
let valueFixture: unknown;

beforeAll(() => {
paramsMock = {
getActivations: jest.fn(),
} as Partial<
jest.Mocked<ResolutionParams>
> as jest.Mocked<ResolutionParams>;
serviceIdentifierFixture = 'service-id';
valueFixture = Symbol();
});

describe('when called, and params.getActivations() returns undefined', () => {
let result: unknown;

beforeAll(() => {
result = resolveBindingActivations(
paramsMock,
serviceIdentifierFixture,
valueFixture,
);
});

afterAll(() => {
jest.clearAllMocks();
});

it('should call params.getActivations', () => {
expect(paramsMock.getActivations).toHaveBeenCalledTimes(1);
expect(paramsMock.getActivations).toHaveBeenCalledWith(
serviceIdentifierFixture,
);
});

it('should return value', () => {
expect(result).toBe(valueFixture);
});
});

describe('when called, and params.getActivations() returns sync activations', () => {
let activationMock: jest.Mock<BindingActivation>;
let activationResult: unknown;

let result: unknown;

beforeAll(() => {
activationResult = Symbol('activation-result');

activationMock = jest.fn().mockReturnValueOnce(activationResult);

paramsMock.getActivations.mockReturnValueOnce([activationMock]);

result = resolveBindingActivations(
paramsMock,
serviceIdentifierFixture,
valueFixture,
);
});

afterAll(() => {
jest.clearAllMocks();
});

it('should call params.getActivations', () => {
expect(paramsMock.getActivations).toHaveBeenCalledTimes(1);
expect(paramsMock.getActivations).toHaveBeenCalledWith(
serviceIdentifierFixture,
);
});

it('should call activation', () => {
expect(activationMock).toHaveBeenCalledTimes(1);
expect(activationMock).toHaveBeenCalledWith(valueFixture);
});

it('should return value', () => {
expect(result).toBe(activationResult);
});
});

describe('when called, and params.getActivations() returns async activations', () => {
let activationMock: jest.Mock<BindingActivation>;
let activationResult: unknown;

let result: unknown;

beforeAll(async () => {
activationResult = Symbol('activation-result');

activationMock = jest
.fn()
.mockReturnValueOnce(Promise.resolve(activationResult));

paramsMock.getActivations.mockReturnValueOnce([activationMock]);

result = await resolveBindingActivations(
paramsMock,
serviceIdentifierFixture,
valueFixture,
);
});

afterAll(() => {
jest.clearAllMocks();
});

it('should call params.getActivations', () => {
expect(paramsMock.getActivations).toHaveBeenCalledTimes(1);
expect(paramsMock.getActivations).toHaveBeenCalledWith(
serviceIdentifierFixture,
);
});

it('should call activation', () => {
expect(activationMock).toHaveBeenCalledTimes(1);
expect(activationMock).toHaveBeenCalledWith(valueFixture);
});

it('should return value', () => {
expect(result).toBe(activationResult);
});
});
});

describe('having a promise value', () => {
let paramsMock: jest.Mocked<ResolutionParams>;
let serviceIdentifierFixture: ServiceIdentifier;
let valueFixture: unknown;

beforeAll(() => {
paramsMock = {
getActivations: jest.fn(),
} as Partial<
jest.Mocked<ResolutionParams>
> as jest.Mocked<ResolutionParams>;
serviceIdentifierFixture = 'service-id';
valueFixture = Symbol();
});

describe('when called, and params.getActivations() returns undefined', () => {
let result: unknown;

beforeAll(async () => {
result = await resolveBindingActivations(
paramsMock,
serviceIdentifierFixture,
Promise.resolve(valueFixture),
);
});

afterAll(() => {
jest.clearAllMocks();
});

it('should call params.getActivations', () => {
expect(paramsMock.getActivations).toHaveBeenCalledTimes(1);
expect(paramsMock.getActivations).toHaveBeenCalledWith(
serviceIdentifierFixture,
);
});

it('should return value', () => {
expect(result).toBe(valueFixture);
});
});

describe('when called, and params.getActivations() returns sync activations', () => {
let activationMock: jest.Mock<BindingActivation>;
let activationResult: unknown;

let result: unknown;

beforeAll(async () => {
activationResult = Symbol('activation-result');

activationMock = jest.fn().mockReturnValueOnce(activationResult);

paramsMock.getActivations.mockReturnValueOnce([activationMock]);

result = await resolveBindingActivations(
paramsMock,
serviceIdentifierFixture,
Promise.resolve(valueFixture),
);
});

afterAll(() => {
jest.clearAllMocks();
});

it('should call params.getActivations', () => {
expect(paramsMock.getActivations).toHaveBeenCalledTimes(1);
expect(paramsMock.getActivations).toHaveBeenCalledWith(
serviceIdentifierFixture,
);
});

it('should call activation', () => {
expect(activationMock).toHaveBeenCalledTimes(1);
expect(activationMock).toHaveBeenCalledWith(valueFixture);
});

it('should return value', () => {
expect(result).toBe(activationResult);
});
});

describe('when called, and params.getActivations() returns async activations', () => {
let activationMock: jest.Mock<BindingActivation>;
let activationResult: unknown;

let result: unknown;

beforeAll(async () => {
activationResult = Symbol('activation-result');

activationMock = jest
.fn()
.mockReturnValueOnce(Promise.resolve(activationResult));

paramsMock.getActivations.mockReturnValueOnce([activationMock]);

result = await resolveBindingActivations(
paramsMock,
serviceIdentifierFixture,
Promise.resolve(valueFixture),
);
});

afterAll(() => {
jest.clearAllMocks();
});

it('should call params.getActivations', () => {
expect(paramsMock.getActivations).toHaveBeenCalledTimes(1);
expect(paramsMock.getActivations).toHaveBeenCalledWith(
serviceIdentifierFixture,
);
});

it('should call activation', () => {
expect(activationMock).toHaveBeenCalledTimes(1);
expect(activationMock).toHaveBeenCalledWith(valueFixture);
});

it('should return value', () => {
expect(result).toBe(activationResult);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ServiceIdentifier } from '@inversifyjs/common';
import { BindingActivation } from '../../binding/models/BindingActivation';
import { isPromise } from '../../common/calculations/isPromise';
import { ResolutionParams } from '../models/ResolutionParams';
import { Resolved } from '../models/Resolved';
import { Resolved, SyncResolved } from '../models/Resolved';

export function resolveBindingActivations<TActivated>(
params: ResolutionParams,
Expand All @@ -13,28 +13,28 @@ export function resolveBindingActivations<TActivated>(
const activations: Iterable<BindingActivation<TActivated>> | undefined =
params.getActivations(serviceIdentifier);

if (activations !== undefined) {
if (isPromise(value)) {
return resolveBindingActivationsFromIteratorAsync(
value,
activations[Symbol.iterator](),
);
} else {
return resolveBindingActivationsFromIterator(
value,
activations[Symbol.iterator](),
);
}
if (activations === undefined) {
return value;
}

if (isPromise(value)) {
return resolveBindingActivationsFromIteratorAsync(
value,
activations[Symbol.iterator](),
);
}

return value;
return resolveBindingActivationsFromIterator(
value,
activations[Symbol.iterator](),
);
}

function resolveBindingActivationsFromIterator<TActivated>(
value: Awaited<TActivated>,
value: SyncResolved<TActivated>,
activationsIterator: Iterator<BindingActivation<TActivated>>,
): Resolved<TActivated> {
let activatedValue: Awaited<TActivated> = value;
let activatedValue: SyncResolved<TActivated> = value;

let activationIteratorResult: IteratorResult<BindingActivation<TActivated>> =
activationsIterator.next();
Expand All @@ -61,8 +61,8 @@ function resolveBindingActivationsFromIterator<TActivated>(
async function resolveBindingActivationsFromIteratorAsync<TActivated>(
value: Promise<TActivated>,
activationsIterator: Iterator<BindingActivation<TActivated>>,
): Promise<Awaited<TActivated>> {
let activatedValue: Awaited<TActivated> = await value;
): Promise<SyncResolved<TActivated>> {
let activatedValue: SyncResolved<TActivated> = await value;

let activationIteratorResult: IteratorResult<BindingActivation<TActivated>> =
activationsIterator.next();
Expand Down
Loading

0 comments on commit 04094c0

Please sign in to comment.