-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Expand file tree
/
Copy pathfixture-validation.spec.ts
More file actions
187 lines (166 loc) · 6.97 KB
/
fixture-validation.spec.ts
File metadata and controls
187 lines (166 loc) · 6.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// eslint-disable-next-line import-x/no-nodejs-modules, import-x/no-namespace
import * as fs from 'fs';
// eslint-disable-next-line import-x/no-namespace, import-x/no-nodejs-modules
import * as path from 'path';
import { FixtureValidation } from '../../tags';
import { CreateNewWallet } from '../../flows/wallet.flow';
import FixtureBuilder from '../../framework/fixtures/FixtureBuilder';
import { withFixtures } from '../../framework/fixtures/FixtureHelper';
import { TestSuiteParams } from '../../framework/types';
import {
readFixtureFile,
computeSchemaDiff,
formatSchemaDiff,
mergeFixtureChanges,
sortObjectKeysDeep,
normalizeExportedState,
hasStructuralChanges as hasStructuralChangesCheck,
getAutoUpdatableKeys,
FixtureSchemaDiff,
} from '../../framework/fixtures/fixture-validation';
describe(FixtureValidation('Fixture Validation — Post-Onboarding'), () => {
beforeAll(async () => {
jest.setTimeout(150000);
});
it('validates the committed fixture and exports updates when structural changes exist', async () => {
await withFixtures(
{
fixture: new FixtureBuilder().withOnboardingFixture().build(),
restartDevice: true,
useCommandQueueServer: true,
},
async ({ commandQueueServer }: TestSuiteParams) => {
if (!commandQueueServer) {
throw new Error('Command queue server not available');
}
// Complete onboarding flow
await CreateNewWallet();
// Capture live app state
commandQueueServer.requestStateExport();
const exported = await commandQueueServer.getExportedState();
// Read the committed default fixture (existing-user baseline)
const fixture = readFixtureFile('default-fixture.json');
const fixtureState = fixture.state as Record<string, unknown>;
// Normalize exported state to match fixture shape
const liveState = normalizeExportedState(exported);
// Compare
const diff = computeSchemaDiff(fixtureState, liveState);
const report = formatSchemaDiff(diff);
const hasStructuralChanges = hasStructuralChangesCheck(diff);
// --- Validation: write reports for CI ---
const reportsDir = path.resolve(__dirname, '..', '..', 'reports');
if (!fs.existsSync(reportsDir)) {
fs.mkdirSync(reportsDir, { recursive: true });
}
// Human-readable diff report (written to reportsDir so it's always uploaded)
const diffPath = path.join(reportsDir, 'fixture-validation-diff.txt');
if (hasStructuralChanges || diff.valueMismatches.length > 0) {
const summary = [
'--- Fixture Diff Report ---',
'',
report,
'',
`New keys: ${diff.newKeys.length}`,
`Missing keys: ${diff.missingKeys.length}`,
`Type mismatches: ${diff.typeMismatches.length}`,
`Value mismatches: ${diff.valueMismatches.length} (informational)`,
'',
'To update the committed fixture, comment on the PR:',
' @metamaskbot update-mobile-fixture',
].join('\n');
fs.writeFileSync(diffPath, summary, 'utf-8');
console.log(`\nFull diff written to: ${diffPath}`);
} else {
fs.writeFileSync(
diffPath,
'No differences found — fixture is up to date.',
'utf-8',
);
}
// Machine-readable JSON summary for downstream CI job
fs.writeFileSync(
path.join(reportsDir, 'fixture-validation-result.json'),
JSON.stringify(
{
hasStructuralChanges,
newKeys: diff.newKeys.length,
missingKeys: diff.missingKeys.length,
typeMismatches: diff.typeMismatches.length,
valueMismatches: diff.valueMismatches.length,
},
null,
2,
),
'utf-8',
);
// --- Export: update fixture file when changes exist ---
// Promote auto-updatable value mismatches (e.g. fiatOrders.networks)
// so they get merged alongside structural changes.
const autoUpdatableKeys = getAutoUpdatableKeys();
const autoUpdateMismatches = diff.valueMismatches.filter((m) =>
autoUpdatableKeys.includes(m.key),
);
const shouldUpdate =
hasStructuralChanges || autoUpdateMismatches.length > 0;
if (shouldUpdate) {
// Merge structural changes + auto-updatable value mismatches.
// Other value mismatches are NOT auto-merged because the default
// fixture represents an existing user, not a fresh post-onboarding state.
const structuralDiff: FixtureSchemaDiff = {
newKeys: diff.newKeys,
missingKeys: diff.missingKeys,
typeMismatches: diff.typeMismatches,
valueMismatches: autoUpdateMismatches,
};
const mergedState = mergeFixtureChanges(
fixtureState,
liveState,
structuralDiff,
);
const updatedFixture = sortObjectKeysDeep({
...fixture,
state: mergedState,
}) as Record<string, unknown>;
// Only write to the source fixture file in CI to avoid accidental
// local modifications. Locally the diff report is still written to
// the reports directory for inspection.
const isCI =
process.env.CI === 'true' || process.env.GITHUB_CI === 'true';
const fixturePath = isCI
? path.resolve(
__dirname,
'..',
'..',
'framework',
'fixtures',
'json',
'default-fixture.json',
)
: path.join(reportsDir, 'updated-default-fixture.json');
fs.writeFileSync(
fixturePath,
JSON.stringify(updatedFixture, null, 2) + '\n',
'utf-8',
);
throw new Error(
`Committed fixture is out of date.\n` +
` New keys: ${diff.newKeys.length}\n` +
` Missing keys: ${diff.missingKeys.length}\n` +
` Type mismatches: ${diff.typeMismatches.length}\n` +
` Auto-updated values: ${autoUpdateMismatches.length}\n\n` +
`Updated fixture written to: ${fixturePath}\n` +
`Structural changes and auto-updatable keys were applied.\n` +
`Other value mismatches require manual review.\n\n` +
`To fix: commit the updated fixture, or add new keys to getMobileFixtureIgnoredKeys() in fixture-validation.ts.`,
);
} else if (diff.valueMismatches.length > 0) {
console.log(
`\nFixture schema is up to date. ${diff.valueMismatches.length} value mismatches detected (expected — fixture represents an existing user).`,
);
} else {
console.log('No differences found — fixture is up to date.');
}
},
);
});
});