chromium/third_party/blink/web_tests/wpt_internal/digital-goods/resources/mock-digital-goods-service.js

import {
  BillingResponseCode,
  CreateDigitalGoodsResponseCode,
  ItemType,
} from '/gen/components/digital_goods/mojom/digital_goods.mojom.m.js';

import {
  DigitalGoodsFactory,
  DigitalGoodsFactoryReceiver,
  DigitalGoodsReceiver,
  DigitalGoodsRemote,
} from '/gen/third_party/blink/public/mojom/digital_goods/digital_goods.mojom.m.js';

class MockDigitalGoods {
  constructor() {
    this.resetRecordedAction_();
  }

  bind(request) {
    this.receiver = new DigitalGoodsReceiver(this);
    this.receiver.$.bindHandle(request.handle);
  }

  getRecordedAction_() {
    return this.action;
  }

  resetRecordedAction_() {
    this.action = new Promise((resolve, reject) => {
      this.actionResolve_ = resolve;
    });
  }

  makeItemDetails_(id) {
    // itemDetails is a payments.mojom.ItemDetails.
    let itemDetails = {};
    itemDetails.itemId = id;
    itemDetails.title = 'title:' + id;
    itemDetails.description = 'description:' + id;
    // price is a payments.mojom.PaymentCurrencyAmount.
    itemDetails.price = {};
    itemDetails.price.currency = 'AUD';
    // Set price.value as a number in |id| dollars.
    const matchNum = id.match(/\d+/);
    const num = matchNum ? matchNum[0] : 0;
    itemDetails.price.value = num + '.00';
    if (num % 2) {
      // Add optional fields.
      itemDetails.subscriptionPeriod = 'P' + num + 'Y';
      itemDetails.freeTrialPeriod = 'P' + num + 'M';
      itemDetails.introductoryPrice = {};
      itemDetails.introductoryPrice.currency = 'JPY';
      itemDetails.introductoryPrice.value = 2*num + '';
      itemDetails.introductoryPricePeriod = 'P' + num + 'D';
      itemDetails.introductoryPriceCycles = 3*num;
      itemDetails.type = Math.floor(num / 2) % 2 ? ItemType.kProduct : ItemType.kSubscription;
      itemDetails.iconUrls = [{url: 'https://example.com/icon.png'}];
    }
    return itemDetails;
  }

  async getDetails(itemIds) {
    this.actionResolve_('getDetails:' + itemIds);

    // Simulate some backend failure response.
    if (itemIds.includes('fail')) {
      return {code: BillingResponseCode.kError, itemDetailsList: []};
    }

    let itemDetailsList = [];
    // Simulate some specified IDs are not found.
    const found = itemIds.filter(id => !id.includes('gone'));
    for (const id of found) {
      itemDetailsList.push(this.makeItemDetails_(id));
    }

    return {
      code: BillingResponseCode.kOk,
      itemDetailsList,
    };
  }

  makePurchaseReference_(id) {
    // purchaseReference is a payments.mojom.PurchaseReference.
    let purchaseReference = {};
    purchaseReference.itemId = 'id:' + id;
    purchaseReference.purchaseToken = 'purchaseToken:' + id;
    return purchaseReference;
  }

  async listPurchases() {
    this.actionResolve_('listPurchases');

    let result = [];
    for (let i = 0; i < 10; i++) {
      result.push(this.makePurchaseReference_(i));
    }

    return {
      code: BillingResponseCode.kOk,
      purchaseReferenceList: result
    };
  }

  async listPurchaseHistory() {
    this.actionResolve_('listPurchaseHistory');

    let result = [];
    for (let i = 0; i < 20; i++) {
      result.push(this.makePurchaseReference_(i));
    }

    return {
      code: BillingResponseCode.kOk,
      purchaseReferenceList: result
    };
  }

  async consume(purchaseToken) {
    this.actionResolve_('consume:' + purchaseToken);

    if (purchaseToken === 'fail') {
      return { code: BillingResponseCode.kError };
    }
    return { code: BillingResponseCode.kOk };
  }
}

let mockDigitalGoods = new MockDigitalGoods();

class MockDigitalGoodsFactory {
  constructor() {
    this.interceptor_ =
        new MojoInterfaceInterceptor(DigitalGoodsFactory.$interfaceName);
    this.interceptor_.oninterfacerequest = e => this.bind(e.handle);
    this.receiver_ = new DigitalGoodsFactoryReceiver(this);

    this.interceptor_.start();
  }

  bind(handle) {
    this.receiver_.$.bindHandle(handle);
  }

  async createDigitalGoods(paymentMethod) {
    if (paymentMethod !== 'https://example.com/billing') {
      return {
        code: CreateDigitalGoodsResponseCode.kUnsupportedPaymentMethod,
        digitalGoods: null
      };
    }

    const digitalGoods = new DigitalGoodsRemote();
    mockDigitalGoods.bind(digitalGoods.$.bindNewPipeAndPassReceiver());

    return {
      code: CreateDigitalGoodsResponseCode.kOk,
      digitalGoods,
    };
  }
}

let mockDigitalGoodsFactory = new MockDigitalGoodsFactory();

export function digital_goods_test(func, {
  title,
  expectedAction,
  paymentMethod = 'https://example.com/billing',
} = {}) {
  promise_test(async () => {
    mockDigitalGoods.resetRecordedAction_();
    const service = await window.getDigitalGoodsService(paymentMethod);

    await func(service);

    if (expectedAction) {
      const action = await mockDigitalGoods.getRecordedAction_();
      assert_equals(action, expectedAction);
    }
  }, title);
}