Skip to content

Commit

Permalink
test: refactor e2e test (#640)
Browse files Browse the repository at this point in the history
Co-authored-by: hung-nguyen <[email protected]>
  • Loading branch information
tuanphamcybozu and hung-cybo authored Jan 8, 2024
1 parent ecd8b9a commit ce32dd5
Show file tree
Hide file tree
Showing 11 changed files with 327 additions and 111 deletions.
6 changes: 3 additions & 3 deletions features/common.feature
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ Feature: common test cases
And The output error message should match with the pattern: "Unknown argument: foo"

Scenario: CliKintoneTest-2 Should return the error message when specifying unknown subcommand
When I run the command with args "export"
When I run the command with args "foo"
Then I should get the exit code is non-zero
And The output error message should match with the pattern: "Unknown argument: export"
And The output error message should match with the pattern: "Unknown argument: foo"

Scenario: CliKintoneTest-3 Should return the correct cli-kintone version when using `cli-kintone --version`
Scenario: CliKintoneTest-3 Should return the cli-kintone version in correct format when using `cli-kintone --version`
When I run the command with args "--version"
Then I should get the version formatted in "\d+.\d+.\d+"

Expand Down
2 changes: 1 addition & 1 deletion features/delete.feature
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@isolated
Feature: cli-kintone delete command

Scenario: CliKintoneTest-126 Should return the error message when the user has no privilege to delete records.
Scenario: CliKintoneTest-126 Should return the error message with an API Token without Delete permission.
Given The app "app_for_delete" has no records
And The app "app_for_delete" has some records as below:
| Text | Number |
Expand Down
68 changes: 34 additions & 34 deletions features/export.feature
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ Feature: cli-kintone export command
| \d+ | Bob | 20 |
| \d+ | Jenny | 30 |

Scenario: CliKintoneTest-90 Should return the record contents and download attachments successfully with an existing directory.
Scenario: CliKintoneTest-90 Should return the record contents and download attachments successfully to an existing directory.
Given The app "app_for_export_attachments" has no records
And I have a file "attachments/file1.txt" with content: "123"
And The app "app_for_export_attachments" has some records with attachments in directory "attachments" as below:
Expand All @@ -173,11 +173,11 @@ Feature: cli-kintone export command
And The output message should match with the data below:
| Record_number | Text | Attachment |
| $RECORD_NUMBERS[0] | Alice | Attachment-$RECORD_NUMBERS[0][\/\\\\]file1.txt |
And The directory "exported-attachments" should contain files as below:
And The directory "exported-attachments" should contain files with filename and content as below:
| FilePath | FileName | Content |
| Attachment-$RECORD_NUMBERS[0] | file1.txt | 123 |

Scenario: CliKintoneTest-91 Should return the record contents and download attachments successfully with a non-existent directory.
Scenario: CliKintoneTest-91 Should return the record contents and download attachments successfully to a non-existent directory.
Given The app "app_for_export_attachments" has no records
And I have a file "attachments/file1.txt" with content: "123"
And The app "app_for_export_attachments" has some records with attachments in directory "attachments" as below:
Expand All @@ -191,51 +191,51 @@ Feature: cli-kintone export command
And The output message should match with the data below:
| Record_number | Text | Attachment |
| $RECORD_NUMBERS[0] | Alice | Attachment-$RECORD_NUMBERS[0][\/\\\\]file1.txt |
And The directory "new-directory" should contain files as below:
And The directory "new-directory" should contain files with filename and content as below:
| FilePath | FileName | Content |
| Attachment-$RECORD_NUMBERS[0] | file1.txt | 123 |

Scenario: CliKintoneTest-92 Should return the record contents and download attachments successfully with attachments in different records.
Given The app "app_for_export_attachments" has no records
And I have a file "attachments/file1.txt" with content: "123"
And I have a file "attachments/file2.txt" with content: "abc"
And I have a file in "attachments/file1.txt"
And I have a file in "attachments/image1.png"
And The app "app_for_export_attachments" has some records with attachments in directory "attachments" as below:
| Text | Attachment |
| Alice | file1.txt |
| Bob | file2.txt |
| Bob | image1.png |
And Load the record numbers of the app "app_for_export_attachments" as variable: "RECORD_NUMBERS"
And Load app ID of the app "app_for_export_attachments" as env var: "APP_ID"
And Load app token of the app "app_for_export_attachments" with exact permissions "view" as env var: "API_TOKEN"
When I run the command with args "record export --base-url $$TEST_KINTONE_BASE_URL --app $APP_ID --api-token $API_TOKEN --attachments-dir exported-attachments"
Then I should get the exit code is zero
And The output message should match with the data below:
| Record_number | Text | Attachment |
| $RECORD_NUMBERS[0] | Alice | Attachment-$RECORD_NUMBERS[0][\/\\\\]file1.txt |
| $RECORD_NUMBERS[1] | Bob | Attachment-$RECORD_NUMBERS[1][\/\\\\]file2.txt |
And The directory "exported-attachments" should contain files as below:
| FilePath | FileName | Content |
| Attachment-$RECORD_NUMBERS[0] | file1.txt | 123 |
| Attachment-$RECORD_NUMBERS[1] | file2.txt | abc |
| Record_number | Text | Attachment |
| $RECORD_NUMBERS[0] | Alice | Attachment-$RECORD_NUMBERS[0][\/\\\\]file1.txt |
| $RECORD_NUMBERS[1] | Bob | Attachment-$RECORD_NUMBERS[1][\/\\\\]image1.png |
And The exported files should match as below:
| Expected_FilePath | Actual_FilePath |
| attachments/file1.txt | exported-attachments/Attachment-$RECORD_NUMBERS[0]/file1.txt |
| attachments/image1.png | exported-attachments/Attachment-$RECORD_NUMBERS[1]/image1.png |

Scenario: CliKintoneTest-93 Should return the record contents and download attachments successfully with attachments in a record.
Given The app "app_for_export_attachments" has no records
And I have a file "attachments/file1.txt" with content: "123"
And I have a file "attachments/file2.txt" with content: "abc"
And I have a file in "attachments/file1.txt"
And I have a file in "attachments/Image1.png"
And The app "app_for_export_attachments" has some records with attachments in directory "attachments" as below:
| Text | Attachment |
| Alice | file1.txt\nfile2.txt |
| Text | Attachment |
| Alice | file1.txt\nImage1.png |
And Load the record numbers of the app "app_for_export_attachments" as variable: "RECORD_NUMBERS"
And Load app ID of the app "app_for_export_attachments" as env var: "APP_ID"
And Load app token of the app "app_for_export_attachments" with exact permissions "view" as env var: "API_TOKEN"
When I run the command with args "record export --base-url $$TEST_KINTONE_BASE_URL --app $APP_ID --api-token $API_TOKEN --attachments-dir exported-attachments"
Then I should get the exit code is zero
And The output message should match with the data below:
| Record_number | Text | Attachment |
| $RECORD_NUMBERS[0] | Alice | Attachment-$RECORD_NUMBERS[0][\/\\\\]file1.txt\nAttachment-$RECORD_NUMBERS[0][\/\\\\]file2.txt |
And The directory "exported-attachments" should contain files as below:
| FilePath | FileName | Content |
| Attachment-$RECORD_NUMBERS[0] | file1.txt | 123 |
| Attachment-$RECORD_NUMBERS[0] | file2.txt | abc |
| Record_number | Text | Attachment |
| $RECORD_NUMBERS[0] | Alice | Attachment-$RECORD_NUMBERS[0][\/\\\\]file1.txt\nAttachment-$RECORD_NUMBERS[0][\/\\\\]Image1.png |
And The exported files should match as below:
| Expected_FilePath | Actual_FilePath |
| attachments/file1.txt | exported-attachments/Attachment-$RECORD_NUMBERS[0]/file1.txt |
| attachments/Image1.png | exported-attachments/Attachment-$RECORD_NUMBERS[0]/Image1.png |

Scenario: CliKintoneTest-94 Should return the record contents and download attachments successfully with a TXT file.
Given The app "app_for_export_attachments" has no records
Expand All @@ -251,7 +251,7 @@ Feature: cli-kintone export command
And The output message should match with the data below:
| Record_number | Text | Attachment |
| $RECORD_NUMBERS[0] | Alice | Attachment-$RECORD_NUMBERS[0][\/\\\\]file1.txt |
And The directory "exported-attachments" should contain files as below:
And The directory "exported-attachments" should contain files with filename and content as below:
| FilePath | FileName | Content |
| Attachment-$RECORD_NUMBERS[0] | file1.txt | 123 |

Expand Down Expand Up @@ -302,8 +302,8 @@ Feature: cli-kintone export command
Given The app "app_for_export" has no records
And The app "app_for_export" has some records as below:
| Text | Number |
| Alice | 10 |
| Bob | 20 |
| Alice | 20 |
| Bob | 10 |
| Jenny | 30 |
And Load app ID of the app "app_for_export" as env var: "APP_ID"
And Load app token of the app "app_for_export" with exact permissions "view" as env var: "API_TOKEN"
Expand All @@ -312,8 +312,8 @@ Feature: cli-kintone export command
And The output message should match the data in the order as below:
| Record_number | Text | Number |
| \d+ | Jenny | 30 |
| \d+ | Bob | 20 |
| \d+ | Alice | 10 |
| \d+ | Alice | 20 |
| \d+ | Bob | 10 |

Scenario: CliKintoneTest-99 Should return the error message when exporting the record with invalid order by query.
Given The app "app_for_export" has no records
Expand Down Expand Up @@ -415,28 +415,28 @@ Feature: cli-kintone export command
Scenario: CliKintoneTest-111 Should return the record contents when exporting the record with --encoding option is utf8.
Given The app "app_for_export" has no records
And The app "app_for_export" has some records as below:
| Text | Number |
| Text | Number |
| レコード番号 | 10 |
And Load app ID of the app "app_for_export" as env var: "APP_ID"
And Load app token of the app "app_for_export" with exact permissions "view" as env var: "API_TOKEN"
When I run the command with args "record export --base-url $$TEST_KINTONE_BASE_URL --app $APP_ID --api-token $API_TOKEN --encoding utf8"
Then I should get the exit code is zero
And The output message with "utf8" encoded should match with the data below:
| Record_number | Text | Number |
| Record_number | Text | Number |
| \d+ | レコード番号 | 10 |

Scenario: CliKintoneTest-112 Should return the record contents when exporting the record with --encoding option is sjis.
Given The app "app_for_export" has no records
And The app "app_for_export" has some records as below:
| Text | Number |
| Text | Number |
| 作成日時 | 10 |
And Load app ID of the app "app_for_export" as env var: "APP_ID"
And Load app token of the app "app_for_export" with exact permissions "view" as env var: "API_TOKEN"
When I run the command with args "record export --base-url $$TEST_KINTONE_BASE_URL --app $APP_ID --api-token $API_TOKEN --encoding sjis"
Then I should get the exit code is zero
And The output message with "sjis" encoded should match with the data below:
| Record_number | Text | Number |
| \d+ | 作成日時 | 10 |
| Record_number | Text | Number |
| \d+ | 作成日時 | 10 |

Scenario: CliKintoneTest-113 Should return the error message when exporting the record with an unsupported character encoding.
Given Load app ID of the app "app_for_export" as env var: "APP_ID"
Expand Down
4 changes: 4 additions & 0 deletions features/step_definitions/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,7 @@ Then(
);
},
);

