Skip to content

Commit

Permalink
add types, clean up functions, fix lint
Browse files Browse the repository at this point in the history
  • Loading branch information
tyiuhc committed Jan 7, 2025
1 parent 6e8e25b commit 3fcf8c7
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 40 deletions.
80 changes: 41 additions & 39 deletions packages/experiment-tag/src/experiment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ import mutate, { MutationController } from 'dom-mutator';
import { WebExperimentConfig } from './config';
import { getInjectUtils } from './inject-utils';
import { WindowMessenger } from './messenger';
import {
ApplyVariantsOption,
RevertVariantsOptions,
WebExperimentContext,
} from './types';
import {
convertEvaluationVariantToVariant,
getUrlParams,
Expand Down Expand Up @@ -216,7 +221,7 @@ export class WebExperiment {
}

// apply local variants
this.applyVariants(this.localFlagKeys);
this.applyVariants({ flagKeys: this.localFlagKeys });

if (
!this.isRemoteBlocking ||
Expand All @@ -232,7 +237,7 @@ export class WebExperiment {

await this.fetchRemoteFlags();
// apply remote variants - if fetch is unsuccessful, fallback order: 1. localStorage flags, 2. initial flags
this.applyVariants(this.remoteFlagKeys);
this.applyVariants({ flagKeys: this.remoteFlagKeys });
}

/**
Expand All @@ -244,30 +249,26 @@ export class WebExperiment {

/**
* Set the context for evaluating experiments.
* If user is not provided, the current user is used.
* If currentUrl is not provided, the current URL is used.
* @param user
* @param currentUrl
* If user is undefined, the current user is used.
* If currentUrl is undefined, the current URL is used.
* @param webExperimentContext
*/
public setContext(
user: ExperimentUser | undefined = undefined,
currentUrl: string | undefined = undefined,
) {
public setContext(webExperimentContext: WebExperimentContext) {
if (this.experimentClient) {
const existingUser = this.experimentClient?.getUser();
if (user) {
if (currentUrl) {
if (webExperimentContext.user) {
if (webExperimentContext.currentUrl) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
user.currentUrl = currentUrl;
}
this.experimentClient.setUser(user);
this.experimentClient.setUser(webExperimentContext.user);
} else {
this.experimentClient.setUser({
...existingUser,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
currentUrl: currentUrl,
currentUrl: webExperimentContext.currentUrl,
});
}
}
Expand All @@ -284,9 +285,10 @@ export class WebExperiment {

/**
* Apply evaluated variants to the page.
* @param flagKeys
* @param applyVariantsOption
*/
public applyVariants(flagKeys: string[] | undefined = undefined) {
public applyVariants(applyVariantsOption?: ApplyVariantsOption) {
const { flagKeys } = applyVariantsOption || {};
const variants = this.experimentClient?.all() || {};
if (Object.keys(variants).length === 0) {
return;
Expand Down Expand Up @@ -328,9 +330,10 @@ export class WebExperiment {

/**
* Revert mutations applied by the experiment.
* @param flagKeys
* @param revertVariantsOptions
*/
public revertMutations(flagKeys: string[] | undefined = undefined) {
public revertVariants(revertVariantsOptions?: RevertVariantsOptions) {
let { flagKeys } = revertVariantsOptions || {};
if (!flagKeys) {
flagKeys = Object.keys(this.appliedMutations);
}
Expand All @@ -347,7 +350,7 @@ export class WebExperiment {
* @param flagKeys
*/
public getRedirectUrls(
flagKeys: string[] | undefined = undefined,
flagKeys?: string[],
): Record<string, Record<string, string>> {
const redirectUrlMap: Record<string, Record<string, string>> = {};
if (!flagKeys) {
Expand Down Expand Up @@ -387,7 +390,7 @@ export class WebExperiment {
*/
public previewVariant(key: string, variant: string) {
if (this.appliedMutations[key]) {
this.revertMutations([key]);
this.revertVariants({ flagKeys: [key] });
}
const flag = this.flagVariantMap[key];
if (!flag) {
Expand All @@ -405,23 +408,24 @@ export class WebExperiment {
}

/**
* Get all variants for a user. If user is not provided, the current user is used.
* If currentUrl is not provided, the current URL is used.
* If flagKeys is not provided, all variants are returned.
* @param user
* @param currentUrl
* Get all variants for a given WebExperimentContext.
* If user is undefined, the current user is used.
* If currentUrl is undefined, the current URL is used.
* If flagKeys is undefined, all variants are returned.
* @param webExperimentContext
* @param flagKeys
*/
public getVariants(
user: ExperimentUser | undefined = undefined,
currentUrl: string | undefined = undefined,
flagKeys: string[] | undefined = undefined,
webExperimentContext?: WebExperimentContext,
flagKeys?: string[],
): Variants {
if (!this.experimentClient) {
return {};
}
const existingUser = this.experimentClient?.getUser();
this.setContext(user, currentUrl);
const existingContext: WebExperimentContext = {
user: this.experimentClient?.getUser(),
};
webExperimentContext && this.setContext(webExperimentContext);
const variants = this.experimentClient.all();
if (flagKeys) {
const filteredVariants = {};
Expand All @@ -430,7 +434,7 @@ export class WebExperiment {
}
return filteredVariants;
}
this.setContext(existingUser, undefined);
this.setContext(existingContext);
return variants;
}

Expand All @@ -450,10 +454,8 @@ export class WebExperiment {
}
}

public getActiveExperimentsOnPage(
currentUrl: string | undefined = undefined,
): string[] {
const variants = this.getVariants(undefined, currentUrl);
public getActiveExperimentsOnPage(currentUrl?: string): string[] {
const variants = this.getVariants({ currentUrl: currentUrl });
return Object.keys(variants).filter((key) => {
return (
variants[key].metadata?.segmentName !== PAGE_NOT_TARGETED &&
Expand All @@ -473,13 +475,13 @@ export class WebExperiment {
}
// Add URL change listener for back/forward navigation
globalScope.addEventListener('popstate', () => {
this.revertMutations();
this.applyVariants(flagKeys);
this.revertVariants();
this.applyVariants({ flagKeys: flagKeys });
});

const handleUrlChange = () => {
this.revertMutations();
this.applyVariants(flagKeys);
this.revertVariants();
this.applyVariants({ flagKeys: flagKeys });
this.previousUrl = globalScope.location.href;
};

Expand Down
14 changes: 14 additions & 0 deletions packages/experiment-tag/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ExperimentUser } from '@amplitude/experiment-js-client';

export type WebExperimentContext = {
user?: ExperimentUser;
currentUrl?: string;
};

export type ApplyVariantsOption = {
flagKeys?: string[];
};

export type RevertVariantsOptions = {
flagKeys?: string[];
};
2 changes: 1 addition & 1 deletion packages/experiment-tag/test/experiment.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as experimentCore from '@amplitude/experiment-core';
import { safeGlobal } from '@amplitude/experiment-core';
import { ExperimentClient } from '@amplitude/experiment-js-client';
import { Base64 } from 'js-base64';
import { WebExperiment } from 'src/experiment';
Expand All @@ -7,7 +8,6 @@ import { stringify } from 'ts-jest';

import { createMutateFlag, createRedirectFlag } from './util/create-flag';
import { MockHttpClient } from './util/mock-http-client';
import { safeGlobal } from '@amplitude/experiment-core';

let apiKey = 0;

Expand Down

0 comments on commit 3fcf8c7

Please sign in to comment.