From b1850676c55f8ecfdc06fa900f46ffeac785df92 Mon Sep 17 00:00:00 2001
From: "Luke \"Jared\" Bennett" <lbennett@gitlab.com>
Date: Thu, 20 Jul 2017 13:32:29 +0100
Subject: [PATCH] Tidied up repo_service and added tests

---
 app/assets/javascripts/repo/repo_service.js |  50 ++++----
 spec/javascripts/repo/repo_service_spec.js  | 121 ++++++++++++++++++++
 2 files changed, 150 insertions(+), 21 deletions(-)
 create mode 100644 spec/javascripts/repo/repo_service_spec.js

diff --git a/app/assets/javascripts/repo/repo_service.js b/app/assets/javascripts/repo/repo_service.js
index 8fb9a8ed73b..ff90de48ef9 100644
--- a/app/assets/javascripts/repo/repo_service.js
+++ b/app/assets/javascripts/repo/repo_service.js
@@ -2,38 +2,46 @@ import axios from 'axios';
 
 const RepoService = {
   url: '',
-  params: {
+  options: {
     params: {
       format: 'json',
     },
   },
+  richExtensionRegExp: /md/,
 
-  setUrl(url) {
-    this.url = url;
-  },
+  buildParams(url = this.url) {
+    // shallow clone object without reference
+    const params = Object.assign({}, this.options.params);
+
+    if (this.urlIsRichBlob(url)) params.viewer = 'rich';
 
-  paramsWithRich(url) {
-    // copy the obj so we don't modify perm.
-    const params = JSON.parse(JSON.stringify(this.params));
-    if (url.substr(url.length - 2) === 'md') {
-      params.params.viewer = 'rich';
-    }
     return params;
   },
 
-  getContent(url) {
-    if (url) {
-      return axios.get(url, this.paramsWithRich(url, this.params));
-    }
-    return axios.get(this.url, this.paramsWithRich(this.url, this.params));
+  urlIsRichBlob(url = this.url) {
+    const extension = url.split('.').pop();
+
+    return this.richExtensionRegExp.test(extension);
+  },
+
+  getContent(url = this.url) {
+    const params = this.buildParams(url);
+
+    return axios.get(url, {
+      params,
+    });
+  },
+
+  getBase64Content(url = this.url) {
+    const request = axios.get(url, {
+      responseType: 'arraybuffer',
+    });
+
+    return request.then(response => this.bufferToBase64(response.data));
   },
 
-  getBase64Content(url) {
-    return axios
-      .get(url, {
-        responseType: 'arraybuffer',
-      })
-      .then(response => new Buffer(response.data, 'binary').toString('base64'));
+  bufferToBase64(data) {
+    return new Buffer(data, 'binary').toString('base64');
   },
 };
 
diff --git a/spec/javascripts/repo/repo_service_spec.js b/spec/javascripts/repo/repo_service_spec.js
new file mode 100644
index 00000000000..fde00056b5c
--- /dev/null
+++ b/spec/javascripts/repo/repo_service_spec.js
@@ -0,0 +1,121 @@
+import axios from 'axios';
+import RepoService from '~/repo/repo_service';
+
+describe('RepoService', () => {
+  it('has default json format param', () => {
+    expect(RepoService.options.params.format).toBe('json');
+  });
+
+  describe('buildParams', () => {
+    let newParams;
+    const url = 'url';
+
+    beforeEach(() => {
+      newParams = {};
+
+      spyOn(Object, 'assign').and.returnValue(newParams);
+    });
+
+    it('clones params', () => {
+      const params = RepoService.buildParams(url);
+
+      expect(Object.assign).toHaveBeenCalledWith({}, RepoService.options.params);
+
+      expect(params).toBe(newParams);
+    });
+
+    it('sets and returns viewer params to richif urlIsRichBlob is true', () => {
+      spyOn(RepoService, 'urlIsRichBlob').and.returnValue(true);
+
+      const params = RepoService.buildParams(url);
+
+      expect(params.viewer).toEqual('rich');
+    });
+
+    it('returns params urlIsRichBlob is false', () => {
+      spyOn(RepoService, 'urlIsRichBlob').and.returnValue(false);
+
+      const params = RepoService.buildParams(url);
+
+      expect(params.viewer).toBeUndefined();
+    });
+
+    it('calls urlIsRichBlob with the objects url prop if no url arg is provided', () => {
+      spyOn(RepoService, 'urlIsRichBlob');
+      RepoService.url = url;
+
+      RepoService.buildParams();
+
+      expect(RepoService.urlIsRichBlob).toHaveBeenCalledWith(url);
+    });
+  });
+
+  describe('urlIsRichBlob', () => {
+    it('returns true for md extension', () => {
+      const isRichBlob = RepoService.urlIsRichBlob('url.md');
+
+      expect(isRichBlob).toBeTruthy();
+    });
+
+    it('returns false for js extension', () => {
+      const isRichBlob = RepoService.urlIsRichBlob('url.js');
+
+      expect(isRichBlob).toBeFalsy();
+    });
+  });
+
+  describe('getContent', () => {
+    const params = {};
+    const url = 'url';
+    const requestPromise = Promise.resolve();
+
+    beforeEach(() => {
+      spyOn(RepoService, 'buildParams').and.returnValue(params);
+      spyOn(axios, 'get').and.returnValue(requestPromise);
+    });
+
+    it('calls buildParams and axios.get', () => {
+      const request = RepoService.getContent(url);
+
+      expect(RepoService.buildParams).toHaveBeenCalledWith(url);
+      expect(axios.get).toHaveBeenCalledWith(url, {
+        params,
+      });
+      expect(request).toBe(requestPromise);
+    });
+
+    it('uses object url prop if no url arg is provided', () => {
+      RepoService.url = url;
+
+      RepoService.getContent();
+
+      expect(axios.get).toHaveBeenCalledWith(url, {
+        params,
+      });
+    });
+  });
+
+  describe('getBase64Content', () => {
+    const url = 'url';
+    const response = { data: 'data' };
+
+    beforeEach(() => {
+      spyOn(RepoService, 'bufferToBase64');
+      spyOn(axios, 'get').and.returnValue(Promise.resolve(response));
+    });
+
+    it('calls axios.get and bufferToBase64 on completion', (done) => {
+      const request = RepoService.getBase64Content(url);
+
+      expect(axios.get).toHaveBeenCalledWith(url, {
+        responseType: 'arraybuffer',
+      });
+      expect(request).toEqual(jasmine.any(Promise));
+
+      request.then(() => {
+        expect(RepoService.bufferToBase64).toHaveBeenCalledWith(response.data);
+        done();
+      }).catch(done.fail);
+    });
+  });
+});
-- 
2.30.9