Skip to content

Commit

Permalink
Merge pull request #6 from amplication/fix/e2e-tests-compose-approach
Browse files Browse the repository at this point in the history
Fix/e2e-tests-compose-approach
  • Loading branch information
abrl91 authored Apr 5, 2024
2 parents 64ed416 + 083faf8 commit 839fc90
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 51 deletions.
7 changes: 2 additions & 5 deletions .github/workflows/dsg-e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,8 @@ jobs:
exit 1
fi
- name: Run generated code
run: |
cd test-cases/${{ matrix.test-cases }}/generated/server
docker-compose up -d
- name: Run e2e tests
run: npm run e2e:test
env:
TEST_CASE: ${{ matrix.test-cases }}

1 change: 1 addition & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Config } from "jest";
const config: Config = {
preset: "ts-jest",
testEnvironment: "node",
testTimeout: 10000000,
};

export default config;
32 changes: 32 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
"@types/jest": "^29.5.12",
"@types/lodash": "^4.17.0",
"@types/uuid": "^9.0.8",
"docker-compose": "^0.24.7",
"get-port-please": "^3.1.2",
"jest": "^29.7.0",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
Expand Down
152 changes: 106 additions & 46 deletions tests/data-service-generator.e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import * as os from "os";
import * as fs from "fs";
import * as path from "path";
import {
ApolloClient,
Expand All @@ -12,19 +10,15 @@ import { onError } from "@apollo/client/link/error";
import fetch from "cross-fetch";
import { omit } from "lodash";
import env from "../test-data/env";
import { v4 } from "uuid";

const SERVER_START_TIMEOUT = 30000;
import { v2 as compose } from "docker-compose";
import { getRandomPort } from "get-port-please";

const JSON_MIME = "application/json";
const STATUS_OK = 200;
const STATUS_NO_CONTENT = 204;
const STATUS_CREATED = 201;
const NOT_FOUND = 404;

const {
APP_HOST,
APP_PORT,
APP_USERNAME,
APP_PASSWORD,
APP_DEFAULT_USER_ROLES,
Expand All @@ -42,23 +36,82 @@ const EXAMPLE_ORGANIZATION = {
name: "Amplication",
};

const testCaseName = process.env.TEST_CASE || "postgres-basic";
const verbose = process.env.VERBOSE ? true : false;
const SERVER_START_TIMEOUT = 30000;

function sleep(time: number) {
return new Promise((resolve) => setTimeout(resolve, time));
}

describe("Data Service Generator", () => {
const host = `${APP_HOST}:${APP_PORT}`;
let host: string;
let customer: { id: number };
let apolloClient: ApolloClient<any>;

describe("DSG E2E tests", () => {
const testId = v4();

beforeAll(async () => {
const directory = path.join(os.tmpdir(), "test-data-service", testId);
// Clean the temporary directory
try {
await fs.promises.rm(directory, { recursive: true });
} catch {
/* empty */
}
await fs.promises.mkdir(directory, { recursive: true });
console.info("Setting up test environment...");
const dockerComposeDir = path.resolve(
__dirname,
`../test-cases/${testCaseName}/generated/server`
);
const dotEnvPath = path.join(dockerComposeDir, ".env");
const port = await getRandomPort();
const dbPort = await getRandomPort();
host = `localhost:${port}`;

const dockerComposeOptions: compose.IDockerComposeOptions = {
cwd: dockerComposeDir,
log: verbose,
composeOptions: [
`--project-name=${testCaseName}`,
`--env-file=${dotEnvPath}`,
],
env: {
...process.env,
PORT: String(port),
DB_PORT: String(dbPort),
},
};

console.info("Running docker-compose up");
await compose.downAll(dockerComposeOptions);
await compose.upAll({
...dockerComposeOptions,
commandOptions: ["--build", "--force-recreate"],
});

compose
.logs([], {
...dockerComposeOptions,
follow: true,
})
.catch(console.error);

console.info("Waiting for db migration to be completed...");
let migrationCompleted = false;
let startTime = Date.now();

do {
console.info("...");
const containers = await compose.ps({
...dockerComposeOptions,
commandOptions: ["--all"],
});
const migrateContainer = containers.data.services.find((s) =>
s.name.endsWith("migrate-1")
);
if (migrateContainer?.state.indexOf("Exited (0)") !== -1) {
migrationCompleted = true;
console.info("migration completed!");
break;
}
await sleep(2000);
} while (
!migrationCompleted ||
startTime + SERVER_START_TIMEOUT < Date.now()
);

const authLink = setContext((_, { headers }) => ({
headers: {
Expand Down Expand Up @@ -90,28 +143,18 @@ describe("Data Service Generator", () => {
link: authLink.concat(errorLink).concat(httpLink),
cache: new InMemoryCache(),
});
});

console.log("Waiting for server to be ready...");
let servicesNotReady = true;
let startTime = Date.now();
do {
console.log("...");
try {
const res = await fetch(`http://${host}/api/_health/live`, {
method: "GET",
});
if (res.status === STATUS_NO_CONTENT) {
servicesNotReady = false;
console.log("server ready!");
break;
}
} catch (error) {
/**/
}
} while (
servicesNotReady ||
startTime + SERVER_START_TIMEOUT < Date.now()
);
afterAll(async () => {
console.info("Tearing down test environment...");
const dockerComposeDir = path.resolve(__dirname, "../..");
const dockerComposeOptions: compose.IDockerComposeOptions = {
cwd: dockerComposeDir,
composeOptions: [`--project-name=${testCaseName}`],
commandOptions: ["-v"],
};

await compose.downAll(dockerComposeOptions);
});

it("check /api/health/live endpoint", async () => {
Expand Down Expand Up @@ -272,7 +315,10 @@ describe("Data Service Generator", () => {
"Content-Type": JSON_MIME,
Authorization: APP_BASIC_AUTHORIZATION,
},
body: JSON.stringify(EXAMPLE_CUSTOMER),
body: JSON.stringify({
...EXAMPLE_CUSTOMER,
email: "[email protected]",
}),
});

const newCustomer = await newCustomerRes.json();
Expand All @@ -291,6 +337,7 @@ describe("Data Service Generator", () => {
expect.objectContaining({
...EXAMPLE_CUSTOMER,
id: expect.any(String),
email: "[email protected]",
createdAt: expect.any(String),
updatedAt: expect.any(String),
})
Expand Down Expand Up @@ -343,15 +390,18 @@ describe("Data Service Generator", () => {
}
`,
variables: {
data: EXAMPLE_CUSTOMER,
data: {
...EXAMPLE_CUSTOMER,
email: `[email protected]`,
},
},
});
expect(resp).toEqual(
expect.objectContaining({
data: {
createCustomer: expect.objectContaining({
id: expect.any(String),
email: EXAMPLE_CUSTOMER.email,
email: "[email protected]",
}),
},
})
Expand All @@ -373,7 +423,10 @@ describe("Data Service Generator", () => {
"Content-Type": JSON_MIME,
Authorization: APP_BASIC_AUTHORIZATION,
},
body: JSON.stringify(EXAMPLE_CUSTOMER),
body: JSON.stringify({
...EXAMPLE_CUSTOMER,
email: "[email protected]",
}),
})
).json();

Expand Down Expand Up @@ -416,7 +469,10 @@ describe("Data Service Generator", () => {
"Content-Type": JSON_MIME,
Authorization: APP_BASIC_AUTHORIZATION,
},
body: JSON.stringify(EXAMPLE_CUSTOMER),
body: JSON.stringify({
...EXAMPLE_CUSTOMER,
email: "[email protected]",
}),
})
).json();
const organization = await (
Expand Down Expand Up @@ -474,7 +530,10 @@ describe("Data Service Generator", () => {
"Content-Type": JSON_MIME,
Authorization: APP_BASIC_AUTHORIZATION,
},
body: JSON.stringify(EXAMPLE_CUSTOMER),
body: JSON.stringify({
...EXAMPLE_CUSTOMER,
email: "[email protected]",
}),
})
).json();
const organization = await (
Expand Down Expand Up @@ -521,6 +580,7 @@ describe("Data Service Generator", () => {
expect.objectContaining({
...EXAMPLE_CUSTOMER,
id: customer.id,
email: "[email protected]",
createdAt: expect.any(String),
updatedAt: expect.any(String),
organization: {
Expand Down

0 comments on commit 839fc90

Please sign in to comment.