go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/common/services/resultdb/resultdb.test.ts (about)

     1  // Copyright 2021 The LUCI Authors.
     2  //
     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  import {
    16    createTVCmpFn,
    17    createTVPropGetter,
    18    getInvIdFromBuildId,
    19    getInvIdFromBuildNum,
    20    TestVariant,
    21    TestVariantStatus,
    22  } from './resultdb';
    23  
    24  describe('resultdb', () => {
    25    test('should compute invocation ID from build number correctly', async () => {
    26      const invId = await getInvIdFromBuildNum(
    27        { project: 'chromium', bucket: 'ci', builder: 'ios-device' },
    28        179945,
    29      );
    30      expect(invId).toStrictEqual(
    31        'build-135d246ed1a40cc3e77d8b1daacc7198fe344b1ac7b95c08cb12f1cc383867d7-179945',
    32      );
    33    });
    34  
    35    test('should compute invocation ID from build ID correctly', async () => {
    36      const invId = await getInvIdFromBuildId('123456');
    37      expect(invId).toStrictEqual('build-123456');
    38    });
    39  });
    40  
    41  describe('createTVPropGetter', () => {
    42    test('can create a status getter', async () => {
    43      const getter = createTVPropGetter('status');
    44      const prop = getter({
    45        status: TestVariantStatus.EXONERATED,
    46      } as Partial<TestVariant> as TestVariant);
    47      expect(prop).toStrictEqual(TestVariantStatus.EXONERATED);
    48    });
    49  
    50    test('can create a name getter', async () => {
    51      const getter = createTVPropGetter('Name');
    52  
    53      const prop1 = getter({
    54        testId: 'test-id',
    55        testMetadata: { name: 'test-name' },
    56      } as Partial<TestVariant> as TestVariant);
    57      expect(prop1).toStrictEqual('test-name');
    58  
    59      // Fallback to test id.
    60      const prop2 = getter({
    61        testId: 'test-id',
    62      } as Partial<TestVariant> as TestVariant);
    63      expect(prop2).toStrictEqual('test-id');
    64    });
    65  
    66    test('can create a variant value getter', async () => {
    67      const getter = createTVPropGetter('v.variant_key');
    68  
    69      const prop1 = getter({
    70        variant: { def: { variant_key: 'variant_value' } },
    71      } as Partial<TestVariant> as TestVariant);
    72      expect(prop1).toStrictEqual('variant_value');
    73  
    74      // Fallback to empty string.
    75      const prop2 = getter({} as Partial<TestVariant> as TestVariant);
    76      expect(prop2).toStrictEqual('');
    77    });
    78  });
    79  
    80  describe('createTVCmpFn', () => {
    81    const variant1 = {
    82      status: TestVariantStatus.UNEXPECTED,
    83      testMetadata: {
    84        name: 'a',
    85      },
    86      variant: { def: { key1: 'val1' } },
    87    } as Partial<TestVariant> as TestVariant;
    88    const variant2 = {
    89      status: TestVariantStatus.EXONERATED,
    90      testMetadata: {
    91        name: 'b',
    92      },
    93      variant: { def: { key1: 'val2' } },
    94    } as Partial<TestVariant> as TestVariant;
    95    const variant3 = {
    96      status: TestVariantStatus.EXONERATED,
    97      testMetadata: {
    98        name: 'b',
    99      },
   100      variant: { def: { key1: 'val1' } },
   101    } as Partial<TestVariant> as TestVariant;
   102  
   103    test('can create a sort fn', async () => {
   104      const cmpFn = createTVCmpFn(['name']);
   105  
   106      expect(cmpFn(variant1, variant2)).toStrictEqual(-1);
   107      expect(cmpFn(variant2, variant1)).toStrictEqual(1);
   108      expect(cmpFn(variant1, variant1)).toStrictEqual(0);
   109    });
   110  
   111    test('can sort in descending order', async () => {
   112      const cmpFn = createTVCmpFn(['-name']);
   113  
   114      expect(cmpFn(variant1, variant2)).toStrictEqual(1);
   115      expect(cmpFn(variant2, variant1)).toStrictEqual(-1);
   116      expect(cmpFn(variant1, variant1)).toStrictEqual(0);
   117    });
   118  
   119    test('can sort by status correctly', async () => {
   120      const cmpFn = createTVCmpFn(['status']);
   121  
   122      // Status should be treated as numbers rather than as strings when sorting.
   123      expect(cmpFn(variant1, variant2)).toStrictEqual(-1);
   124      expect(cmpFn(variant2, variant1)).toStrictEqual(1);
   125      expect(cmpFn(variant1, variant1)).toStrictEqual(0);
   126    });
   127  
   128    test('can sort by multiple keys', async () => {
   129      const cmpFn = createTVCmpFn(['status', '-v.key1']);
   130  
   131      expect(cmpFn(variant1, variant2)).toStrictEqual(-1);
   132      expect(cmpFn(variant2, variant1)).toStrictEqual(1);
   133      expect(cmpFn(variant2, variant3)).toStrictEqual(-1);
   134    });
   135  });