Skip to content

Commit

Permalink
feat(vite-plugin-angular): add snapshot testing support for vitest (#678
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Tenessy authored Oct 2, 2023
1 parent fa755ce commit 54166d7
Show file tree
Hide file tree
Showing 4 changed files with 424 additions and 0 deletions.
132 changes: 132 additions & 0 deletions packages/vite-plugin-angular/setup-vitest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,132 @@ function wrapTestInZone(testBody: string | any[] | undefined) {
return wrappedFunc;
}

/**
* Allows Vitest to handle Angular test fixtures
*
* Vitest Snapshot guide ==> https://vitest.dev/guide/snapshot.html
*
* @returns customSnapshotSerializer for Angular Fixture Component
*/
const customSnapshotSerializer = () => {
function serialize(
val: any,
config: any,
indentation: any,
depth: any,
refs: any,
printer: any
): string {
// `printer` is a function that serializes a value using existing plugins.
return `${printer(
fixtureVitestSerializer(val),
config,
indentation,
depth,
refs
)}`;
}
function test(val: any): boolean {
// * If it's a ComponentFixture we apply the transformation rules
return val && isAngularFixture(val);
}
return {
serialize,
test,
};
};

/**
* Check if is an Angular fixture
*
* @param val Angular fixture
* @returns boolean who check if is an angular fixture
*/
function isAngularFixture(val: any): boolean {
if (typeof val !== 'object') {
return false;
}

// * Angular fixture keys in Fixture component Object
const fixtureKeys = [
'componentRef',
'ngZone',
'_autoDetect',
'_isStable',
'_isDestroyed',
'_resolve',
'_promise',
'_onUnstableSubscription',
'_onStableSubscription',
'_onMicrotaskEmptySubscription',
'_onErrorSubscription',
'changeDetectorRef',
'elementRef',
'debugElement',
'componentInstance',
'nativeElement',
];

// * Angular fixture keys in Fixture componentRef Object
const fixtureComponentRefKeys = [
'location',
'_rootLView',
'_tNode',
'previousInputValues',
'instance',
'changeDetectorRef',
'hostView',
'componentType',
];

return (
JSON.stringify(Object.keys(val)) === JSON.stringify(fixtureKeys) ||
JSON.stringify(Object.keys(val)) === JSON.stringify(fixtureComponentRefKeys)
);
}

/**
* Serialize Angular fixture for Vitest
*
* @param fixture Angular Fixture Component
* @returns HTML Child Node
*/
function fixtureVitestSerializer(fixture: any) {
// * Get Component meta data
const componentType = (
fixture && fixture.componentType
? fixture.componentType
: fixture.componentRef.componentType
) as any;

let inputsData: string = '';

const selector = Reflect.getOwnPropertyDescriptor(
componentType,
'__annotations__'
)?.value[0].selector;

if (componentType && componentType.propDecorators) {
inputsData = Object.entries(componentType.propDecorators)
.map(([key, value]) => `${key}="${value}"`)
.join('');
}

// * Get DOM Elements
const divElement =
fixture && fixture.nativeElement
? fixture.nativeElement
: fixture.location.nativeElement;

// * Convert string data to HTML data
const doc = new DOMParser().parseFromString(
`<${selector} ${inputsData}>${divElement.innerHTML}</${selector}>`,
'text/html'
);

return doc.body.childNodes[0];
}

/**
* bind describe method to wrap describe.each function
*/
Expand Down Expand Up @@ -145,9 +271,15 @@ const bindTest = (originalVitestFn: {

['beforeEach', 'afterEach', 'beforeAll', 'afterAll'].forEach((methodName) => {
const originalvitestFn = env[methodName];

env[methodName] = function (...args: any[]) {
args[0] = wrapTestInZone(args[0]);

return originalvitestFn.apply(this, args);
};
});

['expect'].forEach((methodName) => {
const originalvitestFn = env[methodName];
return originalvitestFn.addSnapshotSerializer(customSnapshotSerializer());
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Angular Fixture Snapshot > create angular component snapshot 1`] = `
TestComponent {
"__ngContext__": 2,
"count": 0,
}
`;

exports[`Angular Fixture Snapshot > create angular fixture snapshot 1`] = `
<app-test>
<div
_ngcontent-a-c3752700837=""
>
<a
_ngcontent-a-c3752700837=""
href="https://analogjs.org/"
target="_blank"
>
<img
_ngcontent-a-c3752700837=""
alt="Analog Logo"
class="logo analog"
src="/analog.svg"
/>
</a>
</div>
<h2
_ngcontent-a-c3752700837=""
>
Analog
</h2>
<h3
_ngcontent-a-c3752700837=""
>
The fullstack meta-framework for Angular!
</h3>
<div
_ngcontent-a-c3752700837=""
class="card"
>
<button
_ngcontent-a-c3752700837=""
type="button"
>
Count 0
</button>
</div>
<p
_ngcontent-a-c3752700837=""
class="read-the-docs"
>
For guides on how to customize this project, visit the
<a
_ngcontent-a-c3752700837=""
href="https://analogjs.org"
target="_blank"
>
Analog documentation
</a>
</p>
</app-test>
`;
Loading

0 comments on commit 54166d7

Please sign in to comment.