Skip to content
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

Web sdk customers identity #564

Merged
merged 7 commits into from
Dec 19, 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
2 changes: 1 addition & 1 deletion .azure/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ trigger: none
pr:
branches:
include:
- main
- "*"


pool:
Expand Down
236 changes: 129 additions & 107 deletions code_blocks/_projects/rc-billing/rc-billing-doc-snippets.test.ts
Original file line number Diff line number Diff line change
@@ -1,149 +1,171 @@
import { expect, test, vi } from 'vitest';
import { getCustomerInfo, checkForSpecificEntitlement, checkForAnyEntitlement, getCurrentOffering, getCustomOffering, displayingPackages, gettingProduct, purchasingPackage, configuringSDK, getOfferingForEUR} from './rc-billing-doc-snippets';
import type { Package, Product } from "@revenuecat/purchases-js";
import { Purchases } from "@revenuecat/purchases-js";
import {expect, test, vi} from 'vitest';
import {
getCustomerInfo,
checkForSpecificEntitlement,
checkForAnyEntitlement,
getCurrentOffering,
getCustomOffering,
displayingPackages,
gettingProduct,
purchasingPackage,
configuringSDK,
configuringSDKWithAnonUser,
getOfferingForEUR
} from './rc-billing-doc-snippets';
import type {Package, Product} from "@revenuecat/purchases-js";
import {Purchases} from "@revenuecat/purchases-js";

const REVENUECAT_BILLING_PUBLIC_API_KEY = 'rcb_sb_NLgftxAMfaRjBxlpJjSfQnGAQ';

test('Snippet "Configuring SDK" works', () => {
const purchases = configuringSDK(REVENUECAT_BILLING_PUBLIC_API_KEY);
expect(purchases).toBeDefined();
purchases.close();
const purchases = configuringSDK(REVENUECAT_BILLING_PUBLIC_API_KEY);
expect(purchases).toBeDefined();
purchases.close();
})

test('Snippet "Configuring SDK Anonymous" works', () => {
const purchases = configuringSDKWithAnonUser(REVENUECAT_BILLING_PUBLIC_API_KEY);
expect(purchases).toBeDefined();
purchases.close();
})

test('Snippet "Get customer info" works', async () => {
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_with_gold_entitlement");
expect(await getCustomerInfo()).toBeDefined();
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_with_gold_entitlement");
expect(await getCustomerInfo()).toBeDefined();
Purchases.getSharedInstance().close();
});

test('Snippet "Check for specific entitlement" works for customer with entitlement', async () => {
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_with_gold_entitlement");
const callback = vi.fn();
await checkForSpecificEntitlement(callback);
expect(callback).toHaveBeenCalled();
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_with_gold_entitlement");
const callback = vi.fn();
await checkForSpecificEntitlement(callback);
expect(callback).toHaveBeenCalled();
Purchases.getSharedInstance().close();
});

test('Snippet "Check for specific entitlement" works for customer without any entitlement', async () => {
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
const callback = vi.fn();
await checkForSpecificEntitlement(callback);
expect(callback).not.toHaveBeenCalled();
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
const callback = vi.fn();
await checkForSpecificEntitlement(callback);
expect(callback).not.toHaveBeenCalled();
Purchases.getSharedInstance().close();
});

test('Snippet "Check for specific entitlement" works for customer with different entitlement', async () => {
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_with_silver_entitlement");
const callback = vi.fn();
await checkForSpecificEntitlement(callback);
expect(callback).not.toHaveBeenCalled();
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_with_silver_entitlement");
const callback = vi.fn();
await checkForSpecificEntitlement(callback);
expect(callback).not.toHaveBeenCalled();
Purchases.getSharedInstance().close();
});

