diff --git a/cypress/elements/shared/button-selectors.js b/cypress/elements/shared/button-selectors.js index 5553459d8..6f9837fa3 100644 --- a/cypress/elements/shared/button-selectors.js +++ b/cypress/elements/shared/button-selectors.js @@ -11,5 +11,6 @@ export const BUTTON_SELECTORS = { expandIcon: '[data-test-id="expand-icon"]', nextPaginationButton: '[data-test="button-pagination-next"]', deleteIcon: '[data-test-id="deleteIcon"]', - showMoreButton: '[data-test-id="showMoreButton"]' + showMoreButton: '[data-test-id="showMoreButton"]', + button: "button" }; diff --git a/cypress/fixtures/urlList.js b/cypress/fixtures/urlList.js index 7da736735..5a2fbf661 100644 --- a/cypress/fixtures/urlList.js +++ b/cypress/fixtures/urlList.js @@ -72,5 +72,9 @@ export const productTypeDetailsUrl = productTypeId => export const giftCardDetailsUrl = giftCardId => `${urlList.giftCards}${giftCardId}`; +export const saleDetailsUrl = saleId => `${urlList.sales}${saleId}`; + +export const voucherDetailsUrl = voucherId => `${urlList.vouchers}${voucherId}`; + export const stripeConfirmationUrl = id => `https://api.stripe.com/v1/payment_intents/${id}/confirm`; diff --git a/cypress/integration/discounts/sales/createSaleWithAssignedProduct.js b/cypress/integration/discounts/sales/createSaleWithAssignedProduct.js new file mode 100644 index 000000000..b1f81cbf5 --- /dev/null +++ b/cypress/integration/discounts/sales/createSaleWithAssignedProduct.js @@ -0,0 +1,202 @@ +/// +/// + +import faker from "faker"; + +import { urlList } from "../../../fixtures/urlList"; +import { createChannel } from "../../../support/api/requests/Channels"; +import { updateChannelInProduct } from "../../../support/api/requests/Product"; +import * as channelsUtils from "../../../support/api/utils/channelsUtils"; +import { deleteSalesStartsWith } from "../../../support/api/utils/discounts/salesUtils"; +import * as productsUtils from "../../../support/api/utils/products/productsUtils"; +import { + createShipping, + deleteShippingStartsWith +} from "../../../support/api/utils/shippingUtils"; +import { getProductPrice } from "../../../support/api/utils/storeFront/storeFrontProductUtils"; +import filterTests from "../../../support/filterTests"; +import { + assignProducts, + createSale, + discountOptions +} from "../../../support/pages/discounts/salesPage"; + +filterTests({ definedTags: ["all"] }, () => { + describe("Create sale with assigned products", () => { + const startsWith = "CyCreateSaleProd-"; + + let productType; + let attribute; + let category; + let defaultChannel; + let warehouse; + + before(() => { + cy.clearSessionData().loginUserViaRequest(); + channelsUtils.deleteChannelsStartsWith(startsWith); + deleteSalesStartsWith(startsWith); + productsUtils.deleteProductsStartsWith(startsWith); + deleteShippingStartsWith(startsWith); + + const name = `${startsWith}${faker.datatype.number()}`; + productsUtils + .createTypeAttributeAndCategoryForProduct({ name }) + .then( + ({ + productType: productTypeResp, + attribute: attributeResp, + category: categoryResp + }) => { + productType = productTypeResp; + attribute = attributeResp; + category = categoryResp; + + channelsUtils.getDefaultChannel(); + } + ) + .then(channel => { + defaultChannel = channel; + cy.fixture("addresses"); + }) + .then(addresses => { + createShipping({ + channelId: defaultChannel.id, + name, + address: addresses.plAddress, + price: 100 + }); + }) + .then(({ warehouse: warehouseResp }) => { + warehouse = warehouseResp; + }); + }); + + beforeEach(() => { + cy.clearSessionData().loginUserViaRequest(); + }); + + it("should create percentage discount", () => { + const saleName = `${startsWith}${faker.datatype.number()}`; + const discountValue = 50; + const productPrice = 100; + + productsUtils + .createProductInChannel({ + name: saleName, + channelId: defaultChannel.id, + warehouseId: warehouse.id, + productTypeId: productType.id, + attributeId: attribute.id, + categoryId: category.id, + price: productPrice + }) + .then(({ product: productResp }) => { + /* Uncomment after fixing SALEOR-3367 bug + cy.clearSessionData() + .loginUserViaRequest("auth", ONE_PERMISSION_USERS.discount) + */ + + cy.visit(urlList.sales); + cy.softExpectSkeletonIsVisible(); + const product = productResp; + createSale({ + saleName, + channelName: defaultChannel.name, + discountValue, + discountOption: discountOptions.PERCENTAGE + }); + assignProducts(product.name); + getProductPrice(product.id, defaultChannel.slug); + }) + .then(price => { + const expectedPrice = (productPrice * discountValue) / 100; + expect(expectedPrice).to.be.eq(price); + }); + }); + + it("should create fixed price discount", () => { + const saleName = `${startsWith}${faker.datatype.number()}`; + const discountValue = 50; + const productPrice = 100; + + productsUtils + .createProductInChannel({ + name: saleName, + channelId: defaultChannel.id, + warehouseId: warehouse.id, + productTypeId: productType.id, + attributeId: attribute.id, + categoryId: category.id, + price: productPrice + }) + .then(({ product: productResp }) => { + /* Uncomment after fixing SALEOR-3367 bug + cy.clearSessionData() + .loginUserViaRequest("auth", ONE_PERMISSION_USERS.discount) + */ + + cy.visit(urlList.sales); + cy.softExpectSkeletonIsVisible(); + const product = productResp; + createSale({ + saleName, + channelName: defaultChannel.name, + discountValue, + discountOption: discountOptions.FIXED + }); + assignProducts(product.name); + getProductPrice(product.id, defaultChannel.slug); + }) + .then(price => { + const expectedPrice = productPrice - discountValue; + expect(expectedPrice).to.be.eq(price); + }); + }); + + it("should not displayed discount not assign to channel", () => { + const saleName = `${startsWith}${faker.datatype.number()}`; + let channel; + let product; + const discountValue = 50; + const productPrice = 100; + + createChannel({ name: saleName }).then( + channelResp => (channel = channelResp) + ); + productsUtils + .createProductInChannel({ + name: saleName, + channelId: defaultChannel.id, + warehouseId: warehouse.id, + productTypeId: productType.id, + attributeId: attribute.id, + categoryId: category.id, + price: productPrice + }) + .then(({ product: productResp }) => { + product = productResp; + updateChannelInProduct({ + productId: product.id, + channelId: channel.id + }); + }) + .then(() => { + /* Uncomment after fixing SALEOR-3367 bug + cy.clearSessionData() + .loginUserViaRequest("auth", ONE_PERMISSION_USERS.discount) + */ + + cy.visit(urlList.sales); + cy.softExpectSkeletonIsVisible(); + createSale({ + saleName, + channelName: channel.name, + discountValue + }); + assignProducts(product.name); + getProductPrice(product.id, defaultChannel.slug); + }) + .then(price => expect(price).to.equal(productPrice)); + }); + }); +}); diff --git a/cypress/integration/discounts/sales/sales.js b/cypress/integration/discounts/sales/sales.js new file mode 100644 index 000000000..22cbf7a23 --- /dev/null +++ b/cypress/integration/discounts/sales/sales.js @@ -0,0 +1,221 @@ +/// +/// + +import faker from "faker"; + +import { SALES_SELECTORS } from "../../../elements/discounts/sales"; +import { BUTTON_SELECTORS } from "../../../elements/shared/button-selectors"; +import { SHARED_ELEMENTS } from "../../../elements/shared/sharedElements"; +import { saleDetailsUrl } from "../../../fixtures/urlList"; +import { createCheckout } from "../../../support/api/requests/Checkout"; +import { updateSale } from "../../../support/api/requests/Discounts/Sales"; +import { + createVariant, + getVariant +} from "../../../support/api/requests/Product"; +import { getDefaultChannel } from "../../../support/api/utils/channelsUtils"; +import { + createSaleInChannel, + createSaleInChannelWithProduct, + deleteSalesStartsWith +} from "../../../support/api/utils/discounts/salesUtils"; +import { + createProductInChannel, + createTypeAttributeAndCategoryForProduct, + deleteProductsStartsWith +} from "../../../support/api/utils/products/productsUtils"; +import { + createShipping, + deleteShippingStartsWith +} from "../../../support/api/utils/shippingUtils"; +import filterTests from "../../../support/filterTests"; + +filterTests({ definedTags: ["all"] }, () => { + describe("Create sale with assigned products", () => { + const startsWith = "CySales"; + const saleValue = 10; + + let channel; + let sale; + let warehouse; + let address; + let productData; + + before(() => { + cy.clearSessionData().loginUserViaRequest(); + deleteProductsStartsWith(startsWith); + deleteShippingStartsWith(startsWith); + deleteSalesStartsWith(startsWith); + getDefaultChannel() + .then(defaultChannel => { + channel = defaultChannel; + createSaleInChannel({ + name: startsWith, + type: "FIXED", + value: saleValue, + channelId: channel.id + }); + }) + .then(saleResp => (sale = saleResp)); + cy.fixture("addresses") + .then(addresses => { + address = addresses.usAddress; + createShipping({ + channelId: channel.id, + address, + name: startsWith + }); + }) + .then(({ warehouse: warehouseResp }) => { + warehouse = warehouseResp; + }); + createTypeAttributeAndCategoryForProduct({ + name: startsWith, + attributeValues: ["value1", "value2"] + }).then(({ attribute, category, productType }) => { + productData = { + attributeId: attribute.id, + categoryId: category.id, + productTypeId: productType.id, + channelId: channel.id, + warehouseId: warehouse.id, + price: 30 + }; + }); + }); + + beforeEach(() => { + cy.clearSessionData().loginUserViaRequest(); + }); + + it("should discount only variants added to sale", () => { + const productName = `${startsWith}${faker.datatype.number()}`; + const name = `${startsWith}${faker.datatype.number()}`; + + let variantNotOnSale; + let variantOnSale; + + productData.name = productName; + createProductInChannel(productData) + .then(({ product, variantsList }) => { + variantNotOnSale = variantsList; + productData.name = name; + productData.sku = name; + productData.productId = product.id; + productData.quantityInWarehouse = 10; + productData.attributeValues = ["value2"]; + createVariant(productData); + }) + .then(variantsList => { + variantOnSale = variantsList; + updateSale({ saleId: sale.id, variants: variantOnSale }); + }) + .then(() => { + createCheckout({ + channelSlug: channel.slug, + email: "example@example.com", + address, + variantsList: variantOnSale.concat(variantNotOnSale) + }); + }) + .then(({ checkout }) => { + const variantRespNotOnSale = checkout.lines.find( + element => element.variant.id === variantNotOnSale[0].id + ).variant; + const variantRespOnSale = checkout.lines.find( + element => element.variant.id === variantOnSale[0].id + ).variant; + expect(variantRespNotOnSale.pricing.onSale).to.be.false; + expect(variantRespOnSale.pricing.onSale).to.be.true; + expect(variantRespNotOnSale.pricing.price.gross.amount).to.eq( + productData.price + ); + expect(variantRespOnSale.pricing.price.gross.amount).to.eq( + productData.price - saleValue + ); + }); + }); + + it("should delete sale", () => { + const name = `${startsWith}${faker.datatype.number()}`; + let variants; + let saleToDelete; + productData.name = name; + createProductInChannel(productData) + .then(({ variantsList }) => { + variants = variantsList; + createSaleInChannelWithProduct({ + name, + type: "FIXED", + value: saleValue, + channelId: channel.id, + variants + }); + }) + .then(saleResp => { + saleToDelete = saleResp; + getVariant(variants[0].id, channel.slug); + }) + .then(variantResp => { + expect(variantResp.pricing.onSale).to.be.true; + expect(variantResp.pricing.price.gross.amount).to.eq( + productData.price - saleValue + ); + cy.visit(saleDetailsUrl(saleToDelete.id)) + .addAliasToGraphRequest("SaleDelete") + .get(BUTTON_SELECTORS.deleteButton) + .click() + .get(BUTTON_SELECTORS.submit) + .click() + .wait("@SaleDelete"); + getVariant(variants[0].id, channel.slug); + }) + .then(variantResp => { + expect(variantResp.pricing.onSale).to.be.false; + expect(variantResp.pricing.price.gross.amount).to.eq( + productData.price + ); + }); + }); + + it("should remove variant from sale", () => { + const name = `${startsWith}${faker.datatype.number()}`; + let product; + let variants; + productData.name = name; + createProductInChannel(productData) + .then(({ variantsList, product: productResp }) => { + product = productResp; + variants = variantsList; + updateSale({ + saleId: sale.id, + variants + }); + }) + .then(() => { + getVariant(variants[0].id, channel.slug); + }) + .then(variantResp => { + expect(variantResp.pricing.onSale).to.be.true; + expect(variantResp.pricing.price.gross.amount).to.eq( + productData.price - saleValue + ); + cy.visit(saleDetailsUrl(sale.id)) + .get(SALES_SELECTORS.variantsTab) + .click() + .addAliasToGraphRequest("SaleCataloguesRemove"); + cy.contains(SHARED_ELEMENTS.tableRow, product.name) + .find(BUTTON_SELECTORS.button) + .click() + .wait("@SaleCataloguesRemove"); + getVariant(variants[0].id, channel.slug); + }) + .then(variantResp => { + expect(variantResp.pricing.onSale).to.be.false; + expect(variantResp.pricing.price.gross.amount).to.eq( + productData.price + ); + }); + }); + }); +}); diff --git a/cypress/integration/discounts/vouchers.js b/cypress/integration/discounts/vouchers.js index 8da728540..84f254f4c 100644 --- a/cypress/integration/discounts/vouchers.js +++ b/cypress/integration/discounts/vouchers.js @@ -3,11 +3,15 @@ import faker from "faker"; -import { urlList } from "../../fixtures/urlList"; +import { BUTTON_SELECTORS } from "../../elements/shared/button-selectors"; +import { urlList, voucherDetailsUrl } from "../../fixtures/urlList"; import { ONE_PERMISSION_USERS } from "../../fixtures/users"; import { createChannel } from "../../support/api/requests/Channels"; import * as channelsUtils from "../../support/api/utils/channelsUtils"; -import { deleteVouchersStartsWith } from "../../support/api/utils/discounts/vouchersUtils"; +import { + createVoucherInChannel, + deleteVouchersStartsWith +} from "../../support/api/utils/discounts/vouchersUtils"; import { createCheckoutWithVoucher } from "../../support/api/utils/ordersUtils"; import * as productsUtils from "../../support/api/utils/products/productsUtils"; import { @@ -33,6 +37,7 @@ filterTests({ definedTags: ["all"] }, () => { let category; let shippingMethod; let variants; + let product; let address; before(() => { @@ -86,7 +91,8 @@ filterTests({ definedTags: ["all"] }, () => { }); } ) - .then(({ variantsList: variantsResp }) => { + .then(({ variantsList: variantsResp, product: productResp }) => { + product = productResp; variants = variantsResp; createChannel({ name }); }) @@ -151,6 +157,39 @@ filterTests({ definedTags: ["all"] }, () => { ); }); + it("should delete voucher", () => { + const name = `${startsWith}${faker.datatype.number()}`; + const voucherValue = 50; + + let voucher; + + cy.clearSessionData().loginUserViaRequest(); + createVoucherInChannel({ + name, + productId: product.id, + channelId: defaultChannel.id, + value: voucherValue + }) + .then(voucherResp => { + voucher = voucherResp; + expect(voucher.id).to.be.ok; + }) + .then(resp => { + cy.visit(voucherDetailsUrl(voucher.id)) + .addAliasToGraphRequest("VoucherDelete") + .get(BUTTON_SELECTORS.deleteButton) + .click() + .get(BUTTON_SELECTORS.submit) + .click() + .wait("@VoucherDelete"); + createCheckoutForCreatedVoucher(voucher.code); + }) + .then(({ addPromoCodeResp }) => { + const errorField = addPromoCodeResp.checkoutErrors[0].field; + expect(errorField).to.be.eq("promoCode"); + }); + }); + function createCheckoutForCreatedVoucher(voucherCode) { return createCheckoutWithVoucher({ channelSlug: defaultChannel.slug, diff --git a/cypress/support/api/requests/Checkout.js b/cypress/support/api/requests/Checkout.js index 8ce36a91f..9e12f4b57 100644 --- a/cypress/support/api/requests/Checkout.js +++ b/cypress/support/api/requests/Checkout.js @@ -48,9 +48,23 @@ export function createCheckout({ checkout{ token id + token availableShippingMethods{ name } + lines{ + variant{ + id + pricing{ + onSale + price{ + gross{ + amount + } + } + } + } + } ${availableCollectionPointsLines} } } diff --git a/cypress/support/api/requests/Discounts/Sales.js b/cypress/support/api/requests/Discounts/Sales.js index e5b7913c2..b8ec14daf 100644 --- a/cypress/support/api/requests/Discounts/Sales.js +++ b/cypress/support/api/requests/Discounts/Sales.js @@ -1,4 +1,8 @@ -import { getValueWithDefault } from "../utils/Utils"; +import { + getValuesInArray, + getValueWithDefault, + getVariantsIdsLines +} from "../utils/Utils"; export function getSales(first, searchQuery) { const filter = getValueWithDefault( @@ -33,3 +37,64 @@ export function deleteSale(saleId) { }`; return cy.sendRequestWithQuery(mutation); } + +export function createSale({ name, type, value, products, variants }) { + const productsLine = getValueWithDefault(products, `products: ${products}`); + const variantsLine = getValueWithDefault(variants, `variants: ${variants}`); + const mutation = `mutation{ + saleCreate(input:{ + name: "${name}" + type: ${type} + value: ${value} + ${productsLine} + ${variantsLine} + }){ + sale{ + id + name + } + } + }`; + return cy.sendRequestWithQuery(mutation).its("body.data.saleCreate.sale"); +} + +export function updateSale({ saleId, variants, productId }) { + const productsLine = getValueWithDefault( + productId, + `products: [${productId}]` + ); + const variantsLines = getValueWithDefault( + variants, + getValuesInArray(getVariantsIdsLines(variants)), + "[]" + ); + const mutation = `mutation{ + saleUpdate(id:"${saleId}" input:{ + ${productsLine} + variants: ${variantsLines} + }){ + errors{ + field + message + } + } + }`; + return cy.sendRequestWithQuery(mutation); +} + +export function addChannelToSale(saleId, channelId, discountValue) { + const mutation = `mutation{ + saleChannelListingUpdate(id:"${saleId}" input:{ + addChannels: [{ + channelId: "${channelId}" + discountValue: "${discountValue}" + }] + }){ + errors{ + field + message + } + } + }`; + return cy.sendRequestWithQuery(mutation); +} diff --git a/cypress/support/api/requests/Discounts/Vouchers.js b/cypress/support/api/requests/Discounts/Vouchers.js index e9e99e800..bd0cd669b 100644 --- a/cypress/support/api/requests/Discounts/Vouchers.js +++ b/cypress/support/api/requests/Discounts/Vouchers.js @@ -15,6 +15,7 @@ export function getVouchers(first, startsWith) { .sendRequestWithQuery(query) .then(resp => resp.body.data.vouchers.edges); } + export function deleteVouchers(voucherId) { const mutation = `mutation deleteVouchers{ voucherDelete(id:"${voucherId}"){ @@ -26,3 +27,40 @@ export function deleteVouchers(voucherId) { }`; return cy.sendRequestWithQuery(mutation); } + +export function createVoucher({ name, productId, code = name }) { + const mutation = `mutation{ + voucherCreate(input:{ + name:"${name}", + code:"${code}" + products:["${productId}"] + }){ + voucher{ + id + code + } + errors{ + field + message + } + } + }`; + return cy.sendRequestWithQuery(mutation).its("body.data.voucherCreate"); +} + +export function addChannelToVoucher(voucherId, channelId, value) { + const mutation = `mutation{ + voucherChannelListingUpdate(id:"${voucherId}" input:{ + addChannels:{ + channelId:"${channelId}" + discountValue:"${value}" + } + }){ + errors{ + field + message + } + } + }`; + return cy.sendRequestWithQuery(mutation); +} diff --git a/cypress/support/api/requests/Product.js b/cypress/support/api/requests/Product.js index 01678fc3c..9f3ef3264 100644 --- a/cypress/support/api/requests/Product.js +++ b/cypress/support/api/requests/Product.js @@ -1,5 +1,9 @@ import { stringify } from "../.././formatData/formatJson"; -import { getValueWithDefault, getVariantsListIds } from "./utils/Utils"; +import { + getValuesInArray, + getValueWithDefault, + getVariantsListIds +} from "./utils/Utils"; export function getFirstProducts(first, search) { const filter = search @@ -148,7 +152,8 @@ export function createVariant({ price = 1, costPrice = 1, trackInventory = true, - weight = 1 + weight = 1, + attributeValues = ["value"] }) { const channelListings = getValueWithDefault( channelId, @@ -171,7 +176,7 @@ export function createVariant({ productVariantBulkCreate(product: "${productId}", variants: { attributes: [{ id:"${attributeId}" - values: ["value"] + values: ${getValuesInArray(attributeValues)} }] weight: ${weight} sku: "${sku}" diff --git a/cypress/support/api/requests/utils/Utils.js b/cypress/support/api/requests/utils/Utils.js index b28bfc34a..1ac154723 100644 --- a/cypress/support/api/requests/utils/Utils.js +++ b/cypress/support/api/requests/utils/Utils.js @@ -27,6 +27,10 @@ export function getVariantsLines(variantsList, quantity) { ); } +export function getVariantsIdsLines(variantsList) { + return variantsList.map(variant => `${variant.id}`); +} + export function getVariantsListIds(variantsList) { return variantsList.map(variant => `"${variant.id}"`).join(); } @@ -35,3 +39,6 @@ export const getPaymentDataLine = paymentData => paymentData ? `, paymentData:"{\\"riskData\\":{\\"clientData\\":\\"${paymentData.clientData}\\"}, \\"paymentMethod\\":{\\"type\\":\\"scheme\\", \\"encryptedCardNumber\\":\\"${paymentData.encryptedCardNumber}\\", \\"encryptedExpiryMonth\\":\\"${paymentData.encryptedExpiryMonth}\\", \\"encryptedExpiryYear\\":\\"${paymentData.encryptedExpiryYear}\\", \\"encryptedSecurityCode\\":\\"${paymentData.encryptedSecurityCode}\\", \\"brand\\":\\"${paymentData.brand}\\"}}"` : ""; + +export const getValuesInArray = array => + getValueWithDefault(array.length === 1, `["${array}"]`, `${array}`); diff --git a/cypress/support/api/utils/discounts/salesUtils.js b/cypress/support/api/utils/discounts/salesUtils.js index 3dc537f0b..ca4bab407 100644 --- a/cypress/support/api/utils/discounts/salesUtils.js +++ b/cypress/support/api/utils/discounts/salesUtils.js @@ -1,5 +1,57 @@ -import { deleteSale, getSales } from "../../requests/Discounts/Sales"; +import { + addChannelToSale, + createSale, + deleteSale, + getSales, + updateSale +} from "../../requests/Discounts/Sales"; export function deleteSalesStartsWith(startsWith) { cy.deleteElementsStartsWith(deleteSale, getSales, startsWith); } + +export function createSaleInChannel({ + name, + type, + value, + channelId, + discountValue = value +}) { + let sale; + return createSale({ + name, + type, + value + }) + .then(saleResp => { + sale = saleResp; + addChannelToSale(sale.id, channelId, discountValue); + }) + .then(() => sale); +} + +export function createSaleInChannelWithProduct({ + name, + type, + value, + channelId, + variants, + productId +}) { + let sale; + return createSaleInChannel({ + name, + type, + value, + channelId + }) + .then(saleResp => { + sale = saleResp; + updateSale({ + saleId: sale.id, + variants, + productId + }); + }) + .then(() => sale); +} diff --git a/cypress/support/api/utils/discounts/vouchersUtils.js b/cypress/support/api/utils/discounts/vouchersUtils.js index 1a2e2c1be..63689b254 100644 --- a/cypress/support/api/utils/discounts/vouchersUtils.js +++ b/cypress/support/api/utils/discounts/vouchersUtils.js @@ -1,5 +1,26 @@ -import { deleteVouchers, getVouchers } from "../../requests/Discounts/Vouchers"; +import { + addChannelToVoucher, + createVoucher, + deleteVouchers, + getVouchers +} from "../../requests/Discounts/Vouchers"; export function deleteVouchersStartsWith(startsWith) { cy.deleteElementsStartsWith(deleteVouchers, getVouchers, startsWith, "code"); } + +export function createVoucherInChannel({ + name, + productId, + channelId, + value, + code = name +}) { + let voucher; + return createVoucher({ name, productId, code }) + .then(({ voucher: voucherResp }) => { + voucher = voucherResp; + addChannelToVoucher(voucher.id, channelId, value); + }) + .then(() => voucher); +}