import Debugger from 'src/Debugger'; import Item from 'src/Item'; import ItemTransformer from 'src/transformer/ItemTransformer'; import TransformDescriptor from 'src/TransformDescriptor'; import TransformContext from 'src/transformer/TransformContext'; import LineItemMerger from 'src/debug/LineItemMerger'; import ItemResult from 'src/ItemResult'; import ColumnAnnotation from 'src/debug/ColumnAnnotation'; import AnnotatedColumn from 'src/debug/AnnotatedColumn'; import { items } from './testItems'; class TestTransformer extends ItemTransformer { items: Item[]; constructor(name: string, descriptor: Partial, outputSchema: string[], items: Item[]) { super(name, `Description for ${name}`, descriptor, (_) => outputSchema); this.items = items; } transform(_: TransformContext, __: Item[]): ItemResult { return { items: this.items, messages: [], }; } } describe('Transform Items', () => { test('Basics', async () => { const parsedSchema = ['A', 'B']; const parsedItems = items(0, [ { A: 'a_row1', B: 'b_row1' }, { A: 'a_row2', B: 'b_row2' }, ]); const trans1Desc = { requireColumns: ['A', 'B'] }; const trans1Schema = ['C']; const trans1Items = parsedItems.map((item) => item.withData({ C: `c=${item.value('A')}+${item.value('B')}` })); const transformers = [new TestTransformer('Trans1', trans1Desc, trans1Schema, trans1Items)]; const debug = new Debugger(new Map(), [], 1, parsedSchema, parsedItems, transformers); expect(debug.stageNames).toEqual(['Parse Result', 'Trans1']); expect(debug.stageResult(0).schema).toEqual(parsedSchema.map((column) => ({ name: column }))); expect(debug.stageResult(1).schema).toEqual([ ...parsedSchema.map((column) => ({ name: column, annotation: ColumnAnnotation.REMOVED })), { name: 'C', annotation: ColumnAnnotation.ADDED }, ]); expect(debug.stageResult(0).itemsUnpacked()).toEqual(parsedItems); expect(debug.stageResult(1).itemsUnpacked()).toEqual(trans1Items); }); test('Line Merge', async () => { const parsedSchema = ['id', 'y']; const parsedItems = items(0, [ { id: 1, y: 1 }, { id: 2, y: 2 }, { id: 3, y: 2 }, ]); const trans1Desc = { requireColumns: ['id', 'y'], debug: { itemMerger: new LineItemMerger(true) } }; const trans1Schema = ['id', 'line']; const trans1Items = parsedItems.map((item) => item.withData({ line: item.data['y'] })); const transformers = [new TestTransformer('Trans1', trans1Desc, trans1Schema, trans1Items)]; const debug = new Debugger(new Map(), [], 1, parsedSchema, parsedItems, transformers); expect(debug.stageNames).toEqual(['Parse Result', 'Trans1']); expect(debug.stageResult(0).schema).toEqual([{ name: 'id' }, { name: 'y' }]); expect(debug.stageResult(1).schema).toEqual([ { name: 'id' }, { name: 'y', annotation: ColumnAnnotation.REMOVED }, { name: 'line', annotation: ColumnAnnotation.ADDED }, ]); expect(debug.stageResult(0).itemsUnpacked()).toEqual(parsedItems); expect(debug.stageResult(1).itemsUnpacked()).toEqual(trans1Items); const lineMergingStage = debug.stageResult(1); const { changes, pages } = lineMergingStage; //verify item groups expect(pages[0].itemGroups.map((itemGroup) => changes.hasChanged(itemGroup.top))).toEqual([false, true]); //verify unpacked items expect(lineMergingStage.itemsUnpacked().map((item) => changes.hasChanged(item))).toEqual([false, false, false]); }); }); test('Change inside of Line', async () => { const parsedSchema = ['id', 'line']; const parsedItems = items(0, [ { id: 1, line: 1 }, { id: 2, line: 1 }, { id: 3, line: 2 }, { id: 4, line: 2 }, ]); const trans1Desc = { requireColumns: ['id', 'line'], debug: { itemMerger: new LineItemMerger() } }; const trans1Schema = parsedSchema; const trans1Items = swapElements([...parsedItems], 0, 1); const transformers = [new TestTransformer('Trans1', trans1Desc, trans1Schema, trans1Items)]; const debug = new Debugger(new Map(), [], 1, parsedSchema, parsedItems, transformers); expect(debug.stageNames).toEqual(['Parse Result', 'Trans1']); expect(debug.stageResult(0).schema).toEqual([{ name: 'id' }, { name: 'line' }]); expect(debug.stageResult(1).schema).toEqual([{ name: 'id' }, { name: 'line' }]); expect(debug.stageResult(0).itemsUnpacked()).toEqual(parsedItems); expect(debug.stageResult(1).itemsUnpacked()).toEqual(trans1Items); const { changes, pages } = debug.stageResult(1); //verify item groups expect(pages[0].itemGroups.map((itemGroup) => changes.hasChanged(itemGroup.top))).toEqual([true, false]); //verify unpacked items expect( debug .stageResult(1) .itemsUnpacked() .map((item) => changes.hasChanged(item)), ).toEqual([true, true, false, false]); }); var swapElements = function (arr: Item[], indexA: number, indexB: number): Item[] { var temp = arr[indexA]; arr[indexA] = arr[indexB]; arr[indexB] = temp; return arr; }; describe('build schemas', () => { const items: Item[] = []; function calculateSchema(inputSchema: string[], outputSchema: string[]): AnnotatedColumn[] { const transformers = [new TestTransformer('Trans1', {}, outputSchema, items)]; const debug = new Debugger(new Map(), [], 1, inputSchema, items, transformers); return debug.stageResult(1).schema; } test('Add', async () => { const annotatedSchema = calculateSchema(['A', 'B'], ['A', 'B', 'C']); expect(annotatedSchema).toEqual([{ name: 'A' }, { name: 'B' }, { name: 'C', annotation: ColumnAnnotation.ADDED }]); }); test('Remove', async () => { const annotatedSchema = calculateSchema(['A', 'B'], ['A']); expect(annotatedSchema).toEqual([{ name: 'A' }, { name: 'B', annotation: ColumnAnnotation.REMOVED }]); }); test('Replace first', async () => { const annotatedSchema = calculateSchema(['A', 'B', 'C'], ['X', 'B', 'C']); expect(annotatedSchema).toEqual([ { name: 'A', annotation: ColumnAnnotation.REMOVED }, { name: 'X', annotation: ColumnAnnotation.ADDED }, { name: 'B' }, { name: 'C' }, ]); }); test('Replace middle', async () => { const annotatedSchema = calculateSchema(['A', 'B', 'C'], ['A', 'X', 'C']); expect(annotatedSchema).toEqual([ { name: 'A' }, { name: 'B', annotation: ColumnAnnotation.REMOVED }, { name: 'X', annotation: ColumnAnnotation.ADDED }, { name: 'C' }, ]); }); test('Replace last', async () => { const annotatedSchema = calculateSchema(['A', 'B', 'C'], ['A', 'B', 'X']); expect(annotatedSchema).toEqual([ { name: 'A' }, { name: 'B' }, { name: 'C', annotation: ColumnAnnotation.REMOVED }, { name: 'X', annotation: ColumnAnnotation.ADDED }, ]); }); test('Replace first with 2', async () => { const annotatedSchema = calculateSchema(['A', 'B', 'C'], ['X', 'Y', 'B', 'C']); expect(annotatedSchema).toEqual([ { name: 'A', annotation: ColumnAnnotation.REMOVED }, { name: 'X', annotation: ColumnAnnotation.ADDED }, { name: 'Y', annotation: ColumnAnnotation.ADDED }, { name: 'B' }, { name: 'C' }, ]); }); test('Replace middle with 2', async () => { const annotatedSchema = calculateSchema(['A', 'B', 'C'], ['A', 'X', 'Y', 'C']); expect(annotatedSchema).toEqual([ { name: 'A' }, { name: 'B', annotation: ColumnAnnotation.REMOVED }, { name: 'X', annotation: ColumnAnnotation.ADDED }, { name: 'Y', annotation: ColumnAnnotation.ADDED }, { name: 'C' }, ]); }); test('Replace last with 2', async () => { const annotatedSchema = calculateSchema(['A', 'B', 'C'], ['A', 'B', 'X', 'Y']); expect(annotatedSchema).toEqual([ { name: 'A' }, { name: 'B' }, { name: 'C', annotation: ColumnAnnotation.REMOVED }, { name: 'X', annotation: ColumnAnnotation.ADDED }, { name: 'Y', annotation: ColumnAnnotation.ADDED }, ]); }); test('Replace 2 with one', async () => { const annotatedSchema = calculateSchema(['A', 'B', 'C', 'D'], ['A', 'X', 'D']); expect(annotatedSchema).toEqual([ { name: 'A' }, { name: 'B', annotation: ColumnAnnotation.REMOVED }, { name: 'C', annotation: ColumnAnnotation.REMOVED }, { name: 'X', annotation: ColumnAnnotation.ADDED }, { name: 'D' }, ]); }); test('Replace all', async () => { const annotatedSchema = calculateSchema(['A', 'B', 'C'], ['X']); expect(annotatedSchema).toEqual([ { name: 'A', annotation: ColumnAnnotation.REMOVED }, { name: 'B', annotation: ColumnAnnotation.REMOVED }, { name: 'C', annotation: ColumnAnnotation.REMOVED }, { name: 'X', annotation: ColumnAnnotation.ADDED }, ]); }); test('Wild mix all', async () => { const annotatedSchema = calculateSchema(['A', 'B', 'C', 'E', 'F', 'G'], ['B', 'X', 'E', 'Y', 'Z', 'G', 'XX']); expect(annotatedSchema).toEqual([ { name: 'A', annotation: ColumnAnnotation.REMOVED }, { name: 'B' }, { name: 'C', annotation: ColumnAnnotation.REMOVED }, { name: 'X', annotation: ColumnAnnotation.ADDED }, { name: 'E' }, { name: 'F', annotation: ColumnAnnotation.REMOVED }, { name: 'Y', annotation: ColumnAnnotation.ADDED }, { name: 'Z', annotation: ColumnAnnotation.ADDED }, { name: 'G' }, { name: 'XX', annotation: ColumnAnnotation.ADDED }, ]); }); });