UNPKG

stripe-stateful-mock

Version:
373 lines (333 loc) 16 kB
import * as chai from "chai"; import Stripe from "stripe"; import {generateId} from "../src/api/utils"; import {buildStripeParityTest} from "./buildStripeParityTest"; import {getLocalStripeClient} from "./stripeUtils"; describe("customers", () => { const localStripeClient = getLocalStripeClient(); it("supports basic creation with no params", buildStripeParityTest( async (stripeClient) => { const customer = await stripeClient.customers.create({}); const customerGet = await stripeClient.customers.retrieve(customer.id); const customerGetExpanded = await stripeClient.customers.retrieve(customer.id, {expand: ["sources", "subscriptions"]}); return [customer, customerGet, customerGetExpanded]; } )); it("supports creating with a specific ID", buildStripeParityTest( async (stripeClient) => { // This isn't documented anywhere but it does work. const id = `cus_${generateId()}`; const customer = await stripeClient.customers.create({id} as any); chai.assert.equal(customer.id, id); const customerGet = await stripeClient.customers.retrieve(customer.id); chai.assert.equal(customerGet.id, id); return [customer]; } )); it("supports creation with expand ", buildStripeParityTest( async (stripeClient) => { const customerExpanded = await stripeClient.customers.create({expand: ["sources", "subscriptions"]}); return [customerExpanded]; } )); it("creating and charging a default source", buildStripeParityTest( async (stripeClient) => { const customer = await stripeClient.customers.create({ source: "tok_visa" }); const charge = await stripeClient.charges.create({ currency: "usd", amount: 8675309, customer: customer.id }); return [customer, charge]; } )); it("supports creating and charging an additional source", buildStripeParityTest( async (stripeClient) => { const customer = await stripeClient.customers.create({ source: "tok_mastercard", expand: ["sources"] }); const additionalSource = await stripeClient.customers.createSource(customer.id, { source: "tok_visa" }) as Stripe.Card; const customerWithAdditionalSource = await stripeClient.customers.retrieve(customer.id, {expand: ["sources"]}) as Stripe.Customer; const charge = await stripeClient.charges.create({ amount: 1000, currency: "usd", customer: customer.id, source: additionalSource.id }); chai.assert.notEqual(additionalSource.id, customer.default_source); chai.assert.equal(customerWithAdditionalSource.default_source, customerWithAdditionalSource.sources.data[0].id); chai.assert.equal(customerWithAdditionalSource.sources.data[1].id, additionalSource.id); return [customer, additionalSource, customerWithAdditionalSource, charge]; } )); it("errors on charging an invalid non-default source", buildStripeParityTest( async (stripeClient) => { const customer = await stripeClient.customers.create({ source: "tok_visa" }); let chargeError: any = null; try { await stripeClient.charges.create({ currency: "usd", amount: 8675309, customer: customer.id, source: `invalid-${generateId(12)}` }); } catch (err) { chargeError = err; } return [customer, chargeError]; } )); it("supports tok_chargeDeclined", buildStripeParityTest( async (stripeClient) => { let customerError: any = null; try { await stripeClient.customers.create({ source: "tok_chargeDeclined" }); } catch (err) { customerError = err; } return [customerError]; } )); it("supports tok_chargeDeclinedInsufficientFunds", buildStripeParityTest( async (stripeClient) => { let customerError: any = null; try { await stripeClient.customers.create({ source: "tok_chargeDeclinedInsufficientFunds" }); } catch (err) { customerError = err; } return [customerError]; } )); it("supports tok_chargeDeclinedIncorrectCvc", buildStripeParityTest( async (stripeClient) => { let customerError: any = null; try { await stripeClient.customers.create({ source: "tok_chargeDeclinedIncorrectCvc" }); } catch (err) { customerError = err; } return [customerError]; } )); it("supports tok_chargeDeclinedIncorrectCvc", buildStripeParityTest( async (stripeClient) => { let customerError: any = null; try { await stripeClient.customers.create({ source: "tok_chargeDeclinedIncorrectCvc" }); } catch (err) { customerError = err; } return [customerError]; } )); it("supports tok_chargeDeclinedExpiredCard", buildStripeParityTest( async (stripeClient) => { let customerError: any = null; try { await stripeClient.customers.create({ source: "tok_chargeDeclinedExpiredCard" }); } catch (err) { customerError = err; } return [customerError]; } )); it("supports tok_chargeCustomerFail", buildStripeParityTest( async (stripeClient) => { const customer = await stripeClient.customers.create({ source: "tok_chargeCustomerFail" }); let chargeError: any = null; try { await stripeClient.charges.create({ currency: "usd", amount: 8675309, customer: customer.id }); } catch (err) { chargeError = err; } return [customer, chargeError]; } )); it("supports Stripe-Account header (Connect account)", buildStripeParityTest( async (stripeClient, mode) => { let connectedAccountId: string; if (mode === "live") { chai.assert.isString(process.env["STRIPE_CONNECTED_ACCOUNT_ID"], "connected account ID is set"); connectedAccountId = process.env["STRIPE_CONNECTED_ACCOUNT_ID"]; } else { const account = await stripeClient.accounts.create({type: "custom"}); connectedAccountId = account.id; } const customer = await stripeClient.customers.create({source: "tok_visa"}, {stripeAccount: connectedAccountId}); let retrieveError: any; try { await stripeClient.customers.retrieve(customer.id); } catch (err) { retrieveError = err; } chai.assert.isDefined(retrieveError, "customer should not be in the account, but should be in the connected account"); const connectRetrieveCustomer = await stripeClient.customers.retrieve(customer.id, {stripeAccount: connectedAccountId}); chai.assert.deepEqual(connectRetrieveCustomer, customer); const connectRetrieveCard = await stripeClient.customers.retrieveSource(customer.id, customer.default_source as string, {stripeAccount: connectedAccountId}) as Stripe.Card; chai.assert.equal(connectRetrieveCard.id, customer.default_source as string); return [customer, retrieveError, connectRetrieveCustomer, connectRetrieveCard]; } )); it("can list customers", async () => { // Create a fresh account to get a clean slate. const account = await localStripeClient.accounts.create({type: "custom"}); const listEmpty = await localStripeClient.customers.list({stripeAccount: account.id}); chai.assert.lengthOf(listEmpty.data, 0); const customer0 = await localStripeClient.customers.create({email: "luser0@example.com"}, {stripeAccount: account.id}); const listOne = await localStripeClient.customers.list({stripeAccount: account.id}); chai.assert.lengthOf(listOne.data, 1); chai.assert.sameDeepMembers(listOne.data, [customer0]); const charge1 = await localStripeClient.customers.create({email: "luser1@example.com"}, {stripeAccount: account.id}); const listTwo = await localStripeClient.customers.list({stripeAccount: account.id}); chai.assert.lengthOf(listTwo.data, 2); chai.assert.sameDeepMembers(listTwo.data, [charge1, customer0]); const listLimit1 = await localStripeClient.customers.list({limit: 1}, {stripeAccount: account.id}); chai.assert.lengthOf(listLimit1.data, 1); chai.assert.isUndefined(listLimit1.data[0].sources); chai.assert.isUndefined(listLimit1.data[0].subscriptions); const listLimit1Expanded = await localStripeClient.customers.list({ limit: 1, expand: ["sources", "subscriptions"] }, {stripeAccount: account.id}); chai.assert.lengthOf(listLimit1Expanded.data, 1); chai.assert.isDefined(listLimit1Expanded.data[0].sources); chai.assert.isDefined(listLimit1Expanded.data[0].subscriptions); const listLimit2 = await localStripeClient.customers.list({ limit: 1, starting_after: listLimit1.data[0].id }, {stripeAccount: account.id}); chai.assert.lengthOf(listLimit1.data, 1); chai.assert.sameDeepMembers([...listLimit2.data, ...listLimit1.data], listTwo.data); }); describe("unofficial token support", () => { describe("tok_forget", () => { it("forgets the customer when specified on customer create", async () => { const customer = await localStripeClient.customers.create({ source: "tok_forget" }); chai.assert.isString(customer.id); let getCustomerError: any; try { await localStripeClient.customers.retrieve(customer.id); } catch (err) { getCustomerError = err; } chai.assert.isDefined(getCustomerError); chai.assert.equal(getCustomerError.statusCode, 404); }); }); }); describe("deleting", () => { it("supports deleting the only source", buildStripeParityTest( async (stripeClient) => { const customerBeforeDelete = await stripeClient.customers.create({ source: "tok_visa" }); await stripeClient.customers.deleteSource(customerBeforeDelete.id, customerBeforeDelete.default_source as string); const customerAfterDelete = await stripeClient.customers.retrieve(customerBeforeDelete.id); return [customerBeforeDelete, customerAfterDelete]; } )); it("supports deleting the non-default_source", buildStripeParityTest( async (stripeClient) => { const customerBeforeDelete = await stripeClient.customers.create({ source: "tok_visa", expand: ["sources"] }); const secondSource = await stripeClient.customers.createSource(customerBeforeDelete.id, {source: "tok_visa"}); await stripeClient.customers.deleteSource(customerBeforeDelete.id, secondSource.id); const customerAfterDelete = await stripeClient.customers.retrieve(customerBeforeDelete.id, {expand: ["sources"]}); return [customerBeforeDelete, secondSource as Stripe.Card, customerAfterDelete]; } )); it("supports deleting the default_source with a second source", buildStripeParityTest( async (stripeClient) => { const customerBeforeDelete = await stripeClient.customers.create({ source: "tok_visa", expand: ["sources"] }); const secondSource = await stripeClient.customers.createSource(customerBeforeDelete.id, {source: "tok_visa"}); await stripeClient.customers.deleteSource(customerBeforeDelete.id, customerBeforeDelete.default_source as string); const customerAfterDelete = await stripeClient.customers.retrieve(customerBeforeDelete.id, {expand: ["sources"]}); return [customerBeforeDelete, secondSource as Stripe.Card, customerAfterDelete]; } )); }); describe("updating", () => { it("supports updating", buildStripeParityTest( async (stripeClient) => { const customer = await stripeClient.customers.create({ source: "tok_visa" }); const customerAfterUpdate = await stripeClient.customers.update(customer.id, { description: "foobar", email: "email@example.com", name: "foo bar" }); return [customer, customerAfterUpdate]; } )); it("supports updating the default source", buildStripeParityTest( async (stripeClient) => { const customer = await stripeClient.customers.create({ source: "tok_visa" }); const secondSource = await stripeClient.customers.createSource(customer.id, {source: "tok_visa"}); const customerAfterUpdate = await stripeClient.customers.update(customer.id, {default_source: secondSource.id}); chai.assert.equal(customerAfterUpdate.default_source, secondSource.id); return [customer, secondSource as Stripe.Card, customerAfterUpdate]; } )); it("errors updating the default source to a non-existant source", buildStripeParityTest( async (stripeClient) => { const customer = await stripeClient.customers.create({ source: "tok_visa" }); let updateError: any = null; try { await stripeClient.customers.update(customer.id, {default_source: generateId()}); } catch (err) { updateError = err; } return [customer, updateError]; } )); it("supports updating the source", buildStripeParityTest( async (stripeClient) => { const customer = await stripeClient.customers.create({}); const customerAfterUpdate = await stripeClient.customers.update(customer.id, { source: "tok_visa", expand: ["sources"] }); const customerGet = await stripeClient.customers.retrieve(customer.id, {expand: ["sources"]}); chai.assert.isString(customerAfterUpdate.default_source); chai.assert.lengthOf(customerAfterUpdate.sources.data, 1); return [customer, customerAfterUpdate, customerGet]; } )); }); });