Skip to content

Implement the test data source.#27

Merged
kinyoklion merged 6 commits into
mainfrom
rlamb/sc-154356/implement-test-data
Aug 1, 2022
Merged

Implement the test data source.#27
kinyoklion merged 6 commits into
mainfrom
rlamb/sc-154356/implement-test-data

Conversation

@kinyoklion

Copy link
Copy Markdown
Member

There are a few things that are different from this and the node implementation.

Unlike the other code that has been ported I have removed the interface files. This is because there are cross dependencies between the different components of the implementation and all the dependencies between components cannot be represented by the interfaces. We need methods that are implementation only and not intended for external consumption.

One of the implementations is also a generic to allow having the implementation, with cross dependencies, span multiple files. If it was not this way, then there would be a circular dependency between the types.

An additional change is that constructing a test data object returns an actual test data object instead of a function/object that is a factory for data sources as well as being the implementation for the TestData object. Instead you call a method to get a factory, and that is given to the configuration.

@shortcut-integration

Copy link
Copy Markdown

This pull request has been linked to Shortcut Story #154356: Implement test data source..

td.update(flag);
const flagCopy = td.flag('test-flag');

const flagRules: FlagRule[] = [{

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, being able to have this FlagRule[] here prevents some of the problems with the original testing.
In the original versions of these tests the operator is also in the test, versus op. So everything seems fine.


it('can set a value for all', () => {
const flag = td.flag('test-flag');
flag.valueForAll('potato');

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not tested in original tests.

expect(flagCopy).not.toEqual(flag);
});

it('can clone a complex flag configuration', () => {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copying a complex object was not a consideration initially. Because the flag configuration was just data, it didn't have things like AttributeReferences in it.

@@ -0,0 +1,398 @@
import { AttributeReference, LDClientImpl } from '../../../src';

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original version of these tests worked with the client, this variation just uses a store. I don't think using fewer dependencies is a bad change in this case.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Longer term I can test things more by updating some of the other tests to use this instead of hand constructed objects. I will use it for the client level tests as well of course.

@@ -0,0 +1,194 @@
import { LDStreamProcessor } from '../../api';

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've not exported TestData yet. I put it in this integrations folder, and need to work on how the exports will work.

* Finally, call `thenReturn` to finish defining the rule.
*/

export default class TestDataRuleBuilder<BuilderType> {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the type I made generic to remove the circular dependency.

variation?: number,
) {
if (clauses) {
this.clauses = JSON.parse(JSON.stringify(clauses));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use JSON cloning a few places in here. Being as this is for specific testing situations I cannot imagine it being too much of a problem.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why wouldn't a shallow copy of the array work? We won't be modifying anything inside of an individual clause.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made this change.


it('can make not matching rules', () => {
const flag = td.flag('flag')
.ifNotMatch('user', 'name', 'Saffron', 'Bubble')

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was not tested in the original.

this.tags = new ApplicationTags(validatedOptions);
this.diagnosticRecordingInterval = validatedOptions.diagnosticRecordingInterval;

if (TypeValidators.Function.is(validatedOptions.featureStore)) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I am using the validated features for this. Which is a little different than LDOptions. So I may need to make some updates when I handle the updates for integrations like redis.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It moved down here, so the rest of config can be initialized before using it. Could defer construction. A subset of the configuration interface, with specifically what stores need, is probably better.

}

function processFlag(flag: Flag) {
/**

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exported so they can be used handling the free-form flag data.

@kinyoklion kinyoklion marked this pull request as ready for review July 15, 2022 23:01
@eli-darkly

Copy link
Copy Markdown
Contributor

An additional change is that constructing a test data object returns an actual test data object instead of a function/object that is a factory for data sources as well as being the implementation for the TestData object. Instead you call a method to get a factory, and that is given to the configuration.

This is why in other SDKs like Go, Java, and .NET, the idea of a data source factory is represented as an interface with a particular method, rather than just being a function: because it's often advantageous for the same class to be able to do more than one thing. (As another example, the Redis and DynamoDB data source builders in those SDKs are usable as both a regular data store factory and a big segment store factory.)

@kinyoklion kinyoklion merged commit 32949a6 into main Aug 1, 2022
@kinyoklion kinyoklion deleted the rlamb/sc-154356/implement-test-data branch August 1, 2022 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants