"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 fs = require("fs");
const internal_1 = require("../../../internal");
const Storage_1 = require("../../../Storage");
const AttributeResolutionDirectiveSet_1 = require("../../../Utilities/AttributeResolutionDirectiveSet");
const resolveOptions_1 = require("../../../Utilities/resolveOptions");
const testHelper_1 = require("../../testHelper");
// tslint:disable-next-line: max-func-body-length
describe('Cdm.ResolutionGuidance', () => {
    /**
     * Test path between TestDataPath and TestName.
     */
    const testsSubpath = 'Cdm/ResolutionGuidance';
    const schemaDocsPath = testHelper_1.testHelper.schemaDocumentsPath;
    /**
     * Tests if a warning is logged if resolution guidance is used
     */
    it('TestResolutionGuidanceDeprecation', (done) => __awaiter(void 0, void 0, void 0, function* () {
        var corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestResolutionGuidanceDeprecation');
        // Tests warning log when resolution guidance is used on a data typed attribute.
        var entity = yield corpus.fetchObjectAsync('local:/TypeAttribute.cdm.json/Entity');
        yield entity.createResolvedEntityAsync('res-entity');
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.WarnDeprecatedResolutionGuidance, true);
        // Tests warning log when resolution guidance is used on a entity typed attribute.
        entity = yield corpus.fetchObjectAsync('local:/EntityAttribute.cdm.json/Entity');
        yield entity.createResolvedEntityAsync('res-entity');
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.WarnDeprecatedResolutionGuidance, true);
        // Tests warning log when resolution guidance is used when extending an entity.
        entity = yield corpus.fetchObjectAsync('local:/ExtendsEntity.cdm.json/Entity');
        yield entity.createResolvedEntityAsync('res-entity');
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.WarnDeprecatedResolutionGuidance, true);
        done();
    }));
    /**
     * Resolution Guidance Test - Resolve entity by name
     */
    it('TestByEntityName', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'TestByEntityName';
        yield runTest(testName, 'Sales');
        done();
    }));
    /**
     * Resolution Guidance Test - Resolve entity by primarykey
     */
    it('TestByPrimaryKey', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'TestByPrimaryKey';
        yield runTest(testName, 'Sales');
        done();
    }));
    /**
     * Resolution Guidance Test- Empty ResolutionGuidance
     */
    it('TestEmptyResolutionGuidance', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'TestEmptyResolutionGuidance';
        yield runTest(testName, 'Sales');
        done();
    }));
    /**
     * Resolution Guidance Test - With RenameFormat property
     */
    it('TestRenameFormat', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'TestRenameFormat';
        yield runTest(testName, 'Sales');
        done();
    }));
    /**
     * Resolution Guidance Test - Empty EntityReference property
     */
    it('TestEmptyEntityReference', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'TestEmptyEntityReference';
        yield runTest(testName, 'Sales');
        done();
    }));
    /**
     * Resolution Guidance Test - With AllowReferences = true
     */
    it('TestAllowReferencesTrue', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'TestAllowReferencesTrue';
        yield runTest(testName, 'Sales');
        done();
    }));
    /**
     * Resolution Guidance Test - With AlwaysIncludeForeignKey = true
     */
    it('TestAlwaysIncludeForeignKeyTrue', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'TestAlwaysIncludeForeignKeyTrue';
        yield runTest(testName, 'Sales');
        done();
    }));
    /**
     * Resolution Guidance Test - With ForeignKeyAttribute property
     */
    it('TestForeignKeyAttribute', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'TestForeignKeyAttribute';
        yield runTest(testName, 'Sales');
        done();
    }));
    /**
     * Resolution Guidance Test - With Cardinality = "one"
     */
    it('TestCardinalityOne', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'TestCardinalityOne';
        yield runTest(testName, 'Sales');
        done();
    }));
    /**
     * Resolution Guidance Test - With SelectsSubAttribute - Take Names
     */
    it('TestSelectsSubAttributeTakeNames', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestSelectsSubAttributeTakeNames');
        const entity = yield corpus.fetchObjectAsync('local:/Sales.cdm.json/Sales');
        const resOpt = new resolveOptions_1.resolveOptions(entity.inDocument, new AttributeResolutionDirectiveSet_1.AttributeResolutionDirectiveSet(new Set(['normalized', 'referenceOnly'])));
        const resolvedEntity = yield entity.createResolvedEntityAsync('resolved', resOpt);
        const att1 = resolvedEntity.attributes.allItems[3];
        const att2 = resolvedEntity.attributes.allItems[4];
        // Check that the attributes in selectsSomeTakeNames were added.
        expect(att1.name)
            .toBe('SalesProductProductId');
        expect(att2.name)
            .toBe('SalesProductProductColor');
        done();
    }));
    /**
     * Resolution Guidance Test - With SelectsSubAttribute - Avoid Names
     */
    it('TestSelectsSubAttributeAvoidNames', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestSelectsSubAttributeAvoidNames');
        const entity = yield corpus.fetchObjectAsync('local:/Sales.cdm.json/Sales');
        const resOpt = new resolveOptions_1.resolveOptions(entity.inDocument, new AttributeResolutionDirectiveSet_1.AttributeResolutionDirectiveSet(new Set(['normalized', 'referenceOnly'])));
        const resolvedEntity = yield entity.createResolvedEntityAsync('resolved', resOpt);
        // Check that the attributes in selectsSomeAvoidNames were not added.
        resolvedEntity.attributes.allItems.forEach((att) => {
            expect(att.name).not
                .toBe('SalesProductProductId');
            expect(att.name).not
                .toBe('SalesProductProductColor');
        });
        done();
    }));
    /*
     * Resolution Guidance Test - With structured/normal imposed directives.
     * This test directly read imposed directives from json file instead of setting resOpt in code as runTest().
     */
    it('TestImposedDirectives', (done) => __awaiter(void 0, void 0, void 0, function* () {
        const testName = 'TestImposedDirectives';
        const testExpectedOutputPath = testHelper_1.testHelper.getExpectedOutputFolderPath(testsSubpath, testName);
        const testActualOutputPath = testHelper_1.testHelper.getActualOutputFolderPath(testsSubpath, testName);
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, testName);
        corpus.storage.mount('localActualOutput', new Storage_1.LocalAdapter(testActualOutputPath));
        corpus.storage.mount('cdm', new Storage_1.LocalAdapter(schemaDocsPath));
        const actualOutputFolder = yield corpus.fetchObjectAsync('localActualOutput:/');
        // Test "structured" imposed directive.
        let entity = yield corpus.fetchObjectAsync('local:/Person_Structured.cdm.json/Person');
        let resolvedEntity = yield entity.createResolvedEntityAsync('Person_Resolved', undefined, actualOutputFolder);
        yield resolvedEntity.inDocument.saveAsAsync('Person_Structured_Resolved.cdm.json', true);
        validateOutput('Person_Structured_Resolved.cdm.json', testExpectedOutputPath, testActualOutputPath);
        // Test default imposed directive.
        entity = yield corpus.fetchObjectAsync('local:/Person_Default.cdm.json/Person');
        resolvedEntity = yield entity.createResolvedEntityAsync('Person_Resolved', undefined, actualOutputFolder);
        yield resolvedEntity.inDocument.saveAsAsync('Person_Default_Resolved.cdm.json', true);
        validateOutput('Person_Default_Resolved.cdm.json', testExpectedOutputPath, testActualOutputPath);
        done();
    }));
    function runTest(testName, sourceEntityName) {
        return __awaiter(this, void 0, void 0, function* () {
            const testInputPath = testHelper_1.testHelper.getInputFolderPath(testsSubpath, testName);
            const testExpectedOutputPath = testHelper_1.testHelper.getExpectedOutputFolderPath(testsSubpath, testName);
            const testActualOutputPath = testHelper_1.testHelper.getActualOutputFolderPath(testsSubpath, testName);
            const corpus = new internal_1.CdmCorpusDefinition();
            corpus.setEventCallback(() => { }, internal_1.cdmStatusLevel.warning);
            corpus.storage.mount('localInput', new Storage_1.LocalAdapter(testInputPath));
            corpus.storage.mount('localExpectedOutput', new Storage_1.LocalAdapter(testExpectedOutputPath));
            corpus.storage.mount('localActualOutput', new Storage_1.LocalAdapter(testActualOutputPath));
            corpus.storage.mount('cdm', new Storage_1.LocalAdapter(schemaDocsPath));
            corpus.storage.defaultNamespace = 'localInput';
            const srcEntityDef = yield corpus.fetchObjectAsync(`localInput:/${sourceEntityName}.cdm.json/${sourceEntityName}`);
            expect(srcEntityDef)
                .toBeDefined();
            const resOpt = new resolveOptions_1.resolveOptions(srcEntityDef.inDocument, new AttributeResolutionDirectiveSet_1.AttributeResolutionDirectiveSet());
            const actualOutputFolder = yield corpus.fetchObjectAsync('localActualOutput:/');
            let resolvedEntityDef;
            let outputEntityFileName = '';
            let entityFileName = '';
            entityFileName = 'default';
            resOpt.directives = new AttributeResolutionDirectiveSet_1.AttributeResolutionDirectiveSet();
            outputEntityFileName = `${sourceEntityName}_Resolved_${entityFileName}.cdm.json`;
            resolvedEntityDef = yield srcEntityDef.createResolvedEntityAsync(outputEntityFileName, resOpt, actualOutputFolder);
            if (yield resolvedEntityDef.inDocument.saveAsAsync(outputEntityFileName, true)) {
                validateOutput(outputEntityFileName, testExpectedOutputPath, testActualOutputPath);
            }
            entityFileName = 'referenceOnly';
            resOpt.directives = new AttributeResolutionDirectiveSet_1.AttributeResolutionDirectiveSet(new Set(['referenceOnly']));
            outputEntityFileName = `${sourceEntityName}_Resolved_${entityFileName}.cdm.json`;
            resolvedEntityDef = yield srcEntityDef.createResolvedEntityAsync(outputEntityFileName, resOpt, actualOutputFolder);
            if (yield resolvedEntityDef.inDocument.saveAsAsync(outputEntityFileName, true)) {
                validateOutput(outputEntityFileName, testExpectedOutputPath, testActualOutputPath);
            }
            entityFileName = 'normalized';
            resOpt.directives = new AttributeResolutionDirectiveSet_1.AttributeResolutionDirectiveSet(new Set(['normalized']));
            outputEntityFileName = `${sourceEntityName}_Resolved_${entityFileName}.cdm.json`;
            resolvedEntityDef = yield srcEntityDef.createResolvedEntityAsync(outputEntityFileName, resOpt, actualOutputFolder);
            if (yield resolvedEntityDef.inDocument.saveAsAsync(outputEntityFileName, true)) {
                validateOutput(outputEntityFileName, testExpectedOutputPath, testActualOutputPath);
            }
            entityFileName = 'structured';
            resOpt.directives = new AttributeResolutionDirectiveSet_1.AttributeResolutionDirectiveSet(new Set(['structured']));
            outputEntityFileName = `${sourceEntityName}_Resolved_${entityFileName}.cdm.json`;
            resolvedEntityDef = yield srcEntityDef.createResolvedEntityAsync(outputEntityFileName, resOpt, actualOutputFolder);
            if (yield resolvedEntityDef.inDocument.saveAsAsync(outputEntityFileName, true)) {
                validateOutput(outputEntityFileName, testExpectedOutputPath, testActualOutputPath);
            }
            entityFileName = 'referenceOnly_normalized';
            resOpt.directives = new AttributeResolutionDirectiveSet_1.AttributeResolutionDirectiveSet(new Set(['referenceOnly', 'normalized']));
            outputEntityFileName = `${sourceEntityName}_Resolved_${entityFileName}.cdm.json`;
            resolvedEntityDef = yield srcEntityDef.createResolvedEntityAsync(outputEntityFileName, resOpt, actualOutputFolder);
            if (yield resolvedEntityDef.inDocument.saveAsAsync(outputEntityFileName, true)) {
                validateOutput(outputEntityFileName, testExpectedOutputPath, testActualOutputPath);
            }
            entityFileName = 'referenceOnly_structured';
            resOpt.directives = new AttributeResolutionDirectiveSet_1.AttributeResolutionDirectiveSet(new Set(['referenceOnly', 'structured']));
            outputEntityFileName = `${sourceEntityName}_Resolved_${entityFileName}.cdm.json`;
            resolvedEntityDef = yield srcEntityDef.createResolvedEntityAsync(outputEntityFileName, resOpt, actualOutputFolder);
            if (yield resolvedEntityDef.inDocument.saveAsAsync(outputEntityFileName, true)) {
                validateOutput(outputEntityFileName, testExpectedOutputPath, testActualOutputPath);
            }
            entityFileName = 'normalized_structured';
            resOpt.directives = new AttributeResolutionDirectiveSet_1.AttributeResolutionDirectiveSet(new Set(['normalized', 'structured']));
            outputEntityFileName = `${sourceEntityName}_Resolved_${entityFileName}.cdm.json`;
            resolvedEntityDef = yield srcEntityDef.createResolvedEntityAsync(outputEntityFileName, resOpt, actualOutputFolder);
            if (yield resolvedEntityDef.inDocument.saveAsAsync(outputEntityFileName, true)) {
                validateOutput(outputEntityFileName, testExpectedOutputPath, testActualOutputPath);
            }
            entityFileName = 'referenceOnly_normalized_structured';
            resOpt.directives = new AttributeResolutionDirectiveSet_1.AttributeResolutionDirectiveSet(new Set(['referenceOnly', 'normalized', 'structured']));
            outputEntityFileName = `${sourceEntityName}_Resolved_${entityFileName}.cdm.json`;
            resolvedEntityDef = yield srcEntityDef.createResolvedEntityAsync(outputEntityFileName, resOpt, actualOutputFolder);
            if (yield resolvedEntityDef.inDocument.saveAsAsync(outputEntityFileName, true)) {
                validateOutput(outputEntityFileName, testExpectedOutputPath, testActualOutputPath);
            }
        });
    }
    function validateOutput(outputEntityFileName, testExpectedOutputPath, testAcutalOutputPath) {
        // tslint:disable-next-line: non-literal-fs-path
        const expected = fs.readFileSync(`${testExpectedOutputPath}/${outputEntityFileName}`)
            .toString();
        // tslint:disable-next-line: non-literal-fs-path
        const actual = fs.readFileSync(`${testAcutalOutputPath}/${outputEntityFileName}`)
            .toString();
        testHelper_1.testHelper.assertObjectContentEquality(JSON.parse(expected), JSON.parse(actual));
    }
});
//# sourceMappingURL=ResolutionGuidance.test.js.map