UNPKG

@wmfs/sharepoint

Version:

A library that allows Node.js applications to interact with a Sharepoint Online site

405 lines (346 loc) 15.5 kB
/* eslint-env mocha */ 'use strict' const chai = require('chai') const expect = chai.expect const Sharepoint = require('./../lib') const process = require('node:process') const path = require('node:path') const fs = require('node:fs') describe('tests', function () { this.timeout(15000) const FOLDER_NAME1 = 'TestFolder1' const FOLDER_NAME2 = 'TestFolder8834634' const FOLDER_NAME3 = 'TestFolder0' const FOLDER_NAME4 = 'TestFolder396' const FILE_NAME1 = 'test-file-453446.txt' const FILE_NAME2 = 'test-file-5.txt' const FILE_NAME3 = 'test-file-0.txt' const FILE_NAME4 = 'test-file-10.txt' const TEXT_FILE_FILENAME = 'Test.txt' const BINARY_FILE_FILENAME = 'Test.png' const authScope = process.env.SHAREPOINT_AUTH_SCOPE const certFingerprint = process.env.SHAREPOINT_CERT_FINGERPRINT const certPassphrase = process.env.SHAREPOINT_CERT_PASSPHRASE const certPrivateKeyFile = process.env.SHAREPOINT_CERT_PRIVATE_KEY_FILE const clientId = process.env.SHAREPOINT_CLIENT_ID const tenantId = process.env.SHAREPOINT_TENANT_ID let sharepoint before(function () { if (!( process.env.SHAREPOINT_AUTH_SCOPE && process.env.SHAREPOINT_CERT_FINGERPRINT && process.env.SHAREPOINT_CERT_PASSPHRASE && process.env.SHAREPOINT_CERT_PRIVATE_KEY_FILE && process.env.SHAREPOINT_CLIENT_ID && process.env.SHAREPOINT_TENANT_ID && process.env.SHAREPOINT_URL && process.env.SHAREPOINT_TESTS_DIR_PATH )) { console.log('Missing environment variables, skipping tests.') this.skip() } }) describe('check for handling of missing environment variables', () => { it('construct Sharepoint instance with no auth scope env var set', () => { delete process.env.SHAREPOINT_AUTH_SCOPE try { new Sharepoint(process.env.SHAREPOINT_URL) // eslint-disable-line } catch (err) { expect(err.message).to.eql('SHAREPOINT_AUTH_SCOPE environment variable has not been set') } }) it('construct Sharepoint instance with auth scope env var set to an invalid value', () => { process.env.SHAREPOINT_AUTH_SCOPE = 'https://invalid-value' try { new Sharepoint(process.env.SHAREPOINT_URL) // eslint-disable-line } catch (err) { expect(err.message).to.eql('SHAREPOINT_AUTH_SCOPE environment variable value is not valid - it must begin with "https://" and end with ".sharepoint.com/.default"') } }) it('construct Sharepoint instance with no client id env var set', () => { process.env.SHAREPOINT_AUTH_SCOPE = authScope delete process.env.SHAREPOINT_CLIENT_ID try { new Sharepoint(process.env.SHAREPOINT_URL) // eslint-disable-line } catch (err) { expect(err.message).to.eql('SHAREPOINT_CLIENT_ID environment variable has not been set') } }) it('construct Sharepoint instance with no tenant id env var set', () => { process.env.SHAREPOINT_CLIENT_ID = clientId delete process.env.SHAREPOINT_TENANT_ID try { new Sharepoint(process.env.SHAREPOINT_URL) // eslint-disable-line } catch (err) { expect(err.message).to.eql('SHAREPOINT_TENANT_ID environment variable has not been set') } }) it('construct Sharepoint instance with no cert passphrase env var set', () => { process.env.SHAREPOINT_TENANT_ID = tenantId delete process.env.SHAREPOINT_CERT_PASSPHRASE try { new Sharepoint(process.env.SHAREPOINT_URL) // eslint-disable-line } catch (err) { expect(err.message).to.eql('SHAREPOINT_CERT_PASSPHRASE environment variable has not been set') } }) it('construct Sharepoint instance with no cert fingerprint env var set', () => { process.env.SHAREPOINT_CERT_PASSPHRASE = certPassphrase delete process.env.SHAREPOINT_CERT_FINGERPRINT try { new Sharepoint(process.env.SHAREPOINT_URL) // eslint-disable-line } catch (err) { expect(err.message).to.eql('SHAREPOINT_CERT_FINGERPRINT environment variable has not been set') } }) it('construct Sharepoint instance with cert fingerprint env var set to an invalid value', () => { process.env.SHAREPOINT_CERT_FINGERPRINT = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' try { new Sharepoint(process.env.SHAREPOINT_URL) // eslint-disable-line } catch (err) { expect(err.message).to.eql('SHAREPOINT_CERT_FINGERPRINT environment variable value is not valid - it must be exactly 40 characters in length') } }) it('construct Sharepoint instance with no cert private key file env var set', () => { process.env.SHAREPOINT_CERT_FINGERPRINT = certFingerprint delete process.env.SHAREPOINT_CERT_PRIVATE_KEY_FILE try { new Sharepoint(process.env.SHAREPOINT_URL) // eslint-disable-line } catch (err) { expect(err.message).to.eql('SHAREPOINT_CERT_PRIVATE_KEY_FILE environment variable has not been set') } }) it('construct Sharepoint instance with no cert private key file env var set', () => { process.env.SHAREPOINT_CERT_PRIVATE_KEY_FILE = './fixtures/no-such-file.pem' try { new Sharepoint(process.env.SHAREPOINT_URL) // eslint-disable-line } catch (err) { expect(err.message).to.eql('specified sharepoint certificate private key file (\'./fixtures/no-such-file.pem\') does not exist') } }) }) describe('sharepoint interactivity tests', () => { it('attempt to construct Sharepoint instance without a siteUrl', () => { try { new Sharepoint() // eslint-disable-line } catch (err) { expect(err.message).to.eql('siteUrl has not been specified') } }) it('construct Sharepoint instance', () => { process.env.SHAREPOINT_CERT_PRIVATE_KEY_FILE = certPrivateKeyFile sharepoint = new Sharepoint(process.env.SHAREPOINT_URL) expect(sharepoint.siteUrl).to.eql(process.env.SHAREPOINT_URL) }) it('authenticate', async () => { await sharepoint.authenticate() expect(sharepoint.accessToken).to.not.eql(null) }) it('call the web endpoint', async () => { await sharepoint.getWebEndpoint() expect(sharepoint.baseUrl).to.not.eql(null) expect(sharepoint.encodedBaseUrl).to.not.eql(null) }) it('attempt to create a folder, without passing in a path', async () => { let error try { await sharepoint.createFolder() } catch (e) { error = e.message } expect(error).to.eql('You must provide a path.') }) it('attempt to delete a folder, without passing in a path', async () => { let error try { await sharepoint.deleteFolder() } catch (e) { error = e.message } expect(error).to.eql('You must provide a path.') }) it('attempt to create a file, without passing in a file name', async () => { let error try { await sharepoint.createFile({ path: process.env.SHAREPOINT_TESTS_DIR_PATH, data: '...' }) } catch (e) { error = e.message } expect(error).to.eql('You must provide a file name.') }) it('attempt to create a file, without passing in data', async () => { let error try { await sharepoint.createFile({ path: process.env.SHAREPOINT_TESTS_DIR_PATH, fileName: 'new file' }) } catch (e) { error = e.message } expect(error).to.eql('You must provide data.') }) it('attempt to delete a file, without passing in a file name', async () => { let error try { await sharepoint.deleteFile({ path: process.env.SHAREPOINT_TESTS_DIR_PATH }) } catch (e) { error = e.message } expect(error).to.eql('You must provide a file name.') }) it('get test directory contents, should be empty', async () => { const contents = await sharepoint.getContents(process.env.SHAREPOINT_TESTS_DIR_PATH) expect(contents.length).to.eql(0) }) it('check main test folder exists before creating it', async () => { const result = await sharepoint.checkFolderExists(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`) expect(result).to.eql(false) }) it('create main test folder', async () => { await sharepoint.createFolder(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`) }) it('check main test folder exists after creating it', async () => { const result = await sharepoint.checkFolderExists(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`) expect(result).to.eql(true) }) it('create test folder 2', async () => { await sharepoint.createFolder(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME2}`) }) it('create test folder 3', async () => { await sharepoint.createFolder(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME3}`) }) it('create test folder 4', async () => { await sharepoint.createFolder(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME4}`) }) it('get directory contents, check folders returned in expected natural order', async () => { const contents = await sharepoint.getContents(process.env.SHAREPOINT_TESTS_DIR_PATH) expect(contents.length).to.eql(4) expect(contents[0].Name).to.eql(FOLDER_NAME3) expect(contents[1].Name).to.eql(FOLDER_NAME1) expect(contents[2].Name).to.eql(FOLDER_NAME4) expect(contents[3].Name).to.eql(FOLDER_NAME2) }) it('get contents of new folder, should be empty', async () => { const contents = await sharepoint.getContents(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`) expect(contents).to.eql([]) }) it('create file in new folder', async () => { await sharepoint.createFile({ path: `${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`, fileName: TEXT_FILE_FILENAME, data: 'Testing 1 2 3...' }) }) it('get contents of new folder, expect new file', async () => { const contents = await sharepoint.getContents(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`) expect(contents.length).to.eql(1) expect(contents[0].Name).to.eql(TEXT_FILE_FILENAME) }) it('delete the new file', async () => { await sharepoint.deleteFile({ path: `${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`, fileName: TEXT_FILE_FILENAME }) }) it('get contents of new folder, new file should be deleted', async () => { const contents = await sharepoint.getContents(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`) expect(contents).to.eql([]) }) it('upload text file with filename 1', async () => { const data = getBinaryData(path.resolve(__dirname, 'fixtures', TEXT_FILE_FILENAME)) await sharepoint.createFile({ path: `${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`, fileName: FILE_NAME1, data }) }) it('upload text file with filename 2', async () => { const data = getBinaryData(path.resolve(__dirname, 'fixtures', TEXT_FILE_FILENAME)) await sharepoint.createFile({ path: `${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`, fileName: FILE_NAME2, data }) }) it('upload text file with filename 3', async () => { const data = getBinaryData(path.resolve(__dirname, 'fixtures', TEXT_FILE_FILENAME)) await sharepoint.createFile({ path: `${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`, fileName: FILE_NAME3, data }) }) it('upload text file with filename 4', async () => { const data = getBinaryData(path.resolve(__dirname, 'fixtures', TEXT_FILE_FILENAME)) await sharepoint.createFile({ path: `${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`, fileName: FILE_NAME4, data }) }) it('get directory contents, check files returned in expected natural order', async () => { const contents = await sharepoint.getContents(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`) expect(contents.length).to.eql(4) expect(contents[0].Name).to.eql(FILE_NAME3) expect(contents[1].Name).to.eql(FILE_NAME2) expect(contents[2].Name).to.eql(FILE_NAME4) expect(contents[3].Name).to.eql(FILE_NAME1) }) it('upload file of different format (png) from fixtures', async () => { const data = getBinaryData(path.resolve(__dirname, 'fixtures', BINARY_FILE_FILENAME)) await sharepoint.createFile({ path: `${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`, fileName: BINARY_FILE_FILENAME, data }) }) it('get contents of new folder, expect new png file from fixtures', async () => { const contents = await sharepoint.getContents(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`) expect(contents.length).to.eql(5) expect(contents[4].Name).to.eql(BINARY_FILE_FILENAME) }) it('upload file read in from fixtures using chunks', async () => { const filePath = path.resolve(__dirname, 'fixtures', BINARY_FILE_FILENAME) const { size } = fs.statSync(filePath) const stream = fs.createReadStream(filePath, { highWaterMark: 1024 * 2 }) await sharepoint.createFileChunked({ path: `${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`, fileName: BINARY_FILE_FILENAME, stream, fileSize: size, chunkSize: 1024 * 2 }) }) it('delete folder 1', async () => { await sharepoint.deleteFolder(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME1}`) }) it('delete folder 2', async () => { await sharepoint.deleteFolder(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME2}`) }) it('delete folder 3', async () => { await sharepoint.deleteFolder(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME3}`) }) it('delete folder 4', async () => { await sharepoint.deleteFolder(`${process.env.SHAREPOINT_TESTS_DIR_PATH}/${FOLDER_NAME4}`) }) it('get directory contents, check folders have been deleted', async () => { const contents = await sharepoint.getContents(process.env.SHAREPOINT_TESTS_DIR_PATH) expect(contents).to.not.eql(null) expect(contents.map(i => i.Name).includes(FOLDER_NAME1)).to.eql(false) expect(contents.map(i => i.Name).includes(FOLDER_NAME2)).to.eql(false) expect(contents.map(i => i.Name).includes(FOLDER_NAME3)).to.eql(false) expect(contents.map(i => i.Name).includes(FOLDER_NAME4)).to.eql(false) }) }) }) function getBinaryData (filepath) { const base64 = fs.readFileSync(filepath, { encoding: 'base64' }) const encodedBase64String = base64.replace(/^data:+[a-z]+\/+[a-z]+;base64,/, '') return Buffer.from(encodedBase64String, 'base64') }