Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/snapshot/src/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { basename, dirname, isAbsolute, join, resolve } from 'pathe'
export class SnapshotManager {
public summary!: SnapshotSummary
public extension = '.snap'
public result?: SnapshotResult

constructor(
public options: Omit<SnapshotStateOptions, 'snapshotEnvironment'>,
Expand All @@ -17,10 +18,12 @@ export class SnapshotManager {

clear(): void {
this.summary = emptySummary(this.options)
this.result = undefined
}

add(result: SnapshotResult): void {
addSnapshotResult(this.summary, result)
this.result = result
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need a separate variable? What does result represent?

}

resolvePath<T = any>(testPath: string, context?: T): string {
Expand Down
44 changes: 44 additions & 0 deletions packages/snapshot/src/port/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ export default class SnapshotState {
private _matched = new CounterMap<string>()
private _unmatched = new CounterMap<string>()
private _updated = new CounterMap<string>()

// Track snapshot keys by category
private _addedKeys = new Set<string>()
private _matchedKeys = new Set<string>()
private _unmatchedKeys = new Set<string>()
private _updatedKeys = new Set<string>()

get added(): CounterMap<string> { return this._added }
set added(value: number) { this._added._total = value }
get matched(): CounterMap<string> { return this._matched }
Expand Down Expand Up @@ -149,6 +156,11 @@ export default class SnapshotState {
}
this._counters.set(name, count - 1)
}
// Remove from key tracking sets
this._addedKeys.delete(key)
this._updatedKeys.delete(key)
this._matchedKeys.delete(key)
this._unmatchedKeys.delete(key)
}
this._testIdToKeys.delete(testId)

Expand Down Expand Up @@ -250,6 +262,10 @@ export default class SnapshotState {
return Array.from(this._uncheckedKeys)
}

getSnapshotData(): SnapshotData {
return { ...this._snapshotData }
}

removeUncheckedKeys(): void {
if (this._updateSnapshot === 'all' && this._uncheckedKeys.size) {
this._dirty = true
Expand Down Expand Up @@ -386,9 +402,11 @@ export default class SnapshotState {
if (!pass) {
if (hasSnapshot) {
this.updated.increment(testId)
this._updatedKeys.add(key)
}
else {
this.added.increment(testId)
this._addedKeys.add(key)
}

this._addSnapshot(key, receivedSerialized, {
Expand All @@ -399,6 +417,7 @@ export default class SnapshotState {
}
else {
this.matched.increment(testId)
this._matchedKeys.add(key)
}
}
else {
Expand All @@ -408,6 +427,7 @@ export default class SnapshotState {
rawSnapshot,
})
this.added.increment(testId)
this._addedKeys.add(key)
}

return {
Expand All @@ -421,6 +441,7 @@ export default class SnapshotState {
else {
if (!pass) {
this.unmatched.increment(testId)
this._unmatchedKeys.add(key)
return {
actual: rawSnapshot ? receivedSerialized : removeExtraLineBreaks(receivedSerialized),
count,
Expand All @@ -434,6 +455,7 @@ export default class SnapshotState {
}
else {
this.matched.increment(testId)
this._matchedKeys.add(key)
return {
actual: '',
count,
Expand All @@ -446,15 +468,33 @@ export default class SnapshotState {
}

async pack(): Promise<SnapshotResult> {
// Merge inline snapshots with external snapshots
const mergedSnapshots = { ...this._snapshotData }

for (const inline of [...this._inlineSnapshotStacks, ...this._inlineSnapshots]) {
// Use testId to key mapping to find the snapshot key
const keys = this._testIdToKeys.get(inline.testId)
if (keys.length > 0) {
// For inline snapshots, typically there's one key per testId
const key = keys[0]
mergedSnapshots[key] = inline.snapshot
}
}

const snapshot: SnapshotResult = {
filepath: this.testFilePath,
snapshot: mergedSnapshots,
added: 0,
addedKeys: [],
fileDeleted: false,
matched: 0,
matchedKeys: [],
unchecked: 0,
uncheckedKeys: [],
unmatched: 0,
unmatchedKeys: [],
updated: 0,
updatedKeys: [],
}
const uncheckedCount = this.getUncheckedCount()
const uncheckedKeys = this.getUncheckedKeys()
Expand All @@ -465,9 +505,13 @@ export default class SnapshotState {
const status = await this.save()
snapshot.fileDeleted = status.deleted
snapshot.added = this.added.total()
snapshot.addedKeys = Array.from(this._addedKeys)
snapshot.matched = this.matched.total()
snapshot.matchedKeys = Array.from(this._matchedKeys)
snapshot.unmatched = this.unmatched.total()
snapshot.unmatchedKeys = Array.from(this._unmatchedKeys)
snapshot.updated = this.updated.total()
snapshot.updatedKeys = Array.from(this._updatedKeys)
snapshot.unchecked = !status.deleted ? uncheckedCount : 0
snapshot.uncheckedKeys = Array.from(uncheckedKeys)

Expand Down
5 changes: 5 additions & 0 deletions packages/snapshot/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,18 @@ export interface SnapshotMatchOptions {

export interface SnapshotResult {
filepath: string
snapshot: Record<string, string>
added: number
addedKeys: Array<string>
fileDeleted: boolean
matched: number
matchedKeys: Array<string>
unchecked: number
uncheckedKeys: Array<string>
unmatched: number
unmatchedKeys: Array<string>
updated: number
updatedKeys: Array<string>
}

export interface UncheckedSnapshot {
Expand Down
1 change: 1 addition & 0 deletions packages/ui/client/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ declare module 'vue' {
ViewModuleGraph: typeof import('./components/views/ViewModuleGraph.vue')['default']
ViewReport: typeof import('./components/views/ViewReport.vue')['default']
ViewReportError: typeof import('./components/views/ViewReportError.vue')['default']
ViewSnapshot: typeof import('./components/views/ViewSnapshot.vue')['default']
ViewTestReport: typeof import('./components/views/ViewTestReport.vue')['default']
}
}
18 changes: 18 additions & 0 deletions packages/ui/client/components/FileDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,19 @@ const testTitle = computed(() => {
<span class="block w-1.4em h-1.4em i-carbon:terminal-3270" />
Console ({{ consoleCount }})
</button>
<button
tab-button
data-testid="btn-snapshots"
class="flex items-center gap-2"
:class="{
'tab-button-active': viewMode === 'snapshots',
'op20': viewMode !== 'snapshots' && !failedSnapshot,
}"
@click="changeViewMode('snapshots')"
>
<span class="block w-1.4em h-1.4em i-carbon:camera" />
Snapshots
</button>
</div>
</div>

Expand All @@ -279,6 +292,11 @@ const testTitle = computed(() => {
:file="current"
data-testid="console"
/>
<ViewSnapshot
v-else-if="viewMode === 'snapshots'"
:file="current"
data-testid="snapshots"
/>
<ViewReport v-else-if="!viewMode && !test && current" :file="current" data-testid="report" />
<ViewTestReport v-else-if="!viewMode && test" :test="test" data-testid="report" />
</div>
Expand Down
Loading
Loading