@orbit-love/stackoverflow
Version:
A community project to integrate Stack Overflow interactions into Orbit workspaces
196 lines (170 loc) • 7.86 kB
JavaScript
/**
* @jest-environment node
*/
const OrbitActivities = require('@orbit-love/activities')
const OrbitStackOverflow = require('../src/index.js')
const STACK_OVERFLOW_QUESTIONS = require('./STACK_OVERFLOW_QUESTIONS.json')
beforeAll(() => {
jest.spyOn(OrbitStackOverflow.prototype, 'getQuestions').mockImplementation(options => {
if(!options.tag) throw new Error('You must provide a tag')
if(!options.hours) throw new Error('You must provide hours')
return Promise.resolve(STACK_OVERFLOW_QUESTIONS.items)
})
})
describe('client', () => {
it('initializes with arguments passed in directly', () => {
envVars(false)
const orbitStackOverflow = new OrbitStackOverflow('val1', 'val2', 'val3')
expect(orbitStackOverflow.credentials.orbitWorkspaceId).toBe('val1')
expect(orbitStackOverflow.credentials.orbitApiKey).toBe('val2')
expect(orbitStackOverflow.credentials.stackAppsKey).toBe('val3')
})
it('initializes with credentials from environment variables', () => {
envVars(true)
new OrbitStackOverflow()
})
it('throws with incomplete set of credentials', () => {
expect(() => { envVars(false); process.env.ORBIT_WORKSPACE_ID = "val1"; new OrbitStackOverflow(); }).toThrow()
expect(() => { envVars(false); process.env.ORBIT_API_KEY = "val2"; new OrbitStackOverflow(); } ).toThrow()
expect(() => { envVars(false); process.env.STACK_APPS_KEY = "val3"; new OrbitStackOverflow(); } ).toThrow()
expect(() => {
envVars(false)
process.env.ORBIT_WORKSPACE_ID = "val1"
process.env.ORBIT_API_KEY = "val2"
new OrbitStackOverflow()
}).toThrow()
expect(() => {
envVars(false)
process.env.ORBIT_API_KEY = "val2"
process.env.STACK_APPS_KEY= "val3"
new OrbitStackOverflow()
}).toThrow()
expect(() => {
envVars(false)
process.env.ORBIT_WORKSPACE_ID = "val2"
process.env.STACK_APPS_KEY= "val3"
new OrbitStackOverflow()
}).toThrow()
expect(() => { envVars(false); new OrbitStackOverflow('val1', 'val2') }).toThrow()
expect(() => { envVars(false); new OrbitStackOverflow('val1') }).toThrow()
})
})
describe('get questions', () => {
it('returns array', async () => {
envVars(true)
const orbitStackOverflow = new OrbitStackOverflow()
const questions = await orbitStackOverflow.getQuestions({ tag: 'javascript', hours: 1 })
expect(Array.isArray(questions)).toBe(true)
})
it('requires hours', async () => {
try {
const orbitStackOverflow = new OrbitStackOverflow()
await orbitStackOverflow.getQuestions({ tag: 'javascript' })
fail()
} catch(error) {
expect(String(error).includes('hours')).toBeTruthy()
}
})
it('requires tag', async () => {
try {
const orbitStackOverflow = new OrbitStackOverflow()
await orbitStackOverflow.getQuestions({ hours: 12 })
fail()
} catch(error) {
expect(String(error).includes('tag')).toBeTruthy()
}
})
})
describe('prepare questions', () => {
it('returns array of same size as the input', async () => {
envVars(true)
const orbitStackOverflow = new OrbitStackOverflow()
const questions = await orbitStackOverflow.getQuestions({ tag: 'javascript', hours: 1 })
const prepared = await orbitStackOverflow.prepareQuestions(questions)
expect(questions.length).toEqual(prepared.length)
}),
it('structure is correct', async () => {
envVars(true)
const orbitStackOverflow = new OrbitStackOverflow()
const questions = await orbitStackOverflow.getQuestions({ tag: 'javascript', hours: 1 })
const prepared = await orbitStackOverflow.prepareQuestions(questions)
const p = prepared[0]
expect(p.activity).toBeTruthy()
expect(p.activity.activity_type).toBe('stackoverflow:question')
expect(p.activity.title).toBeTruthy()
expect(p.identity.source_host).toBe('stackoverflow.com')
}),
it('determines username value', async() => {
envVars(true)
const orbitStackOverflow = new OrbitStackOverflow()
const questions = await orbitStackOverflow.getQuestions({ tag: 'javascript', hours: 1 })
const prepared = await orbitStackOverflow.prepareQuestions(questions)
// registered user
const p0 = prepared[0]
expect(p0.identity.username).toBeTruthy()
expect(p0.identity.url).toBeDefined()
// unregistered user
const p2 = prepared[2]
expect(p2.identity.username).toBeTruthy()
expect(p2.identity.url).toBeUndefined()
})
})
describe('addActivities', () => {
it('builds a `stats` object with `added`, `duplicates` and `errors`', async () => {
const orbitStackOverflow = new OrbitStackOverflow()
const addedActivities = await orbitStackOverflow.addActivities([])
expect(addedActivities).toEqual({"added": 0, "duplicates": 0, "errors": []})
})
it('increments `added` for each activity creation', async () => {
jest.spyOn(OrbitActivities.prototype, 'createActivity').mockImplementation(() => {
// Simulates a successful activity creation
return Promise.resolve()
})
const orbitStackOverflow = new OrbitStackOverflow()
const addedActivities = await orbitStackOverflow.addActivities([{}])
expect(addedActivities.added).toBe(1)
expect(addedActivities.duplicates).toBe(0)
expect(addedActivities.errors).toEqual([])
})
it('increments `duplicate` for each activity that already exists', async () => {
jest.spyOn(OrbitActivities.prototype, 'createActivity').mockImplementation(() => {
// Simulates a successful activity creation
return Promise.reject({errors: { key: 'key already exists' } })
})
const orbitStackOverflow = new OrbitStackOverflow()
const addedActivities = await orbitStackOverflow.addActivities([{}])
expect(addedActivities.added).toBe(0)
expect(addedActivities.duplicates).toBe(1)
expect(addedActivities.errors).toEqual([])
})
it('pushes other errors to `errors`', async () => {
jest.spyOn(OrbitActivities.prototype, 'createActivity').mockImplementation(() => {
// Simulates a successful activity creation
return Promise.reject({errors: { name: 'is too long (maximum is 250 characters)' } })
})
const orbitStackOverflow = new OrbitStackOverflow()
const addedActivities = await orbitStackOverflow.addActivities([{}])
expect(addedActivities.added).toBe(0)
expect(addedActivities.duplicates).toBe(0)
expect(addedActivities.errors).toEqual([{errors: {name: 'is too long (maximum is 250 characters)'}}])
})
it('throws if the workspace ID does not resolve to a workspace', async () => {
jest.spyOn(OrbitActivities.prototype, 'createActivity').mockImplementation(() => {
// Simulates a 404 error
return Promise.reject({error: 'Not found'})
})
const orbitStackOverflow = new OrbitStackOverflow()
await expect(orbitStackOverflow.addActivities([{}])).rejects.toThrow(/No workspace found/)
})
})
function envVars(toHaveVars) {
if(toHaveVars) {
process.env.ORBIT_WORKSPACE_ID = 'var1'
process.env.ORBIT_API_KEY = 'var2'
process.env.STACK_APPS_KEY = 'var3'
} else {
delete process.env.ORBIT_WORKSPACE_ID
delete process.env.ORBIT_API_KEY
delete process.env.STACK_APPS_KEY
}
}