test('Snippet "Check for any entitlement" works for both customers with entitlement', async () => {
const callback = vi.fn();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_with_gold_entitlement");
await checkForAnyEntitlement(callback);
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_with_silver_entitlement");
await checkForAnyEntitlement(callback);
Purchases.getSharedInstance().close();
expect(callback).toHaveBeenCalledTimes(2);
const callback = vi.fn();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_with_gold_entitlement");
await checkForAnyEntitlement(callback);
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_with_silver_entitlement");
await checkForAnyEntitlement(callback);
Purchases.getSharedInstance().close();
expect(callback).toHaveBeenCalledTimes(2);
});

test('Snippet "Check for any entitlement" works for customer without any entitlement', async () => {
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
const callback = vi.fn();
await checkForAnyEntitlement(callback);
expect(callback).not.toHaveBeenCalled();
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
const callback = vi.fn();
await checkForAnyEntitlement(callback);
expect(callback).not.toHaveBeenCalled();
Purchases.getSharedInstance().close();
});

test('Snippet "Get current offering" works', async () => {
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
let pkgs : Package[]|undefined;
const callback = vi.fn().mockImplementation((availablePackages : Package[]) => {
pkgs = availablePackages;
});
await getCurrentOffering(callback);
expect(callback).toHaveBeenCalled();
expect(pkgs).toBeDefined();
expect((pkgs ?? []).length).toBe(1);
expect(pkgs !== undefined && pkgs[0]?.identifier).toBe("$rc_monthly");
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
let pkgs: Package[] | undefined;
const callback = vi.fn().mockImplementation((availablePackages: Package[]) => {
pkgs = availablePackages;
});
await getCurrentOffering(callback);
expect(callback).toHaveBeenCalled();
expect(pkgs).toBeDefined();
expect((pkgs ?? []).length).toBe(1);
expect(pkgs !== undefined && pkgs[0]?.identifier).toBe("$rc_monthly");
Purchases.getSharedInstance().close();
});

test('Snippet "Get current offering for EUR" works', async () => {
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
let pkgs : Package[]|undefined;
const callback = vi.fn().mockImplementation((availablePackages : Package[]) => {
pkgs = availablePackages;
});
await getOfferingForEUR(callback);
expect(callback).toHaveBeenCalled();
expect(pkgs).toBeDefined();
expect((pkgs ?? []).length).toBe(1);
expect(pkgs !== undefined && pkgs[0]?.identifier).toBe("$rc_monthly");
expect(pkgs !== undefined && pkgs[0]?.rcBillingProduct.currentPrice.currency).toBe("EUR");
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
let pkgs: Package[] | undefined;
const callback = vi.fn().mockImplementation((availablePackages: Package[]) => {
pkgs = availablePackages;
});
await getOfferingForEUR(callback);
expect(callback).toHaveBeenCalled();
expect(pkgs).toBeDefined();
expect((pkgs ?? []).length).toBe(1);
expect(pkgs !== undefined && pkgs[0]?.identifier).toBe("$rc_monthly");
expect(pkgs !== undefined && pkgs[0]?.rcBillingProduct.currentPrice.currency).toBe("EUR");
Purchases.getSharedInstance().close();
});

test('Snippet "Get custom offering" works', async () => {
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
let pkgs : Package[]|null = null;
const callback = vi.fn().mockImplementation((availablePackages : Package[]) => {
pkgs = availablePackages;
});
await getCustomOffering(callback);
expect(callback).toHaveBeenCalled();
expect(pkgs).toBeTruthy();
expect((pkgs ?? []).length).toBe(3);
expect((pkgs ?? [] as Package[]).find(pkg => pkg.identifier == "experiment_group_package")).toBeDefined();
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
let pkgs: Package[] | null = null;
const callback = vi.fn().mockImplementation((availablePackages: Package[]) => {
pkgs = availablePackages;
});
await getCustomOffering(callback);
expect(callback).toHaveBeenCalled();
expect(pkgs).toBeTruthy();
expect((pkgs ?? []).length).toBe(3);
expect((pkgs ?? [] as Package[]).find(pkg => pkg.identifier == "experiment_group_package")).toBeDefined();
Purchases.getSharedInstance().close();
});


