"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const testHelper_1 = require("../../testHelper");
const projectionTestUtils_1 = require("../../Utilities/projectionTestUtils");
/**
 * A test class for testing the AddSupportingAttribute operation in a projection and in a resolution guidance
 */
describe('Cdm/Projection/ProjectionAddSupportingAttributeTest', () => {
    /**
     * All possible combinations of the different resolution directives
     */
    const resOptsCombinations = [
        [],
        ['referenceOnly'],
        ['normalized'],
        ['structured'],
        ['referenceOnly', 'normalized'],
        ['referenceOnly', 'virtual'],
        ['referenceOnly', 'structured'],
        ['normalized', 'structured'],
        ['normalized', 'structured', 'virtual'],
        ['referenceOnly', 'normalized', 'structured'],
        ['referenceOnly', 'normalized', 'structured', 'virtual']
    ];
    /**
     * The path between TestDataPath and TestName.
     */
    const testsSubpath = 'Cdm/Projection/ProjectionAddSupportingAttributeTest';
    /**
     * AddSupportingAttribute with replaceAsForeignKey operation in the same projection
     */
    it('testCombineOpsProj', () => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'testCombineOpsProj';
        const entityName = 'NewPerson';
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, testName);
        for (const resOpt of resOptsCombinations) {
            yield projectionTestUtils_1.projectionTestUtils.loadEntityForResolutionOptionAndSave(corpus, testName, testsSubpath, entityName, resOpt);
        }
        const entity = yield corpus.fetchObjectAsync(`local:/${entityName}.cdm.json/${entityName}`);
        const resolvedEntity = yield projectionTestUtils_1.projectionTestUtils.getResolvedEntity(corpus, entity, []);
        //// Original set of attributes: ['name', 'age', 'address', 'phoneNumber', 'email']
        // Supporting attribute: 'PersonInfo_display', rename 'address' to 'homeAddress'
        expect(resolvedEntity.attributes.length)
            .toEqual(7);
        expect(resolvedEntity.attributes.allItems[0].name)
            .toEqual('name');
        expect(resolvedEntity.attributes.allItems[1].name)
            .toEqual('age');
        expect(resolvedEntity.attributes.allItems[2].name)
            .toEqual('homeAddress');
        expect(resolvedEntity.attributes.allItems[3].name)
            .toEqual('phoneNumber');
        expect(resolvedEntity.attributes.allItems[4].name)
            .toEqual('email');
        expect(resolvedEntity.attributes.allItems[5].name)
            .toEqual('address');
        expect(resolvedEntity.attributes.allItems[6].name)
            .toEqual('PersonInfo_display');
        validateInSupportOfAttribute(resolvedEntity.attributes.allItems[6], 'email');
    }));
    /**
     * Test AddAttributeGroup operation with a 'referenceOnly' and 'virtual' condition
     */
    it('testConditionalProj', () => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'testConditionalProj';
        const entityName = 'NewPerson';
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, testName);
        // for (const resOpt of resOptsCombinations) {
        //   await projectionTestUtils.loadEntityForResolutionOptionAndSave(corpus, testName, testsSubpath, entityName, resOpt);
        // }
        const entity = yield corpus.fetchObjectAsync(`local:/${entityName}.cdm.json/${entityName}`);
        const resolvedEntity = yield projectionTestUtils_1.projectionTestUtils.getResolvedEntity(corpus, entity, ['referenceOnly']);
        //// Original set of attributes: ['name', 'age', 'address', 'phoneNumber', 'email']
        //// Condition not met, don't include supporting attribute
        expect(resolvedEntity.attributes.length)
            .toEqual(5);
        expect(resolvedEntity.attributes.allItems[0].name)
            .toEqual('name');
        expect(resolvedEntity.attributes.allItems[1].name)
            .toEqual('age');
        expect(resolvedEntity.attributes.allItems[2].name)
            .toEqual('address');
        expect(resolvedEntity.attributes.allItems[3].name)
            .toEqual('phoneNumber');
        expect(resolvedEntity.attributes.allItems[4].name)
            .toEqual('email');
        const resolvedEntity2 = yield projectionTestUtils_1.projectionTestUtils.getResolvedEntity(corpus, entity, ['referenceOnly', 'virtual']);
        // Original set of attributes: ['name', 'age', 'address', 'phoneNumber', 'email']
        // Condition met, include the supporting attribute
        expect(resolvedEntity2.attributes.length)
            .toEqual(6);
        expect(resolvedEntity2.attributes.allItems[0].name)
            .toEqual('name');
        expect(resolvedEntity2.attributes.allItems[1].name)
            .toEqual('age');
        expect(resolvedEntity2.attributes.allItems[2].name)
            .toEqual('address');
        expect(resolvedEntity2.attributes.allItems[3].name)
            .toEqual('phoneNumber');
        expect(resolvedEntity2.attributes.allItems[4].name)
            .toEqual('email');
        expect(resolvedEntity2.attributes.allItems[5].name)
            .toEqual('PersonInfo_display');
        validateInSupportOfAttribute(resolvedEntity2.attributes.allItems[5], 'email');
    }));
    /**
     * Test resolving an entity attribute using resolution guidance
     */
    it('testEntityAttribute', () => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'testEntityAttribute';
        const entityName = 'NewPerson';
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, testName);
        for (const resOpt of resOptsCombinations) {
            yield projectionTestUtils_1.projectionTestUtils.loadEntityForResolutionOptionAndSave(corpus, testName, testsSubpath, entityName, resOpt);
        }
        const entity = yield corpus.fetchObjectAsync(`local:/${entityName}.cdm.json/${entityName}`);
        let resolvedEntity = yield projectionTestUtils_1.projectionTestUtils.getResolvedEntity(corpus, entity, ['referenceOnly']);
        // Original set of attributes: ['name', 'age', 'address', 'phoneNumber', 'email']
        expect(resolvedEntity.attributes.length)
            .toEqual(2);
        expect(resolvedEntity.attributes.allItems[0].name)
            .toEqual('id');
        expect(resolvedEntity.attributes.allItems[1].name)
            .toEqual('PersonInfo_display');
        validateInSupportOfAttribute(resolvedEntity.attributes.allItems[1], 'id', false);
        // Resolve without directives
        resolvedEntity = yield projectionTestUtils_1.projectionTestUtils.getResolvedEntity(corpus, entity, []);
        // Original set of attributes: ['name', 'age', 'address', 'phoneNumber', 'email']
        expect(resolvedEntity.attributes.length)
            .toEqual(6);
        expect(resolvedEntity.attributes.allItems[0].name)
            .toEqual('name');
        expect(resolvedEntity.attributes.allItems[1].name)
            .toEqual('age');
        expect(resolvedEntity.attributes.allItems[2].name)
            .toEqual('address');
        expect(resolvedEntity.attributes.allItems[3].name)
            .toEqual('phoneNumber');
        expect(resolvedEntity.attributes.allItems[4].name)
            .toEqual('email');
        expect(resolvedEntity.attributes.allItems[5].name)
            .toEqual('PersonInfo_display');
        validateInSupportOfAttribute(resolvedEntity.attributes.allItems[5], 'email', false);
    }));
    /**
     * Test resolving an entity attribute with add supporint attribute operation
     */
    it('testEntityAttributeProj', () => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'testEntityAttributeProj';
        const entityName = 'NewPerson';
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, testName);
        for (const resOpt of resOptsCombinations) {
            yield projectionTestUtils_1.projectionTestUtils.loadEntityForResolutionOptionAndSave(corpus, testName, testsSubpath, entityName, resOpt);
        }
        const entity = yield corpus.fetchObjectAsync(`local:/${entityName}.cdm.json/${entityName}`);
        const resolvedEntity = yield projectionTestUtils_1.projectionTestUtils.getResolvedEntity(corpus, entity, ['referenceOnly']);
        // Original set of attributes: ['name', 'age', 'address', 'phoneNumber', 'email']
        expect(resolvedEntity.attributes.length)
            .toEqual(6);
        expect(resolvedEntity.attributes.allItems[0].name)
            .toEqual('name');
        expect(resolvedEntity.attributes.allItems[1].name)
            .toEqual('age');
        expect(resolvedEntity.attributes.allItems[2].name)
            .toEqual('address');
        expect(resolvedEntity.attributes.allItems[3].name)
            .toEqual('phoneNumber');
        expect(resolvedEntity.attributes.allItems[4].name)
            .toEqual('email');
        expect(resolvedEntity.attributes.allItems[5].name)
            .toEqual('PersonInfo_display');
        validateInSupportOfAttribute(resolvedEntity.attributes.allItems[5], 'email');
    }));
    /**
     * addSupportingAttribute on an entity definition using resolution guidance
     */
    it('testExtendsEntity', () => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'testExtendsEntity';
        const entityName = 'NewPerson';
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, testName);
        for (const resOpt of resOptsCombinations) {
            yield projectionTestUtils_1.projectionTestUtils.loadEntityForResolutionOptionAndSave(corpus, testName, testsSubpath, entityName, resOpt);
        }
        const entity = yield corpus.fetchObjectAsync(`local:/${entityName}.cdm.json/${entityName}`);
        const resolvedEntity = yield projectionTestUtils_1.projectionTestUtils.getResolvedEntity(corpus, entity, []);
        // Original set of attributes: ['name', 'age', 'address', 'phoneNumber', 'email']
        // Supporting attribute: 'PersonInfo_display' (using extendsEntityResolutionGuidance)
        expect(resolvedEntity.attributes.length)
            .toEqual(6);
        expect(resolvedEntity.attributes.allItems[0].name)
            .toEqual('name');
        expect(resolvedEntity.attributes.allItems[1].name)
            .toEqual('age');
        expect(resolvedEntity.attributes.allItems[2].name)
            .toEqual('address');
        expect(resolvedEntity.attributes.allItems[3].name)
            .toEqual('phoneNumber');
        expect(resolvedEntity.attributes.allItems[4].name)
            .toEqual('email');
        expect(resolvedEntity.attributes.allItems[5].name)
            .toEqual('PersonInfo_display');
        validateInSupportOfAttribute(resolvedEntity.attributes.allItems[5], 'email', false);
    }));
    /**
     * addSupportingAttribute on an entity definition
     */
    it('testExtendsEntityProj', () => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'testExtendsEntityProj';
        const entityName = 'NewPerson';
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, testName);
        for (const resOpt of resOptsCombinations) {
            yield projectionTestUtils_1.projectionTestUtils.loadEntityForResolutionOptionAndSave(corpus, testName, testsSubpath, entityName, resOpt);
        }
        const entity = yield corpus.fetchObjectAsync(`local:/${entityName}.cdm.json/${entityName}`);
        const resolvedEntity = yield projectionTestUtils_1.projectionTestUtils.getResolvedEntity(corpus, entity, []);
        // Original set of attributes: ['name', 'age', 'address', 'phoneNumber', 'email']
        // Supporting attribute: 'PersonInfo_display' (using extendsEntityResolutionGuidance)
        expect(resolvedEntity.attributes.length)
            .toEqual(6);
        expect(resolvedEntity.attributes.allItems[0].name)
            .toEqual('name');
        expect(resolvedEntity.attributes.allItems[1].name)
            .toEqual('age');
        expect(resolvedEntity.attributes.allItems[2].name)
            .toEqual('address');
        expect(resolvedEntity.attributes.allItems[3].name)
            .toEqual('phoneNumber');
        expect(resolvedEntity.attributes.allItems[4].name)
            .toEqual('email');
        expect(resolvedEntity.attributes.allItems[5].name)
            .toEqual('PersonInfo_display');
        validateInSupportOfAttribute(resolvedEntity.attributes.allItems[5], 'email');
    }));
    /**
     * Nested replaceAsForeignKey with addSupporingAttribute
     */
    it('testNestedProj', () => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'testNestedProj';
        const entityName = 'NewPerson';
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, testName);
        for (const resOpt of resOptsCombinations) {
            yield projectionTestUtils_1.projectionTestUtils.loadEntityForResolutionOptionAndSave(corpus, testName, testsSubpath, entityName, resOpt);
        }
        const entity = yield corpus.fetchObjectAsync(`local:/${entityName}.cdm.json/${entityName}`);
        const resolvedEntity = yield projectionTestUtils_1.projectionTestUtils.getResolvedEntity(corpus, entity, ['referenceOnly']);
        // Original set of attributes: ['name', 'age', 'address', 'phoneNumber', 'email']
        expect(resolvedEntity.attributes.length)
            .toEqual(2);
        expect(resolvedEntity.attributes.allItems[0].name)
            .toEqual('personId');
        expect(resolvedEntity.attributes.allItems[1].name)
            .toEqual('PersonInfo_display');
        validateInSupportOfAttribute(resolvedEntity.attributes.allItems[1], 'personId');
    }));
    /**
     * Test resolving a type attribute with a nested add supporting attribute operation
     */
    it('TestNestedTypeAttributeProj', () => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'testNestedTAProj';
        const entityName = 'NewPerson';
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, testName);
        for (const resOpt of resOptsCombinations) {
            yield projectionTestUtils_1.projectionTestUtils.loadEntityForResolutionOptionAndSave(corpus, testName, testsSubpath, entityName, resOpt);
        }
        const entity = yield corpus.fetchObjectAsync(`local:/${entityName}.cdm.json/${entityName}`);
        const resolvedEntity = yield projectionTestUtils_1.projectionTestUtils.getResolvedEntity(corpus, entity, ['referenceOnly']);
        // Original set of attributes: ["PersonInfo"]
        expect(resolvedEntity.attributes.length)
            .toEqual(2);
        expect(resolvedEntity.attributes.allItems[0].name)
            .toEqual('name');
        const supportingAttribute = resolvedEntity.attributes.allItems[1];
        expect(supportingAttribute.name)
            .toEqual('name_display');
        validateInSupportOfAttribute(supportingAttribute, 'name', false);
    }));
    /**
     * Test resolving a type attribute using resolution guidance
     */
    it('testTypeAttribute', () => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'testTypeAttribute';
        const entityName = 'NewPerson';
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, testName);
        // for (const resOpt of resOptsCombinations) {
        //   await projectionTestUtils.loadEntityForResolutionOptionAndSave(corpus, testName, testsSubpath, entityName, resOpt);
        // }
        const entity = yield corpus.fetchObjectAsync(`local:/${entityName}.cdm.json/${entityName}`);
        const resolvedEntity = yield projectionTestUtils_1.projectionTestUtils.getResolvedEntity(corpus, entity, ['structured']);
        // Original set of attributes: ["PersonInfo"]
        expect(resolvedEntity.attributes.length)
            .toEqual(2);
        expect(resolvedEntity.attributes.allItems[0].name)
            .toEqual('PersonInfo');
        const supportingAttribute = resolvedEntity.attributes.allItems[1];
        expect(supportingAttribute.name)
            .toEqual('PersonInfo_display');
        validateInSupportOfAttribute(supportingAttribute, 'PersonInfo', false);
    }));
    /**
     * Test resolving a type attribute with a nested add supporting attribute operation
     */
    it('testTypeAttributeProj', () => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'testTypeAttributeProj';
        const entityName = 'NewPerson';
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, testName);
        for (const resOpt of resOptsCombinations) {
            yield projectionTestUtils_1.projectionTestUtils.loadEntityForResolutionOptionAndSave(corpus, testName, testsSubpath, entityName, resOpt);
        }
        const entity = yield corpus.fetchObjectAsync(`local:/${entityName}.cdm.json/${entityName}`);
        const resolvedEntity = yield projectionTestUtils_1.projectionTestUtils.getResolvedEntity(corpus, entity, ['structured']);
        // Original set of attributes: ["PersonInfo"]
        expect(resolvedEntity.attributes.length)
            .toEqual(2);
        expect(resolvedEntity.attributes.allItems[0].name)
            .toEqual('PersonInfo');
        const supportingAttribute = resolvedEntity.attributes.allItems[1];
        expect(supportingAttribute.name)
            .toEqual('PersonInfo_display');
        validateInSupportOfAttribute(supportingAttribute, 'PersonInfo', false);
    }));
    /**
     * Validates that the supporting attribute has the 'is.addedInSupportOf' and 'is.virtual.attribute' traits
     * @param supportingAttribute
     * @param fromAttribute
     */
    function validateInSupportOfAttribute(supportingAttribute, fromAttribute, checkVirtualTrait = true) {
        const inSupportOfTrait = supportingAttribute.appliedTraits.item('is.addedInSupportOf');
        expect(inSupportOfTrait)
            .not
            .toBeUndefined();
        expect(inSupportOfTrait.arguments.length)
            .toEqual(1);
        expect(inSupportOfTrait.arguments.allItems[0].value)
            .toEqual(fromAttribute);
        if (checkVirtualTrait) {
            expect(supportingAttribute.appliedTraits.item('is.virtual.attribute'))
                .not
                .toBeUndefined();
        }
    }
});
//# sourceMappingURL=ProjectionAddSupportingAttribute.test.js.map