Given("I have a file in {string}", async function (filePath: string) {
await this.generateFile(filePath);
});
71 changes: 61 additions & 10 deletions features/step_definitions/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { Given, Then } from "../utils/world";
import fs from "fs";
import path from "path";
import iconv from "iconv-lite";
import { generateCsvRow } from "../utils/helper";
import {
compareBuffers,
generateCsvRow,
validateRequireColumnsInTable,
} from "../utils/helper";

Given("I have a directory {string}", function (directory: string) {
fs.mkdirSync(path.join(this.workingDir, directory));
Expand All @@ -12,16 +16,31 @@ Given("I have a directory {string}", function (directory: string) {
Then(
"The directory {string} should contain files as below:",
function (attachmentDir, table) {
const columns: string[] = table.raw()[0];
const requiredColumns = ["FilePath", "FileName", "Content"];
requiredColumns.forEach((requiredColumn) => {
if (!columns.includes(requiredColumn)) {
throw new Error(`The table should have ${requiredColumn} column.`);
}
});
validateRequireColumnsInTable(table.raw()[0], ["FilePath", "FileName"]);

const records = this.replacePlaceholdersInHashesDataTables(table.hashes());
for (let index = 0; index < records.length; index++) {
const record = records[index];
const actualFilePath = `${this.workingDir}/${attachmentDir}/${record.FilePath}/${record.FileName}`;

assert.ok(
fs.existsSync(actualFilePath),
`The file "${actualFilePath}" is not found`,
);
}
},
);

Then(
"The directory {string} should contain files with filename and content as below:",
function (attachmentDir, table) {
validateRequireColumnsInTable(table.raw()[0], [
"FilePath",
"FileName",
"Content",
]);

const records: Array<{ [key: string]: string }> =
this.replacePlaceholdersInHashesDataTables(table.hashes());
const records = this.replacePlaceholdersInHashesDataTables(table.hashes());
for (let index = 0; index < records.length; index++) {
const record = records[index];
const actualFilePath = `${this.workingDir}/${attachmentDir}/${record.FilePath}/${record.FileName}`;
Expand All @@ -41,6 +60,38 @@ Then(
},
);

Then("The exported files should match as below:", function (table) {
validateRequireColumnsInTable(table.raw()[0], [
"Expected_FilePath",
"Actual_FilePath",
]);

const records = this.replacePlaceholdersInHashesDataTables(table.hashes());
for (let index = 0; index < records.length; index++) {
const record = records[index];
const actualFilePath = path.join(this.workingDir, record.Actual_FilePath);
const expectedFilePath = path.join(
this.workingDir,
record.Expected_FilePath,
);

assert.ok(
fs.existsSync(actualFilePath),
`The file "${actualFilePath}" is not found.`,
);

assert.ok(
compareBuffers(
fs.readFileSync(actualFilePath),
fs.readFileSync(expectedFilePath),
),
`The content of the file "${record.Actual_FilePath}" does not matched.\n` +
`Expected file path: ${expectedFilePath}\n` +
`Actual file path: ${actualFilePath}`,
);
}
});

Then(
"The output message should match the data in the order as below:",
async function (table) {
Expand Down
2 changes: 1 addition & 1 deletion features/step_definitions/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Given(
Given(
"I have a file {string} with content: {string}",
async function (filePath: string, content: string) {
await this.generateFile(content, filePath);
await this.generateFileWithContent(content, filePath);
},
);

Expand Down
49 changes: 49 additions & 0 deletions features/utils/__tests__/fileGenerator.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { generateFile } from "../fileGenerator";
import { promises as fs } from "fs";
import path from "path";
import os from "os";
import { rimraf } from "rimraf";

describe("File Generator functions", () => {
describe("Generate file success", () => {
let tempDir: string;
beforeEach(async () => {
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "cli-kintone-"));
});

it("should generate file correctly", async () => {
const filePath = path.join(tempDir, "/tmp/test.png");
await generateFile(filePath, {});

const actual = fs.stat(filePath);
expect(actual).toBeTruthy();
});

it("should generate file correctly with baseDir", async () => {
const filePath = "test.png";
const baseDir = path.join(tempDir, "./tmp");
await generateFile(filePath, { baseDir });

const actual = fs.stat(`${baseDir}/${filePath}`);
expect(actual).toBeTruthy();
});

afterEach(() => {
rimraf.sync(tempDir);
});
});

it("should throw error when generating unsupported file extension", async () => {
const filePath = "test.xlsx";
await expect(generateFile(filePath, {})).rejects.toThrow(
`File extension "xlsx" is not supported`,
);
});

it("should throw error when file path is invalid", async () => {
const filePath = "test";
await expect(generateFile(filePath, {})).rejects.toThrow(
`Invalid file path "${filePath}".`,
);
});
});
34 changes: 33 additions & 1 deletion features/utils/__tests__/helper.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { generateCsvRow, replacePlaceholders } from "../helper";
import {
compareBuffers,
generateCsvRow,
replacePlaceholders,
validateRequireColumnsInTable,
} from "../helper";

describe("Helper functions", () => {
describe("generateCsvRow", () => {
Expand Down Expand Up @@ -75,4 +80,31 @@ describe("Helper functions", () => {
});
});
});

describe("validateRequireColumnsInTable", () => {
it("should throw error when required columns are not found", () => {
const columns = ["FilePath"];
const requiredColumns = ["FilePath", "FileName"];

expect(() => {
validateRequireColumnsInTable(columns, requiredColumns);
}).toThrowError("The table should have FileName column");
});
});

describe("compareBuffers", () => {
it("should return TRUE if two buffers are the same", () => {
const buffer1 = Buffer.from("This is the same buffer");
const buffer2 = Buffer.from("This is the same buffer");

expect(compareBuffers(buffer1, buffer2)).toBe(true);
});

it("should return FALSE if two buffers are different", () => {
const buffer1 = Buffer.from("This is the first buffer");
const buffer2 = Buffer.from("This is the second buffer");

expect(compareBuffers(buffer1, buffer2)).toBe(false);
});
});
});
Loading

0 comments on commit ce32dd5

Please sign in to comment.