track-cli 4.0.3 → 4.1.0-rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/esm/_dnt.shims.d.ts +1 -1
  2. package/esm/_dnt.test_shims.d.ts +20 -0
  3. package/esm/_dnt.test_shims.js +77 -0
  4. package/esm/deps/deno.land/std@0.195.0/_util/diff.d.ts +26 -0
  5. package/esm/deps/deno.land/std@0.195.0/_util/diff.js +311 -0
  6. package/esm/deps/deno.land/std@0.195.0/assert/_constants.d.ts +1 -0
  7. package/esm/deps/deno.land/std@0.195.0/assert/_constants.js +2 -0
  8. package/esm/deps/deno.land/std@0.195.0/assert/_format.d.ts +1 -0
  9. package/esm/deps/deno.land/std@0.195.0/assert/_format.js +23 -0
  10. package/esm/deps/deno.land/std@0.195.0/assert/assert_almost_equals.d.ts +18 -0
  11. package/esm/deps/deno.land/std@0.195.0/assert/assert_almost_equals.js +32 -0
  12. package/esm/deps/deno.land/std@0.195.0/assert/assert_array_includes.d.ts +14 -0
  13. package/esm/deps/deno.land/std@0.195.0/assert/assert_array_includes.js +38 -0
  14. package/esm/deps/deno.land/std@0.195.0/assert/assert_equals.d.ts +17 -0
  15. package/esm/deps/deno.land/std@0.195.0/assert/assert_equals.js +45 -0
  16. package/esm/deps/deno.land/std@0.195.0/assert/assert_exists.d.ts +5 -0
  17. package/esm/deps/deno.land/std@0.195.0/assert/assert_exists.js +14 -0
  18. package/esm/deps/deno.land/std@0.195.0/assert/assert_false.d.ts +4 -0
  19. package/esm/deps/deno.land/std@0.195.0/assert/assert_false.js +7 -0
  20. package/esm/deps/deno.land/std@0.195.0/assert/assert_instance_of.d.ts +8 -0
  21. package/esm/deps/deno.land/std@0.195.0/assert/assert_instance_of.js +38 -0
  22. package/esm/deps/deno.land/std@0.195.0/assert/assert_is_error.d.ts +7 -0
  23. package/esm/deps/deno.land/std@0.195.0/assert/assert_is_error.js +26 -0
  24. package/esm/deps/deno.land/std@0.195.0/assert/assert_match.d.ts +5 -0
  25. package/esm/deps/deno.land/std@0.195.0/assert/assert_match.js +13 -0
  26. package/esm/deps/deno.land/std@0.195.0/assert/assert_not_equals.d.ts +14 -0
  27. package/esm/deps/deno.land/std@0.195.0/assert/assert_not_equals.js +37 -0
  28. package/esm/deps/deno.land/std@0.195.0/assert/assert_not_instance_of.d.ts +5 -0
  29. package/esm/deps/deno.land/std@0.195.0/assert/assert_not_instance_of.js +14 -0
  30. package/esm/deps/deno.land/std@0.195.0/assert/assert_not_match.d.ts +5 -0
  31. package/esm/deps/deno.land/std@0.195.0/assert/assert_not_match.js +14 -0
  32. package/esm/deps/deno.land/std@0.195.0/assert/assert_not_strict_equals.d.ts +11 -0
  33. package/esm/deps/deno.land/std@0.195.0/assert/assert_not_strict_equals.js +20 -0
  34. package/esm/deps/deno.land/std@0.195.0/assert/assert_object_match.d.ts +5 -0
  35. package/esm/deps/deno.land/std@0.195.0/assert/assert_object_match.js +78 -0
  36. package/esm/deps/deno.land/std@0.195.0/assert/assert_rejects.d.ts +64 -0
  37. package/esm/deps/deno.land/std@0.195.0/assert/assert_rejects.js +50 -0
  38. package/esm/deps/deno.land/std@0.195.0/assert/assert_strict_equals.d.ts +23 -0
  39. package/esm/deps/deno.land/std@0.195.0/assert/assert_strict_equals.js +60 -0
  40. package/esm/deps/deno.land/std@0.195.0/assert/assert_string_includes.d.ts +5 -0
  41. package/esm/deps/deno.land/std@0.195.0/assert/assert_string_includes.js +13 -0
  42. package/esm/deps/deno.land/std@0.195.0/assert/assert_throws.d.ts +54 -0
  43. package/esm/deps/deno.land/std@0.195.0/assert/assert_throws.js +44 -0
  44. package/esm/deps/deno.land/std@0.195.0/assert/equal.d.ts +6 -0
  45. package/esm/deps/deno.land/std@0.195.0/assert/equal.js +102 -0
  46. package/esm/deps/deno.land/std@0.195.0/assert/fail.d.ts +4 -0
  47. package/esm/deps/deno.land/std@0.195.0/assert/fail.js +9 -0
  48. package/esm/deps/deno.land/std@0.195.0/assert/mod.d.ts +32 -0
  49. package/esm/deps/deno.land/std@0.195.0/assert/mod.js +33 -0
  50. package/esm/deps/deno.land/std@0.195.0/assert/unimplemented.d.ts +2 -0
  51. package/esm/deps/deno.land/std@0.195.0/assert/unimplemented.js +7 -0
  52. package/esm/deps/deno.land/std@0.195.0/assert/unreachable.d.ts +2 -0
  53. package/esm/deps/deno.land/std@0.195.0/assert/unreachable.js +6 -0
  54. package/esm/deps/deno.land/std@0.195.0/testing/_test_suite.d.ts +70 -0
  55. package/esm/deps/deno.land/std@0.195.0/testing/_test_suite.js +321 -0
  56. package/esm/deps/deno.land/std@0.195.0/testing/asserts.d.ts +329 -0
  57. package/esm/deps/deno.land/std@0.195.0/testing/asserts.js +330 -0
  58. package/esm/deps/deno.land/std@0.195.0/testing/bdd.d.ts +440 -0
  59. package/esm/deps/deno.land/std@0.195.0/testing/bdd.js +215 -0
  60. package/esm/deps/deno.land/std@0.195.0/testing/mock.d.ts +110 -0
  61. package/esm/deps/deno.land/std@0.195.0/testing/mock.js +746 -0
  62. package/esm/src/action/clone.js +4 -3
  63. package/esm/src/action/frontend-template-switch.d.ts +1 -0
  64. package/esm/src/action/frontend-template-switch.js +53 -0
  65. package/esm/src/action/frontend-template.d.ts +2 -0
  66. package/esm/src/action/frontend-template.js +12 -0
  67. package/esm/src/action/lang.js +11 -2
  68. package/esm/src/action/run.js +6 -7
  69. package/esm/src/main.js +9 -2
  70. package/esm/src/meta.d.ts +1 -1
  71. package/esm/src/meta.js +108 -25
  72. package/esm/src/orca/client.js +1 -1
  73. package/esm/src/shared/config.d.ts +1 -0
  74. package/esm/src/shared/errors.d.ts +7 -1
  75. package/esm/src/shared/errors.js +16 -3
  76. package/esm/src/shared/file.js +1 -1
  77. package/esm/src/shared/mod.d.ts +1 -1
  78. package/esm/src/shared/mod.js +10 -2
  79. package/esm/src/shared/types.d.ts +16 -0
  80. package/esm/src/shared/types.js +2 -0
  81. package/esm/src/track/client.d.ts +4 -1
  82. package/esm/src/track/test.d.ts +6 -2
  83. package/esm/src/track/test.js +28 -5
  84. package/esm/src/track/training.d.ts +4 -1
  85. package/esm/src/track/training.js +9 -0
  86. package/esm/test/shared/config_test.d.ts +1 -0
  87. package/esm/test/shared/config_test.js +57 -0
  88. package/esm/test/shared/file_test.d.ts +1 -0
  89. package/esm/test/shared/file_test.js +265 -0
  90. package/esm/test/shared/mod_test.d.ts +1 -0
  91. package/esm/test/shared/mod_test.js +353 -0
  92. package/package.json +1 -1
  93. package/test_runner.js +186 -0
