"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 testHelper_1 = require("../testHelper");
describe('Utilities.EventList', () => {
    const testsSubpath = 'Utilities';
    /** Dummy value used for correlation ID testing. */
    const DummyCorrelationId = '12345';
    /** Declare a blackhole callback. We're focusing on event recorder, don't care about output going to the standard log stream. */
    const eventCallback = () => { };
    /**
     * Test update and fetch list lookup default value without attributeValue and displayOrder.
     */
    it('TestWithoutNesting', () => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestEventList');
        corpus.setEventCallback(eventCallback, internal_1.cdmStatusLevel.warning, DummyCorrelationId);
        // Test fetching an object from invalid namespace results in at least one error message in the recorder
        yield corpus.fetchObjectAsync('foo:/bar');
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrStorageAdapterNotFound, true);
        // Test fetching a good object, this should leave event recorder empty
        yield corpus.fetchObjectAsync('local:/default.manifest.cdm.json');
        TestNoLogsState(corpus);
        // Test saving a manifest to invalid namespace results in at least one error message in the recorder
        let manifest = corpus.MakeObject(internal_1.cdmObjectType.manifestDef, 'dummy');
        yield manifest.saveAsAsync('foo:/bar', true);
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrValdnMissingDoc, true);
        // Test resolving a manifest not added to a folder, this should yield at least one error message in the recorder
        yield manifest.createResolvedManifestAsync('new dummy', null);
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrResolveManifestFailed, true);
        // Test resolving an entity without WRT doc, this should yield at least one error message in the recorder
        let entity2 = corpus.MakeObject(internal_1.cdmObjectType.entityDef, 'MyEntity2');
        yield entity2.createResolvedEntityAsync('MyEntity2-Resolved');
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrDocWrtDocNotfound, true);
        // Test invoking FileStatusCheckAsync on the manifest, this should yield at least one error message in the recorder
        yield manifest.fileStatusCheckAsync();
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrStorageNullNamespace, true);
        // Repeat the same test but with status level 'None', no events should be recorded
        corpus.ctx.reportAtLevel = internal_1.cdmStatusLevel.none;
        yield entity2.createResolvedEntityAsync('MyEntity2-Resolved');
        TestNoLogsState(corpus);
        // Test checking file status on a data partition
        // We're at log level 'Progress', so we get the EnterScope/LeaveScope messages too
        corpus.ctx.reportAtLevel = internal_1.cdmStatusLevel.progress;
        const part = corpus.MakeObject(internal_1.cdmObjectType.dataPartitionDef, 'part');
        yield part.fileStatusCheckAsync();
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrPathNullObjectPath, true);
        // Test checking file status on a data partition pattern
        const refDoc = corpus.MakeObject(internal_1.cdmObjectType.documentDef, 'RefEntDoc');
        const partPattern = corpus.MakeObject(internal_1.cdmObjectType.dataPartitionPatternDef, 'partPattern');
        partPattern.inDocument = refDoc;
        yield partPattern.fileStatusCheckAsync();
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrStorageNullCorpusPath, true);
        // Test calculating relationships - no errors/warnings
        yield corpus.calculateEntityGraphAsync(manifest);
        TestBasicLogsState(corpus);
        // Test populating relationships in manifest - no errors/warnings
        yield manifest.populateManifestRelationshipsAsync();
        TestBasicLogsState(corpus);
        // Test filtering code logic 
        corpus.ctx.suppressedLogCodes.add(internal_1.cdmLogCode.ErrPathNullObjectPath);
        const part2 = corpus.MakeObject(internal_1.cdmObjectType.dataPartitionDef, 'part2');
        yield part2.fileStatusCheckAsync();
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrPathNullObjectPath, false);
    }));
    /**
     * Tests a use case where recording nesting happens, such as CreateResolvedManifestAsync making calls to CreateResolvedEntityAsync.
     */
    it('TestWithNesting', () => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestEventList');
        corpus.setEventCallback(eventCallback, internal_1.cdmStatusLevel.warning, DummyCorrelationId);
        let manifest = corpus.MakeObject(internal_1.cdmObjectType.manifestDef, 'dummy');
        // Test resolving a manifest (added to a folder) with an entity in it, this should collect messages from
        // CreateResolvedManifestAsync and CreateResolvedEntityAsync functions
        corpus.storage.fetchRootFolder('local').documents.push(manifest);
        let entity1 = corpus.MakeObject(internal_1.cdmObjectType.entityDef, 'MyEntity1');
        let someAttrib1 = corpus.MakeObject(internal_1.cdmObjectType.typeAttributeDef, 'someAttrib1', false);
        someAttrib1.dataType = corpus.MakeRef(internal_1.cdmObjectType.dataTypeRef, 'entityId', true);
        entity1.attributes.push(someAttrib1);
        let entity1Doc = corpus.MakeObject(internal_1.cdmObjectType.documentDef, 'MyEntity1.cdm.json');
        entity1Doc.definitions.push(entity1);
        corpus.storage.fetchRootFolder('local').documents.push(entity1Doc);
        manifest.entities.push(entity1);
        yield manifest.createResolvedManifestAsync('new dummy 2', null);
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrResolveReferenceFailure, true);
        // Keep for debugging
        // corpus.ctx.events.allItems.forEach(logEntry => {
        //     logEntry.forEach((key: string, value: string) => console.log(`${key}=${value}`))
        // });
    }));
    /**
     * Tests events generated in StorageManager APIs
     */
    it('TestStorageManagerEvents', () => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestEventList');
        corpus.setEventCallback(eventCallback, internal_1.cdmStatusLevel.info, DummyCorrelationId);
        corpus.storage.mount('dummy', null);
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrStorageNullAdapter, true);
        corpus.storage.unMount('nothing');
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.WarnStorageRemoveAdapterFailed, true);
        // No errors/warnings expected here
        corpus.storage.fetchRootFolder(null);
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrStorageNullNamespace, true);
        corpus.storage.adapterPathToCorpusPath('Test');
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrStorageInvalidAdapterPath, true);
        corpus.storage.corpusPathToAdapterPath('unknown:/Test');
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrStorageAdapterNotFound, true);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrStorageNamespaceNotRegistered, true);
        corpus.storage.createAbsoluteCorpusPath(null);
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrPathNullObjectPath, true);
        corpus.storage.createRelativeCorpusPath(null);
        TestBasicLogsState(corpus);
        testHelper_1.testHelper.expectCdmLogCodeEquality(corpus, internal_1.cdmLogCode.ErrPathNullObjectPath, true);
    }));
    /**
     * Test logging of API scope entry/exit.
     */
    it('TestScoping', () => __awaiter(void 0, void 0, void 0, function* () {
        const corpus = testHelper_1.testHelper.getLocalCorpus(testsSubpath, 'TestEventList');
        // For scoping test we need to use log level info
        corpus.setEventCallback(eventCallback, internal_1.cdmStatusLevel.info, DummyCorrelationId);
        yield corpus.fetchObjectAsync('local:/default.manifest.cdm.json');
        expect(corpus.ctx.events.isRecording).toBe(false);
        expect(corpus.ctx.events.length).toBeGreaterThan(2);
        TestBasicLogsState(corpus);
        // Verify method on entry/exit event
        expect(corpus.ctx.events.allItems[0].get('method')).toBe('fetchObjectAsync');
        expect(corpus.ctx.events.allItems[corpus.ctx.events.length - 1].get('method')).toBe('fetchObjectAsync');
        // Keep for debugging
        // corpus.ctx.events.allItems.forEach(logEntry => {
        //     logEntry.forEach((key: string, value: string) => console.log(`${key}=${value}`))
        // });
    }));
    /// <summary>
    /// Helper function to test that recording is stopped and no logs are recorded.
    /// </summary>
    /// <param name="corpus"></param>
    function TestNoLogsState(corpus) {
        TestBasicLogsState(corpus, true);
    }
    /// <summary>
    /// Helper function to check for event list state and presence of scope enter/leave logs.
    /// </summary>
    /// <param name="corpus"></param>
    /// <param name="expectNoLogs">If true, tests that recording is stopped and there are no logs in EventList. If false,
    /// tests that there are multiple entries and log enter/exit events were logged.</param>
    function TestBasicLogsState(corpus, expectNoLogs = false) {
        expect(corpus.ctx.events).not.toBeUndefined();
        expect(corpus.ctx.events.isRecording).toBe(false);
        if (expectNoLogs) {
            expect(corpus.ctx.events.length).toBe(0);
        }
        else {
            expect(corpus.ctx.events.length).toBeGreaterThan(0);
            expect(corpus.ctx.events.allItems[0].has('timestamp')).toBe(true);
            expect(corpus.ctx.events.allItems[0].get('cid')).toBe(DummyCorrelationId);
            if (corpus.ctx.reportAtLevel == internal_1.cdmStatusLevel.progress) {
                expect(corpus.ctx.events.allItems[0].get('message')).toBe('Entering scope');
                expect(corpus.ctx.events.allItems[corpus.ctx.events.length - 1].get('message').startsWith('Leaving scope')).toBe(true);
            }
        }
    }
});
//# sourceMappingURL=EventList.test.js.map