Skip to content

feat: make updateToggles and sendMetrics available as public methods #226

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 14, 2024
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,9 @@ const unleash = new UnleashClient({
**NOTES: ⚠️**
If `bootstrapOverride` is `true` (by default), any local cached data will be overridden with the bootstrap specified.
If `bootstrapOverride` is `false` any local cached data will not be overridden unless the local cache is empty.

## Manage your own refresh mechanism

You can opt out of the Unleash feature flag auto-refresh mechanism and metrics update by settings the `refreshInterval` and/or `metricsInterval` options to `false`.
In this case, it becomes your responsibility to call `updateToggles` and/or `sendMetrics` methods.
This approach is useful in environments that do not support the `setInterval` API, such as service workers.
72 changes: 72 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
lastUpdateKey,
} from './index';
import { getTypeSafeRequest, getTypeSafeRequestUrl } from './test';
import Metrics from './metrics';

jest.useFakeTimers();

Expand Down Expand Up @@ -1657,6 +1658,26 @@ test('Should report metrics', async () => {
client.stop();
});

test('should send metrics when sendMetrics called', async () => {
const config: IConfig = {
url: 'http://localhost/test',
clientKey: '12',
appName: 'web',
};

jest.spyOn(Metrics.prototype, 'sendMetrics');

const client = new UnleashClient(config);

client.start();

expect(Metrics.prototype.sendMetrics).not.toHaveBeenCalled();

await client.sendMetrics();

expect(Metrics.prototype.sendMetrics).toHaveBeenCalled();
});

test('Should emit RECOVERED event when sdkStatus is error and status is less than 400', (done) => {
const data = { status: 200 }; // replace with the actual data you want to test
fetchMock.mockResponseOnce(JSON.stringify(data), { status: 200 });
Expand Down Expand Up @@ -2268,3 +2289,54 @@ describe('Experimental options togglesStorageTTL enabled', () => {
});
});
});

describe('updateToggles', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to suggest that we don't add the word toggles in the public API since we already migrated most UI facing code to flags instead of toggles. But since we already have a public method called getAllToggles in this SDK then introducing another convention adds more confusion rather than improving clarity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So no action needed IMO

it('should not update toggles when not started', () => {
const config: IConfig = {
url: 'http://localhost/test',
clientKey: '12',
appName: 'web',
};
const client = new UnleashClient(config);

client.updateToggles();

expect(fetchMock).not.toHaveBeenCalled();
});

it('should update toggles when started', async () => {
const config: IConfig = {
url: 'http://localhost/test',
clientKey: '12',
appName: 'web',
};
const client = new UnleashClient(config);

await client.start();
fetchMock.mockClear();

client.updateToggles();

expect(fetchMock).toHaveBeenCalled();
});

it('should wait for client readiness before the toggles update', async () => {
const config: IConfig = {
url: 'http://localhost/test',
clientKey: '12',
appName: 'web',
refreshInterval: 0,
};
const client = new UnleashClient(config);

client.start();

client.updateToggles();

expect(fetchMock).not.toHaveBeenCalled();

client.emit(EVENTS.READY);

expect(fetchMock).toHaveBeenCalledTimes(1);
});
});
6 changes: 5 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ export class UnleashClient extends TinyEmitter {
return { ...variant, feature_enabled: enabled };
}

private async updateToggles() {
public async updateToggles() {
if (this.timerRef || this.fetchedFromServer) {
await this.fetchToggles();
} else if (this.started) {
Expand Down Expand Up @@ -446,6 +446,10 @@ export class UnleashClient extends TinyEmitter {
return this.sdkState === 'error' ? this.lastError : undefined;
}

public sendMetrics() {
return this.metrics.sendMetrics();
}

private async resolveSessionId(): Promise<string> {
if (this.context.sessionId) {
return this.context.sessionId;
Expand Down
Loading