@@ -1,11 +1,11 @@
1
- import { ExamCanceled, ExamExpired, ExamSubmitted, ExamUnread, InvalidChallengeId, OtherError, } from "../shared/errors.js";
1
+ import { ExamCanceled, ExamExpired, ExamSubmitted, ExamUnread, InvalidChallengeId, OtherError, UnsupportedChallenge, } from "../shared/errors.js";
2
2
  import { HttpStatus } from "../shared/mod.js";
3
3
  import { ChallengeStyle, } from "../shared/types.js";
4
4
  import { FormType, TrackClientBase, } from "./client.js";
5
5
  // @ts-ignore: has no exported member
6
6
  import { CookieJar, fetch } from "node-fetch-cookies";
7
7
  export class TestClient extends TrackClientBase {
8
- constructor(baseUrl, orgName, token, challengeId, basic, cookies) {
8
+ constructor(baseUrl, orgName, token, challengeId, basic, cookies, applicantExamId, challengeResultId) {
9
9
  super(baseUrl, basic, cookies);
10
10
  Object.defineProperty(this, "orgName", {
11
11
  enumerable: true,
@@ -40,6 +40,8 @@ export class TestClient extends TrackClientBase {
40
40
  this.orgName = orgName;
41
41
  this.token = token;
42
42
  this.challengeId = challengeId;
43
+ this.applicantExamId = applicantExamId ?? 0;
44
+ this.resultId = challengeResultId ?? 0;
43
45
  }
44
46
  config() {
45
47
  return {
@@ -69,6 +71,9 @@ export class TestClient extends TrackClientBase {
69
71
  if (!challenge) {
70
72
  throw new InvalidChallengeId(this.challengeId);
71
73
  }
74
+ else if (!this.isChallengeSupported(challenge)) {
75
+ throw new UnsupportedChallenge(this.challengeId);
76
+ }
72
77
  this.applicantExamId = applicantExam.id;
73
78
  this.resultId = result?.id || 0;
74
79
  return challenge;
@@ -98,14 +103,24 @@ export class TestClient extends TrackClientBase {
98
103
  return examSession.challengesSets
99
104
  .flatMap((s) => s.challenges)
100
105
  .map((esc) => toChallengeSession(esc, result))
101
- .find((c) => c.challengeId === this.challengeId &&
102
- (c.style === ChallengeStyle.Development ||
103
- c.style === ChallengeStyle.Algorithm));
106
+ .find((c) => c.challengeId === this.challengeId);
107
+ }
108
+ isChallengeSupported(c) {
109
+ return (c.style === ChallengeStyle.Development ||
110
+ c.style === ChallengeStyle.Algorithm ||
111
+ c.style === ChallengeStyle.Function ||
112
+ c.style === ChallengeStyle.Frontend);
104
113
  }
105
114
  async languages() {
106
115
  return (await this._get(`/api/enum/challenges/programminglanguages`))
107
116
  .map(toProgrammingLanguageInfo);
108
117
  }
118
+ async frontendTemplates() {
119
+ return await this._get(`/api/dock-public/v2/consumer/frontend-templates`);
120
+ }
121
+ async frontendTemplate(code) {
122
+ return await this._get(`/api/dock-public/v2/consumer/frontend-templates/${code}`);
123
+ }
109
124
  async start() {
110
125
  return await this._put(`/api/applicants/exams/${this.applicantExamId}/results/${this.resultId}/start`, FormType.URLEncoded, {
111
126
  takenBy: 3, // 3 = LocalMachine
@@ -121,6 +136,12 @@ export class TestClient extends TrackClientBase {
121
136
  programmingLanguage: language,
122
137
  }); // ChallengeResult
123
138
  }
139
+ async updateFrontendTemplate(seriesCode) {
140
+ return await this._post(`/api/applicants/exams/${this.applicantExamId}/results/${this.resultId}/frontend/switch-frontend-template`, FormType.JSON, {
141
+ seriesCode,
142
+ forceReset: true,
143
+ });
144
+ }
124
145
  async timeLeft() {
125
146
  return await this._get(`/api/applicants/exams/${this.applicantExamId}/results/${this.resultId}/timeleft`);
126
147
  }
@@ -171,6 +192,8 @@ function toChallengeSession(esc, result) {
171
192
  timeLimitMinutes: esc.timeLimitMinutes,
172
193
  displayOrder: esc.displayOrder,
173
194
  programmingLanguages: esc.programmingLanguages,
195
+ allowedTemplateSeriesCodes: esc.frontendStyleConfig
196
+ ?.allowedTemplateSeriesCodes,
174
197
  localCodingAllowed: esc.localExamEnabled,
175
198
  openTestcases: esc.openTestcases,
176
199
  result,
@@ -1,5 +1,5 @@
1
1
  import { TrackTrainingConfigPart } from "../shared/config.js";
2
- import { ChallengeResult, ChallengeSession, CodingContext, ProgrammingLanguage, ProgrammingLanguageInfo, SaveFilesRequest } from "../shared/types.js";
2
+ import { ChallengeResult, ChallengeSession, CodingContext, FrontendTemplateInfo, ProgrammingLanguage, ProgrammingLanguageInfo, SaveFilesRequest } from "../shared/types.js";
3
3
  import { BasicAuth, TrackClient, TrackClientBase } from "./client.js";
4
4
  export declare class TrainingClient extends TrackClientBase implements TrackClient {
5
5
  private orgName;
@@ -13,9 +13,12 @@ export declare class TrainingClient extends TrackClientBase implements TrackClie
13
13
  startChallengeSession(): Promise<ChallengeSession>;
14
14
  continueChallengeSession(): Promise<ChallengeSession>;
15
15
  languages(): Promise<ProgrammingLanguageInfo[]>;
16
+ frontendTemplates(): Promise<FrontendTemplateInfo[]>;
17
+ frontendTemplate(_code: string): Promise<FrontendTemplateInfo>;
16
18
  start(): Promise<ChallengeResult>;
17
19
  prepare(): Promise<ChallengeResult>;
18
20
  updateLanguage(language: ProgrammingLanguage): Promise<void>;
21
+ updateFrontendTemplate(_templateCode: string): Promise<void>;
19
22
  timeLeft(): Promise<number>;
20
23
  context(): Promise<CodingContext>;
21
24
  presigned(files: string[]): Promise<{
@@ -74,6 +74,12 @@ export class TrainingClient extends TrackClientBase {
74
74
  return (await this._get(`/cli/languages`))
75
75
  .map(toProgrammingLanguageInfo);
76
76
  }
77
+ frontendTemplates() {
78
+ throw new OtherError("Frontend templates are not supported in training mode");
79
+ }
80
+ frontendTemplate(_code) {
81
+ throw new OtherError("Frontend templates are not supported in training mode");
82
+ }
77
83
  async start() {
78
84
  return await this._put(`/api/train/${this.klassId}/challenges/results/${this.klassResultId}/start`, FormType.JSON, {
79
85
  takenBy: 3, // 3 = LocalMachine
@@ -87,6 +93,9 @@ export class TrainingClient extends TrackClientBase {
87
93
  lang: language,
88
94
  });
89
95
  }
96
+ updateFrontendTemplate(_templateCode) {
97
+ throw new OtherError("Frontend templates are not supported in training mode");
98
+ }
90
99
  async timeLeft() {
91
100
  return await this._get(`/api/train/${this.klassId}/challenges/results/${this.klassResultId}/timeleft`);
92
101
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,57 @@
1
+ import * as dntShim from "../../_dnt.test_shims.js";
2
+ import * as config from "../../src/shared/config.js";
3
+ import { MissingConfigFile } from "../../src/shared/errors.js";
4
+ import { assertEquals, assertRejects } from "../../deps/deno.land/std@0.195.0/testing/asserts.js";
5
+ import { afterEach, beforeEach, describe, it } from "../../deps/deno.land/std@0.195.0/testing/bdd.js";
6
+ import { TrackApp } from "../../src/shared/types.js";
7
+ const testConfig = {
8
+ app: TrackApp.Test,
9
+ baseUrl: "https://app.tracks.run",
10
+ orgName: "anorg",
11
+ basicAuth: {
12
+ username: "user",
13
+ password: "pass",
14
+ },
15
+ token: "SECRET_TOKEN",
16
+ applicantExamId: 100,
17
+ challengeId: 200,
18
+ challengeResultId: 300,
19
+ cookies: {
20
+ PLAY_SESSION: "session",
21
+ },
22
+ programmingLanguage: 10,
23
+ };
24
+ describe("save()", () => {
25
+ let dir;
26
+ beforeEach(async () => {
27
+ dir = await dntShim.Deno.makeTempDir();
28
+ });
29
+ afterEach(async () => {
30
+ await dntShim.Deno.remove(dir, { recursive: true });
31
+ });
32
+ it("should save config to file with json format", async () => {
33
+ const path = `${dir}/config.json`;
34
+ await config.save(testConfig, { path });
35
+ const actual = new TextDecoder().decode(await dntShim.Deno.readFile(path));
36
+ assertEquals(JSON.parse(actual), testConfig);
37
+ });
38
+ });
39
+ describe("load()", () => {
40
+ let dir;
41
+ beforeEach(async () => {
42
+ dir = await dntShim.Deno.makeTempDir();
43
+ });
44
+ afterEach(async () => {
45
+ await dntShim.Deno.remove(dir, { recursive: true });
46
+ });
47
+ it("should save config to file with json format", async () => {
48
+ const path = `${dir}/config.json`;
49
+ await dntShim.Deno.writeFile(path, new TextEncoder().encode(JSON.stringify(testConfig)));
50
+ const actual = await config.load({ path });
51
+ assertEquals(actual, testConfig);
52
+ });
53
+ it("should throw error if config file does not exist", async () => {
54
+ const path = `${dir}/config.json`;
55
+ await assertRejects(async () => await config.load({ path }), MissingConfigFile);
56
+ });
57
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,265 @@
1
+ import * as dntShim from "../../_dnt.test_shims.js";
2
+ import * as file from "../../src/shared/file.js";
3
+ import { assertEquals, assertObjectMatch } from "../../deps/deno.land/std@0.195.0/testing/asserts.js";
4
+ import { afterAll, afterEach, beforeAll, beforeEach, describe, it, } from "../../deps/deno.land/std@0.195.0/testing/bdd.js";
5
+ async function prepareFiles(dir, files) {
6
+ for (const [name, content] of Object.entries(files)) {
7
+ if (typeof content === "string") {
8
+ await dntShim.Deno.writeTextFile(`${dir}/${name}`, content);
9
+ }
10
+ else {
11
+ await dntShim.Deno.mkdir(`${dir}/${name}`);
12
+ await prepareFiles(`${dir}/${name}`, content);
13
+ }
14
+ }
15
+ }
16
+ describe("pathsToFilenameSet()", () => {
17
+ let dir;
18
+ const files = {
19
+ "a.txt": "hello",
20
+ "b": {
21
+ "c.txt": "world",
22
+ "d": {
23
+ "e.txt": "foo",
24
+ },
25
+ },
26
+ };
27
+ beforeAll(async () => {
28
+ dir = await dntShim.Deno.makeTempDir();
29
+ await prepareFiles(dir, files);
30
+ });
31
+ afterAll(async () => {
32
+ await dntShim.Deno.remove(dir, { recursive: true });
33
+ });
34
+ it("should list only existing files without options", async () => {
35
+ const result = await file.pathsToFilenameSet(["a.txt", "b/c.txt", "b/d", "x/y", "z.txt"], { root: dir });
36
+ assertEquals(result, new Set(["a.txt", "b/c.txt"]));
37
+ });
38
+ it("should search files recursively with recursive = true", async () => {
39
+ const result = await file.pathsToFilenameSet(["a.txt", "b", "x/y", "z.txt"], { recursive: true, root: dir });
40
+ assertEquals(result, new Set(["a.txt", "b/c.txt", "b/d/e.txt"]));
41
+ });
42
+ it("should search files recursively and list non-existing files and directories with recursive = true and allowNonExistent = true", async () => {
43
+ const result = await file.pathsToFilenameSet(["a.txt", "b", "x/y", "z.txt"], { recursive: true, allowNonExistent: true, root: dir });
44
+ assertEquals(result, new Set(["a.txt", "b/c.txt", "b/d/e.txt", "x/y", "z.txt"]));
45
+ });
46
+ it("should support absolute paths", async () => {
47
+ const result = await file.pathsToFilenameSet([`${dir}/a.txt`, `${dir}/b`, `${dir}/x/y`, `${dir}/z.txt`], { recursive: true, allowNonExistent: true, root: dir });
48
+ assertEquals(result, new Set(["a.txt", "b/c.txt", "b/d/e.txt", "x/y", "z.txt"]));
49
+ });
50
+ it("should support only paths with root", async () => {
51
+ const anotherDir = await dntShim.Deno.makeTempDir();
52
+ await prepareFiles(anotherDir, files);
53
+ const result = await file.pathsToFilenameSet([`${dir}/a.txt`, `${anotherDir}/z.txt`], { recursive: true, allowNonExistent: true, root: dir });
54
+ assertEquals(result, new Set(["a.txt"]));
55
+ });
56
+ });
57
+ describe("stat()", () => {
58
+ let dir;
59
+ const files = {
60
+ "a.txt": "hello",
61
+ "b": {
62
+ "c.txt": "world",
63
+ },
64
+ };
65
+ beforeAll(async () => {
66
+ dir = await dntShim.Deno.makeTempDir();
67
+ await prepareFiles(dir, files);
68
+ });
69
+ afterAll(async () => {
70
+ await dntShim.Deno.remove(dir, { recursive: true });
71
+ });
72
+ it("should return stat of file", async () => {
73
+ const result = await file.stat(`${dir}/a.txt`);
74
+ assertObjectMatch(result, {
75
+ isFile: true,
76
+ isDirectory: false,
77
+ });
78
+ });
79
+ it("should return stat of directory", async () => {
80
+ const result = await file.stat(`${dir}/b`);
81
+ assertObjectMatch(result, {
82
+ isFile: false,
83
+ isDirectory: true,
84
+ });
85
+ });
86
+ it("should return null if file does not exist", async () => {
87
+ const result = await file.stat(`${dir}/x.txt`);
88
+ assertEquals(result, null);
89
+ });
90
+ it("should support subdirectories", async () => {
91
+ const result = await file.stat(`${dir}/b/c.txt`);
92
+ assertObjectMatch(result, {
93
+ isFile: true,
94
+ isDirectory: false,
95
+ });
96
+ });
97
+ });
98
+ describe("isEmptyDirectory()", () => {
99
+ let dir;
100
+ const files = {
101
+ "a.txt": "hello",
102
+ "b": {
103
+ "c.txt": "world",
104
+ },
105
+ "d": {},
106
+ };
107
+ beforeAll(async () => {
108
+ dir = await dntShim.Deno.makeTempDir();
109
+ await prepareFiles(dir, files);
110
+ });
111
+ afterAll(async () => {
112
+ await dntShim.Deno.remove(dir, { recursive: true });
113
+ });
114
+ it("should return ture if directory is empty", async () => {
115
+ const result = await file.isEmptyDirectory(`${dir}/d`);
116
+ assertEquals(result, true);
117
+ });
118
+ it("should return false if directory is not empty", async () => {
119
+ const result = await file.isEmptyDirectory(`${dir}/b`);
120
+ assertEquals(result, false);
121
+ });
122
+ it("should return false if directory nor file does not exist", async () => {
123
+ const result = await file.isEmptyDirectory(`${dir}/x`);
124
+ assertEquals(result, false);
125
+ });
126
+ it("should return false if path is a file", async () => {
127
+ const result = await file.isEmptyDirectory(`${dir}/a.txt`);
128
+ assertEquals(result, false);
129
+ });
130
+ });
131
+ describe("getAllDirFiles()", () => {
132
+ let dir;
133
+ const files = {
134
+ "a.txt": "hello",
135
+ "b": {
136
+ "c.txt": "world",
137
+ },
138
+ "d": {},
139
+ };
140
+ beforeAll(async () => {
141
+ dir = await dntShim.Deno.makeTempDir();
142
+ await prepareFiles(dir, files);
143
+ });
144
+ afterAll(async () => {
145
+ await dntShim.Deno.remove(dir, { recursive: true });
146
+ });
147
+ });
148
+ describe("untgz()", () => {
149
+ it("should extract tar.gz file", async () => {
150
+ const input = `
151
+ 1f8b 0800 0000 0000 0003 edd5 df0a 8230
152
+ 1c86 e11d 7715 5e81 6eee dff5 440a 4586
153
+ 6046 75f7 b9a1 d091 d4c1 26d1 fb30 1c8c.
154
+ 813f f8e0 5b59 89e4 e4c4 4b19 76e5 edbc
155
+ 1b1f cf67 4219 e38c 9261 09a9 c23d 51d8
156
+ f4a3 0971 bb8e fba1 28c4 e5f4 dcaf dd6b
157
+ fac3 b91d 724c 9455 591d dbae ebcb f131
158
+ 26fb 4708 d819 b392 bf5b f2d7 deaa 29ff
159
+ 5a5a 270a 996c a237 7f9e 7f4c 7fb7 f514
160
+ d84a 59dd fba1 6b92 be02 b1ff adfd a4ff
161
+ b5f7 d3b9 52da d2ff 592c f9c7 6fa2 57e0
162
+ abfe 8ff9 ebda 28fa 3f87 983b fd0f 0000
163
+ 0000 0000 0000 0000 3fef 0500 d28d ca00
164
+ 2800 00
165
+ `
166
+ .replaceAll(" ", "")
167
+ .match(/.{2}/g)
168
+ ?.map((byte) => parseInt(byte, 16));
169
+ const expected = [
170
+ { name: "hello.txt", content: "hello\n" },
171
+ { name: "world/world.txt", content: "world\n" },
172
+ ];
173
+ const dir = await dntShim.Deno.makeTempDir();
174
+ await file.untgz(new Uint8Array(input), dir);
175
+ for (const { name, content } of expected) {
176
+ const actual = await dntShim.Deno.readTextFile(`${dir}/${name}`);
177
+ assertEquals(actual, content);
178
+ }
179
+ await dntShim.Deno.remove(dir, { recursive: true });
180
+ });
181
+ });
182
+ describe("toNixStyle()", () => {
183
+ describe("on Windows", () => {
184
+ const originalSeparator = file._internals.SEP;
185
+ beforeAll(() => {
186
+ file._internals.SEP = "/";
187
+ });
188
+ afterAll(() => {
189
+ file._internals.SEP = originalSeparator;
190
+ });
191
+ it("should return path with forward slashes", () => {
192
+ assertEquals(file.toNixStyle("a\\b\\c"), "a/b/c");
193
+ assertEquals(file.toNixStyle("a/b/c"), "a/b/c");
194
+ assertEquals(file.toNixStyle("a\\b/c"), "a/b/c");
195
+ });
196
+ });
197
+ describe("on Linux and macOS", () => {
198
+ const originalSeparator = file._internals.SEP;
199
+ beforeAll(() => {
200
+ file._internals.SEP = "/";
201
+ });
202
+ afterAll(() => {
203
+ file._internals.SEP = originalSeparator;
204
+ });
205
+ it("should return path with forward slashes", () => {
206
+ assertEquals(file.toNixStyle("a\\b\\c"), "a/b/c");
207
+ assertEquals(file.toNixStyle("a/b/c"), "a/b/c");
208
+ assertEquals(file.toNixStyle("a\\b/c"), "a/b/c");
209
+ });
210
+ });
211
+ });
212
+ describe("toNativeStyle()", () => {
213
+ describe("on Windows", () => {
214
+ const originalSeparator = file._internals.SEP;
215
+ beforeAll(() => {
216
+ file._internals.SEP = "\\";
217
+ });
218
+ afterAll(() => {
219
+ file._internals.SEP = originalSeparator;
220
+ });
221
+ it("should return path with forward slashes", () => {
222
+ assertEquals(file.toNativeStyle("a\\b\\c"), "a\\b\\c");
223
+ assertEquals(file.toNativeStyle("a/b/c"), "a\\b\\c");
224
+ assertEquals(file.toNativeStyle("a\\b/c"), "a\\b\\c");
225
+ });
226
+ });
227
+ describe("on Linux and macOS", () => {
228
+ const originalSeparator = file._internals.SEP;
229
+ beforeAll(() => {
230
+ file._internals.SEP = "/";
231
+ });
232
+ afterAll(() => {
233
+ file._internals.SEP = originalSeparator;
234
+ });
235
+ it("should return path with forward slashes", () => {
236
+ assertEquals(file.toNativeStyle("a\\b\\c"), "a/b/c");
237
+ assertEquals(file.toNativeStyle("a/b/c"), "a/b/c");
238
+ assertEquals(file.toNativeStyle("a\\b/c"), "a/b/c");
239
+ });
240
+ });
241
+ });
242
+ describe("getUniqueDirName()", () => {
243
+ let dir;
244
+ const files = {
245
+ "foo": {},
246
+ "foo_1": {},
247
+ "foo_2": {},
248
+ "bar": {},
249
+ };
250
+ beforeEach(async () => {
251
+ dir = await dntShim.Deno.makeTempDir();
252
+ await prepareFiles(dir, files);
253
+ });
254
+ afterEach(async () => {
255
+ await dntShim.Deno.remove(dir, { recursive: true });
256
+ });
257
+ it("should return unique name", async () => {
258
+ const actual = await file.getUniqueDirName("bar", { root: dir });
259
+ assertEquals(actual, "bar_1");
260
+ });
261
+ it("should return unique name with counter > 1 if the candidate exists", async () => {
262
+ const actual = await file.getUniqueDirName("foo", { root: dir });
263
+ assertEquals(actual, "foo_3");
264
+ });
265
+ });
@@ -0,0 +1 @@
1
+ export {};