Skip to content

Commit

Permalink
FF-2509 CI job to validate test data (#34)
Browse files Browse the repository at this point in the history
* FF-2509 CI job to validate test data

* FF-2509 convert to jest testing
  • Loading branch information
greghuels authored Jun 25, 2024
1 parent 33d4d81 commit e79b6e9
Show file tree
Hide file tree
Showing 8 changed files with 2,441 additions and 0 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/validate-test-data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Validate Test Data

on:
workflow_dispatch:
pull_request:
paths:
- '.github/workflows/**'
- 'ufc/tests/**'
push:
branches:
- main

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
validate-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '18.x'
- uses: actions/cache@v2
with:
path: './node_modules'
key: ${{ runner.os }}-root-node-modules-${{ hashFiles('./yarn.lock') }}
- name: Install SDK dependencies
run: yarn --frozen-lockfile
- name: Validate tests
run: yarn validate:tests
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@

# Jetbrains IDE
.idea
node_modules
11 changes: 11 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const jestConfig = {
moduleFileExtensions: ['js', 'json', 'ts'],
rootDir: './',
testRegex: '.*\\.spec\\.ts$',
transform: {
'^.+\\.(t|j)s$': 'ts-jest',
},
testEnvironment: 'node',
};

export default jestConfig;
21 changes: 21 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@eppo/sdk-test-data",
"version": "1.0.0",
"repository": "[email protected]:Eppo-exp/sdk-test-data.git",
"author": "",
"license": "MIT",
"engines": {
"node": ">=18.x"
},
"scripts": {
"validate:tests": "jest ./test-validation"
},
"devDependencies": {
"@types/jest": "^29.5.12",
"@types/node": "18",
"jest": "^29.7.0",
"ts-jest": "^29.1.5",
"ts-node": "^10.9.2",
"typescript": "^4.2.4"
}
}
33 changes: 33 additions & 0 deletions test-validation/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
type VariationValue = string | number | boolean | object;

interface AllocationEvaluation {
key: string;
allocationEvaluationCode: string;
orderPosition: number;
}

interface FlagEvaluationDetails {
value: VariationValue
variationKey: string | null;
variationValue: VariationValue | null;
flagEvaluationCode: string;
flagEvaluationDescription: string;
matchedRule: any;
matchedAllocation: AllocationEvaluation | null;
unmatchedAllocations: Array<AllocationEvaluation>;
unevaluatedAllocations: Array<AllocationEvaluation>;
}

interface SubjectTestCase {
subjectKey: string;
subjectAttributes: Record<string, string | number | boolean>;
assignment: VariationValue;
assignmentDetails: FlagEvaluationDetails;
}

export interface IAssignmentTestCase {
flag: string;
variationType: string;
defaultValue: VariationValue;
subjects: SubjectTestCase[];
}
44 changes: 44 additions & 0 deletions test-validation/validate-tests.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as fs from 'fs';
import { IAssignmentTestCase } from './types';

const getTestFilePaths = () => {
const testDir = './ufc/tests';
return fs.readdirSync(testDir).map((testFilename) => `${testDir}/${testFilename}`);
}

const parseJSON = (testFilePath: string) => {
try {
const fileContents = fs.readFileSync(testFilePath, 'utf-8');
const parsedJSON = JSON.parse(fileContents);
return parsedJSON as IAssignmentTestCase;
} catch (err) {
console.error(`failed to parse JSON in ${testFilePath}`)
console.error(err);
process.exit(1);
}
}

describe('UFC Test Validation', () => {
describe.each(getTestFilePaths())('for file: %s', (testFilePath: string) => {
const testCase = parseJSON(testFilePath);
describe.each(testCase.subjects.map(({subjectKey}) => subjectKey))('with subjectKey %s', (subjectKey) => {
const subject = testCase.subjects.find((subject) => subject.subjectKey === subjectKey)!;

it('should have matching `assignment` and `assignmentDetails.value` values', () => {
expect(subject.assignment).toEqual(subject.assignmentDetails.value);
});

if (subject.assignmentDetails.variationValue === null) {
it('should have `assignmentDetails.value` match `defaultValue` when `assignmentDetails.variationValue` is null', () => {
expect(subject.assignmentDetails.value).toEqual(testCase.defaultValue);
})
}

if (subject.assignmentDetails.variationValue !== null) {
it('should have `assignmentDetails.value` match `assignmentDetails.variationValue` when `assignmentDetails.variationValue` is not null', () => {
expect(subject.assignmentDetails.value).toEqual(subject.assignmentDetails.variationValue);
})
}
});
})
});
20 changes: 20 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"module": "commonjs",
"sourceMap": true,
"target": "es2017",
"strict": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"resolveJsonModule": true,
},
"include": [
"**/*.ts"
],
"exclude": [
"node_modules",
],
"types": [
"jest"
]
}
Loading

0 comments on commit e79b6e9

Please sign in to comment.