Skip to content
Open
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
92 changes: 91 additions & 1 deletion internal/cmd/testdata/success_angular.golden
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
FeatureFlagService,
JsonValue,
} from '@openfeature/angular-sdk';
import { Observable } from 'rxjs';
import { Observable, map } from 'rxjs';

// ============================================================================
// FLAG KEYS
Expand Down Expand Up @@ -131,6 +131,24 @@ export class GeneratedFeatureFlagService {
);
}

/**
* Get the value of the `discountPercentage` flag.
*
* Discount percentage applied to purchases.
*
* @param domain - Optional domain for flag evaluation (scopes the flag to a specific provider).
* @param options - Optional configuration for the flag evaluation.
* @returns An Observable that emits the flag value whenever it changes.
*/
getDiscountPercentage(
domain?: string,
options?: AngularFlagEvaluationOptions
): Observable<number> {
return this.getDiscountPercentageDetails(domain, options).pipe(
map((details) => details.value)
);
}

/**
* Get evaluation details for the `enableFeatureA` flag.
*
Expand Down Expand Up @@ -160,6 +178,24 @@ export class GeneratedFeatureFlagService {
);
}

/**
* Get the value of the `enableFeatureA` flag.
*
* Controls whether Feature A is enabled.
*
* @param domain - Optional domain for flag evaluation (scopes the flag to a specific provider).
* @param options - Optional configuration for the flag evaluation.
* @returns An Observable that emits the flag value whenever it changes.
*/
getEnableFeatureA(
domain?: string,
options?: AngularFlagEvaluationOptions
): Observable<boolean> {
return this.getEnableFeatureADetails(domain, options).pipe(
map((details) => details.value)
);
}

/**
* Get evaluation details for the `greetingMessage` flag.
*
Expand Down Expand Up @@ -189,6 +225,24 @@ export class GeneratedFeatureFlagService {
);
}

/**
* Get the value of the `greetingMessage` flag.
*
* The message to use for greeting users.
*
* @param domain - Optional domain for flag evaluation (scopes the flag to a specific provider).
* @param options - Optional configuration for the flag evaluation.
* @returns An Observable that emits the flag value whenever it changes.
*/
getGreetingMessage(
domain?: string,
options?: AngularFlagEvaluationOptions
): Observable<string> {
return this.getGreetingMessageDetails(domain, options).pipe(
map((details) => details.value)
);
}

/**
* Get evaluation details for the `themeCustomization` flag.
*
Expand Down Expand Up @@ -218,6 +272,24 @@ export class GeneratedFeatureFlagService {
);
}

/**
* Get the value of the `themeCustomization` flag.
*
* Allows customization of theme colors.
*
* @param domain - Optional domain for flag evaluation (scopes the flag to a specific provider).
* @param options - Optional configuration for the flag evaluation.
* @returns An Observable that emits the flag value whenever it changes.
*/
getThemeCustomization(
domain?: string,
options?: AngularFlagEvaluationOptions
): Observable<JsonValue> {
return this.getThemeCustomizationDetails(domain, options).pipe(
map((details) => details.value)
);
}

/**
* Get evaluation details for the `usernameMaxLength` flag.
*
Expand Down Expand Up @@ -247,6 +319,24 @@ export class GeneratedFeatureFlagService {
);
}

/**
* Get the value of the `usernameMaxLength` flag.
*
* Maximum allowed length for usernames.
*
* @param domain - Optional domain for flag evaluation (scopes the flag to a specific provider).
* @param options - Optional configuration for the flag evaluation.
* @returns An Observable that emits the flag value whenever it changes.
*/
getUsernameMaxLength(
domain?: string,
options?: AngularFlagEvaluationOptions
): Observable<number> {
return this.getUsernameMaxLengthDetails(domain, options).pipe(
map((details) => details.value)
);
}

}

// ============================================================================
Expand Down
20 changes: 19 additions & 1 deletion internal/generators/angular/angular.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
FeatureFlagService,
JsonValue,
} from '@openfeature/angular-sdk';
import { Observable } from 'rxjs';
import { Observable, map } from 'rxjs';

