// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { assert } from 'chai';
import * as Trace from '../../models/trace/trace.js';
import * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';
import { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js';
import { microsecondsTraceWindow } from '../../testing/TraceHelpers.js';
import * as Timeline from './timeline.js';
const { getAnnotationEntries, getAnnotationWindow, } = Timeline.AnnotationHelpers;
describe('AnnotationHelpers', () => {
    describe('getAnnotationEntries', () => {
        const FAKE_ENTRY_1 = {};
        const FAKE_ENTRY_2 = {};
        it('returns the entry for an ENTRY_LABEL', async () => {
            const annotation = {
                entry: FAKE_ENTRY_1,
                label: 'Hello world',
                type: 'ENTRY_LABEL',
            };
            assert.deepEqual(getAnnotationEntries(annotation), [FAKE_ENTRY_1]);
        });
        it('returns an empty array for a range', async () => {
            const annotation = {
                bounds: Trace.Helpers.Timing.traceWindowFromMicroSeconds(Trace.Types.Timing.Micro(0), Trace.Types.Timing.Micro(10)),
                type: 'TIME_RANGE',
                label: 'Hello world',
            };
            assert.lengthOf(getAnnotationEntries(annotation), 0);
        });
        it('returns both entries for a link', async () => {
            const annotation = {
                type: 'ENTRIES_LINK',
                state: "connected" /* Trace.Types.File.EntriesLinkState.CONNECTED */,
                entryFrom: FAKE_ENTRY_1,
                entryTo: FAKE_ENTRY_2,
            };
            assert.deepEqual(getAnnotationEntries(annotation), [FAKE_ENTRY_1, FAKE_ENTRY_2]);
        });
    });
    describe('getAnnotationWindow', () => {
        const FAKE_ENTRY_1 = {
            ts: 1,
            dur: 10,
        };
        const FAKE_ENTRY_2 = {
            ts: 20,
            dur: 5,
        };
        it('returns the entry window for an ENTRY_LABEL', async () => {
            const annotation = {
                entry: FAKE_ENTRY_1,
                label: 'Hello world',
                type: 'ENTRY_LABEL',
            };
            assert.deepEqual(getAnnotationWindow(annotation), {
                min: 1,
                max: 11,
                range: 10,
            });
        });
        it('returns the bounds for a TIME_RANGE', async () => {
            const annotation = {
                bounds: Trace.Helpers.Timing.traceWindowFromMicroSeconds(Trace.Types.Timing.Micro(0), Trace.Types.Timing.Micro(10)),
                type: 'TIME_RANGE',
                label: 'Hello world',
            };
            assert.deepEqual(getAnnotationWindow(annotation), {
                min: 0,
                max: 10,
                range: 10,
            });
        });
        it('returns the bounds based on the start and end entry for an ENTRIES_LINK', async () => {
            const annotation = {
                type: 'ENTRIES_LINK',
                state: "connected" /* Trace.Types.File.EntriesLinkState.CONNECTED */,
                entryFrom: FAKE_ENTRY_1,
                entryTo: FAKE_ENTRY_2,
            };
            assert.deepEqual(getAnnotationWindow(annotation), {
                min: 1,
                max: 25,
                range: 24,
            });
        });
    });
    describeWithEnvironment('Aria Announcement', () => {
        const { ariaAnnouncementForModifiedEvent } = Timeline.AnnotationHelpers;
        const FAKE_ENTRY_1 = {
            name: 'fake-one',
            ts: 1,
            dur: 10,
        };
        const FAKE_ENTRY_2 = {
            name: 'fake-two',
            ts: 10,
            dur: 10,
        };
        it('returns text for an annotation being removed', () => {
            const overlay = { type: 'ENTRY_LABEL', entry: FAKE_ENTRY_1, label: 'Hello world' };
            const event = new Timeline.ModificationsManager.AnnotationModifiedEvent(overlay, 'Remove');
            const text = ariaAnnouncementForModifiedEvent(event);
            assert.strictEqual(text, 'The entry label annotation has been removed');
        });
        it('returns text for entering the edit state on a label', () => {
            const overlay = { type: 'ENTRY_LABEL', entry: FAKE_ENTRY_1, label: 'Hello world' };
            const event = new Timeline.ModificationsManager.AnnotationModifiedEvent(overlay, 'EnterLabelEditState');
            const text = ariaAnnouncementForModifiedEvent(event);
            assert.strictEqual(text, 'Editing the annotation label text');
        });
        it('returns text for an annotation being added', async () => {
            const overlay = { type: 'ENTRY_LABEL', entry: FAKE_ENTRY_1, label: 'Hello world' };
            const event = new Timeline.ModificationsManager.AnnotationModifiedEvent(overlay, 'Add');
            const text = ariaAnnouncementForModifiedEvent(event);
            assert.strictEqual(text, 'The entry label annotation has been added');
        });
        it('does not return text if the aria notifcations are muted', async () => {
            const overlay = { type: 'ENTRY_LABEL', entry: FAKE_ENTRY_1, label: 'Hello world' };
            const event = new Timeline.ModificationsManager.AnnotationModifiedEvent(overlay, 'Add', true);
            const text = ariaAnnouncementForModifiedEvent(event);
            assert.isNull(text);
        });
        it('does not return an announcement for new empty labels', async () => {
            const overlay = { type: 'ENTRY_LABEL', entry: FAKE_ENTRY_1, label: '' };
            const event = new Timeline.ModificationsManager.AnnotationModifiedEvent(overlay, 'Add');
            const text = ariaAnnouncementForModifiedEvent(event);
            assert.isNull(text);
        });
        it('returns text for an annotation having its label updated', async () => {
            const overlay = { type: 'ENTRY_LABEL', entry: FAKE_ENTRY_1, label: 'Hello world' };
            const event = new Timeline.ModificationsManager.AnnotationModifiedEvent(overlay, 'UpdateLabel');
            const text = ariaAnnouncementForModifiedEvent(event);
            assert.strictEqual(text, 'Label updated to Hello world');
        });
        it('returns text for a time range having its bounds updated', async () => {
            TraceBounds.TraceBounds.BoundsManager.instance({ forceNew: true })
                .resetWithNewBounds(microsecondsTraceWindow(0, 10_000));
            const timeRange = {
                type: 'TIME_RANGE',
                bounds: microsecondsTraceWindow(0, 5_000),
                label: 'hello',
                showDuration: true,
            };
            const event = new Timeline.ModificationsManager.AnnotationModifiedEvent(timeRange, 'UpdateTimeRange');
            const text = ariaAnnouncementForModifiedEvent(event);
            assert.strictEqual(text, 'Time range updated, starting at 0 ms and ending at 5 ms');
        });
        it('returns text when an entries link has its entries connected', async () => {
            const link = {
                type: 'ENTRIES_LINK',
                state: "connected" /* Trace.Types.File.EntriesLinkState.CONNECTED */,
                entryFrom: FAKE_ENTRY_1,
                entryTo: FAKE_ENTRY_2,
            };
            const event = new Timeline.ModificationsManager.AnnotationModifiedEvent(link, 'UpdateLinkToEntry');
            const text = ariaAnnouncementForModifiedEvent(event);
            assert.strictEqual(text, 'The connected entries annotation now links from fake-one to fake-two');
        });
    });
});
//# sourceMappingURL=AnnotationHelpers.test.js.map