1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { assert, expect } from 'chai';
17import { before } from 'mocha';
18import { 
19  decodeSourcemap,
20  mergeSourceMap,
21  ExistingDecodedSourceMap,
22  Source,
23  SourceMapLink
24} from '../../../src/utils/SourceMapMergingUtil';
25import { RawSourceMap } from 'typescript';
26
27describe('test for SourceMapMergingUtil', function () {
28  it('test the sourcemap merging', function () {
29    /**
30     * // source ts code:
31     * function foo(){
32     *   console.log("hello world");
33     *   return 1;
34     * }
35     */
36    const previousMap = {
37      "version": 3,
38      "file": "index.js",
39      "sources": [
40        "index.ts"
41      ],
42      "names": [],
43      "mappings": "AAAA,SAAS,GAAG;IACV,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC3B,OAAO,CAAC,CAAC;AACX,CAAC",
44      "sourceRoot": "",
45    }
46    /**
47     * // transformed ts code:
48     * function foo() {
49     *     console.log("hello world");
50     *     return 1;
51     * }
52     */
53    const currentMap = {
54      "version": 3,
55      "file": "index.js",
56      "sources": [
57        "index.js"
58      ],
59      "names": [],
60      "mappings": "AAAA;IAEI,OAAO,CAAC,CAAC;CACZ",
61      "sourceRoot": "",
62    }
63    /** 
64     * // obfuscated code:
65     * function a(){
66     *     return 1;
67     * }
68     */
69    const actual = mergeSourceMap(previousMap as RawSourceMap, currentMap as RawSourceMap);
70    const expect = '{"version":3,"file":"index.js","sources":["index.ts"],"names":[],"mappings":"AAAA;IAEE,OAAO,CAAC,CAAC;CACV","sourceRoot":""}'
71    assert.isTrue(JSON.stringify(actual) === expect);
72  });
73
74  describe('test for SourceMapLink', function () {
75    let source: Source;
76    let mappings: ExistingDecodedSourceMap;
77
78    before(() => {
79      source = new Source('example.js', 'console.log("Hello, World!");');
80      mappings = {
81        version: 3,
82        file: 'out.js',
83        sources: ['example.js'],
84        names: ['console', 'log'],
85        mappings: [
86          [[0, 0, 0, 0, 1]]
87        ],
88        sourcesContent: [],
89      };
90    });
91
92    it('should trace mappings correctly', () => {
93      const sourceMapLink = new SourceMapLink(mappings, [source]);
94      const traced = sourceMapLink.traceMappings();
95
96      expect(traced.mappings).to.have.lengthOf(1);
97      expect(traced.names).to.include('log');
98      expect(traced.sources).to.include('example.js');
99    });
100  });
101
102  describe('test for decodeSourcemap', function () {
103    it('should return null for null map', () => {
104      const result = decodeSourcemap(null);
105      expect(result).to.be.null;
106    });
107
108    it('should return empty mappings for empty mappings string', () => {
109      const map: RawSourceMap = {
110        version: 3,
111        file: 'out.js',
112        sources: ['example.js'],
113        names: [],
114        mappings: '', // Empty mappings
115        sourcesContent: ['Hello, World!'],
116      };
117
118      const result = decodeSourcemap(map);
119      expect(result).to.deep.equal({
120        names: [],
121        mappings: [],
122        sources: [],
123        version: 3
124      });
125    });
126  });
127});
128