Skip to content

Commit

Permalink
chore: refactor e2e process, pipeline and ci
Browse files Browse the repository at this point in the history
  • Loading branch information
omermorad committed Oct 13, 2023
1 parent a2b776c commit 3f0e33f
Show file tree
Hide file tree
Showing 22 changed files with 268 additions and 8,132 deletions.
46 changes: 27 additions & 19 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,20 @@ jobs:
build:
name: Build, Prepare and Test
runs-on: ubuntu-latest
strategy:
matrix:
e2e-project: ['e2e/jest/nestjs', 'e2e/sinon/nestjs']
node-version: [16.x, 18.x, 20.x]
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.event.inputs.target_branch }}

- name: Use Node 16.x
- name: Use Node ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: '16.x'
node-version: ${{ matrix.node-version }}

- uses: actions/cache@v2
with:
Expand All @@ -36,26 +40,30 @@ jobs:
- name: Pack
run: lerna exec -- npm pack

- name: Move
run: lerna exec -- mv "*.tgz" $PWD/e2e/tarballs

- name: Install Packages in E2E
run: npm install
working-directory: e2e
- name: Move Tarballs
run: |
mkdir -p $PWD/e2e/tarballs
lerna exec -- mv "*.tgz" $PWD/e2e/tarballs
- name: Copy
- name: Extract & Copy Tarballs
run: |
rm -rf node_modules/@automock
mkdir -p node_modules/@automock
for file in ./tarballs/*.tgz; do
newname=$(echo "$file" | sed -E 's/automock-|-[0-9]+\.[0-9]+\.[0-9]+//g' | sed 's/\.tgz$//')
mkdir -p "$newname"
tar --wildcards -xzvf "$file" -C "$newname" --no-same-owner --strip-components=1 "package/*"
mv "$newname" ./node_modules/@automock
for file in $PWD/e2e/tarballs/automock-*.tgz; do
[[ $file =~ automock-(.+)-[0-9]+\.[0-9]+\.[0-9]+(-dev\.[0-9]+)?\.tgz ]]
new_name="${BASH_REMATCH[1]}.tgz"
mv "$file" $PWD/e2e/tarballs/$new_name
done
working-directory: e2e
cp -r "$PWD/e2e/tarballs" "$PWD/e2e/jest/nestjs"
cp -r "$PWD/e2e/tarballs" "$PWD/e2e/sinon/nestjs"
rm -rf "$PWD/e2e/sinon/nestjs/tarballs/jest.tgz"
rm -rf "$PWD/e2e/jest/nestjs/tarballs/sinon.tgz"
- name: Install Packages in E2E
run: npm install --no-package-lock --no-cache
working-directory: ${{ matrix.e2e-project }}

- name: Test e2e
run: npm run test
working-directory: e2e
working-directory: ${{ matrix.e2e-project }}
41 changes: 33 additions & 8 deletions e2e/jest/nestjs/automock-jest-ctor-injection.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import {
Foo,
Logger,
NestJSTestClass,
SymbolToken,
SymbolTokenSecond,
TestClassFive,
TestClassFour,
TestClassOne,
TestClassThree,
Expand All @@ -22,13 +25,18 @@ describe('Automock Jest / NestJS E2E Test Ctor', () => {
async foo(): Promise<string> {
return 'foo-from-test';
},
bar(): string {
return 'bar';
},
})
.mock<string>('PRIMITIVE_VALUE')
.mock<string>('CONSTANT_VALUE')
.using('arbitrary-string')
.mock('UNDEFINED')
.using({ method: () => 456 })
.mock<Logger>('LOGGER')
.using({ log: () => 'baz-from-test' })
.mock<TestClassFive>(SymbolToken)
.using({ doSomething: () => 'mocked' })
.compile();

unitRef = ref;
Expand All @@ -41,22 +49,35 @@ describe('Automock Jest / NestJS E2E Test Ctor', () => {
});

test('then successfully resolve the dependencies of the tested classes', () => {
expect(() => unitRef.get(TestClassOne).foo).toBeDefined();
expect(() => unitRef.get(TestClassTwo)).toBeDefined();
expect(() => unitRef.get(Foo)).toBeDefined();
expect(() => unitRef.get<{ log: () => void }>('LOGGER')).toBeDefined();
expect(() => unitRef.get(TestClassThree)).toBeDefined();
expect(() => unitRef.get('UNDEFINED')).toBeDefined();
expect(() => unitRef.get('UNDEFINED_SECOND')).toBeDefined();
expect(() => unitRef.get(TestClassFour)).toBeDefined();
expect(() => unitRef.get(TestClassThree)).toBeDefined();
expect(() => unitRef.get(Foo)).toBeDefined();
expect(() => unitRef.get(TestClassTwo)).toBeDefined();
expect(() => unitRef.get('CONSTANT_VALUE')).toBeDefined();
expect(() => unitRef.get(TestClassOne)).toBeDefined();
expect(() => unitRef.get(SymbolToken)).toBeDefined();
expect(() => unitRef.get(SymbolTokenSecond)).toBeDefined();
});

test('call the unit instance method', async () => {
const testClassTwo: jest.Mocked<TestClassTwo> = unitRef.get(TestClassTwo);

testClassTwo.bar.mockResolvedValue('context');

const result = await unit.test();
expect(result).toBe('context-baz-from-test-bar');
});

test('then do not return the actual reflected dependencies of the injectable class', () => {
// Indeed, they all need to be overwritten
expect(() => unitRef.get(TestClassOne)).not.toBeInstanceOf(TestClassOne);
expect(() => unitRef.get(TestClassTwo)).not.toBeInstanceOf(TestClassTwo);
expect(() => unitRef.get(SymbolToken)).not.toBeInstanceOf(TestClassFive);
});

test('then hard-mock the implementation of TestClassOne using the "foo" (partial impl function)', async () => {
test('then mock the implementation of the dependencies', async () => {
const testClassOne: jest.Mocked<TestClassOne> = unitRef.get(TestClassOne);
const logger = unitRef.get<Logger>('LOGGER');

Expand All @@ -69,7 +90,11 @@ describe('Automock Jest / NestJS E2E Test Ctor', () => {
expect(logger.log).toBeDefined();
});

test('then all the un-override classes/dependencies should be stubs', () => {
test('then treat duplicate identifiers as the same reference', async () => {
await expect(unit.testDuplicateIdentifier()).resolves.toBe('foo-from-test<>foo-from-test');
});

test('then all the unoverride classes/dependencies should be stubs as well', () => {
const testClassTwo: jest.Mocked<TestClassTwo> = unitRef.get(TestClassTwo);

expect(testClassTwo.bar.getMockName).toBeDefined();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import {
Foo,
Logger,
NestJSTestClassProp,
SymbolToken,
SymbolTokenSecond,
TestClassFive,
TestClassFour,
TestClassOne,
TestClassThree,
Expand All @@ -25,12 +28,14 @@ describe('Automock Jest / NestJS E2E Test Props', () => {
return 'foo-from-test';
},
})
.mock<string>('PRIMITIVE_VALUE')
.mock<string>('CONSTANT_VALUE')
.using('arbitrary-string')
.mock('UNDEFINED')
.using({ method: () => 456 })
.mock<Logger>('LOGGER')
.using({ log: () => 'baz-from-test' })
.mock<TestClassFive>(SymbolToken)
.using({ doSomething: () => 'mocked' })
.compile();

unitRef = ref;
Expand All @@ -43,22 +48,26 @@ describe('Automock Jest / NestJS E2E Test Props', () => {
});

test('then successfully resolve the dependencies of the tested classes', () => {
expect(() => unitRef.get(TestClassOne).foo).toBeDefined();
expect(() => unitRef.get(TestClassTwo)).toBeDefined();
expect(() => unitRef.get(Foo)).toBeDefined();
expect(() => unitRef.get<{ log: () => void }>('LOGGER')).toBeDefined();
expect(() => unitRef.get(TestClassThree)).toBeDefined();
expect(() => unitRef.get('UNDEFINED')).toBeDefined();
expect(() => unitRef.get('UNDEFINED_SECOND')).toBeDefined();
expect(() => unitRef.get(TestClassFour)).toBeDefined();
expect(() => unitRef.get(TestClassThree)).toBeDefined();
expect(() => unitRef.get(Foo)).toBeDefined();
expect(() => unitRef.get(TestClassTwo)).toBeDefined();
expect(() => unitRef.get('CONSTANT_VALUE')).toBeDefined();
expect(() => unitRef.get(TestClassOne)).toBeDefined();
expect(() => unitRef.get(SymbolToken)).toBeDefined();
expect(() => unitRef.get(SymbolTokenSecond)).toBeDefined();
});

test('then do not return the actual reflected dependencies of the injectable class', () => {
// Indeed, they all need to be overwritten
expect(() => unitRef.get(TestClassOne)).not.toBeInstanceOf(TestClassOne);
expect(() => unitRef.get(TestClassTwo)).not.toBeInstanceOf(TestClassTwo);
expect(() => unitRef.get(SymbolToken)).not.toBeInstanceOf(TestClassFive);
});

test('then hard-mock the implementation of TestClassOne using the "foo" (partial impl function)', async () => {
test('then mock the implementation of the dependencies', async () => {
const testClassOne: jest.Mocked<TestClassOne> = unitRef.get(TestClassOne);
const logger = unitRef.get<Logger>('LOGGER');

Expand All @@ -71,13 +80,22 @@ describe('Automock Jest / NestJS E2E Test Props', () => {
expect(logger.log).toBeDefined();
});

test('then all the un-override classes/dependencies should be stubs', () => {
test('then all the unoverride classes/dependencies should be stubs as well', () => {
const testClassTwo: jest.Mocked<TestClassTwo> = unitRef.get(TestClassTwo);

expect(testClassTwo.bar.getMockName).toBeDefined();
expect(testClassTwo.bar.getMockName()).toBe('jest.fn()');
});

test('call the unit instance method', async () => {
const testClassTwo: jest.Mocked<TestClassTwo> = unitRef.get(TestClassTwo);

testClassTwo.bar.mockResolvedValue('context');

const result = await unit.test();
expect(result).toBe('context-baz-from-test');
});

test('then mock the undefined reflected values and tokens', () => {
const testClassFour: jest.Mocked<TestClassFour> = unitRef.get(TestClassFour);
const undefinedValue: jest.Mocked<{ method: () => number }> = unitRef.get<{
Expand Down
44 changes: 39 additions & 5 deletions e2e/jest/nestjs/e2e-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export class TestClassOne {

return Promise.resolve('foo');
}

bar(): string {
return 'bar';
}
}

@Injectable()
Expand All @@ -32,6 +36,13 @@ export class TestClassFour {
}
}

@Injectable()
export class TestClassFive {
doSomething(): string {
return 'something';
}
}

export interface Repository<T> {
value: T;
}
Expand All @@ -45,10 +56,15 @@ export interface Logger {
export class Foo {}
export class Bar {}

export const SymbolToken = Symbol.for('SymbolToken');
export const SymbolTokenSecond = Symbol.for('SymbolTokenSecond');

type Relation<T> = T;

@Injectable()
export class NestJSTestClass {
private readonly initiatedValue!: string;

public constructor(
@Inject('LOGGER') private readonly logger: Logger,
@Inject('UNDEFINED') private readonly undefinedParam: undefined,
Expand All @@ -58,15 +74,27 @@ export class NestJSTestClass {
private readonly testClassThree: Relation<TestClassThree>,
@Inject(Foo) private readonly fooRepository: Repository<Foo>,
private readonly testClassTwo: TestClassTwo,
@Inject('PRIMITIVE_VALUE') private readonly primitiveValue: string,
private readonly testClassOne: TestClassOne
) {}
@Inject('CONSTANT_VALUE') private readonly primitiveValue: string,
private readonly testClassOne: TestClassOne,
private readonly testClassOneSecond: TestClassOne,
@Inject(SymbolToken) private readonly symbolToken: TestClassFive,
@Inject(SymbolTokenSecond) private readonly symbolTokenSecond: never
) {
this.initiatedValue = this.testClassOne.bar();
}

async test(): Promise<string> {
const value2 = await this.testClassTwo.bar();
const value3 = this.logger.log();

return `${value2}-${value3}`;
return `${value2}-${value3}-${this.initiatedValue}`;
}

async testDuplicateIdentifier() {
const value1 = await this.testClassOne.foo(false);
const value2 = await this.testClassOneSecond.foo(false);

return `${value1}<>${value2}`;
}
}

Expand All @@ -93,12 +121,18 @@ export class NestJSTestClassProp {
@Inject(TestClassTwo)
private readonly testClassTwo: TestClassTwo;

@Inject('PRIMITIVE_VALUE')
@Inject('CONSTANT_VALUE')
private readonly primitiveValue: string;

@Inject(TestClassOne)
private readonly testClassOne: TestClassOne;

@Inject(SymbolToken)
private readonly symbolToken: TestClassFive;

@Inject(SymbolTokenSecond)
private readonly symbolTokenSecond: never;

async test(): Promise<string> {
const value2 = await this.testClassTwo.bar();
const value3 = this.logger.log();
Expand Down
File renamed without changes.
15 changes: 13 additions & 2 deletions e2e/jest/nestjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,20 @@
"private": true,
"version": "1.0.0",
"dependencies": {
"@automock/adapters.nestjs": "*"
"@automock/adapters.nestjs": "file:tarballs/adapters.nestjs.tgz",
"@automock/core": "file:tarballs/core.tgz",
"@automock/common": "file:tarballs/common.tgz",
"@automock/types": "file:tarballs/types.tgz",
"@automock/jest": "file:tarballs/jest.tgz"
},
"devDependencies": {
"@types/jest": "^27.5.2",
"jest": "*",
"ts-jest": "*",
"ts-node": "*",
"typescript": "^4.x"
},
"scripts": {
"test": "exit 0;"
"test": "jest && tsc --noEmit"
}
}
13 changes: 13 additions & 0 deletions e2e/jest/nestjs/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"experimentalDecorators": true,
"allowJs": true
},
"include": [
"*e2e.test.ts"
],
"exclude": [
"node_modules"
]
}
14 changes: 0 additions & 14 deletions e2e/jest/package.json

This file was deleted.

2 changes: 2 additions & 0 deletions e2e/jest/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"sourceMap": true,
"experimentalDecorators": true,
"allowJs": true
}
}

0 comments on commit 3f0e33f

Please sign in to comment.