diff --git a/packages/@aws-cdk/aws-ec2/.gitignore b/packages/@aws-cdk/aws-ec2/.gitignore index 97fd430070d42..1d4a8175e1579 100644 --- a/packages/@aws-cdk/aws-ec2/.gitignore +++ b/packages/@aws-cdk/aws-ec2/.gitignore @@ -14,3 +14,5 @@ nyc.config.js .LAST_PACKAGE *.snk !.eslintrc.js + +!jest.config.js \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/.npmignore b/packages/@aws-cdk/aws-ec2/.npmignore index fe4df9a06d9a9..fba0982f5ee45 100644 --- a/packages/@aws-cdk/aws-ec2/.npmignore +++ b/packages/@aws-cdk/aws-ec2/.npmignore @@ -21,4 +21,5 @@ tsconfig.json .eslintrc.js # exclude cdk artifacts -**/cdk.out \ No newline at end of file +**/cdk.out +jest.config.js \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/jest.config.js b/packages/@aws-cdk/aws-ec2/jest.config.js new file mode 100644 index 0000000000000..cd664e1d069e5 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('../../../tools/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-ec2/package.json b/packages/@aws-cdk/aws-ec2/package.json index eadb31460c21d..ad6075cc5ec77 100644 --- a/packages/@aws-cdk/aws-ec2/package.json +++ b/packages/@aws-cdk/aws-ec2/package.json @@ -47,7 +47,8 @@ "compat": "cdk-compat" }, "cdk-build": { - "cloudformation": "AWS::EC2" + "cloudformation": "AWS::EC2", + "jest": true }, "keywords": [ "aws", @@ -63,11 +64,10 @@ "license": "Apache-2.0", "devDependencies": { "@aws-cdk/assert": "0.0.0", - "@types/nodeunit": "^0.0.31", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", - "nodeunit": "^0.11.3", + "nodeunit-shim": "0.0.0", "pkglint": "0.0.0", "@aws-cdk/cloud-assembly-schema": "0.0.0" }, diff --git a/packages/@aws-cdk/aws-ec2/test/test.bastion-host.ts b/packages/@aws-cdk/aws-ec2/test/bastion-host.test.ts similarity index 96% rename from packages/@aws-cdk/aws-ec2/test/test.bastion-host.ts rename to packages/@aws-cdk/aws-ec2/test/bastion-host.test.ts index 4345718952364..738b66c3d82cc 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.bastion-host.ts +++ b/packages/@aws-cdk/aws-ec2/test/bastion-host.test.ts @@ -1,9 +1,9 @@ import { expect, haveResource } from '@aws-cdk/assert'; import { Stack } from '@aws-cdk/core'; -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; import { BastionHostLinux, BlockDeviceVolume, SubnetType, Vpc } from '../lib'; -export = { +nodeunitShim({ 'default instance is created in basic'(test: Test) { // GIVEN const stack = new Stack(); @@ -85,4 +85,4 @@ export = { test.done(); }, -}; +}); diff --git a/packages/@aws-cdk/aws-ec2/test/test.connections.ts b/packages/@aws-cdk/aws-ec2/test/connections.test.ts similarity index 99% rename from packages/@aws-cdk/aws-ec2/test/test.connections.ts rename to packages/@aws-cdk/aws-ec2/test/connections.test.ts index e49cb7ef4281e..2721f073cf6b0 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.connections.ts +++ b/packages/@aws-cdk/aws-ec2/test/connections.test.ts @@ -1,6 +1,6 @@ import { expect, haveResource } from '@aws-cdk/assert'; import { App, ConstructNode, Stack } from '@aws-cdk/core'; -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; import { Connections, @@ -10,7 +10,7 @@ import { Vpc, } from '../lib'; -export = { +nodeunitShim({ 'peering between two security groups does not recursive infinitely'(test: Test) { // GIVEN const stack = new Stack(undefined, 'TestStack', { env: { account: '12345678', region: 'dummy' }}); @@ -326,7 +326,7 @@ export = { test.done(); }, -}; +}); class SomethingConnectable implements IConnectable { constructor(public readonly connections: Connections) { diff --git a/packages/@aws-cdk/aws-ec2/test/test.instance.ts b/packages/@aws-cdk/aws-ec2/test/instance.test.ts similarity index 99% rename from packages/@aws-cdk/aws-ec2/test/test.instance.ts rename to packages/@aws-cdk/aws-ec2/test/instance.test.ts index 782585960decd..06afe520cb1aa 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.instance.ts +++ b/packages/@aws-cdk/aws-ec2/test/instance.test.ts @@ -2,10 +2,10 @@ import { expect, haveResource } from '@aws-cdk/assert'; import { StringParameter } from '@aws-cdk/aws-ssm'; import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { Stack } from '@aws-cdk/core'; -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; import { AmazonLinuxImage, BlockDeviceVolume, EbsDeviceVolumeType, Instance, InstanceClass, InstanceSize, InstanceType, Vpc } from '../lib'; -export = { +nodeunitShim({ 'instance is created correctly'(test: Test) { // GIVEN const stack = new Stack(); @@ -292,4 +292,4 @@ export = { test.done(); }, -}; +}); diff --git a/packages/@aws-cdk/aws-ec2/test/l1.test.ts b/packages/@aws-cdk/aws-ec2/test/l1.test.ts new file mode 100644 index 0000000000000..0124940b6e3fc --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/test/l1.test.ts @@ -0,0 +1,14 @@ +import * as cdk from '@aws-cdk/core'; +import * as ec2 from '../lib'; + +test('NetworkAclEntry CidrBlock should be optional', () => { + const stack = new cdk.Stack(); + + new ec2.CfnNetworkAclEntry(stack, 'ACL', { + // Note the conspicuous absence of cidrBlock + networkAclId: 'asdf', + protocol: 5, + ruleAction: 'action', + ruleNumber: 1, + }); +}); diff --git a/packages/@aws-cdk/aws-ec2/test/machine-image.test.ts b/packages/@aws-cdk/aws-ec2/test/machine-image.test.ts new file mode 100644 index 0000000000000..f94de3de356fd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/test/machine-image.test.ts @@ -0,0 +1,94 @@ +import { App, Stack } from '@aws-cdk/core'; +import * as ec2 from '../lib'; + +let app: App; +let stack: Stack; + +beforeEach(() => { + app = new App(); + stack = new Stack(app, 'Stack', { + env: { account: '1234', region: 'testregion' }, + }); +}); + +test('can make and use a Windows image', () => { + // WHEN + const image = new ec2.GenericWindowsImage({ + testregion: 'ami-1234', + }); + + // THEN + const details = image.getImage(stack); + expect(details.imageId).toEqual('ami-1234'); + expect(details.osType).toEqual(ec2.OperatingSystemType.WINDOWS); +}); + +test('WindowsImage retains userdata if given', () => { + // WHEN + const ud = ec2.UserData.forWindows(); + + const image = new ec2.GenericWindowsImage({ + testregion: 'ami-1234', + }, { + userData: ud, + }); + + // THEN + const details = image.getImage(stack); + expect(details.userData).toEqual(ud); +}); + +test('WindowsImage creates UserData if not given', () => { + // WHEN + const image = new ec2.GenericWindowsImage({ + testregion: 'ami-1234', + }); + + // THEN + const details = image.getImage(stack); + expect(isWindowsUserData(details.userData)).toBeTruthy(); +}); + +test('LookupMachineImage default search', () => { + // GIVEN + + // WHEN + new ec2.LookupMachineImage({ name: 'bla*', owners: ['amazon'] }).getImage(stack); + + // THEN + const missing = app.synth().manifest.missing || []; + expect(missing).toEqual([ + { + key: 'ami:account=1234:filters.image-type.0=machine:filters.name.0=bla*:filters.state.0=available:owners.0=amazon:region=testregion', + props: { + account: '1234', + region: 'testregion', + owners: [ 'amazon' ], + filters: { + 'name': [ 'bla*' ], + 'state': [ 'available' ], + 'image-type': [ 'machine' ], + }, + }, + provider: 'ami', + }, + ]); +}); + +test('LookupMachineImage creates correct type of UserData', () => { + // WHEN + const linuxDetails = new ec2.LookupMachineImage({ name: 'bla*', owners: ['amazon'] }).getImage(stack); + const windowsDetails = new ec2.LookupMachineImage({ name: 'bla*', owners: ['amazon'], windows: true }).getImage(stack); + + // THEN + expect(isWindowsUserData(windowsDetails.userData)).toBeTruthy(); + expect(isLinuxUserData(linuxDetails.userData)).toBeTruthy(); +}); + +function isWindowsUserData(ud: ec2.UserData) { + return ud.render().indexOf('powershell') > -1; +} + +function isLinuxUserData(ud: ec2.UserData) { + return ud.render().indexOf('bash') > -1; +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/test/test.network-utils.ts b/packages/@aws-cdk/aws-ec2/test/network-utils.test.ts similarity index 98% rename from packages/@aws-cdk/aws-ec2/test/test.network-utils.ts rename to packages/@aws-cdk/aws-ec2/test/network-utils.test.ts index 55e3433f9fb5e..b1904331644f2 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.network-utils.ts +++ b/packages/@aws-cdk/aws-ec2/test/network-utils.test.ts @@ -1,4 +1,4 @@ -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; import { CidrBlock, InvalidCidrRangeError, @@ -6,8 +6,7 @@ import { NetworkUtils, } from '../lib/network-util'; -export = { - +nodeunitShim({ IP: { 'should convert a valid IP Address to an integer'(test: Test) { test.strictEqual(NetworkUtils.ipToNum('174.66.173.168'), 2923605416); @@ -16,7 +15,7 @@ export = { 'should throw on invalid IP Address'(test: Test) { test.throws(() => { NetworkUtils.ipToNum('174.266.173.168'); - }, Error, 'is not valid'); + }, 'is not valid'); test.done(); }, 'should convert a valid IP integer to a staring'(test: Test) { @@ -188,4 +187,4 @@ export = { test.strictEqual(18, builder5.maskForRemainingSubnets(3)); test.done(); }, }, -}; +}); diff --git a/packages/@aws-cdk/aws-ec2/test/test.security-group.ts b/packages/@aws-cdk/aws-ec2/test/security-group.test.ts similarity index 99% rename from packages/@aws-cdk/aws-ec2/test/test.security-group.ts rename to packages/@aws-cdk/aws-ec2/test/security-group.test.ts index b2ec76bf28e7b..0fb952ea1b36c 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.security-group.ts +++ b/packages/@aws-cdk/aws-ec2/test/security-group.test.ts @@ -1,9 +1,9 @@ import { expect, haveResource, not } from '@aws-cdk/assert'; import { Intrinsic, Lazy, Stack, Token } from '@aws-cdk/core'; -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; import { Peer, Port, SecurityGroup, Vpc } from '../lib'; -export = { +nodeunitShim({ 'security group can allows all outbound traffic by default'(test: Test) { // GIVEN const stack = new Stack(); @@ -293,4 +293,4 @@ export = { test.done(); }, }, -}; +}); diff --git a/packages/@aws-cdk/aws-ec2/test/test.l1.ts b/packages/@aws-cdk/aws-ec2/test/test.l1.ts deleted file mode 100644 index 8fab621dac5ea..0000000000000 --- a/packages/@aws-cdk/aws-ec2/test/test.l1.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as cdk from '@aws-cdk/core'; -import { Test } from 'nodeunit'; -import * as ec2 from '../lib'; - -export = { - 'NetworkAclEntry CidrBlock should be optional'(test: Test) { - const stack = new cdk.Stack(); - - new ec2.CfnNetworkAclEntry(stack, 'ACL', { - // Note the conspicuous absence of cidrBlock - networkAclId: 'asdf', - protocol: 5, - ruleAction: 'action', - ruleNumber: 1, - }); - - test.done(); - }, -}; diff --git a/packages/@aws-cdk/aws-ec2/test/test.machine-image.ts b/packages/@aws-cdk/aws-ec2/test/test.machine-image.ts deleted file mode 100644 index dce4195a868f8..0000000000000 --- a/packages/@aws-cdk/aws-ec2/test/test.machine-image.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { App, Stack } from '@aws-cdk/core'; -import { Test } from 'nodeunit'; -import * as ec2 from '../lib'; - -let app: App; -let stack: Stack; - -export = { - 'setUp'(cb: () => void) { - app = new App(); - stack = new Stack(app, 'Stack', { - env: { account: '1234', region: 'testregion' }, - }); - - cb(); - }, - 'can make and use a Windows image'(test: Test) { - // WHEN - const image = new ec2.GenericWindowsImage({ - testregion: 'ami-1234', - }); - - // THEN - const details = image.getImage(stack); - test.equals(details.imageId, 'ami-1234'); - test.equals(details.osType, ec2.OperatingSystemType.WINDOWS); - - test.done(); - }, - - 'WindowsImage retains userdata if given'(test: Test) { - // WHEN - const ud = ec2.UserData.forWindows(); - - const image = new ec2.GenericWindowsImage({ - testregion: 'ami-1234', - }, { - userData: ud, - }); - - // THEN - const details = image.getImage(stack); - test.equals(details.userData, ud); - - test.done(); - }, - - 'WindowsImage creates UserData if not given'(test: Test) { - // WHEN - const image = new ec2.GenericWindowsImage({ - testregion: 'ami-1234', - }); - - // THEN - const details = image.getImage(stack); - test.ok(isWindowsUserData(details.userData)); - - test.done(); - }, - - 'LookupMachineImage default search'(test: Test) { - // GIVEN - - // WHEN - new ec2.LookupMachineImage({ name: 'bla*', owners: ['amazon'] }).getImage(stack); - - // THEN - const missing = app.synth().manifest.missing || []; - test.deepEqual(missing, [ - { - key: 'ami:account=1234:filters.image-type.0=machine:filters.name.0=bla*:filters.state.0=available:owners.0=amazon:region=testregion', - props: { - account: '1234', - region: 'testregion', - owners: [ 'amazon' ], - filters: { - 'name': [ 'bla*' ], - 'state': [ 'available' ], - 'image-type': [ 'machine' ], - }, - }, - provider: 'ami', - }, - ]); - - test.done(); - }, - - 'LookupMachineImage creates correct type of UserData'(test: Test) { - // WHEN - const linuxDetails = new ec2.LookupMachineImage({ name: 'bla*', owners: ['amazon'] }).getImage(stack); - const windowsDetails = new ec2.LookupMachineImage({ name: 'bla*', owners: ['amazon'], windows: true }).getImage(stack); - - // THEN - test.ok(isWindowsUserData(windowsDetails.userData)); - test.ok(isLinuxUserData(linuxDetails.userData)); - test.done(); - }, -}; - -function isWindowsUserData(ud: ec2.UserData) { - return ud.render().indexOf('powershell') > -1; -} - -function isLinuxUserData(ud: ec2.UserData) { - return ud.render().indexOf('bash') > -1; -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/test/test.userdata.ts b/packages/@aws-cdk/aws-ec2/test/userdata.test.ts similarity index 99% rename from packages/@aws-cdk/aws-ec2/test/test.userdata.ts rename to packages/@aws-cdk/aws-ec2/test/userdata.test.ts index d487eb9bb54ed..4f4a357d55e37 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.userdata.ts +++ b/packages/@aws-cdk/aws-ec2/test/userdata.test.ts @@ -1,9 +1,9 @@ import { Bucket } from '@aws-cdk/aws-s3'; -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; import { Stack } from '../../core/lib'; import * as ec2 from '../lib'; -export = { +nodeunitShim({ 'can create Windows user data'(test: Test) { // GIVEN @@ -273,4 +273,4 @@ export = { test.done(); }, -}; +}); diff --git a/packages/@aws-cdk/aws-ec2/test/test.volume.ts b/packages/@aws-cdk/aws-ec2/test/volume.test.ts similarity index 95% rename from packages/@aws-cdk/aws-ec2/test/test.volume.ts rename to packages/@aws-cdk/aws-ec2/test/volume.test.ts index dbef8b6ecfebe..dbe368285fb40 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.volume.ts +++ b/packages/@aws-cdk/aws-ec2/test/volume.test.ts @@ -10,7 +10,7 @@ import { } from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; import * as cdk from '@aws-cdk/core'; -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; import { AmazonLinuxGeneration, EbsDeviceVolumeType, @@ -21,7 +21,7 @@ import { Vpc, } from '../lib'; -export = { +nodeunitShim({ 'basic volume'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -1182,13 +1182,13 @@ export = { volumeId: ' vol-0123456789abcdefABCDEF', // leading invalid character(s) availabilityZone: 'us-east-1a', }); - }, Error, '`volumeId` does not match expected pattern. Expected `vol-` (ex: `vol-05abe246af`) or a Token'); + }, '`volumeId` does not match expected pattern. Expected `vol-` (ex: `vol-05abe246af`) or a Token'); test.throws(() => { Volume.fromVolumeAttributes(stack, `Volume${idx++}`, { volumeId: 'vol-0123456789abcdefABCDEF ', // trailing invalid character(s) availabilityZone: 'us-east-1a', }); - }, Error, '`volumeId` does not match expected pattern. Expected `vol-` (ex: `vol-05abe246af`) or a Token'); + }, '`volumeId` does not match expected pattern. Expected `vol-` (ex: `vol-05abe246af`) or a Token'); test.done(); }, @@ -1203,7 +1203,7 @@ export = { new Volume(stack, `Volume${idx++}`, { availabilityZone: 'us-east-1a', }); - }, Error, 'Must provide at least one of `size` or `snapshotId`'); + }, 'Must provide at least one of `size` or `snapshotId`'); test.doesNotThrow(() => { new Volume(stack, `Volume${idx++}`, { availabilityZone: 'us-east-1a', @@ -1230,7 +1230,7 @@ export = { size: cdk.Size.gibibytes(8), encryptionKey: key, }); - }, Error, '`encrypted` must be true when providing an `encryptionKey`.'); + }, '`encrypted` must be true when providing an `encryptionKey`.'); test.throws(() => { new Volume(stack, `Volume${idx++}`, { availabilityZone: 'us-east-1a', @@ -1238,7 +1238,7 @@ export = { encrypted: false, encryptionKey: key, }); - }, Error, '`encrypted` must be true when providing an `encryptionKey`.'); + }, '`encrypted` must be true when providing an `encryptionKey`.'); test.doesNotThrow(() => { new Volume(stack, `Volume${idx++}`, { availabilityZone: 'us-east-1a', @@ -1272,22 +1272,22 @@ export = { new Volume(stack, `Volume${idx++}`, { availabilityZone: 'us-east-1', }); - }, Error, '`availabilityZone` is a region followed by a letter (ex: `us-east-1a`), or a token'); + }, '`availabilityZone` is a region followed by a letter (ex: `us-east-1a`), or a token'); test.throws(() => { new Volume(stack, `Volume${idx++}`, { availabilityZone: 'Virginia', }); - }, Error, '`availabilityZone` is a region followed by a letter (ex: `us-east-1a`), or a token'); + }, '`availabilityZone` is a region followed by a letter (ex: `us-east-1a`), or a token'); test.throws(() => { new Volume(stack, `Volume${idx++}`, { availabilityZone: ' us-east-1a', // leading character(s) }); - }, Error, '`availabilityZone` is a region followed by a letter (ex: `us-east-1a`), or a token'); + }, '`availabilityZone` is a region followed by a letter (ex: `us-east-1a`), or a token'); test.throws(() => { new Volume(stack, `Volume${idx++}`, { availabilityZone: 'us-east-1a ', // trailing character(s) }); - }, Error, '`availabilityZone` is a region followed by a letter (ex: `us-east-1a`), or a token'); + }, '`availabilityZone` is a region followed by a letter (ex: `us-east-1a`), or a token'); test.done(); }, @@ -1320,13 +1320,13 @@ export = { availabilityZone: 'us-east-1a', snapshotId: ' snap-1234', // leading extra character(s) }); - }, Error, '`snapshotId` does match expected pattern. Expected `snap-` (ex: `snap-05abe246af`) or Token'); + }, '`snapshotId` does match expected pattern. Expected `snap-` (ex: `snap-05abe246af`) or Token'); test.throws(() => { new Volume(stack, `Volume${idx++}`, { availabilityZone: 'us-east-1a', snapshotId: 'snap-1234 ', // trailing extra character(s) }); - }, Error, '`snapshotId` does match expected pattern. Expected `snap-` (ex: `snap-05abe246af`) or Token'); + }, '`snapshotId` does match expected pattern. Expected `snap-` (ex: `snap-05abe246af`) or Token'); test.done(); }, @@ -1351,7 +1351,7 @@ export = { iops: 100, volumeType, }); - }, Error, '`iops` may only be specified if the `volumeType` is `PROVISIONED_IOPS_SSD`/`IO1`'); + }, '`iops` may only be specified if the `volumeType` is `PROVISIONED_IOPS_SSD`/`IO1`'); } // Test: iops in range @@ -1362,7 +1362,7 @@ export = { iops: 99, volumeType: EbsDeviceVolumeType.PROVISIONED_IOPS_SSD, }); - }, Error, '`iops` must be in the range 100 to 64,000, inclusive.'); + }, '`iops` must be in the range 100 to 64,000, inclusive.'); test.doesNotThrow(() => { new Volume(stack, `Volume${idx++}`, { availabilityZone: 'us-east-1a', @@ -1386,7 +1386,7 @@ export = { iops: 64001, volumeType: EbsDeviceVolumeType.PROVISIONED_IOPS_SSD, }); - }, Error, '`iops` must be in the range 100 to 64,000, inclusive.'); + }, '`iops` must be in the range 100 to 64,000, inclusive.'); // Test: iops ratio test.doesNotThrow(() => { @@ -1404,7 +1404,7 @@ export = { iops: 501, volumeType: EbsDeviceVolumeType.PROVISIONED_IOPS_SSD, }); - }, Error, '`iops` has a maximum ratio of 50 IOPS/GiB.'); + }, '`iops` has a maximum ratio of 50 IOPS/GiB.'); test.done(); }, @@ -1425,11 +1425,10 @@ export = { new Volume(stack, `Volume${idx++}`, { availabilityZone: 'us-east-1a', size: cdk.Size.gibibytes(500), - iops: 100, enableMultiAttach: true, volumeType, }); - }, Error, 'multi-attach is supported exclusively on `PROVISIONED_IOPS_SSD` volumes.'); + }, 'multi-attach is supported exclusively on `PROVISIONED_IOPS_SSD` volumes.'); } test.done(); @@ -1457,7 +1456,7 @@ export = { size: cdk.Size.gibibytes(min - 1), volumeType, }); - }, Error, `\`${volumeType}\` volumes must be between ${min} GiB and ${max} GiB in size.`); + }, `\`${volumeType}\` volumes must be between ${min} GiB and ${max} GiB in size.`); test.doesNotThrow(() => { new Volume(stack, `Volume${idx++}`, { availabilityZone: 'us-east-1a', @@ -1478,10 +1477,10 @@ export = { size: cdk.Size.gibibytes(max + 1), volumeType, }); - }, Error, `\`${volumeType}\` volumes must be between ${min} GiB and ${max} GiB in size.`); + }, `\`${volumeType}\` volumes must be between ${min} GiB and ${max} GiB in size.`); } test.done(); }, -}; \ No newline at end of file +}); diff --git a/packages/@aws-cdk/aws-ec2/test/test.vpc-endpoint-service.ts b/packages/@aws-cdk/aws-ec2/test/vpc-endpoint-service.test.ts similarity index 98% rename from packages/@aws-cdk/aws-ec2/test/test.vpc-endpoint-service.ts rename to packages/@aws-cdk/aws-ec2/test/vpc-endpoint-service.test.ts index 7d4439bf0bfc2..f7840f14829a2 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.vpc-endpoint-service.ts +++ b/packages/@aws-cdk/aws-ec2/test/vpc-endpoint-service.test.ts @@ -1,7 +1,7 @@ import { expect, haveResource } from '@aws-cdk/assert'; import { ArnPrincipal } from '@aws-cdk/aws-iam'; import { Stack } from '@aws-cdk/core'; -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; // tslint:disable-next-line:max-line-length import { IVpcEndpointServiceLoadBalancer, Vpc, VpcEndpointService } from '../lib'; @@ -19,7 +19,7 @@ class DummyEndpointLoadBalacer implements IVpcEndpointServiceLoadBalancer { } } -export = { +nodeunitShim({ 'test vpc endpoint service': { 'create endpoint service with no principals'(test: Test) { // GIVEN @@ -104,4 +104,4 @@ export = { test.done(); }, }, -}; \ No newline at end of file +}); diff --git a/packages/@aws-cdk/aws-ec2/test/test.vpc-endpoint.ts b/packages/@aws-cdk/aws-ec2/test/vpc-endpoint.test.ts similarity index 99% rename from packages/@aws-cdk/aws-ec2/test/test.vpc-endpoint.ts rename to packages/@aws-cdk/aws-ec2/test/vpc-endpoint.test.ts index 159447c322749..30c6018c961ac 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.vpc-endpoint.ts +++ b/packages/@aws-cdk/aws-ec2/test/vpc-endpoint.test.ts @@ -2,11 +2,11 @@ import { expect, haveResource, haveResourceLike } from '@aws-cdk/assert'; import { AnyPrincipal, PolicyStatement } from '@aws-cdk/aws-iam'; import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { ContextProvider, Stack } from '@aws-cdk/core'; -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; // tslint:disable-next-line:max-line-length import { GatewayVpcEndpoint, GatewayVpcEndpointAwsService, InterfaceVpcEndpoint, InterfaceVpcEndpointAwsService, InterfaceVpcEndpointService, SecurityGroup, SubnetType, Vpc } from '../lib'; -export = { +nodeunitShim({ 'gateway endpoint': { 'add an endpoint to a vpc'(test: Test) { // GIVEN @@ -473,4 +473,4 @@ export = { test.done(); }, }, -}; +}); diff --git a/packages/@aws-cdk/aws-ec2/test/test.vpc-flow-logs.ts b/packages/@aws-cdk/aws-ec2/test/vpc-flow-logs.test.ts similarity index 98% rename from packages/@aws-cdk/aws-ec2/test/test.vpc-flow-logs.ts rename to packages/@aws-cdk/aws-ec2/test/vpc-flow-logs.test.ts index 65414e376739d..965c538bab5a0 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.vpc-flow-logs.ts +++ b/packages/@aws-cdk/aws-ec2/test/vpc-flow-logs.test.ts @@ -3,10 +3,10 @@ import * as iam from '@aws-cdk/aws-iam'; import * as logs from '@aws-cdk/aws-logs'; import * as s3 from '@aws-cdk/aws-s3'; import { Stack } from '@aws-cdk/core'; -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; import { FlowLog, FlowLogDestination, FlowLogResourceType, Vpc } from '../lib'; -export = { +nodeunitShim({ 'with defaults set, it successfully creates with cloudwatch logs destination'( test: Test, ) { @@ -155,7 +155,7 @@ export = { ); test.done(); }, -}; +}); function getTestStack(): Stack { return new Stack(undefined, 'TestStack', { diff --git a/packages/@aws-cdk/aws-ec2/test/test.vpc.from-lookup.ts b/packages/@aws-cdk/aws-ec2/test/vpc.from-lookup.test.ts similarity index 99% rename from packages/@aws-cdk/aws-ec2/test/test.vpc.from-lookup.ts rename to packages/@aws-cdk/aws-ec2/test/vpc.from-lookup.test.ts index 2cf0fac4a9e33..170f62f6f61a5 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.vpc.from-lookup.ts +++ b/packages/@aws-cdk/aws-ec2/test/vpc.from-lookup.test.ts @@ -1,10 +1,10 @@ import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { Construct, ContextProvider, GetContextValueOptions, GetContextValueResult, Lazy, Stack } from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; import { GenericLinuxImage, Instance, InstanceType, SubnetType, Vpc } from '../lib'; -export = { +nodeunitShim({ 'Vpc.fromLookup()': { 'requires concrete values'(test: Test) { // GIVEN @@ -210,7 +210,7 @@ export = { test.done(); }, }, -}; +}); interface MockVcpContextResponse { readonly vpcId: string; diff --git a/packages/@aws-cdk/aws-ec2/test/test.vpc.ts b/packages/@aws-cdk/aws-ec2/test/vpc.test.ts similarity index 99% rename from packages/@aws-cdk/aws-ec2/test/test.vpc.ts rename to packages/@aws-cdk/aws-ec2/test/vpc.test.ts index fedf67b95c738..13d6d62c8c6a5 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.vpc.ts +++ b/packages/@aws-cdk/aws-ec2/test/vpc.test.ts @@ -1,11 +1,11 @@ import { countResources, expect, haveResource, haveResourceLike, isSuperObject, MatchStyle } from '@aws-cdk/assert'; import { CfnOutput, Lazy, Stack, Tag } from '@aws-cdk/core'; -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; import { AclCidr, AclTraffic, CfnSubnet, CfnVPC, DefaultInstanceTenancy, GenericLinuxImage, InstanceType, InterfaceVpcEndpoint, InterfaceVpcEndpointService, NatProvider, NetworkAcl, NetworkAclEntry, Peer, Port, PrivateSubnet, PublicSubnet, RouterType, Subnet, SubnetType, TrafficDirection, Vpc } from '../lib'; -export = { +nodeunitShim({ 'When creating a VPC': { 'with the default CIDR range': { @@ -1244,7 +1244,7 @@ export = { }, }, -}; +}); function getTestStack(): Stack { return new Stack(undefined, 'TestStack', { env: { account: '123456789012', region: 'us-east-1' } }); diff --git a/packages/@aws-cdk/aws-ec2/test/test.vpn.ts b/packages/@aws-cdk/aws-ec2/test/vpn.test.ts similarity index 99% rename from packages/@aws-cdk/aws-ec2/test/test.vpn.ts rename to packages/@aws-cdk/aws-ec2/test/vpn.test.ts index 2e5989cc1f590..69863f933a76d 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.vpn.ts +++ b/packages/@aws-cdk/aws-ec2/test/vpn.test.ts @@ -1,9 +1,9 @@ import { expect, haveResource } from '@aws-cdk/assert'; import { Duration, Stack } from '@aws-cdk/core'; -import { Test } from 'nodeunit'; +import { nodeunitShim, Test } from 'nodeunit-shim'; import { PublicSubnet, Vpc, VpnConnection } from '../lib'; -export = { +nodeunitShim({ 'can add a vpn connection to a vpc with a vpn gateway'(test: Test) { // GIVEN const stack = new Stack(); @@ -322,4 +322,4 @@ export = { })); test.done(); }, -}; +}); diff --git a/tools/nodeunit-shim/.gitignore b/tools/nodeunit-shim/.gitignore new file mode 100644 index 0000000000000..2d8e8a2d36377 --- /dev/null +++ b/tools/nodeunit-shim/.gitignore @@ -0,0 +1,13 @@ +*.js +*.js.map +*.d.ts +dist + +.LAST_BUILD +*.snk +!jest.config.js + +.nyc_output +coverage +nyc.config.js +!.eslintrc.js \ No newline at end of file diff --git a/tools/nodeunit-shim/README.md b/tools/nodeunit-shim/README.md new file mode 100644 index 0000000000000..163e24b3b1eb7 --- /dev/null +++ b/tools/nodeunit-shim/README.md @@ -0,0 +1,80 @@ +nodeunit-shim +============== + +Tiny helper library to move from nodeunit tests to Jest. + +Why? +---- + +Jest tests have a better runner, better error reporting, better matchers, +and nicer syntax. They're just all around nicer. Plus, nodeunit has long +since been deprecated. + +Rewriting our existing codebase of nodeunit tests is kind of a hassle though. +Therefore, a tiny adapter layer between the 2 APIs. + +How to use +---------- + +### Update package.json + +```json +"devDependencies": { + // Remove these: + "@types/nodeunit": "...", + "nodeunit": "...", + + // Add this + "nodeunit-shim": "0.0.0", +}, +"cdk-build": { + // Add this + "jest": true +} +``` + +### Get jest.config.js + +Copy a `jest.config.js` from another package. + +### Update .gitignore/.npmignore + +Run `yarn pkglint --fix`. + +### Rename tests + +Rename all test files `test.*.ts` -> `*.test.ts` (be sure to rename +the `.js` as well, or remove them). + +### Rewrite tests + +Inside every test file: + +Replace + +```ts +import { Test } from 'nodeunit'; +``` + +with + +```ts +import { nodeunitShim, Test } from 'nodeunit-shim'; +``` + +and replace: + +```ts +export = { + // ... +}; +``` + +with: + +```ts +nodeunitShim({ + // ... +}); +``` + diff --git a/tools/nodeunit-shim/index.ts b/tools/nodeunit-shim/index.ts new file mode 100644 index 0000000000000..840c7390ce7ae --- /dev/null +++ b/tools/nodeunit-shim/index.ts @@ -0,0 +1,79 @@ +/** + * Jest/Nodeunit compatibility shim + * + * Use this to mass-convert Nodeunit tests to Jest tests. + */ + +/** + * Compatibility shim test + */ +export class Test { + constructor(private readonly cb: () => void) { + } + + public equal(a: any, b: any, _message?: string) { + expect(a).toEqual(b); + } + + public equals(a: any, b: any, _message?: string) { + expect(a).toEqual(b); + } + + public strictEqual(a: any, b: any, _message?: string) { + expect(a).toEqual(b); + } + + public deepEqual(a: any, b: any) { + expect(a).toEqual(b); + } + + public ok(a: any) { + expect(a).toBeTruthy(); + } + + public throws(block: () => any, error?: string | RegExp | ErrorConstructor) { + expect(block).toThrow(error); + } + + public doesNotThrow(block: () => any, error?: string | RegExp | ErrorConstructor) { + expect(block).not.toThrow(error); + } + + public done() { + this.cb(); + } +} + +export function nodeunitShim(exports: Record) { + if (exports.setUp) { + beforeEach(() => { + return new Promise(ok => { + exports.setUp(ok); + }); + }); + } + if (exports.tearDown) { + afterEach(() => { + return new Promise(ok => { + exports.tearDown(ok); + }); + }); + } + for (const [testName, testObj] of Object.entries(exports)) { + if (testName === 'setUp' || testName === 'tearDown') { continue; } + + if (typeof testObj === 'object') { + // It's a suite + describe(testName, () => { + nodeunitShim(testObj); + }); + } else { + // It's a test + test(testName, () => new Promise(ok => { + testObj(new Test(ok)); + })); + } + } +} + +type ErrorConstructor = new (...args: any[]) => Error; diff --git a/tools/nodeunit-shim/package.json b/tools/nodeunit-shim/package.json new file mode 100644 index 0000000000000..5037cce6b7c15 --- /dev/null +++ b/tools/nodeunit-shim/package.json @@ -0,0 +1,25 @@ +{ + "name": "nodeunit-shim", + "private": true, + "version": "0.0.0", + "description": "A helper package to migrate tests from nodeunit to Jest", + "main": "index.js", + "scripts": { + "build": "tsc", + "watch": "tsc -w", + "test": "echo No tests", + "build+test+package": "npm run build+test", + "build+test": "npm run build && npm test" + }, + "devDependencies": { + "@types/node": "^10.17.26", + "typescript": "~3.9.5", + "@types/jest": "^26.0.3" + }, + "dependencies": { + "jest": "^25.5.4" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/tools/nodeunit-shim/tsconfig.json b/tools/nodeunit-shim/tsconfig.json new file mode 100644 index 0000000000000..14499cd2abfaf --- /dev/null +++ b/tools/nodeunit-shim/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2018", + "module": "commonjs", + "lib": ["es2018"], + "strict": true, + "alwaysStrict": true, + "declaration": true, + "inlineSourceMap": true, + "inlineSources": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "resolveJsonModule": true, + "composite": true, + "incremental": true + }, + "include": ["**/*.ts"] +}