"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 internal_1 = require("../../../../internal");
const Persistence_1 = require("../../../../Persistence");
const EntityPersistence_1 = require("../../../../Persistence/CdmFolder/EntityPersistence");
const TypeAttributePersistence_1 = require("../../../../Persistence/CdmFolder/TypeAttributePersistence");
const Storage_1 = require("../../../../Storage");
const testHelper_1 = require("../../../testHelper");
// tslint:disable-next-line: max-func-body-length
describe('Persistence.CdmFolder.TypeAttribute', () => {
    /**
     * The path between TestDataPath and TestName.
     */
    const testsSubpath = 'Persistence/CdmFolder/TypeAttribute';
    it('TestNonNullDefaultValueAttribute', () => {
        const theList = [{
                languageTag: 'en',
                displayText: 'Preferred Customer',
                attributeValue: '1',
                displayOrder: '0'
            },
            {
                languageTag: 'en',
                displayText: 'Standard',
                attributeValue: '2',
                displayOrder: '1'
            }];
        const input = {
            defaultValue: theList
        };
        const cdmTypeAttributeDefinition = TypeAttributePersistence_1.TypeAttributePersistence.fromData(new internal_1.resolveContext(new internal_1.CdmCorpusDefinition(), undefined), input, undefined);
        const result = Persistence_1.PersistenceLayer.toData(cdmTypeAttributeDefinition, undefined, undefined, Persistence_1.PersistenceLayer.cdmFolder);
        expect(result)
            .toBeTruthy();
        expect(result.defaultValue)
            .toEqual(input.defaultValue);
    });
    /**
     * Testing that 'isPrimaryKey' property value is correct when reading from an unresolved and resolved entity schema.
     */
    it('TestReadingIsPrimaryKey', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestReadingIsPrimaryKey');
        const resOpt = new internal_1.resolveOptions();
        resOpt.importsLoadStrategy = internal_1.importsLoadStrategy.load;
        // Read from an unresolved entity schema.
        const entity = yield corpus.fetchObjectAsync('local:/TeamMembership.cdm.json/TeamMembership', null, resOpt);
        const attributeGroupRef = entity.attributes.allItems[0];
        const attributeGroup = attributeGroupRef.explicitReference;
        const typeAttribute = attributeGroup.members.allItems[0];
        expect(typeAttribute.isPrimaryKey)
            .toBeTruthy();
        // Check that the trait 'is.identifiedBy' is created with the correct argument.
        const isIdentifiedBy1 = typeAttribute.appliedTraits.allItems[1];
        expect(isIdentifiedBy1.namedReference).toEqual('is.identifiedBy');
        expect(isIdentifiedBy1.arguments.allItems[0].value.namedReference).toEqual('TeamMembership/(resolvedAttributes)/teamMembershipId');
        // Read from a resolved entity schema.
        const resolvedEntity = yield corpus.fetchObjectAsync('local:/TeamMembership_Resolved.cdm.json/TeamMembership', null, resOpt);
        const resolvedTypeAttribute = resolvedEntity.attributes.allItems[0];
        expect(resolvedTypeAttribute.isPrimaryKey)
            .toBeTruthy();
        // Check that the trait 'is.identifiedBy' is created with the correct argument.
        const isIdentifiedBy2 = resolvedTypeAttribute.appliedTraits.allItems[6];
        expect(isIdentifiedBy2.namedReference)
            .toEqual('is.identifiedBy');
        const argumentValue = isIdentifiedBy2.arguments.allItems[0].value;
        expect(argumentValue.namedReference)
            .toEqual('TeamMembership/(resolvedAttributes)/teamMembershipId');
        done();
    }));
    /**
     * Testing that 'isPrimaryKey' property is set to true when 'purpose' = 'identifiedBy'.
     */
    it('TestReadingIsPrimaryKeyConstructedFromPurpose', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestReadingIsPrimaryKeyConstructedFromPurpose');
        const entity = yield corpus.fetchObjectAsync('local:/TeamMembership.cdm.json/TeamMembership');
        const attributeGroupRef = entity.attributes.allItems[0];
        const attributeGroup = attributeGroupRef.explicitReference;
        const typeAttribute = attributeGroup.members.allItems[0];
        expect(typeAttribute.purpose.namedReference)
            .toEqual('identifiedBy');
        expect(typeAttribute.isPrimaryKey)
            .toBeTruthy();
        done();
    }));
    /**
     * Testing fromData and toData correctly handles all properties
     */
    it('TestPropertyPersistence', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestPropertyPersistence');
        corpus.storage.mount('cdm', new Storage_1.LocalAdapter(testHelper_1.testHelper.schemaDocumentsPath));
        let functionWasCalled = false;
        let functionParameter1 = internal_1.cdmStatusLevel.info;
        let functionParameter2;
        const callback = jest.fn((statusLevel, message1) => {
            functionWasCalled = true;
            if (statusLevel === internal_1.cdmStatusLevel.error) {
                functionParameter1 = statusLevel;
                functionParameter2 = message1;
            }
        });
        corpus.setEventCallback(callback);
        const entity = yield corpus.fetchObjectAsync('local:/PropertyEntity.cdm.json/PropertyEntity');
        // test loading properties
        const attribute = entity.attributes.allItems[0];
        expect(attribute.isReadOnly)
            .toBeTruthy();
        expect(attribute.isNullable)
            .toBeTruthy();
        expect(attribute.sourceName)
            .toBe('propertyAttribute');
        expect(attribute.description)
            .toBe('Attribute that has all properties set.');
        expect(attribute.displayName)
            .toBe('Property Attribute');
        expect(attribute.sourceOrdering)
            .toBe(1);
        expect(attribute.valueConstrainedToList)
            .toBeTruthy();
        expect(attribute.maximumLength)
            .toBe(10);
        expect(attribute.maximumValue)
            .toBe('20');
        expect(attribute.minimumValue)
            .toBe('1');
        expect(attribute.dataFormat)
            .toBe(internal_1.cdmDataFormat.string);
        expect(attribute.defaultValue[0].displayText)
            .toBe('Default');
        // test loading negative value properties
        const negativeAttribute = entity.attributes.allItems[1];
        expect(negativeAttribute.isReadOnly)
            .toBeFalsy();
        expect(negativeAttribute.isNullable)
            .toBeFalsy();
        expect(negativeAttribute.sourceName)
            .toBeUndefined();
        expect(negativeAttribute.description)
            .toBeUndefined();
        expect(negativeAttribute.displayName)
            .toBeUndefined();
        expect(negativeAttribute.sourceOrdering)
            .toBe(0);
        expect(negativeAttribute.valueConstrainedToList)
            .toBeFalsy();
        expect(negativeAttribute.maximumLength)
            .toBe(0);
        expect(negativeAttribute.maximumValue)
            .toBe('0');
        expect(negativeAttribute.minimumValue)
            .toBe('0');
        expect(negativeAttribute.dataFormat)
            .toBe(internal_1.cdmDataFormat.unknown);
        expect(negativeAttribute.defaultValue[0].displayText)
            .toBe('');
        // test loading values with wrongs types in file
        const wrongTypesAttribute = entity.attributes.allItems[2];
        expect(wrongTypesAttribute.isReadOnly)
            .toBeTruthy();
        expect(wrongTypesAttribute.isNullable)
            .toBeTruthy();
        expect(wrongTypesAttribute.sourceOrdering)
            .toBe(1);
        expect(wrongTypesAttribute.valueConstrainedToList)
            .toBeFalsy();
        expect(wrongTypesAttribute.maximumLength)
            .toBe(0);
        expect(wrongTypesAttribute.maximumValue)
            .toBe('20');
        expect(wrongTypesAttribute.minimumValue)
            .toBe('0');
        // test loading values with wrong types that cannot be properly converted
        const invalidValuesAttribute = entity.attributes.allItems[3];
        expect(invalidValuesAttribute.isReadOnly)
            .toBeFalsy();
        expect(invalidValuesAttribute.maximumLength)
            .toBeUndefined();
        // test loading values with empty default value list that should log error
        const emptyDefaultValueAttribute = entity.attributes.allItems[4];
        expect(functionWasCalled)
            .toBeTruthy();
        expect(functionParameter1)
            .toEqual(internal_1.cdmStatusLevel.error);
        expect(functionParameter2)
            .toContain('A \'defaultValue\' property is empty or one of its entries is missing \'languageTag\' and \'displayText\' values.');
        expect(emptyDefaultValueAttribute.defaultValue)
            .toBeUndefined();
        // set the default value to an empty list for testing that it should be removed from the generated json.
        emptyDefaultValueAttribute.defaultValue = [];
        const entityData = EntityPersistence_1.EntityPersistence.toData(entity, undefined, undefined);
        // test toData for properties
        const attributeData = entityData.hasAttributes[0];
        expect(attributeData.isReadOnly)
            .toBeTruthy();
        expect(attributeData.isNullable)
            .toBeTruthy();
        expect(attributeData.sourceName)
            .toBe('propertyAttribute');
        expect(attributeData.description)
            .toBe('Attribute that has all properties set.');
        expect(attributeData.displayName)
            .toBe('Property Attribute');
        expect(attributeData.sourceOrdering)
            .toBe(1);
        expect(attributeData.valueConstrainedToList)
            .toBeTruthy();
        expect(attributeData.maximumLength)
            .toBe(10);
        expect(attributeData.maximumValue)
            .toBe('20');
        expect(attributeData.minimumValue)
            .toBe('1');
        expect(attributeData.dataFormat)
            .toBe('String');
        expect(attributeData.defaultValue[0].displayText)
            .toBe('Default');
        // test toData for negative value properties
        const negativeAttributeData = entityData.hasAttributes[1];
        expect(negativeAttributeData.isReadOnly)
            .toBeFalsy();
        expect(negativeAttributeData.isNullable)
            .toBeFalsy();
        expect(negativeAttributeData.sourceName)
            .toBeUndefined();
        expect(negativeAttributeData.description)
            .toBeUndefined();
        expect(negativeAttributeData.displayName)
            .toBeUndefined();
        expect(negativeAttributeData.sourceOrdering)
            .toBeUndefined();
        expect(negativeAttributeData.valueConstrainedToList)
            .toBeUndefined();
        expect(negativeAttributeData.maximumLength)
            .toBe(0);
        expect(negativeAttributeData.maximumValue)
            .toBe('0');
        expect(negativeAttributeData.minimumValue)
            .toBe('0');
        expect(negativeAttributeData.dataFormat)
            .toBeUndefined();
        expect(negativeAttributeData.defaultValue[0].displayText)
            .toBe('');
        // test toData for values with wrong types in file
        const wrongTypesAttributeData = entityData.hasAttributes[2];
        expect(wrongTypesAttributeData.isReadOnly)
            .toBeTruthy();
        expect(wrongTypesAttributeData.isNullable)
            .toBeTruthy();
        expect(wrongTypesAttributeData.sourceOrdering)
            .toBe(1);
        expect(wrongTypesAttributeData.valueConstrainedToList)
            .toBeUndefined();
        expect(wrongTypesAttributeData.maximumLength)
            .toBe(0);
        expect(wrongTypesAttributeData.maximumValue)
            .toBe('20');
        expect(wrongTypesAttributeData.minimumValue)
            .toBe('0');
        // test toData with wrong types that cannot be properly converted
        const invalidValuesAttributeData = entityData.hasAttributes[3];
        expect(invalidValuesAttributeData.isReadOnly)
            .toBeUndefined();
        expect(invalidValuesAttributeData.maximumLength)
            .toBeUndefined();
        // test toData with empty default value list that should be written as null
        const emptyDefaultValueAttributeData = entityData.hasAttributes[4];
        expect(emptyDefaultValueAttributeData.defaultValue)
            .toBeUndefined();
        done();
    }));
    /**
     * Testing that 'is.localized.describedAs' trait with a table of three entries (en, rs and cn)
     *  is fully preserved when running CdmFolder TypeAttributePersistence ToData.
     */
    it('TestCdmFolderToDataTypeAttribute', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = new internal_1.CdmCorpusDefinition();
        corpus.setEventCallback(() => { }, internal_1.cdmStatusLevel.warning);
        corpus.storage.mount('local', new Storage_1.LocalAdapter('C:\\Root\\Path'));
        corpus.storage.defaultNamespace = 'local';
        const cdmTypeAttributeDefinition = corpus.MakeObject(internal_1.cdmObjectType.typeAttributeDef, 'TestSavingTraitAttribute', false);
        const englishConstantsList = ['en', 'Some description in English language'];
        const serbianConstantsList = ['sr', 'Opis na srpskom jeziku'];
        const chineseConstantsList = ['cn', '一些中文描述'];
        const listOfConstLists = [englishConstantsList, serbianConstantsList, chineseConstantsList];
        const constEntDef = corpus.MakeObject(internal_1.cdmObjectType.constantEntityDef, 'localizedDescriptions', false);
        constEntDef.constantValues = listOfConstLists;
        constEntDef.entityShape = corpus.MakeRef(internal_1.cdmObjectType.entityRef, 'localizedTable', true);
        const traitReference2 = corpus.MakeObject(internal_1.cdmObjectType.traitRef, 'is.localized.describedAs', false);
        traitReference2.arguments.push('localizedDisplayText', corpus.MakeRef(internal_1.cdmObjectType.entityRef, constEntDef, true));
        cdmTypeAttributeDefinition.appliedTraits.push(traitReference2);
        const result = Persistence_1.PersistenceLayer.toData(cdmTypeAttributeDefinition, undefined, undefined, Persistence_1.PersistenceLayer.cdmFolder);
        expect(result)
            .toBeTruthy();
        const argument = result.appliedTraits[0].arguments[0];
        const constantValues = (argument.value.entityReference).constantValues;
        expect(constantValues[0][0])
            .toBe('en');
        expect(constantValues[0][1])
            .toBe('Some description in English language');
        expect(constantValues[1][0])
            .toBe('sr');
        expect(constantValues[1][1])
            .toBe('Opis na srpskom jeziku');
        expect(constantValues[2][0])
            .toBe('cn');
        expect(constantValues[2][1])
            .toBe('一些中文描述');
        done();
    }));
    /**
     * Testing fromData and toData correctly handles all properties
     */
    it('TestDataFormatToTraitMappings', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestDataFormatToTraitMappings');
        const entity = yield corpus.fetchObjectAsync('local:/Entity.cdm.json/Entity');
        // Check that the traits we expect for each DataFormat are found in the type attribute's applied traits.
        // DataFormat = Int16
        const attributeA = entity.attributes.allItems[0];
        const aTraitNamedReferences = fetchTraitNamedReferences(attributeA.appliedTraits);
        expect(aTraitNamedReferences.has('is.dataFormat.integer'))
            .toBeTruthy();
        expect(aTraitNamedReferences.has('is.dataFormat.small'))
            .toBeTruthy();
        // DataFormat = Int32
        const attributeB = entity.attributes.allItems[1];
        const bTraitNamedReferences = fetchTraitNamedReferences(attributeB.appliedTraits);
        expect(bTraitNamedReferences.has('is.dataFormat.integer'))
            .toBeTruthy();
        // DataFormat = Int64
        const attributeC = entity.attributes.allItems[2];
        const cTraitNamedReferences = fetchTraitNamedReferences(attributeC.appliedTraits);
        expect(cTraitNamedReferences.has('is.dataFormat.integer'))
            .toBeTruthy();
        expect(cTraitNamedReferences.has('is.dataFormat.big'))
            .toBeTruthy();
        // DataFormat = Float
        const attributeD = entity.attributes.allItems[3];
        const dTraitNamedReferences = fetchTraitNamedReferences(attributeD.appliedTraits);
        expect(dTraitNamedReferences.has('is.dataFormat.floatingPoint'))
            .toBeTruthy();
        // DataFormat = Double
        const attributeE = entity.attributes.allItems[4];
        const eTraitNamedReferences = fetchTraitNamedReferences(attributeE.appliedTraits);
        expect(eTraitNamedReferences.has('is.dataFormat.floatingPoint'))
            .toBeTruthy();
        expect(eTraitNamedReferences.has('is.dataFormat.big'))
            .toBeTruthy();
        // DataFormat = Guid
        const attributeF = entity.attributes.allItems[5];
        const fTraitNamedReferences = fetchTraitNamedReferences(attributeF.appliedTraits);
        expect(fTraitNamedReferences.has('is.dataFormat.guid'))
            .toBeTruthy();
        expect(fTraitNamedReferences.has('is.dataFormat.character'))
            .toBeTruthy();
        expect(fTraitNamedReferences.has('is.dataFormat.array'))
            .toBeTruthy();
        // DataFormat = String
        const attributeG = entity.attributes.allItems[6];
        const gTraitNamedReferences = fetchTraitNamedReferences(attributeG.appliedTraits);
        expect(gTraitNamedReferences.has('is.dataFormat.character'))
            .toBeTruthy();
        expect(gTraitNamedReferences.has('is.dataFormat.array'))
            .toBeTruthy();
        // DataFormat = Char
        const attributeH = entity.attributes.allItems[7];
        const hTraitNamedReferences = fetchTraitNamedReferences(attributeH.appliedTraits);
        expect(hTraitNamedReferences.has('is.dataFormat.character'))
            .toBeTruthy();
        expect(hTraitNamedReferences.has('is.dataFormat.big'))
            .toBeTruthy();
        // DataFormat = Byte
        const attributeI = entity.attributes.allItems[8];
        const iTraitNamedReferences = fetchTraitNamedReferences(attributeI.appliedTraits);
        expect(iTraitNamedReferences.has('is.dataFormat.byte'))
            .toBeTruthy();
        // DataFormat = Binary
        const attributeJ = entity.attributes.allItems[9];
        const jTraitNamedReferences = fetchTraitNamedReferences(attributeJ.appliedTraits);
        expect(jTraitNamedReferences.has('is.dataFormat.byte'))
            .toBeTruthy();
        expect(jTraitNamedReferences.has('is.dataFormat.array'))
            .toBeTruthy();
        // DataFormat = Time
        const attributeK = entity.attributes.allItems[10];
        const kTraitNamedReferences = fetchTraitNamedReferences(attributeK.appliedTraits);
        expect(kTraitNamedReferences.has('is.dataFormat.time'))
            .toBeTruthy();
        // DataFormat = Date
        const attributeL = entity.attributes.allItems[11];
        const lTraitNamedReferences = fetchTraitNamedReferences(attributeL.appliedTraits);
        expect(lTraitNamedReferences.has('is.dataFormat.date'))
            .toBeTruthy();
        // DataFormat = DateTime
        const attributeM = entity.attributes.allItems[12];
        const mTraitNamedReferences = fetchTraitNamedReferences(attributeM.appliedTraits);
        expect(mTraitNamedReferences.has('is.dataFormat.time'))
            .toBeTruthy();
        expect(mTraitNamedReferences.has('is.dataFormat.date'))
            .toBeTruthy();
        // DataFormat = DateTimeOffset
        const attributeN = entity.attributes.allItems[13];
        const nTraitNamedReferences = fetchTraitNamedReferences(attributeN.appliedTraits);
        expect(nTraitNamedReferences.has('is.dataFormat.time'))
            .toBeTruthy();
        expect(nTraitNamedReferences.has('is.dataFormat.date'))
            .toBeTruthy();
        expect(nTraitNamedReferences.has('is.dataFormat.timeOffset'))
            .toBeTruthy();
        // DataFormat = Boolean
        const attributeO = entity.attributes.allItems[14];
        const oTraitNamedReferences = fetchTraitNamedReferences(attributeO.appliedTraits);
        expect(oTraitNamedReferences.has('is.dataFormat.boolean'))
            .toBeTruthy();
        // DataFormat = Decimal
        const attributeP = entity.attributes.allItems[15];
        const pTraitNamedReferences = fetchTraitNamedReferences(attributeP.appliedTraits);
        expect(pTraitNamedReferences.has('is.dataFormat.numeric.shaped'))
            .toBeTruthy();
        // DataFormat = Json
        const attributeQ = entity.attributes.allItems[16];
        const qTraitNamedReferences = fetchTraitNamedReferences(attributeQ.appliedTraits);
        expect(qTraitNamedReferences.has('is.dataFormat.array'))
            .toBeTruthy();
        expect(qTraitNamedReferences.has('means.content.text.JSON'))
            .toBeTruthy();
        done();
    }));
    /**
     * Testing that cardinality settings are loaded and saved correctly
     */
    it('TestCardinalityPersistence', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestCardinalityPersistence');
        // test fromData
        const entity = yield corpus.fetchObjectAsync('local:/someEntity.cdm.json/someEntity');
        const attribute = entity.attributes.allItems[0];
        expect(attribute.cardinality)
            .not.toBeUndefined();
        expect(attribute.cardinality.minimum)
            .toEqual('0');
        expect(attribute.cardinality.maximum)
            .toEqual('1');
        // test toData
        const attributeData = TypeAttributePersistence_1.TypeAttributePersistence.toData(attribute, new internal_1.resolveOptions(entity.inDocument), new internal_1.copyOptions());
        expect(attributeData.cardinality)
            .not.toBeUndefined();
        expect(attributeData.cardinality.minimum)
            .toBe('0');
        expect(attributeData.cardinality.maximum)
            .toBe('1');
        done();
    }));
    function fetchTraitNamedReferences(traits) {
        const namedReferences = new Set();
        traits.allItems.forEach((trait) => {
            namedReferences.add(trait.namedReference);
        });
        return namedReferences;
    }
});
//# sourceMappingURL=TypeAttribute.test.js.map