
These are some changes in the way the monorepo is structured, that are aimed at making it easier to get started. There are two important changes: **Multiple workspaces** We had a yarn workspaces setup at `packages/*`. But our monorepo has grown to 92 packages which can be overwhelming for people not familiar with the package names. To remedy this, I've split it into 4 different workspaces: - `designs/*`: Holds FreeSewing designs (think patterns) - `plugins/*`: Holds FreeSewing plugins - `packages/*`: Holds other packages published on NPM - `sites/*`: Holds software that is not published as an NPM package, such as our various websites and backend API This should make it easier to find things, and to answer questions like *where do I find the code for the plugins*. **Updated reconfigure script to handle build order** One problem when bootstrapping the repo is inter-dependencies between packages. For example, building a pattern will only work once `plugin-bundle` is built. Which will only work once all plugins in the bundle or built. And that will only work when `core` is built, and so on. This can be frustrating for new users as `yarn buildall` will fail. And it gets overlooked by seasoned devs because they're likely to have every package built in their repo so this issue doesn't concern them. To remedy this, we now have a `config/build-order.mjs` file and the updated `/scripts/reconfigure.mjs` script will enforce the build order so that things *just work*.
349 lines
9.6 KiB
JavaScript
349 lines
9.6 KiB
JavaScript
module.exports = function tests(store, config, chai) {
|
|
describe('Non language-specific User controller signup routes', () => {
|
|
it('should not create signup without email address', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.post('/signup')
|
|
.send({
|
|
password: config.user.password,
|
|
language: 'en'
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(400)
|
|
res.text.should.equal('emailMissing')
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should not create signup without password', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.post('/signup')
|
|
.send({
|
|
email: config.user.email,
|
|
language: 'en'
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(400)
|
|
res.text.should.equal('passwordMissing')
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should not create signup without language', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.post('/signup')
|
|
.send({
|
|
email: config.user.email,
|
|
password: config.user.password
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(400)
|
|
res.text.should.equal('languageMissing')
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('Login/Logout and session handling', () => {
|
|
it('should login with the username', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.post('/login')
|
|
.send({
|
|
username: config.user.username,
|
|
password: config.user.password
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
let data = JSON.parse(res.text)
|
|
data.account.username.should.equal(config.user.username)
|
|
data.token.should.be.a('string')
|
|
config.user.token = data.token
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should login with the email address', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.post('/login')
|
|
.send({
|
|
username: config.user.email,
|
|
password: config.user.password
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
let data = JSON.parse(res.text)
|
|
data.account.username.should.equal(config.user.username)
|
|
data.token.should.be.a('string')
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should load account with JSON Web Token', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.get('/account')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.end((err, res) => {
|
|
if (err) console.log(err)
|
|
let data = JSON.parse(res.text)
|
|
res.should.have.status(200)
|
|
data.account.username.should.equal(config.user.username)
|
|
// Enable this once cleanup is implemented
|
|
//Object.keys(data.recipes).length.should.equal(0)
|
|
//Object.keys(data.people).length.should.equal(0)
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('Account management', () => {
|
|
it('should update the account avatar', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.put('/account')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.send({
|
|
avatar: config.avatar
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
let data = JSON.parse(res.text)
|
|
data.account.pictureUris.l.slice(-4).should.equal('.png')
|
|
done()
|
|
})
|
|
})
|
|
it('should update the account username', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.put('/account')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.send({
|
|
username: config.user.username + '_updated'
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
let data = JSON.parse(res.text)
|
|
data.account.username.should.equal(config.user.username + '_updated')
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should restore the account username', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.put('/account')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.send({
|
|
username: config.user.username
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
let data = JSON.parse(res.text)
|
|
data.account.username.should.equal(config.user.username)
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should not update the account username if that username is taken', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.put('/account')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.send({
|
|
username: 'admin'
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(400)
|
|
res.text.should.equal('usernameTaken')
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should update the account bio', done => {
|
|
let bio = 'This is the test bio '
|
|
chai
|
|
.request(config.backend)
|
|
.put('/account')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.send({
|
|
bio: bio
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
let data = JSON.parse(res.text)
|
|
data.account.bio.should.equal(bio)
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should update the account language', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.put('/account')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.send({
|
|
settings: {
|
|
language: 'nl'
|
|
}
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
let data = JSON.parse(res.text)
|
|
data.account.settings.language.should.equal('nl')
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should update the account units', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.put('/account')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.send({
|
|
settings: {
|
|
units: 'imperial'
|
|
}
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
let data = JSON.parse(res.text)
|
|
data.account.settings.units.should.equal('imperial')
|
|
done()
|
|
})
|
|
})
|
|
|
|
for (let network of ['github', 'twitter', 'instagram']) {
|
|
it(`should update the account's ${network} username`, done => {
|
|
let data = { social: {} }
|
|
data.social[network] = network
|
|
chai
|
|
.request(config.backend)
|
|
.put('/account')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.send(data)
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
JSON.parse(res.text).account.social[network].should.equal(network)
|
|
done()
|
|
})
|
|
})
|
|
}
|
|
|
|
it('should update the account password', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.put('/account')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.send({
|
|
password: 'changeme'
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should login with the new password', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.post('/login')
|
|
.send({
|
|
username: config.user.username,
|
|
password: 'changeme'
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should restore the account password', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.put('/account')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.send({
|
|
password: config.user.password
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('Other user endpoints', () => {
|
|
it("should load a user's profile", done => {
|
|
chai
|
|
.request(config.backend)
|
|
.get('/users/admin')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
let data = JSON.parse(res.text)
|
|
data.username.should.equal('admin')
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should confirm that a username is available', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.post('/available/username')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.send({
|
|
username: Date.now() + ' ' + Date.now()
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should confirm that a username is not available', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.post('/available/username')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.send({
|
|
username: 'admin'
|
|
})
|
|
.end((err, res) => {
|
|
res.should.have.status(400)
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should load the patron list', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.get('/patrons')
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
let data = JSON.parse(res.text)
|
|
data['2'].should.be.an('array')
|
|
data['4'].should.be.an('array')
|
|
data['8'].should.be.an('array')
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('should export the user data', done => {
|
|
chai
|
|
.request(config.backend)
|
|
.get('/account/export')
|
|
.set('Authorization', 'Bearer ' + config.user.token)
|
|
.end((err, res) => {
|
|
res.should.have.status(200)
|
|
let data = JSON.parse(res.text)
|
|
data.export.should.be.a('string')
|
|
store.exportLink = data.export
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
}
|