@symbiosis-lab/moss-plugin-github 1.5.1

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 (38) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +18 -0
  3. package/assets/icon.svg +3 -0
  4. package/assets/manifest.json +19 -0
  5. package/e2e/deploy-api.test.ts +1129 -0
  6. package/e2e/moss-cli.test.ts +478 -0
  7. package/features/auth/device-flow.feature +41 -0
  8. package/features/deploy/validation.feature +50 -0
  9. package/features/steps/auth.steps.ts +285 -0
  10. package/features/steps/deploy.steps.ts +354 -0
  11. package/package.json +51 -0
  12. package/src/__tests__/auth-flow.integration.test.ts +738 -0
  13. package/src/__tests__/auth.test.ts +147 -0
  14. package/src/__tests__/configure-domain.test.ts +263 -0
  15. package/src/__tests__/deploy.integration.test.ts +798 -0
  16. package/src/__tests__/git.test.ts +190 -0
  17. package/src/__tests__/github-api.test.ts +761 -0
  18. package/src/__tests__/github-deploy.test.ts +2411 -0
  19. package/src/__tests__/progress-timeout.test.ts +209 -0
  20. package/src/__tests__/repo-setup-progress.test.ts +367 -0
  21. package/src/__tests__/repo-setup.test.ts +370 -0
  22. package/src/__tests__/token.test.ts +152 -0
  23. package/src/__tests__/utils.test.ts +129 -0
  24. package/src/__tests__/workflow.test.ts +146 -0
  25. package/src/auth.ts +588 -0
  26. package/src/constants.ts +7 -0
  27. package/src/git.ts +60 -0
  28. package/src/github-api.ts +601 -0
  29. package/src/github-deploy.ts +593 -0
  30. package/src/main.ts +646 -0
  31. package/src/repo-setup.ts +685 -0
  32. package/src/token.ts +202 -0
  33. package/src/types.ts +91 -0
  34. package/src/utils.ts +108 -0
  35. package/src/workflow.ts +79 -0
  36. package/test-helpers/mock-github-api.ts +217 -0
  37. package/tsconfig.json +20 -0
  38. package/vitest.config.ts +50 -0
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Unit tests for git.ts pure functions
3
+ *
4
+ * These tests cover the pure functions for URL parsing.
5
+ */
6
+
7
+ import { describe, it, expect } from "vitest";
8
+ import { parseGitHubUrl, extractGitHubPagesUrl, buildPagesUrl, isRootRepo } from "../git";
9
+
10
+ describe("parseGitHubUrl", () => {
11
+ describe("HTTPS URLs", () => {
12
+ it("parses standard HTTPS URL", () => {
13
+ const result = parseGitHubUrl("https://github.com/user/repo.git");
14
+ expect(result).toEqual({ owner: "user", repo: "repo" });
15
+ });
16
+
17
+ it("parses HTTPS URL without .git extension", () => {
18
+ const result = parseGitHubUrl("https://github.com/user/repo");
19
+ expect(result).toEqual({ owner: "user", repo: "repo" });
20
+ });
21
+
22
+ it("parses org repo HTTPS URL", () => {
23
+ const result = parseGitHubUrl("https://github.com/symbiosis-lab/moss.git");
24
+ expect(result).toEqual({ owner: "symbiosis-lab", repo: "moss" });
25
+ });
26
+
27
+ it("handles hyphenated repo names", () => {
28
+ const result = parseGitHubUrl("https://github.com/user/my-awesome-repo.git");
29
+ expect(result).toEqual({ owner: "user", repo: "my-awesome-repo" });
30
+ });
31
+
32
+ it("handles underscored repo names", () => {
33
+ const result = parseGitHubUrl("https://github.com/user/my_repo.git");
34
+ expect(result).toEqual({ owner: "user", repo: "my_repo" });
35
+ });
36
+
37
+ it("parses user site repo with dots (username.github.io)", () => {
38
+ const result = parseGitHubUrl("https://github.com/guoliu/guoliu.github.io.git");
39
+ expect(result).toEqual({ owner: "guoliu", repo: "guoliu.github.io" });
40
+ });
41
+
42
+ it("parses user site repo without .git suffix", () => {
43
+ const result = parseGitHubUrl("https://github.com/guoliu/guoliu.github.io");
44
+ expect(result).toEqual({ owner: "guoliu", repo: "guoliu.github.io" });
45
+ });
46
+
47
+ it("parses repo name with dots", () => {
48
+ const result = parseGitHubUrl("https://github.com/user/my.project.name.git");
49
+ expect(result).toEqual({ owner: "user", repo: "my.project.name" });
50
+ });
51
+ });
52
+
53
+ describe("SSH URLs", () => {
54
+ it("parses standard SSH URL", () => {
55
+ const result = parseGitHubUrl("git@github.com:user/repo.git");
56
+ expect(result).toEqual({ owner: "user", repo: "repo" });
57
+ });
58
+
59
+ it("parses SSH URL without .git extension", () => {
60
+ const result = parseGitHubUrl("git@github.com:user/repo");
61
+ expect(result).toEqual({ owner: "user", repo: "repo" });
62
+ });
63
+
64
+ it("parses org repo SSH URL", () => {
65
+ const result = parseGitHubUrl("git@github.com:symbiosis-lab/moss.git");
66
+ expect(result).toEqual({ owner: "symbiosis-lab", repo: "moss" });
67
+ });
68
+
69
+ it("parses user site repo with dots (username.github.io) via SSH", () => {
70
+ const result = parseGitHubUrl("git@github.com:guoliu/guoliu.github.io.git");
71
+ expect(result).toEqual({ owner: "guoliu", repo: "guoliu.github.io" });
72
+ });
73
+
74
+ it("parses user site repo without .git suffix via SSH", () => {
75
+ const result = parseGitHubUrl("git@github.com:guoliu/guoliu.github.io");
76
+ expect(result).toEqual({ owner: "guoliu", repo: "guoliu.github.io" });
77
+ });
78
+ });
79
+
80
+ describe("invalid URLs", () => {
81
+ it("returns null for non-GitHub HTTPS URL", () => {
82
+ const result = parseGitHubUrl("https://gitlab.com/user/repo.git");
83
+ expect(result).toBeNull();
84
+ });
85
+
86
+ it("returns null for non-GitHub SSH URL", () => {
87
+ const result = parseGitHubUrl("git@gitlab.com:user/repo.git");
88
+ expect(result).toBeNull();
89
+ });
90
+
91
+ it("returns null for malformed URL", () => {
92
+ const result = parseGitHubUrl("not-a-valid-url");
93
+ expect(result).toBeNull();
94
+ });
95
+
96
+ it("returns null for empty string", () => {
97
+ const result = parseGitHubUrl("");
98
+ expect(result).toBeNull();
99
+ });
100
+
101
+ it("returns null for GitHub URL with extra path segments", () => {
102
+ const result = parseGitHubUrl("https://github.com/user/repo/extra");
103
+ expect(result).toBeNull();
104
+ });
105
+ });
106
+ });
107
+
108
+ describe("extractGitHubPagesUrl", () => {
109
+ it("generates correct Pages URL from HTTPS remote", () => {
110
+ const result = extractGitHubPagesUrl("https://github.com/user/repo.git");
111
+ expect(result).toBe("https://user.github.io/repo");
112
+ });
113
+
114
+ it("generates correct Pages URL from SSH remote", () => {
115
+ const result = extractGitHubPagesUrl("git@github.com:user/repo.git");
116
+ expect(result).toBe("https://user.github.io/repo");
117
+ });
118
+
119
+ it("generates correct Pages URL for org repos", () => {
120
+ const result = extractGitHubPagesUrl("https://github.com/symbiosis-lab/moss.git");
121
+ expect(result).toBe("https://symbiosis-lab.github.io/moss");
122
+ });
123
+
124
+ it("generates root URL for user site repo (SSH)", () => {
125
+ const result = extractGitHubPagesUrl("git@github.com:guoliu/guoliu.github.io.git");
126
+ expect(result).toBe("https://guoliu.github.io");
127
+ });
128
+
129
+ it("generates root URL for user site repo (HTTPS)", () => {
130
+ const result = extractGitHubPagesUrl("https://github.com/guoliu/guoliu.github.io.git");
131
+ expect(result).toBe("https://guoliu.github.io");
132
+ });
133
+
134
+ it("generates root URL for user site repo (case-insensitive)", () => {
135
+ const result = extractGitHubPagesUrl("git@github.com:GuoLiu/GuoLiu.github.io.git");
136
+ expect(result).toBe("https://GuoLiu.github.io");
137
+ });
138
+
139
+ it("throws for non-GitHub URLs", () => {
140
+ expect(() => {
141
+ extractGitHubPagesUrl("https://gitlab.com/user/repo.git");
142
+ }).toThrow("Could not parse GitHub URL from remote");
143
+ });
144
+
145
+ it("throws for invalid URLs", () => {
146
+ expect(() => {
147
+ extractGitHubPagesUrl("not-a-url");
148
+ }).toThrow("Could not parse GitHub URL from remote");
149
+ });
150
+ });
151
+
152
+ describe("isRootRepo", () => {
153
+ it("returns true for exact match (alice/alice.github.io)", () => {
154
+ expect(isRootRepo("alice", "alice.github.io")).toBe(true);
155
+ });
156
+
157
+ it("returns true for case-insensitive owner (Alice/alice.github.io)", () => {
158
+ expect(isRootRepo("Alice", "alice.github.io")).toBe(true);
159
+ });
160
+
161
+ it("returns true for case-insensitive both (Alice/Alice.github.io)", () => {
162
+ expect(isRootRepo("Alice", "Alice.github.io")).toBe(true);
163
+ });
164
+
165
+ it("returns false for non-root repo (alice/my-website)", () => {
166
+ expect(isRootRepo("alice", "my-website")).toBe(false);
167
+ });
168
+
169
+ it("returns false for different user's root repo (alice/bob.github.io)", () => {
170
+ expect(isRootRepo("alice", "bob.github.io")).toBe(false);
171
+ });
172
+ });
173
+
174
+ describe("buildPagesUrl", () => {
175
+ it("generates project URL for regular repo", () => {
176
+ expect(buildPagesUrl("user", "repo")).toBe("https://user.github.io/repo");
177
+ });
178
+
179
+ it("generates root URL for user site repo (exact match)", () => {
180
+ expect(buildPagesUrl("guoliu", "guoliu.github.io")).toBe("https://guoliu.github.io");
181
+ });
182
+
183
+ it("generates root URL for user site repo (case-insensitive)", () => {
184
+ expect(buildPagesUrl("GuoLiu", "GuoLiu.github.io")).toBe("https://GuoLiu.github.io");
185
+ });
186
+
187
+ it("generates project URL for org repo", () => {
188
+ expect(buildPagesUrl("symbiosis-lab", "moss")).toBe("https://symbiosis-lab.github.io/moss");
189
+ });
190
+ });