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());
    });
};
import chaiAsPromised from 'chai-as-promised';
import sinon from 'sinon';
import chai, { expect } from 'chai';
import { DataStoreLevel } from '../../../../src/store/data-store-level.js';
import { DidKeyResolver } from '../../../../src/did/did-key-resolver.js';
import { EventLogLevel } from '../../../../src/event-log/event-log-level.js';
import { GeneralJwsSigner } from '../../../../src/jose/jws/general/signer.js';
import { Message } from '../../../../src/core/message.js';
import { MessageStoreLevel } from '../../../../src/store/message-store-level.js';
import { TestDataGenerator } from '../../../utils/test-data-generator.js';
import { TestStubGenerator } from '../../../utils/test-stub-generator.js';
import { DidResolver, Dwn, DwnErrorCode, Encoder, Jws } from '../../../../src/index.js';
chai.use(chaiAsPromised);
describe('ProtocolsQueryHandler.handle()', () => {
    if (process.env.TESTSOFF === 'true') {
        return;
    }
    let didResolver;
    let messageStore;
    let dataStore;
    let eventLog;
    let dwn;
    describe('functional tests', () => {
        before(() => __awaiter(void 0, void 0, void 0, function* () {
            didResolver = new DidResolver([new DidKeyResolver()]);
            // important to follow this pattern to initialize and clean the message and data store in tests
            // so that different suites can reuse the same block store and index location for testing
            messageStore = new MessageStoreLevel({
                blockstoreLocation: 'tests/data/TEST-MESSAGESTORE',
                indexLocation: 'tests/data/TEST-INDEX'
            });
            dataStore = new DataStoreLevel({
                blockstoreLocation: 'tests/data/TEST-DATASTORE'
            });
            eventLog = new EventLogLevel({
                location: 'tests/data/TEST-EVENTLOG'
            });
            dwn = yield Dwn.create({ didResolver, messageStore, dataStore, eventLog });
        }));
        beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
            sinon.restore(); // wipe all previous stubs/spies/mocks/fakes
            // clean up before each test rather than after so that a test does not depend on other tests to do the clean up
            yield messageStore.clear();
            yield dataStore.clear();
            yield eventLog.clear();
        }));
        after(() => __awaiter(void 0, void 0, void 0, function* () {
            yield dwn.close();
        }));
        it('should return protocols matching the query', () => __awaiter(void 0, void 0, void 0, function* () {
            var _a, _b;
            const alice = yield TestDataGenerator.generatePersona();
            // setting up a stub method resolver
            TestStubGenerator.stubDidResolver(didResolver, [alice]);
            // insert three messages into DB, two with matching protocol
            const protocol1 = yield TestDataGenerator.generateProtocolsConfigure({ author: alice });
            const protocol2 = yield TestDataGenerator.generateProtocolsConfigure({ author: alice });
            const protocol3 = yield TestDataGenerator.generateProtocolsConfigure({ author: alice });
            yield dwn.processMessage(alice.did, protocol1.message, protocol1.dataStream);
            yield dwn.processMessage(alice.did, protocol2.message, protocol2.dataStream);
            yield dwn.processMessage(alice.did, protocol3.message, protocol3.dataStream);
            // testing singular conditional query
            const queryMessageData = yield TestDataGenerator.generateProtocolsQuery({
                author: alice,
                filter: { protocol: protocol1.message.descriptor.definition.protocol }
            });
            const reply = yield dwn.processMessage(alice.did, queryMessageData.message);
            expect(reply.status.code).to.equal(200);
            expect((_a = reply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1); // only 1 entry should match the query on protocol
            // testing fetch-all query without filter
            const queryMessageData2 = yield TestDataGenerator.generateProtocolsQuery({
                author: alice
            });
            const reply2 = yield dwn.processMessage(alice.did, queryMessageData2.message);
            expect(reply2.status.code).to.equal(200);
            expect((_b = reply2.entries) === null || _b === void 0 ? void 0 : _b.length).to.equal(3); // expecting all 3 entries written above match the query
        }));
        it('should return 400 if protocol is not normalized', () => __awaiter(void 0, void 0, void 0, function* () {
            const alice = yield DidKeyResolver.generate();
            // query for non-normalized protocol
            const protocolsQuery = yield TestDataGenerator.generateProtocolsQuery({
                author: alice,
                filter: { protocol: 'example.com/' },
            });
            // overwrite protocol because #create auto-normalizes protocol
            protocolsQuery.message.descriptor.filter.protocol = 'example.com/';
            // Re-create auth because we altered the descriptor after signing
            protocolsQuery.message.authorization = yield Message.signAsAuthorization(protocolsQuery.message.descriptor, Jws.createSignatureInput(alice));
            // Send records write message
            const reply = yield dwn.processMessage(alice.did, protocolsQuery.message);
            expect(reply.status.code).to.equal(400);
            expect(reply.status.detail).to.contain(DwnErrorCode.UrlProtocolNotNormalized);
        }));
        it('should fail with 400 if `authorization` is referencing a different message (`descriptorCid`)', () => __awaiter(void 0, void 0, void 0, function* () {
            const { author, message, protocolsQuery } = yield TestDataGenerator.generateProtocolsQuery();
            const tenant = author.did;
            // replace `authorization` with incorrect `descriptorCid`, even though signature is still valid
            const incorrectDescriptorCid = yield TestDataGenerator.randomCborSha256Cid();
            const authorizationPayload = Object.assign({}, protocolsQuery.authorizationPayload);
            authorizationPayload.descriptorCid = incorrectDescriptorCid;
            const authorizationPayloadBytes = Encoder.objectToBytes(authorizationPayload);
            const signatureInput = Jws.createSignatureInput(author);
            const signer = yield GeneralJwsSigner.create(authorizationPayloadBytes, [signatureInput]);
            message.authorization = signer.getJws();
            const reply = yield dwn.processMessage(tenant, message);
            expect(reply.status.code).to.equal(400);
            expect(reply.status.detail).to.contain(`${incorrectDescriptorCid} does not match expected CID`);
        }));
        it('should return 401 if auth fails', () => __awaiter(void 0, void 0, void 0, function* () {
            const alice = yield DidKeyResolver.generate();
            alice.keyId = 'wrongValue'; // to fail authentication
            const { message } = yield TestDataGenerator.generateProtocolsQuery({ author: alice });
            const reply = yield dwn.processMessage(alice.did, message);
            expect(reply.status.code).to.equal(401);
            expect(reply.status.detail).to.contain('not a valid DID');
        }));
    });
});
//# sourceMappingURL=protocols-query.spec.js.map