cancel
Showing results for 
Search instead for 
Did you mean: 

Using DELETE/CANCEL on draft data when writing tests

MaxZiegler
Explorer
0 Kudos
254

Hey guys,

I am having some struggle with unittesting my custom action which works on draft tables.

From the beginning: I know we use cds version 5.8 which is very old. But the idea is first to expand our test suite significantly before we change the major release.

Scenario is the following. I have an app to maintain material master data using drafts. My custom action is only callable in draft mode and creates supplier specific EAN/GTIN data from in draft tables available data of GTINs and Info Records. The custom action should create all non existing supplier specific entries.

So for testing I wonder if I can do a delete/cancel on my draft data to play aound with different scenarios close to user interaction.

I tried to follow the example from the SFLIGHT sample to get into touch with using draft data in unit tests, but deletion isn't covered I think.

So I tried something like this:

await DELETE(`products/AdditionalGTIN(ID=${toDeletID},IsActiveEntity=false)`);

Also some normal DELETE Queries on the draft tables using cds facade object or an service instance. Not able to make it work.

Hoping for your help. Maybe I made a quite simple mistake.

Regards Max

My test file looks like this. I know it is hurting the principle of independent test cases a little bit, but in that case of UI close implementation I think it's quite okay.:

const cds = require('@sap/cds/lib');
const { expect, GET, POST, PATCH, axios, data } = cds.test(__dirname + '/../../..');
axios.defaults.auth = { username: 'IT_Test', password: 'hallo' }


const SAVE = (url) => POST (url+'/ProductService.draftActivate')

describe('Logic of ProductService for entity AdditionalGTIN', () => {

let oProductDraftGlobal, oInfrecDraftGlobal, oUoMDraftGlobal, aGTINsDraftGlobal = [];

beforeAll(async () => {
const { data: oProductDraft } = await POST(`/products/Products`, { UIProductCategory: '00' });
oProductDraftGlobal = oProductDraft;
const { data: oInfrecDraft } = await POST(`/products/PurchaseInfoRecords`, { product_ID: oProductDraft.ID, Supplier: 'TEST_LIEF1'});
oInfrecDraftGlobal = oInfrecDraft;
})

describe('Handler for Action customCreate', () => {

it('no existing units of measure at execution', async () => {
// not intressting for the problem....
});

it('no existing gtins at execution', async () => {
// not intressting for the problem....
});

it('first creation for supplier', async () => {
// create some GTINs and run action for the first expecting initial supplier specific GTINs are created
});

it('using supplier again without changes', async () => {
// cruns action again expecting no new supplier specific gtins are created
});

it('using supplier again after deleting one additional GTIN', async () => {
// delete one entry and run action again, expecting the deleted one is recreated
const aAdditionalGTINs = await SELECT.from('ProductService.AdditionalGTIN_drafts');
const toDeletID = aAdditionalGTINs[1].ID;
// THIS LINE DOES NOT WORK --->
await DELETE(`products/AdditionalGTIN(ID=${toDeletID},IsActiveEntity=false)`);
// <--- THIS LINE DOES NOT WORK

// run action and check the results.....
});

})

describe('Handler for before PATCH', () => {
// not intressting for the problem....
})
})

Accepted Solutions (0)

Answers (2)

Answers (2)

MaxZiegler
Explorer
0 Kudos

Hi Sebastian,

thanks for your response. Does not working in my original project but it works in a small sample project.

Back to the original coding I found out that I have a permission problem. Fortunatly we've earlier build a little database logging functionality based on db.prepend (at this point thanks to David Kunz for this great idea 😉 ), where I can check a little bit whats going on with the requests.

So problem seems to be how user permission works in the cds.test. I am not really sure but that's what I can see. We have four roles in our project, which have all mock user defined in .cdsrc.json. ProductService requires one of them.

For my test cases I used axios for the login using one of the mock users. This works without any problem but seems also logical to me that it works only with the POST statements which are from the cds.test.

axios.defaults.auth = { username: 'IT_Test', password: 'hallo' };

For earlier test cases where we have tested logic which is based on user attributes I wrote some classes which extends the cds.User.Privileged which works fine for the case of testing the req.user object. But when I use this now for cds.context.user the request only knows them as priviledged at not as a user with the role 'IT' for example.

But the strangest thing is, that when I completly ignore the cds.context.user object the delete in the test case works with 'anonymous'.

So I am really confused about that. Can anyone make sense of this? Can I improve my extend of the cds.User.priviledged class maybe?


class userIT extends cds.User.Privileged {
    constructor(_) { super(_ || {}) }
    is() { return true }
    get attr() { return { /* some attributes */ }
    is(role) {return role === 'IT}
}

Thanks in advance
Max

vansyckel
Advisor
Advisor
0 Kudos

Hi zieglermax ,

The following should work:

const { Books } = cds.services.CatalogService.entities
await DELETE(Books.drafts).where({ ID: '...' })

Best,
Sebastian