// ============================================================================
// FLAG KEYS
Expand Down Expand Up @@ -108,6 +108,24 @@ export class GeneratedFeatureFlagService {
}
);
}

/**
* Get the value of the `{{ .Key }}` flag.
*
* {{ if .Description }}{{ .Description }}{{ else }}Feature flag.{{ end }}
*
* @param domain - Optional domain for flag evaluation (scopes the flag to a specific provider).
* @param options - Optional configuration for the flag evaluation.
* @returns An Observable that emits the flag value whenever it changes.
*/
get{{ .Key | ToPascal }}(
domain?: string,
options?: AngularFlagEvaluationOptions
): Observable<{{ if eq (.Type | OpenFeatureType) "object" }}JsonValue{{ else }}{{ .Type | OpenFeatureType }}{{ end }}> {
return this.get{{ .Key | ToPascal }}Details(domain, options).pipe(
map((details) => details.value)
);
}
{{ end }}
}

Expand Down
99 changes: 99 additions & 0 deletions test/angular-integration/specs/service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,4 +211,103 @@ describe("GeneratedFeatureFlagService", () => {
});
});
});

describe("getEnableFeatureA (convenience)", () => {
it("should return boolean value directly", async () => {
const value = await firstValueFrom(service.getEnableFeatureA(domain));

expect(typeof value).toBe("boolean");
expect(value).toBe(true);
});

it("should return default value when flag is not configured", async () => {
const emptyDomain = uuid();
const emptyProvider = new InMemoryProvider({});
await OpenFeature.setProviderAndWait(emptyDomain, emptyProvider);

const value = await firstValueFrom(
service.getEnableFeatureA(emptyDomain),
);

expect(value).toBe(false);
});
});

describe("getGreetingMessage (convenience)", () => {
it("should return string value directly", async () => {
const value = await firstValueFrom(service.getGreetingMessage(domain));

expect(typeof value).toBe("string");
expect(value).toBe("Hello from provider!");
});

it("should return default value when flag is not configured", async () => {
const emptyDomain = uuid();
const emptyProvider = new InMemoryProvider({});
await OpenFeature.setProviderAndWait(emptyDomain, emptyProvider);

const value = await firstValueFrom(
service.getGreetingMessage(emptyDomain),
);

expect(value).toBe("Hello there!");
});
});

describe("getDiscountPercentage (convenience)", () => {
it("should return number value directly", async () => {
const value = await firstValueFrom(service.getDiscountPercentage(domain));

expect(typeof value).toBe("number");
expect(value).toBe(0.25);
});

it("should return default value when flag is not configured", async () => {
const emptyDomain = uuid();
const emptyProvider = new InMemoryProvider({});
await OpenFeature.setProviderAndWait(emptyDomain, emptyProvider);

const value = await firstValueFrom(
service.getDiscountPercentage(emptyDomain),
);

expect(value).toBe(0.15);
});
});

describe("getUsernameMaxLength (convenience)", () => {
it("should return number value directly", async () => {
const value = await firstValueFrom(service.getUsernameMaxLength(domain));

expect(typeof value).toBe("number");
expect(value).toBe(100);
});
});

describe("getThemeCustomization (convenience)", () => {
it("should return object value directly", async () => {
const value = await firstValueFrom(service.getThemeCustomization(domain));

expect(typeof value).toBe("object");
expect(value).toEqual({
primaryColor: "#ff0000",
secondaryColor: "#00ff00",
});
});

it("should return default value when flag is not configured", async () => {
const emptyDomain = uuid();
const emptyProvider = new InMemoryProvider({});
await OpenFeature.setProviderAndWait(emptyDomain, emptyProvider);

const value = await firstValueFrom(
service.getThemeCustomization(emptyDomain),
);

expect(value).toEqual({
primaryColor: "#007bff",
secondaryColor: "#6c757d",
});
});
});
});
Loading