UNPKG

8.17 kBJavaScriptView Raw
1'use strict'
2
3const sinon = require('sinon')
4const index = require('../index')
5const memory = require('../adaptors/in-memory')
6const local = require('../repositories/local')
7const remote = require('../repositories/remote')
8const ConflictError = require('../errors/conflict')
9const MigrationUpError = require('../errors/migration-up')
10const MigrationDownError = require('../errors/migration-down')
11
12describe('mygreat', () => {
13 describe('.from(localAdaptor Object, remoteAdaptor Object): Object', () => {
14 it('creates an instance of mygreat using built-in repositories', () => {
15 const mygreat = index.from(memory([]), memory([]))
16
17 expect( mygreat ).to.have.property('up')
18 expect( mygreat ).to.have.property('down')
19 })
20 })
21})
22
23describe('mygreat(localRepository Object, remoteRepository Object): Object', () => {
24 const localAdaptor = memory([
25 {
26 name: '20170914202400',
27 content: {
28 up: (spies) => { spies['20170914202400'].up() },
29 down: (spies) => { spies['20170914202400'].down() }
30 }
31 },
32 {
33 name: '20170914210100',
34 content: {
35 up: (spies) => { spies['20170914210100'].up() },
36 down: (spies) => { spies['20170914210100'].down() }
37 }
38 },
39 {
40 name: '20170914210300',
41 content: {
42 up: (spies) => { spies['20170914210300'].up() },
43 down: (spies) => { spies['20170914210300'].down() }
44 }
45 }
46 ])
47
48 describe('.up(...args): Promise<Object>', () => {
49 const mygreatConflict = index(local(localAdaptor), remote(memory([{
50 name: '832185ad-1041-2343-2342-2a80a7c23c4b',
51 content: [
52 '20170914210300'
53 ]
54 }])))
55
56 it('fails if there are any conflictable-unsynced migrations', () => {
57 return expect( mygreatConflict.up(null) )
58 .to.eventually.be.rejectedWith(ConflictError)
59 })
60
61 it('the error thrown in case of conflicts carries the array of conflicts', () => {
62 return expect( mygreatConflict.up(null).catch(err => err.conflicts) )
63 .to.eventually.be.an('array')
64 })
65
66 it('returns a migration registry', () => {
67 const mygreat = index(local(memory([])), remote(memory([])))
68 return expect( mygreat.up({}) ).to.eventually.have.property('content')
69 })
70
71 it('passes a given set of arguments to all unsynced migrations', () => {
72 const mygreat = index(local(localAdaptor), remote(memory([{
73 name: '832185ad-1041-2343-2342-2a80a7c23c4b',
74 content: [
75 '20170914202400',
76 ]
77 }])))
78
79 const arg = {
80 '20170914202400': { up: sinon.spy(), down: sinon.spy() },
81 '20170914210100': { up: sinon.spy(), down: sinon.spy() },
82 '20170914210300': { up: sinon.spy(), down: sinon.spy() },
83 }
84
85 return expect(
86 mygreat.up(arg)
87 .then(() => Object.values(arg).map(m => ({
88 up: m.up.calledOnce,
89 down: m.down.calledOnce
90 })))
91 ).to.eventually.be.deep.equals([
92 { up: false, down: false },
93 { up: true, down: false },
94 { up: true, down: false }
95 ])
96 })
97
98 it('none migrations are executed if everything is synced', () => {
99 const mygreat = index(local(localAdaptor), remote(memory([{
100 name: '832185ad-1041-2343-2342-2a80a7c23c4b',
101 content: [
102 '20170914202400',
103 '20170914210100',
104 '20170914210300'
105 ]
106 }])))
107
108 const arg = {
109 '20170914202400': { up: sinon.spy(), down: sinon.spy() },
110 '20170914210100': { up: sinon.spy(), down: sinon.spy() },
111 '20170914210300': { up: sinon.spy(), down: sinon.spy() },
112 }
113
114 return expect(
115 mygreat.up(arg)
116 .then(() => Object.values(arg).map(m => ({
117 up: m.up.calledOnce,
118 down: m.down.calledOnce
119 })))
120 ).to.eventually.be.deep.equals([
121 { up: false, down: false },
122 { up: false, down: false },
123 { up: false, down: false }
124 ])
125 })
126
127 it('creates a new registry on remote repository on success, if at least one migration file has ran', () => {
128 const adaptor = memory([{
129 name: '832185ad-1041-2343-2342-2a80a7c23c4b',
130 content: [
131 '20170914202400',
132 ]
133 }])
134
135 const mygreat = index(local(localAdaptor), remote(adaptor))
136
137 const arg = {
138 '20170914202400': { up: sinon.spy(), down: sinon.spy() },
139 '20170914210100': { up: sinon.spy(), down: sinon.spy() },
140 '20170914210300': { up: sinon.spy(), down: sinon.spy() },
141 }
142
143 return expect(
144 mygreat.up(arg)
145 .then(() => adaptor.all())
146 .then(all => all.length)
147 ).to.eventually.be.equals(2)
148 })
149
150 it('creates none new registry on remote repository on success when none migration files ran', () => {
151 const adaptor = memory([{
152 name: '832185ad-1041-2343-2342-2a80a7c23c4b',
153 content: [
154 '20170914202400',
155 '20170914210100',
156 '20170914210300'
157 ]
158 }])
159
160 const mygreat = index(local(localAdaptor), remote(adaptor))
161
162 const arg = {
163 '20170914202400': { up: sinon.spy(), down: sinon.spy() },
164 '20170914210100': { up: sinon.spy(), down: sinon.spy() },
165 '20170914210300': { up: sinon.spy(), down: sinon.spy() },
166 }
167
168 return expect(
169 mygreat.up(arg)
170 .then(() => adaptor.all())
171 .then(all => all.length)
172 ).to.eventually.be.equals(1)
173 })
174
175 it('throw a MigrationException if an exception is thrown during the execution', () => {
176 const crachable = index(local(memory([{
177 name: '20170914210300',
178 content: {
179 up: async (instance) => { throw Error('expected error') },
180 down: async (instance) => { }
181 }
182 }])), remote(memory([])))
183
184 return expect( crachable.up({}) )
185 .to.eventually.be.rejectedWith(MigrationUpError)
186 })
187
188 it('thrown MigrationException carries the migrationRegistry', () => {
189 const crachable = index(local(memory([{
190 name: '20170914210300',
191 content: {
192 up: async (instance) => { throw Error('expected error') },
193 down: async (instance) => { }
194 }
195 }])), remote(memory([])))
196
197 return expect( crachable.up({}).catch(err => err.migrationRegistry) )
198 .to.eventually.be.shallowDeepEqual({ content: [] })
199 })
200 })
201
202 describe('.down(...args): Promise<Object>', () => {
203 it('takes the latest migration registry\'s files and pass the given arguments to their down methods', () => {
204 const mygreat = index(local(memory([
205 { name: '20170914202400', content: { down: async (spies) => spies['20170914202400'].down() } },
206 { name: '20170914210100', content: { down: async (spies) => spies['20170914210100'].down() } },
207 ])), remote(memory([{
208 name: '832185ad-1041-2343-2342-2a80a7c23c4b',
209 content: [
210 '20170914202400',
211 '20170914210100'
212 ]
213 }])))
214
215 const arg = {
216 '20170914202400': { up: sinon.spy(), down: sinon.spy() },
217 '20170914210100': { up: sinon.spy(), down: sinon.spy() }
218 }
219
220 return expect(
221 mygreat.down(arg)
222 .then(() => Object.values(arg).map(m => ({
223 up: m.up.called,
224 down: m.down.called
225 })))
226 ).to.eventually.be.deep.equals([
227 { up: false, down: true },
228 { up: false, down: true }
229 ])
230 })
231
232 it('removes the migration registry after the execution', () => {
233 const remoteAdaptor = memory([{
234 name: '832185ad-1041-2343-2342-2a80a7c23c4b',
235 content: [
236 '20170914202400',
237 '20170914210100'
238 ]
239 }])
240
241 const mygreat = index(local(memory([
242 { name: '20170914202400', content: { down: async () => { } } },
243 { name: '20170914210100', content: { down: async () => { } } },
244 ])), remote(remoteAdaptor))
245
246 return expect(
247 mygreat.down(null)
248 .then(() => remoteAdaptor.all())
249 ).to.eventually.be.deep.equals([])
250 })
251 })
252})