How to define custom search attribute in a TypeScript test environment?

In my TS project I am using TestWorkflowEnvironment to run some tests. I am trying out custom search attributes, and I defined these attributes in Temporal Cloud via temporal CLI, and I added some searchAttribute options to my executeChild workflow command. My local automated tests fail, however, with the error “BadSearchAttributes: Namespace default has no mapping defined for search attribute…”

The error makes sense, I don’t specify a namespace in my test so it uses default, and in my real environments the namespace is something else. So I am just looking for a way to set in code (e.g. in my before() function) the default namespace search attributes and add my custom ones.

I found this post: BadSearchAttributes: Namespace default has no mapping defined for search attribute. But they are using Python and I couldn’t find an equivalent with the TS SDK. Any ideas?

Here is the code we use in SDK internal tests for this.

import * as iface from '@temporalio/proto';

const client = new Client({ connection }).workflow;
try {
  await connection.operatorService.addSearchAttributes({
    namespace: 'default',
    searchAttributes: {
      CustomIntField: iface.temporal.api.enums.v1.IndexedValueType.INDEXED_VALUE_TYPE_INT,
      CustomBoolField: iface.temporal.api.enums.v1.IndexedValueType.INDEXED_VALUE_TYPE_BOOL,
      CustomKeywordField: iface.temporal.api.enums.v1.IndexedValueType.INDEXED_VALUE_TYPE_KEYWORD,
      CustomTextField: iface.temporal.api.enums.v1.IndexedValueType.INDEXED_VALUE_TYPE_TEXT,
      CustomDatetimeField: iface.temporal.api.enums.v1.IndexedValueType.INDEXED_VALUE_TYPE_DATETIME,
      CustomDoubleField: iface.temporal.api.enums.v1.IndexedValueType.INDEXED_VALUE_TYPE_DOUBLE,
    },
  });
} catch (err: any) {
  // Don't throw if attributes already exist
  if (err.code !== grpc.status.ALREADY_EXISTS) {
    throw err;
  }
}

You may also want to add the following options when creating your local server environment, to avoid delay after adding your new search attributes:

    await TestWorkflowEnvironment.createLocal({
      server: {
        extraArgs: [
          '--dynamic-config-value',
          'system.forceSearchAttributesCacheRefreshOnRead=true',
        ],
      },
    });

Thanks, this basically worked. I am first doing TestLocalEnvironment.createLocal() and then passing the returned TestWorkflowEnvironment nativeConnection to my worker. So I was originally looking for operatorService on the nativeConnection, but it is not there. TestWorkflowEnvironment has BOTH a connection and nativeConnection. Calling that TestWorkflowEnvironment’s connection.operatorService.addSearchAttributes worked. I hope that helps anyone else confused by this.