Reputation: 1316
I am writing cypress tests using mocha.
I have 2 applications under the test which are separate apps but kind of have similar functionality that is being tested.
The thing is that I end up with 2 spec files having basically similar logic, the only difference is in the test data provided and maybe some function implementation which is specific to the particular app.
In order to visualize it here are my spec files.
For the sake of an example we have dogs app and cats app where you can buy products for your lovely dogs or cats. This tests the voucher functionality so that you could get some discount on the products.
This is redeem-voucher-catsapp-spec.ts
import checkoutActions from '../../../support/actions/catsapp/checkout-actions';
import voucherActions from '../../../support/actions/common/voucher-actions';
import {sampleAddressData} from '../../../support/types/checkout-data';
import {localsCatsApp} from '../../../support/types/locals';
import {CheckoutGuestModel, Voucher} from '../../../support/types/types';
context('CatsApp', function() {
const env = Cypress.env('dataEnv');
const loc = localsCatsApp.de;
beforeEach(function() {
cy.fixture(env + '/users').as('users');
cy.fixture(env + '/products').as('products');
cy.fixture(env + '/vouchers').as('vouchers');
});
describe('Redeem voucher as a guest user', function() {
beforeEach(function() {
this.catsVouchers = this.vouchers.catsapp.voucher;
this.url = Cypress.env('catsAppBaseurl') + loc.language;
});
it('I can redeem valid voucher', function() {
const voucher: Voucher = {
code: this.catsVouchers.CHF15.code,
value: this.catsVouchers.CHF15.value,
type: this.catsVouchers.CHF15.type,
threshold: this.catsVouchers.CHF15.threshold
};
const checkoutGuestModel: CheckoutGuestModel = {
url: this.url,
userAddressData: sampleAddressData,
product: this.products.catsapp.standardProduct,
threshold: voucher.threshold
};
checkoutActions.landOnCheckoutPageAsGuest(checkoutGuestModel);
voucherActions.saveCheckoutPricesBeforeApplyingVoucher();
voucherActions.redeemVoucher(voucher, true, loc);
voucherActions.verifyVoucherApplied(voucher);
checkoutActions.finalizeOrder(loc.checkout.orderNowText);
checkoutActions.verifyCheckoutThankYouPage(loc.checkout.thankYouMessage);
});
});
});
This is redeem-voucher-dogsapp-spec.ts
import checkoutActions from '../../../support/actions/DogsApp/checkout-actions';
import voucherActions from '../../../support/actions/common/voucher-actions';
import {sampleAddressData} from '../../../support/types/checkout-data';
import {localsDogsApp} from '../../../support/types/locals';
import {CheckoutGuestModel, Voucher} from '../../../support/types/types';
context('DogsApp', function() {
const env = Cypress.env('dataEnv');
const loc = localsDogsApp.de;
beforeEach(function() {
cy.fixture(env + '/users').as('users');
cy.fixture(env + '/products').as('products');
cy.fixture(env + '/vouchers').as('vouchers');
});
describe('Redeem voucher as a guest user', function() {
beforeEach(function() {
this.dogsVouchers = this.vouchers.dogsapp.voucher;
this.url = Cypress.env('DogsAppBaseurl') + loc.language;
});
it('I can redeem valid voucher', function() {
const voucher: Voucher = {
code: this.dogsVouchers.CHF30.code,
value: this.dogsVouchers.CHF30.value,
type: this.dogsVouchers.CHF30.type,
threshold: this.dogsVouchers.CHF30.threshold
};
const checkoutGuestModel: CheckoutGuestModel = {
url: this.url,
userAddressData: sampleAddressData,
product: this.products.dogsapp.standardProduct3,
threshold: voucher.threshold
};
checkoutActions.landOnCheckoutPageAsGuest(checkoutGuestModel);
voucherActions.saveCheckoutPricesBeforeApplyingVoucher();
voucherActions.redeemVoucher(voucher, true, loc);
voucherActions.verifyVoucherApplied(voucher);
checkoutActions.finalizeOrder(loc.checkout.orderNowText);
checkoutActions.verifyCheckoutThankYouPage(loc.checkout.thankYouMessage);
});
});
});
As you can see there is a lot of code duplication going on there.
So I am trying to find a way to write one mocha template spec file which could be parametrized and in which I could pass in test data and function implementation specific to the particular app (like voucher object, url string, voucher fixture file, checkoutActions class specific to each app and so on) and then write 2 spec files which would just "call" my mocha template file with the specific parameters.
Is this possible to do with mocha? And how would you do it?
Please help :)
EDIT:
This is what I have tried inspired by the answers provided example. But the data.ctx seems to be undefined in the mocha context(
Testing ...)
function:
export interface VoucherTestData {
ctx: string;
checkoutActions: CheckoutActions;
}
export function testVoucher(data: VoucherTestData) {
context(`Testing ${data.ctx}`, function() {
const env = Cypress.env('dataEnv')
const loc = data.ctx === 'dog' ? localsDogsApp.de : localsCatsApp.de
beforeEach(function() {
cy.fixture(env + '/users').as('users');
cy.fixture(env + '/products').then(function(products) {
this.product = this.products[`${data.ctx}app`]
});
cy.fixture(env + '/vouchers').then(function(vouchers) {
this.testVoucher = vouchers[`${data.ctx}app`].voucher
})
this.url = Cypress.env(`${data.ctx}AppBaseurl${loc.language}`)
})
describe('...', function() {
it('...', function() {
const voucher: Voucher = {
code: this.testVoucher.CHF30.code,
...
}
const checkoutGuestModel: CheckoutGuestModel = {
...
product: this.product.standardProduct3,
};
Upvotes: 2
Views: 963
Reputation: 4481
You've got two ways to apply generic context in javascript
For example,
['dog', 'cat'].forEach(ctx=> {
context(`Testing ${ctx}`, function() {
const env = Cypress.env('dataEnv')
const loc = ctx === 'dog' ? localsDogsApp.de : localsCatsApp.de
beforeEach(function() {
cy.fixture(env + '/users').as('users');
cy.fixture(env + '/products').then(function(products) {
this.product = this.products[`${ctx}app`]
});
cy.fixture(env + '/vouchers').then(function(vouchers) {
this.testVoucher = vouchers[`${ctx}app`].voucher
})
this.url = Cypress.env(`${ctx}AppBaseurl${loc.language}`)
})
describe('...', function() {
it('...', function() {
const voucher: Voucher = {
code: this.testVoucher.CHF30.code,
...
}
const checkoutGuestModel: CheckoutGuestModel = {
...
product: this.product.standardProduct3,
};
Upvotes: 5