Yuki Takei 2 лет назад
Родитель
Сommit
1d0cba43fe

+ 55 - 0
apps/app/src/features/growi-plugin/models/vo/github-url.spec.ts

@@ -0,0 +1,55 @@
+import { GitHubUrl } from './github-url';
+
+describe('GitHubUrl Constructor throws an error when the url string is', () => {
+
+  it.concurrent.each`
+    url
+    ${'//example.com/org/repos'}
+    ${'https://example.com'}
+    ${'https://github.com/org/repos/foo'}
+  `("'$url'", ({ url }) => {
+    // when
+    const caller = () => new GitHubUrl(url);
+
+    // then
+    expect(caller).toThrowError(`The specified URL is invalid. : url='${url}'`);
+  });
+
+});
+
+describe('GitHubUrl Constructor is successfully processed', () => {
+
+  it('with http schemed url', () => {
+    // when
+    const githubUrl = new GitHubUrl('http://github.com/org/repos');
+
+    // then
+    expect(githubUrl).not.toBeNull();
+    expect(githubUrl.organizationName).toEqual('org');
+    expect(githubUrl.reposName).toEqual('repos');
+    expect(githubUrl.branchName).toEqual('main');
+  });
+
+  it('with https schemed url', () => {
+    // when
+    const githubUrl = new GitHubUrl('https://github.com/org/repos');
+
+    // then
+    expect(githubUrl).not.toBeNull();
+    expect(githubUrl.organizationName).toEqual('org');
+    expect(githubUrl.reposName).toEqual('repos');
+    expect(githubUrl.branchName).toEqual('main');
+  });
+
+  it('with branchName', () => {
+    // when
+    const githubUrl = new GitHubUrl('https://github.com/org/repos', 'fix/bug');
+
+    // then
+    expect(githubUrl).not.toBeNull();
+    expect(githubUrl.organizationName).toEqual('org');
+    expect(githubUrl.reposName).toEqual('repos');
+    expect(githubUrl.branchName).toEqual('fix/bug');
+  });
+
+});

+ 46 - 0
apps/app/src/features/growi-plugin/models/vo/github-url.ts

@@ -0,0 +1,46 @@
+// https://regex101.com/r/fK2rV3/1
+const githubReposIdPattern = new RegExp(/^\/([^/]+)\/([^/]+)$/);
+
+export class GitHubUrl {
+
+  private _organizationName: string;
+
+  private _reposName: string;
+
+  private _branchName: string;
+
+  get organizationName(): string {
+    return this._organizationName;
+  }
+
+  get reposName(): string {
+    return this._reposName;
+  }
+
+  get branchName(): string {
+    return this._branchName;
+  }
+
+  constructor(url: string, branchName = 'main') {
+
+    let matched;
+    try {
+      const ghUrl = new URL(url);
+
+      matched = ghUrl.pathname.match(githubReposIdPattern);
+
+      if (ghUrl.hostname !== 'github.com' || matched == null) {
+        throw new Error();
+      }
+    }
+    catch (err) {
+      throw new Error(`The specified URL is invalid. : url='${url}'`);
+    }
+
+    this._branchName = branchName;
+
+    this._organizationName = matched[1];
+    this._reposName = matched[2];
+  }
+
+}