1// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import {assert} from 'chai';
6
7import {click, getBrowserAndPages, step, timeout, waitFor, waitForFunction} from '../../shared/helper.js';
8import {describe, it} from '../../shared/mocha-extensions.js';
9import {addBreakpointForLine, getScopeNames, getValuesForScope, openSourceCodeEditorForFile, PAUSE_INDICATOR_SELECTOR, RESUME_BUTTON, waitForSourceCodeLines} from '../helpers/sources-helpers.js';
10
11describe('Source Tab', async () => {
12  it('shows and updates the module, local, and stack scope while pausing', async () => {
13    const {frontend, target} = getBrowserAndPages();
14    const breakpointLine = 12;
15    const numberOfLines = 16;
16    let moduleScopeValues: string[];
17    let localScopeValues: string[];
18
19    await step('navigate to a page and open the Sources tab', async () => {
20      await openSourceCodeEditorForFile('scopes.wasm', 'wasm/scopes.html');
21    });
22
23    await step(`add a breakpoint to line No.${breakpointLine}`, async () => {
24      await addBreakpointForLine(frontend, breakpointLine);
25    });
26
27    await step('reload the page', async () => {
28      await target.reload();
29      // FIXME(crbug/1112692): Refactor test to remove the timeout.
30      await timeout(100);
31    });
32
33    await step('wait for all the source code to appear', async () => {
34      await waitForSourceCodeLines(numberOfLines);
35    });
36
37    await step('check that the module, local, and stack scope appear', async () => {
38      const scopeNames = await waitForFunction(async () => {
39        const names = await getScopeNames();
40        return names.length === 3 ? names : undefined;
41      });
42      assert.deepEqual(scopeNames, ['Module', 'Local', 'Stack']);
43    });
44
45    await step('check that the module scope content is as expected', async () => {
46      moduleScopeValues = await getValuesForScope('Module');
47      // Remove occurrences of arrays.
48      const formattedValues = moduleScopeValues.map((line: string) => {
49        return line.replace(/\[[^\]]*\]/, '').trim();
50      });
51      assert.deepEqual(
52          formattedValues, ['globals: {imports.global: 24}', 'instance: Instance\xA0{}', 'memory0: Uint8Array(65536)']);
53    });
54
55    await step('check that the local scope content is as expected', async () => {
56      localScopeValues = await getValuesForScope('Local');
57      assert.deepEqual(localScopeValues, ['f32_var: 5.5', 'f64_var: 2.23e-11', 'i32: 42', 'i64_var: 9221120237041090']);
58    });
59
60    await step('expand the stack scope', async () => {
61      await click('[aria-label="Stack"]');
62    });
63
64    await step('check that the stack scope content is as expected', async () => {
65      const stackScopeValues = await getValuesForScope('Stack');
66      assert.deepEqual(stackScopeValues, []);
67    });
68
69    await step('step one time', async () => {
70      await frontend.keyboard.press('F9');
71      await waitFor(PAUSE_INDICATOR_SELECTOR);
72    });
73
74    await step('check that the module scope content is as before', async () => {
75      const currentModuleScopeValues = await getValuesForScope('Module', 0, moduleScopeValues.length);
76      assert.deepEqual(currentModuleScopeValues, moduleScopeValues);
77    });
78
79    await step('check that the local scope content is as before', async () => {
80      const updatedLocalScopeValues = await getValuesForScope('Local', 0, localScopeValues.length);
81      assert.deepEqual(updatedLocalScopeValues, localScopeValues);
82    });
83
84    await step('check that the stack scope content is updated to reflect the change', async () => {
85      const stackScopeValues = await getValuesForScope('Stack');
86      assert.deepEqual(stackScopeValues, ['0: 24']);
87    });
88
89    await step('resume execution', async () => {
90      await click(RESUME_BUTTON);
91    });
92  });
93});
94