Skip to content

chore: end 2 end snapshot tests for generate and refactor#14654

Draft
iliapolo wants to merge 3 commits intogen2-migrationfrom
epolon/snapshot-refactor
Draft

chore: end 2 end snapshot tests for generate and refactor#14654
iliapolo wants to merge 3 commits intogen2-migrationfrom
epolon/snapshot-refactor

Conversation

@iliapolo
Copy link
Copy Markdown
Contributor

@iliapolo iliapolo commented Mar 9, 2026

Description of changes

This PR introduces end-to-end snapshot tests for both the gen2-migration generate and gen2-migration refactor commands, along with the supporting test framework, migration app fixtures, and several production code fixes discovered during test development.

Snapshot Test Framework (packages/amplify-cli/src/__tests__/commands/gen2-migration/_framework/)

A new test framework that enables snapshot-testing the migration commands against real Amplify Gen1 app configurations without requiring AWS credentials. Key components:

  • MigrationApp — sets up an isolated temp directory, reads app metadata, and orchestrates mock clients for a test run.
  • MockClients — per-service AWS SDK mocks (Amplify, AppSync, CloudFormation, Cognito, DynamoDB, Lambda, S3, STS) that derive responses from local snapshot input files (_snapshot.pre.generate/, _snapshot.pre.refactor/).
  • Snapshot / Report — directory-level comparison and human-readable diff output for verifying codegen output against expected snapshots.
  • Supports --updateSnapshot for regenerating expected output when intentional changes are made.

Migration App Fixtures (amplify-migration-apps/)

Seven test apps with full pre/post snapshot directories for both generate and refactor:

  • backend-only — auth, data (GraphQL), function, storage
  • discussions — auth, data, functions (DynamoDB triggers), storage (DynamoDB)
  • fitness-tracker — auth (with pre-signup trigger, user pool groups), data, functions (REST API), storage
  • media-vault — auth (with user pool groups, social providers), data, functions (user group management), storage (S3 with triggers)
  • mood-board — auth, data, functions, storage, analytics (Kinesis)
  • product-catalog — auth, data (multi-model with custom auth rules), functions (Lambda with DynamoDB access), storage (S3 with triggers)
  • project-boards — auth, data, function, storage

Each app includes _snapshot.pre.generate/ (Gen1 amplify project state), _snapshot.post.generate/ (expected Gen2 codegen output), _snapshot.pre.refactor/ (CloudFormation stack descriptions), and refactor operation snapshots.

Renamed project-boards-backend-only to backend-only for consistency.

Production Code Fixes

Fixes discovered and applied while developing the snapshot tests:

  • command-handlers.ts — extracted DependenciesInstaller class to allow mocking npm install in tests; fixed .gitignore output to include trailing newline.
  • migration-pipeline.ts — added prettier formatting for generated .ts files; skip node_modules/ when copying Gen1 function files.
  • npm_package/renderer.ts — sort dependencies and devDependencies keys alphabetically for deterministic output.
  • renderers/package_json.ts — format JSON output with prettier for consistency.
  • synthesizer.ts — emit AllowedOAuthFlows as a commented-out property when already included in the OAuth block to avoid duplication; replace dynamic REST API IDs with placeholder tokens (<gen1-{name}-api-id>) since these are runtime values.
  • data_definition_fetcher.ts — removed live APIGatewayClient call for fetching root resource IDs (replaced with placeholders above).

Refactor Command Fixes

  • snap.ts (new) — captures refactor operations (UpdateStack, CreateStackRefactor) to disk for snapshot comparison.
  • cfn-stack-updater.ts / cfn-stack-refactor-updater.ts — integrated snap hooks before CloudFormation calls.
  • category-template-generator.ts / template-generator.ts — use extractStackNameFromId() for resource mappings to handle both ARN and plain stack name formats.
  • utils.tsextractStackNameFromId now handles plain stack names (not just ARNs).

Developer Experience

  • Added CODING_GUIDELINES.md with expanded guidelines for the project.
  • Added REFACTORING_GENERATE.md and REFACTORING_REFACTOR.md documenting guideline violations in the generate and refactor commands respectively, as a roadmap for future refactoring.
  • Updated AGENTS.md with improved workflow instructions and added a Kiro skill for adding new generate snapshot tests.
  • Added amplify-migration-apps/sanitize.ts and snapshot.ts utilities for managing test app data.

Issue #, if available

N/A

Description of how you validated changes

  • All seven migration apps pass snapshot tests for the generate command (command-handlers.test.ts).
  • Five migration apps pass snapshot tests for the refactor command (refactor.test.ts): product-catalog, project-boards, backend-only, discussions, mood-board.
  • Existing unit tests in synthesizer.test.ts updated to reflect the REST API placeholder change.
  • Tests run without AWS credentials using the mock client framework.

Checklist

  • PR description included
  • yarn test passes
  • Tests are changed or added
  • Relevant documentation is changed or added (and PR referenced)
  • New AWS SDK calls or CloudFormation actions have been added to relevant test and service IAM policies
  • Pull request labels are added

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