test('Snippet "Displaying packages" works', async () => {
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
let allPackages : Package[] = [];
let monthlyPackage : Package|undefined;
let customPackage : Package|undefined;
const callback = vi.fn().mockImplementation((props : {allPackages : Package[], monthlyPackage : Package|null, customPackage : Package|null}) => {
allPackages = props.allPackages;
monthlyPackage = props.monthlyPackage ?? undefined;
customPackage = props.customPackage ?? undefined;
});
await displayingPackages(callback);
expect(callback).toHaveBeenCalled();
expect(allPackages).toBeTruthy();
expect((allPackages ?? []).length).toBe(3);
expect(monthlyPackage).not.toBe(null);
monthlyPackage
expect(monthlyPackage?.identifier).toBe("$rc_monthly");
expect(customPackage).not.toBe(null);
expect(customPackage?.identifier).toBe("<package_id>");
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
let allPackages: Package[] = [];
let monthlyPackage: Package | undefined;
let customPackage: Package | undefined;
const callback = vi.fn().mockImplementation((props: {
allPackages: Package[],
monthlyPackage: Package | null,
customPackage: Package | null
}) => {
allPackages = props.allPackages;
monthlyPackage = props.monthlyPackage ?? undefined;
customPackage = props.customPackage ?? undefined;
});
await displayingPackages(callback);
expect(callback).toHaveBeenCalled();
expect(allPackages).toBeTruthy();
expect((allPackages ?? []).length).toBe(3);
expect(monthlyPackage).not.toBe(null);
monthlyPackage
expect(monthlyPackage?.identifier).toBe("$rc_monthly");
expect(customPackage).not.toBe(null);
expect(customPackage?.identifier).toBe("<package_id>");
Purchases.getSharedInstance().close();
});

test('Snippet "Getting product" works', async () => {
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
let product : Product|undefined;
const callback = vi.fn().mockImplementation((theProduct : Product) => {
product = theProduct;
});
await gettingProduct(callback);
expect(callback).toHaveBeenCalled();
expect(product).toBeDefined()
expect(product?.currentPrice.amountMicros).toBe(10000000);
expect(product?.currentPrice.currency).toBe("USD");
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
let product: Product | undefined;
const callback = vi.fn().mockImplementation((theProduct: Product) => {
product = theProduct;
});
await gettingProduct(callback);
expect(callback).toHaveBeenCalled();
expect(product).toBeDefined()
expect(product?.currentPrice.amountMicros).toBe(10000000);
expect(product?.currentPrice.currency).toBe("USD");
Purchases.getSharedInstance().close();
});

test('Snippet "Purchasing package" works', async () => {
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");
await purchasingPackage();
Purchases.getSharedInstance().close();
Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, "customer_without_entitlement");

await purchasingPackage();
Purchases.getSharedInstance().close();
});

11 changes: 11 additions & 0 deletions code_blocks/_projects/rc-billing/rc-billing-doc-snippets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ const purchases = Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, appUser
return purchases;
}

function configuringSDKWithAnonUser(REVENUECAT_BILLING_PUBLIC_API_KEY: string) {
// MARK: Configuring SDK Anonymous
// This function will generate a unique anonymous ID for the user.
// Make sure to enable the Redemption Links feature in the RevenueCat dashboard and use the
// redemption link to redeem the purchase in your mobile app.
const appUserId = Purchases.generateRevenueCatAnonymousAppUserId();
const purchases = Purchases.configure(REVENUECAT_BILLING_PUBLIC_API_KEY, appUserId);
// END
return purchases;
}

async function getCustomerInfo() : Promise<CustomerInfo | null> {
let customerInfo : CustomerInfo|null = null;
// MARK: Getting customer information
Expand Down
Loading