Skip to content

Commit

Permalink
Merge pull request #1310 from inversify/fix/issue-1190-when-target-is…
Browse files Browse the repository at this point in the history
…-default-with-optional-injection

fix: update Target.isTagged to exclude optional
  • Loading branch information
notaphplover authored Apr 16, 2021
2 parents bb55be0 + dc501ab commit 28d20cc
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 13 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Upgrade information for v4.x to v5.x

### Fixed
- Fix `Target.isTagged()` to exclude `optional` from tag injections #1190.

## [5.0.1] - 2018-10-17
### Added
- Updating constructor injection wiki document with concrete injection example #922
Expand Down
13 changes: 13 additions & 0 deletions src/constants/metadata_keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,16 @@ export const DESIGN_PARAM_TYPES = "design:paramtypes";

// used to identify postConstruct functions
export const POST_CONSTRUCT = "post_construct";

function getNonCustomTagKeys(): string[] {
return [
INJECT_TAG,
MULTI_INJECT_TAG,
NAME_TAG,
UNMANAGED_TAG,
NAMED_TAG,
OPTIONAL_TAG,
];
}

export const NON_CUSTOM_TAG_KEYS: string[] = getNonCustomTagKeys();
21 changes: 8 additions & 13 deletions src/planning/target.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,9 @@ class Target implements interfaces.Target {
}

public isTagged(): boolean {
return this.metadata.some((m) =>
(m.key !== METADATA_KEY.INJECT_TAG) &&
(m.key !== METADATA_KEY.MULTI_INJECT_TAG) &&
(m.key !== METADATA_KEY.NAME_TAG) &&
(m.key !== METADATA_KEY.UNMANAGED_TAG) &&
(m.key !== METADATA_KEY.NAMED_TAG));
return this.metadata.some(
(metadata) => METADATA_KEY.NON_CUSTOM_TAG_KEYS.every((key) => metadata.key !== key),
);
}

public isOptional(): boolean {
Expand All @@ -85,14 +82,12 @@ class Target implements interfaces.Target {

public getCustomTags(): interfaces.Metadata[] | null {
if (this.isTagged()) {
return this.metadata.filter((m) =>
(m.key !== METADATA_KEY.INJECT_TAG) &&
(m.key !== METADATA_KEY.MULTI_INJECT_TAG) &&
(m.key !== METADATA_KEY.NAME_TAG) &&
(m.key !== METADATA_KEY.UNMANAGED_TAG) &&
(m.key !== METADATA_KEY.NAMED_TAG));
return this.metadata.filter(
(metadata) => METADATA_KEY.NON_CUSTOM_TAG_KEYS.every((key) => metadata.key !== key),
);
} else {
return null;
}
return null;
}

public matchesNamedTag(name: string): boolean {
Expand Down
61 changes: 61 additions & 0 deletions test/bugs/issue_1190.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { expect } from "chai";
import { injectable, inject, optional, Container, named } from "../../src/inversify";

describe("Issue 1190", () => {

it('should inject a katana as default weapon to ninja', () => {
const TYPES = {
Weapon: "Weapon"
};

const TAG = {
throwable: "throwable"
};

interface Weapon {
name: string;
}

@injectable()
class Katana implements Weapon {
public name: string;
public constructor() {
this.name = "Katana";
}
}

@injectable()
class Shuriken implements Weapon {
public name: string;
public constructor() {
this.name = "Shuriken";
}
}

@injectable()
class Ninja {
public name: string;
public katana: Katana;
public shuriken: Shuriken;
public constructor(
@inject(TYPES.Weapon) @optional() katana: Weapon,
@inject(TYPES.Weapon) @named(TAG.throwable) shuriken: Weapon
) {
this.name = "Ninja";
this.katana = katana;
this.shuriken = shuriken;
}
}

const container = new Container();

container.bind<Weapon>(TYPES.Weapon).to(Katana).whenTargetIsDefault();
container.bind<Weapon>(TYPES.Weapon).to(Shuriken).whenTargetNamed(TAG.throwable);

container.bind<Ninja>("Ninja").to(Ninja);

const ninja = container.get<Ninja>("Ninja");

expect(ninja.katana).to.deep.eq(new Katana());
});
});
23 changes: 23 additions & 0 deletions test/planning/target.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,29 @@ describe("Target", () => {
target3.metadata.push(new Metadata("power", 5), new Metadata("speed", 5));
expect(target3.isTagged()).to.be.eql(true);

const target4 = new Target(TargetTypeEnum.Variable, "", "Katana");
target4.metadata.push(new Metadata(METADATA_KEY.INJECT_TAG, "Katana"))
expect(target4.isTagged()).to.be.eql(false);

const target5 = new Target(TargetTypeEnum.Variable, "", "Katana");
target5.metadata.push(new Metadata(METADATA_KEY.MULTI_INJECT_TAG, "Katana"))
expect(target5.isTagged()).to.be.eql(false);

const target6 = new Target(TargetTypeEnum.Variable, "katanaName", "Katana");
target6.metadata.push(new Metadata(METADATA_KEY.NAME_TAG, "katanaName"))
expect(target6.isTagged()).to.be.eql(false);

const target7 = new Target(TargetTypeEnum.Variable, "", "Katana");
target7.metadata.push(new Metadata(METADATA_KEY.UNMANAGED_TAG, true))
expect(target7.isTagged()).to.be.eql(false);

const target8 = new Target(TargetTypeEnum.Variable, "katanaName", "Katana");
target8.metadata.push(new Metadata(METADATA_KEY.NAMED_TAG, "katanaName"))
expect(target8.isTagged()).to.be.eql(false);

const target9 = new Target(TargetTypeEnum.Variable, "", "Katana");
target9.metadata.push(new Metadata(METADATA_KEY.OPTIONAL_TAG, true))
expect(target9.isTagged()).to.be.eql(false);
});

it("Should be able to match tagged metadata", () => {
Expand Down

0 comments on commit 28d20cc

Please sign in to comment.