iliapolo added 3 commits March 8, 2026 16:46
The app structure diagram incorrectly listed a top-level
amplify/ directory. The Gen1 project structure actually lives
inside _snapshot.pre.generate/. Updated the diagram to reflect
the actual layout and added the src/ directory for frontend
code.
---
Prompt: fix migration apps readme - app structure says each
dir contains an "amplify" directory but it doesn't, and add
src directory for frontend code.
},
});

const cognitoUnauthPolicy = new iam.CfnPolicy(this, 'CognitoUnauthPolicy', {

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused variable cognitoUnauthPolicy.

Copilot Autofix

AI 21 days ago

In general, to fix an unused variable whose initializer has important side effects (like creating a CDK construct), you remove the variable binding but keep the expression. That way, the side effect still occurs, but there is no unused identifier.

Here, the best fix is to change the declaration const cognitoUnauthPolicy = new iam.CfnPolicy(...) into a bare instantiation new iam.CfnPolicy(...). We should not remove the new call because the unauthenticated Cognito policy resource must still be created in the stack. No imports or additional methods are needed, and no other lines need updating.

Concretely, in amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/analytics/moodboardKinesis-construct.ts, replace the block starting at line 73 where cognitoUnauthPolicy is declared with an identical block that omits the const cognitoUnauthPolicy = portion.

Suggested changeset 1
amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/analytics/moodboardKinesis-construct.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/analytics/moodboardKinesis-construct.ts b/amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/analytics/moodboardKinesis-construct.ts
--- a/amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/analytics/moodboardKinesis-construct.ts
+++ b/amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/analytics/moodboardKinesis-construct.ts
@@ -70,7 +70,7 @@
       },
     });
 
-    const cognitoUnauthPolicy = new iam.CfnPolicy(this, 'CognitoUnauthPolicy', {
+    new iam.CfnPolicy(this, 'CognitoUnauthPolicy', {
       policyName: props.unauthPolicyName!,
       roles: [props.unauthRoleName!],
       policyDocument: {
EOF
@@ -70,7 +70,7 @@
},
});

const cognitoUnauthPolicy = new iam.CfnPolicy(this, 'CognitoUnauthPolicy', {
new iam.CfnPolicy(this, 'CognitoUnauthPolicy', {
policyName: props.unauthPolicyName!,
roles: [props.unauthRoleName!],
policyDocument: {
Copilot is powered by AI and may make mistakes. Always verify output.
@@ -0,0 +1,26 @@
import { CfnStream } from 'aws-cdk-lib/aws-kinesis';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import CfnStream.

Copilot Autofix

AI 21 days ago

To fix the unused import, remove the CfnStream import statement since it is not referenced in active code. This aligns with the recommendation to delete unused program elements and will not affect runtime behavior.

Concretely, in amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/analytics/resource.ts, delete line 1 that imports CfnStream from aws-cdk-lib/aws-kinesis. No additional imports, methods, or definitions are required. The commented-out line can remain as-is; if future code needs CfnStream, it can reintroduce the import at that time.

Suggested changeset 1
amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/analytics/resource.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/analytics/resource.ts b/amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/analytics/resource.ts
--- a/amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/analytics/resource.ts
+++ b/amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/analytics/resource.ts
@@ -1,4 +1,3 @@
-import { CfnStream } from 'aws-cdk-lib/aws-kinesis';
 import { analyticsmoodboardKinesis } from './moodboardKinesis-construct';
 import { Backend } from '@aws-amplify/backend';
 
EOF
@@ -1,4 +1,3 @@
import { CfnStream } from 'aws-cdk-lib/aws-kinesis';
import { analyticsmoodboardKinesis } from './moodboardKinesis-construct';
import { Backend } from '@aws-amplify/backend';

Copilot is powered by AI and may make mistakes. Always verify output.
moodboardGetRandomEmoji,
moodboardKinesisReader,
});
const analytics = defineAnalytics(backend);

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused variable analytics.

Copilot Autofix

AI 21 days ago

In general, unused variables should be removed to avoid confusion and potential performance overhead from computing unused values. If the initializer has required side effects, keep the expression but drop the binding.

Specifically here, we should remove the const analytics = binding and just invoke defineAnalytics(backend); so that any initialization side effects still occur. This change is localized to line 17 in amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/backend.ts. No new imports or definitions are required; we only adjust that single line to eliminate the unused analytics variable without altering existing functionality.

Suggested changeset 1
amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/backend.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/backend.ts b/amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/backend.ts
--- a/amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/backend.ts
+++ b/amplify-migration-apps/mood-board/_snapshot.post.generate/amplify/backend.ts
@@ -14,7 +14,7 @@
   moodboardGetRandomEmoji,
   moodboardKinesisReader,
 });
-const analytics = defineAnalytics(backend);
+defineAnalytics(backend);
 const cfnUserPool = backend.auth.resources.cfnResources.cfnUserPool;
 cfnUserPool.usernameAttributes = ['email'];
 cfnUserPool.policies = {
EOF
@@ -14,7 +14,7 @@
moodboardGetRandomEmoji,
moodboardKinesisReader,
});
const analytics = defineAnalytics(backend);
defineAnalytics(backend);
const cfnUserPool = backend.auth.resources.cfnResources.cfnUserPool;
cfnUserPool.usernameAttributes = ['email'];
cfnUserPool.policies = {
Copilot is powered by AI and may make mistakes. Always verify output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant