feat(gift): 받을 주소 관리 및 카카오 주소 검색 추가
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@
|
||||
"serve": "vue-cli-service serve --port 8888",
|
||||
"build": "vue-cli-service build",
|
||||
"build_development": "vue-cli-service build --mode development",
|
||||
"test:gift": "node tests/gift.test.js && node tests/gift_category.test.js && node tests/gift_size.test.js",
|
||||
"test:gift": "node tests/gift.test.js && node tests/gift_category.test.js && node tests/gift_size.test.js && node tests/gift_mailbox.test.js",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
const baseUrl = '/api/v2/admin/gift-mailbox'
|
||||
|
||||
async function getGiftMailbox() {
|
||||
const response = await Vue.axios.get(baseUrl)
|
||||
return response.data
|
||||
}
|
||||
|
||||
async function updateGiftMailbox(request) {
|
||||
const response = await Vue.axios.put(baseUrl, request)
|
||||
return response.data
|
||||
}
|
||||
|
||||
export { getGiftMailbox, updateGiftMailbox }
|
||||
@@ -118,6 +118,9 @@ export default {
|
||||
if (!giftMenu.items.some(item => item && item.route === '/gift/size')) {
|
||||
giftMenu.items.push({ title: '선물 사이즈', route: '/gift/size', items: null })
|
||||
}
|
||||
if (!giftMenu.items.some(item => item && item.route === '/gift/mailbox')) {
|
||||
giftMenu.items.push({ title: '받을 주소', route: '/gift/mailbox', items: null })
|
||||
}
|
||||
} else {
|
||||
this.items.push({
|
||||
title: '선물함 관리',
|
||||
@@ -126,7 +129,8 @@ export default {
|
||||
items: [
|
||||
{ title: '선물함 리스트', route: '/gift/list', items: null },
|
||||
{ title: '선물 카테고리', route: '/gift/category', items: null },
|
||||
{ title: '선물 사이즈', route: '/gift/size', items: null }
|
||||
{ title: '선물 사이즈', route: '/gift/size', items: null },
|
||||
{ title: '받을 주소', route: '/gift/mailbox', items: null }
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
@@ -377,6 +377,11 @@ const routes = [
|
||||
name: 'GiftSize',
|
||||
component: () => import(/* webpackChunkName: "gift" */ '../views/Gift/GiftSize.vue')
|
||||
},
|
||||
{
|
||||
path: '/gift/mailbox',
|
||||
name: 'GiftMailbox',
|
||||
component: () => import(/* webpackChunkName: "gift" */ '../views/Gift/GiftMailbox.vue')
|
||||
},
|
||||
{
|
||||
path: '/original-work',
|
||||
name: 'OriginalList',
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
let loading
|
||||
|
||||
export function loadPostcode() {
|
||||
if (window.daum && window.daum.Postcode) return Promise.resolve(window.daum.Postcode)
|
||||
if (loading) return loading
|
||||
loading = new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script')
|
||||
const finish = error => {
|
||||
clearTimeout(timer)
|
||||
script.onload = null
|
||||
script.onerror = null
|
||||
if (error) {
|
||||
script.remove()
|
||||
loading = null
|
||||
reject(error)
|
||||
} else {
|
||||
resolve(window.daum.Postcode)
|
||||
}
|
||||
}
|
||||
const timer = setTimeout(() => finish(new Error('주소 검색을 불러오지 못했습니다. 다시 시도해주세요.')), 15000)
|
||||
script.src = 'https://t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js'
|
||||
script.async = true
|
||||
script.onload = () => finish(window.daum && window.daum.Postcode ? null : new Error('주소 검색을 불러오지 못했습니다. 다시 시도해주세요.'))
|
||||
script.onerror = () => finish(new Error('주소 검색을 불러오지 못했습니다. 다시 시도해주세요.'))
|
||||
document.head.appendChild(script)
|
||||
})
|
||||
return loading
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-toolbar dark>
|
||||
<v-spacer />
|
||||
<v-toolbar-title>받을 주소</v-toolbar-title>
|
||||
<v-spacer />
|
||||
</v-toolbar>
|
||||
|
||||
<br>
|
||||
|
||||
<v-container fluid>
|
||||
<p>팬이 선물을 발송할 때 확인하는 받을 주소입니다.</p>
|
||||
<v-progress-linear
|
||||
v-if="is_loading"
|
||||
indeterminate
|
||||
/>
|
||||
<v-alert
|
||||
v-if="load_error"
|
||||
type="error"
|
||||
text
|
||||
>
|
||||
받을 주소를 불러오지 못했습니다.
|
||||
<v-btn
|
||||
text
|
||||
:disabled="is_loading"
|
||||
@click="getMailbox"
|
||||
>
|
||||
다시 조회
|
||||
</v-btn>
|
||||
</v-alert>
|
||||
<p v-else-if="loaded && !mailbox">
|
||||
등록된 받을 주소가 없습니다. 주소를 입력하고 저장해주세요.
|
||||
</p>
|
||||
<v-card>
|
||||
<v-form @submit.prevent="saveMailbox">
|
||||
<v-card-text>
|
||||
<div
|
||||
v-for="field in fields"
|
||||
:key="field.key"
|
||||
:class="{ 'mailbox-postcode-row': field.key === 'zipCode' }"
|
||||
>
|
||||
<v-text-field
|
||||
:key="field.key"
|
||||
v-model="form[field.key]"
|
||||
:label="field.label"
|
||||
:readonly="field.key === 'zipCode' || field.key === 'address'"
|
||||
:disabled="field.key === 'zipCode' || field.key === 'address' || !loaded || is_loading || is_operating"
|
||||
:filled="field.key === 'zipCode' || field.key === 'address'"
|
||||
:error-messages="form_errors[field.key]"
|
||||
outlined
|
||||
dense
|
||||
@input="$set(form_errors, field.key, '')"
|
||||
/>
|
||||
<v-btn
|
||||
v-if="field.key === 'zipCode'"
|
||||
type="button"
|
||||
outlined
|
||||
color="primary"
|
||||
height="40"
|
||||
:disabled="!loaded || is_loading || is_operating"
|
||||
@click="openAddressSearch"
|
||||
>
|
||||
주소 검색
|
||||
</v-btn>
|
||||
</div>
|
||||
<p class="text-caption grey--text text--darken-1">
|
||||
우편번호와 주소는 주소 검색으로 입력해주세요. 상세주소는 직접 입력할 수 있습니다.
|
||||
</p>
|
||||
<p v-if="mailbox">
|
||||
등록된 받을 주소: {{ mailbox.address }}
|
||||
</p>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
type="submit"
|
||||
color="primary"
|
||||
:loading="is_operating"
|
||||
:disabled="!loaded || is_loading || is_operating"
|
||||
>
|
||||
저장
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-form>
|
||||
</v-card>
|
||||
</v-container>
|
||||
<v-dialog
|
||||
v-model="show_address_search"
|
||||
max-width="560px"
|
||||
>
|
||||
<v-card>
|
||||
<v-card-title>주소 검색</v-card-title>
|
||||
<v-card-text>
|
||||
<v-progress-linear
|
||||
v-if="is_postcode_loading"
|
||||
indeterminate
|
||||
/>
|
||||
<div
|
||||
ref="postcodeContainer"
|
||||
style="width: 100%; height: 500px;"
|
||||
/>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
text
|
||||
@click="show_address_search = false"
|
||||
>
|
||||
닫기
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as api from '@/api/gift_mailbox'
|
||||
import { loadPostcode } from '@/utils/postcode'
|
||||
|
||||
export default {
|
||||
name: 'GiftMailbox',
|
||||
data() {
|
||||
return {
|
||||
fields: [
|
||||
{ key: 'name', label: '받을 사람 이름', required: true },
|
||||
{ key: 'phoneNumber', label: '연락처', required: true },
|
||||
{ key: 'zipCode', label: '우편번호', required: true },
|
||||
{ key: 'address', label: '주소', required: true },
|
||||
{ key: 'addressDetail', label: '상세주소', required: false }
|
||||
],
|
||||
form: { name: '', phoneNumber: '', zipCode: '', address: '', addressDetail: '' },
|
||||
form_errors: {},
|
||||
mailbox: null,
|
||||
loaded: false,
|
||||
load_error: false,
|
||||
is_loading: false,
|
||||
show_address_search: false,
|
||||
is_postcode_loading: false,
|
||||
postcodeRequestId: 0,
|
||||
is_operating: false
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
await this.getMailbox()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.postcodeRequestId++
|
||||
},
|
||||
methods: {
|
||||
async openAddressSearch() {
|
||||
if (!this.loaded || this.is_loading || this.is_operating) return
|
||||
const requestId = ++this.postcodeRequestId
|
||||
this.show_address_search = true
|
||||
this.is_postcode_loading = true
|
||||
try {
|
||||
const Postcode = await loadPostcode()
|
||||
await this.$nextTick()
|
||||
if (requestId !== this.postcodeRequestId || !this.show_address_search) return
|
||||
this.$refs.postcodeContainer.innerHTML = ''
|
||||
new Postcode({
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
oncomplete: data => {
|
||||
if (requestId !== this.postcodeRequestId || !this.show_address_search || this.is_operating) return
|
||||
this.form.zipCode = data.zonecode
|
||||
this.form.address = data.userSelectedType === 'R' ? data.roadAddress : data.jibunAddress
|
||||
this.form.addressDetail = ''
|
||||
this.$set(this.form_errors, 'zipCode', '')
|
||||
this.$set(this.form_errors, 'address', '')
|
||||
this.show_address_search = false
|
||||
}
|
||||
}).embed(this.$refs.postcodeContainer)
|
||||
} catch (error) {
|
||||
if (requestId !== this.postcodeRequestId || !this.show_address_search) return
|
||||
this.show_address_search = false
|
||||
this.notifyError(error)
|
||||
} finally {
|
||||
if (requestId === this.postcodeRequestId) this.is_postcode_loading = false
|
||||
}
|
||||
},
|
||||
notifyError(error) {
|
||||
const response = error.response && error.response.data
|
||||
this.$dialog.notify.error((response && response.message) || error.message || '알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
|
||||
},
|
||||
checkResponse(response) {
|
||||
if (response.success !== true) throw new Error(response.message || '알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
|
||||
},
|
||||
async getMailbox() {
|
||||
if (this.is_loading || this.is_operating) return
|
||||
this.is_loading = true
|
||||
this.loaded = false
|
||||
this.load_error = false
|
||||
try {
|
||||
const response = await api.getGiftMailbox()
|
||||
this.checkResponse(response)
|
||||
this.mailbox = response.data
|
||||
const item = response.data || {}
|
||||
const address = item.address || ''
|
||||
const parts = address.match(/^\(([^)]+)\)\s*(.*)$/)
|
||||
const street = parts ? parts[2] : address
|
||||
const separator = street.indexOf(', ')
|
||||
this.form = {
|
||||
name: item.name || '',
|
||||
phoneNumber: item.phoneNumber || '',
|
||||
zipCode: parts ? parts[1] : '',
|
||||
address: separator < 0 ? street : street.slice(0, separator),
|
||||
addressDetail: separator < 0 ? '' : street.slice(separator + 2)
|
||||
}
|
||||
this.form_errors = {}
|
||||
this.loaded = true
|
||||
} catch (error) {
|
||||
this.load_error = true
|
||||
this.notifyError(error)
|
||||
} finally {
|
||||
this.is_loading = false
|
||||
}
|
||||
},
|
||||
async saveMailbox() {
|
||||
if (!this.loaded || this.is_loading || this.is_operating) return
|
||||
const request = {}
|
||||
this.form_errors = {}
|
||||
this.fields.forEach(field => {
|
||||
const value = (this.form[field.key] || '').trim()
|
||||
request[field.key] = field.required ? value : value || null
|
||||
if (field.required && !value) {
|
||||
this.$set(this.form_errors, field.key, `${field.label}을(를) 입력해주세요.`)
|
||||
}
|
||||
})
|
||||
if (Object.keys(this.form_errors).length) return
|
||||
this.is_operating = true
|
||||
try {
|
||||
const response = await api.updateGiftMailbox(request)
|
||||
this.checkResponse(response)
|
||||
this.mailbox = response.data
|
||||
this.form.name = response.data.name
|
||||
this.form.phoneNumber = response.data.phoneNumber
|
||||
this.$dialog.notify.success('받을 주소가 저장되었습니다.')
|
||||
} catch (error) {
|
||||
this.notifyError(error)
|
||||
} finally {
|
||||
this.is_operating = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mailbox-postcode-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 200px) max-content;
|
||||
gap: 12px;
|
||||
align-items: start;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,294 @@
|
||||
const assert = require('assert').strict
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const Module = require('module')
|
||||
const { transformSync } = require('@babel/core')
|
||||
const compiler = require('vue-template-compiler')
|
||||
const Vue = require('vue')
|
||||
|
||||
const root = path.resolve(__dirname, '..')
|
||||
const originalResolve = Module._resolveFilename
|
||||
Module._resolveFilename = function(request, parent, ...rest) {
|
||||
return originalResolve.call(this, request.startsWith('@/') ? path.join(root, 'src', request.slice(2)) : request, parent, ...rest)
|
||||
}
|
||||
const originalJs = require.extensions['.js']
|
||||
function compileScript(source, filename) {
|
||||
return transformSync(source, {
|
||||
filename, babelrc: false, configFile: false,
|
||||
plugins: ['@babel/plugin-transform-modules-commonjs']
|
||||
}).code
|
||||
}
|
||||
require.extensions['.js'] = (module, filename) => {
|
||||
if (!filename.startsWith(path.join(root, 'src') + path.sep)) return originalJs(module, filename)
|
||||
module._compile(compileScript(fs.readFileSync(filename, 'utf8'), filename), filename)
|
||||
}
|
||||
require.extensions['.vue'] = (module, filename) => {
|
||||
const { script, template } = compiler.parseComponent(fs.readFileSync(filename, 'utf8'))
|
||||
assert.deepEqual(compiler.compile(template.content).errors, [])
|
||||
module._compile(compileScript(script.content, filename), filename)
|
||||
Object.assign(module.exports.default, compiler.compileToFunctions(template.content))
|
||||
}
|
||||
|
||||
const GiftMailbox = require('../src/views/Gift/GiftMailbox.vue').default
|
||||
const SideMenu = require('../src/components/SideMenu.vue').default
|
||||
const tests = []
|
||||
const test = (name, run) => tests.push({ name, run })
|
||||
const envelope = data => ({ data: { success: true, data } })
|
||||
const saved = { name: '운영팀', phoneNumber: '010-1234-5678', address: '(01234) 서울시 도로 1, 2층, 운영실' }
|
||||
const form = () => ({ name: ' 운영팀 ', phoneNumber: ' 010-1234-5678 ', zipCode: '01234', address: '서울시 도로 1', addressDetail: '2층, 운영실' })
|
||||
function page() {
|
||||
const vm = new Vue({ ...GiftMailbox, created: undefined })
|
||||
const errors = []
|
||||
const successes = []
|
||||
vm.$dialog = { notify: { error: message => errors.push(message), success: message => successes.push(message) } }
|
||||
return { vm, errors, successes }
|
||||
}
|
||||
function nodes(vnode) {
|
||||
return vnode ? [vnode].concat((vnode.children || []).flatMap(nodes)) : []
|
||||
}
|
||||
const text = vm => nodes(vm._render()).map(node => node.text || '').join('')
|
||||
|
||||
test('초기 GET과 null 빈 폼, 안내 및 필드 표시', async () => {
|
||||
const { vm } = page()
|
||||
const calls = []
|
||||
Vue.axios = { get: async (...args) => { calls.push(args); return envelope(null) } }
|
||||
await GiftMailbox.created.call(vm)
|
||||
assert.deepEqual(calls, [['/api/v2/admin/gift-mailbox']])
|
||||
assert.ok(Object.values(vm.form).every(value => value === ''))
|
||||
assert.ok(text(vm).includes('등록된 받을 주소가 없습니다.'))
|
||||
assert.equal(nodes(vm._render()).filter(node => node.tag === 'v-text-field').length, 5)
|
||||
})
|
||||
|
||||
test('등록된 주소 조회 및 상세주소 없는 주소 편집', async () => {
|
||||
const { vm } = page()
|
||||
Vue.axios = { get: async () => envelope(saved) }
|
||||
await vm.getMailbox()
|
||||
assert.deepEqual(vm.form, { ...form(), name: saved.name, phoneNumber: saved.phoneNumber })
|
||||
Vue.axios.get = async () => envelope({ ...saved, address: '(01234) 서울시 도로 1' })
|
||||
await vm.getMailbox()
|
||||
assert.equal(vm.form.address, '서울시 도로 1')
|
||||
assert.equal(vm.form.addressDetail, '')
|
||||
})
|
||||
|
||||
test('필수값 공백 시 필드 오류 표시 및 PUT 차단', async () => {
|
||||
const { vm } = page()
|
||||
vm.loaded = true
|
||||
let calls = 0
|
||||
Vue.axios = { put: async () => { calls++ } }
|
||||
for (const key of ['name', 'phoneNumber', 'zipCode', 'address']) {
|
||||
for (const value of ['', ' \t\n ', null]) {
|
||||
vm.form = { ...form(), [key]: value }
|
||||
await vm.saveMailbox()
|
||||
assert.deepEqual(Object.keys(vm.form_errors), [key])
|
||||
const field = nodes(vm._render()).find(node => node.tag === 'v-text-field' && node.key === key)
|
||||
assert.ok(field.data.attrs['error-messages'])
|
||||
}
|
||||
}
|
||||
assert.equal(calls, 0)
|
||||
})
|
||||
|
||||
test('생성·수정 PUT 본문, 선택값 null, 성공 알림 및 서버 응답 반영', async () => {
|
||||
for (const detail of ['2층, 운영실', ' ']) {
|
||||
const { vm, successes } = page()
|
||||
vm.loaded = true
|
||||
vm.form = { ...form(), addressDetail: detail, extra: '제외' }
|
||||
const calls = []
|
||||
const result = { ...saved, name: '서버 이름', phoneNumber: '서버 연락처' }
|
||||
Vue.axios = { put: async (...args) => { calls.push(args); return envelope(result) } }
|
||||
await vm.saveMailbox()
|
||||
await vm.saveMailbox()
|
||||
assert.equal(calls.length, 2)
|
||||
assert.deepEqual(calls[0], ['/api/v2/admin/gift-mailbox', {
|
||||
...form(), name: saved.name, phoneNumber: saved.phoneNumber, addressDetail: detail.trim() || null
|
||||
}])
|
||||
assert.equal(vm.form.name, result.name)
|
||||
assert.equal(vm.form.phoneNumber, result.phoneNumber)
|
||||
assert.equal(vm.form.address, form().address)
|
||||
assert.equal(vm.form.addressDetail, detail)
|
||||
assert.equal(successes.length, 2)
|
||||
assert.ok(text(vm).includes(saved.address))
|
||||
}
|
||||
})
|
||||
|
||||
test('조회·저장 실패 알림, 입력 유지, 조회 재시도', async () => {
|
||||
for (const fail of [
|
||||
async () => ({ data: { success: false, message: '실패' } }),
|
||||
async () => { throw { response: { data: { message: '실패' } } } }
|
||||
]) {
|
||||
const { vm, errors, successes } = page()
|
||||
let puts = 0
|
||||
Vue.axios = { get: fail, put: async () => { puts++; return fail() } }
|
||||
await vm.getMailbox()
|
||||
await vm.saveMailbox()
|
||||
assert.equal(puts, 0)
|
||||
assert.equal(vm.load_error, true)
|
||||
assert.ok(text(vm).includes('다시 조회'))
|
||||
Vue.axios.get = async () => envelope(null)
|
||||
await vm.getMailbox()
|
||||
vm.form = form()
|
||||
await vm.saveMailbox()
|
||||
assert.deepEqual(vm.form, form())
|
||||
assert.deepEqual(errors, ['실패', '실패'])
|
||||
assert.deepEqual(successes, [])
|
||||
assert.equal(vm.is_operating, false)
|
||||
}
|
||||
})
|
||||
|
||||
test('조회 중 저장 및 중복 저장 차단', async () => {
|
||||
const { vm } = page()
|
||||
let resolve
|
||||
let puts = 0
|
||||
Vue.axios = {
|
||||
get: () => new Promise(done => { resolve = done }),
|
||||
put: () => { puts++; return new Promise(done => { resolve = done }) }
|
||||
}
|
||||
const load = vm.getMailbox()
|
||||
await vm.saveMailbox()
|
||||
assert.equal(puts, 0)
|
||||
resolve(envelope(null))
|
||||
await load
|
||||
vm.form = form()
|
||||
const save = vm.saveMailbox()
|
||||
await vm.saveMailbox()
|
||||
assert.equal(puts, 1)
|
||||
resolve(envelope(saved))
|
||||
await save
|
||||
})
|
||||
|
||||
test('주소 검색 선택: 읽기 전용 필드, 도로명·지번 선택 및 PUT 반영', async () => {
|
||||
const postcode = require('../src/utils/postcode')
|
||||
const original = postcode.loadPostcode
|
||||
try {
|
||||
for (const type of ['R', 'J']) {
|
||||
const { vm } = page()
|
||||
vm.loaded = true
|
||||
vm.form = form()
|
||||
vm.form_errors = { zipCode: '필수', address: '필수' }
|
||||
vm.$refs.postcodeContainer = { innerHTML: '이전 검색' }
|
||||
let options
|
||||
postcode.loadPostcode = async () => function(config) {
|
||||
options = config
|
||||
this.embed = container => assert.equal(container, vm.$refs.postcodeContainer)
|
||||
}
|
||||
const fields = nodes(vm._render()).filter(node => node.tag === 'v-text-field')
|
||||
for (const field of fields) {
|
||||
assert.equal(field.data.attrs.readonly, ['zipCode', 'address'].includes(field.key))
|
||||
assert.equal(field.data.attrs.disabled, ['zipCode', 'address'].includes(field.key))
|
||||
}
|
||||
const postcodeRow = nodes(vm._render()).find(node => node.data && node.data.class && node.data.class['mailbox-postcode-row'])
|
||||
assert.ok(postcodeRow, '우편번호와 검색 버튼을 같은 행에 배치한다')
|
||||
assert.ok(nodes(postcodeRow).some(node => node.key === 'zipCode'))
|
||||
assert.ok(nodes(postcodeRow).some(node => node.tag === 'v-btn' && nodes(node).map(child => child.text || '').join('').trim() === '주소 검색'))
|
||||
await vm.openAddressSearch()
|
||||
assert.equal(vm.show_address_search, true)
|
||||
options.oncomplete({ zonecode: '04524', userSelectedType: type, roadAddress: '서울 중구 세종대로 110', jibunAddress: '서울 중구 태평로1가 31' })
|
||||
assert.equal(vm.form.zipCode, '04524')
|
||||
assert.equal(vm.form.address, type === 'R' ? '서울 중구 세종대로 110' : '서울 중구 태평로1가 31')
|
||||
assert.equal(vm.form.addressDetail, '')
|
||||
assert.equal(vm.form_errors.zipCode, '')
|
||||
assert.equal(vm.form_errors.address, '')
|
||||
assert.equal(vm.show_address_search, false)
|
||||
vm.form.addressDetail = '3층'
|
||||
let request
|
||||
Vue.axios = { put: async (url, body) => { request = body; return envelope(saved) } }
|
||||
await vm.saveMailbox()
|
||||
assert.equal(request.zipCode, '04524')
|
||||
assert.equal(request.address, vm.form.address)
|
||||
assert.equal(request.addressDetail, '3층')
|
||||
}
|
||||
} finally {
|
||||
postcode.loadPostcode = original
|
||||
}
|
||||
})
|
||||
|
||||
test('주소 검색 취소·화면 종료·오류 시 기존 입력 보존 및 재시도', async () => {
|
||||
const postcode = require('../src/utils/postcode')
|
||||
const original = postcode.loadPostcode
|
||||
try {
|
||||
const { vm, errors } = page()
|
||||
vm.loaded = true
|
||||
vm.form = form()
|
||||
let resolve
|
||||
let embeds = 0
|
||||
postcode.loadPostcode = () => new Promise(done => { resolve = done })
|
||||
const pending = vm.openAddressSearch()
|
||||
vm.show_address_search = false
|
||||
resolve(function() { this.embed = () => { embeds++ } })
|
||||
await pending
|
||||
assert.equal(embeds, 0)
|
||||
assert.deepEqual(vm.form, form())
|
||||
postcode.loadPostcode = async () => { throw new Error('검색 로딩 실패') }
|
||||
await vm.openAddressSearch()
|
||||
assert.deepEqual(errors, ['검색 로딩 실패'])
|
||||
assert.equal(vm.is_postcode_loading, false)
|
||||
assert.equal(vm.show_address_search, false)
|
||||
assert.deepEqual(vm.form, form())
|
||||
postcode.loadPostcode = () => new Promise(done => { resolve = done })
|
||||
const retry = vm.openAddressSearch()
|
||||
GiftMailbox.beforeDestroy.call(vm)
|
||||
resolve(function() { this.embed = () => { embeds++ } })
|
||||
await retry
|
||||
assert.equal(embeds, 0)
|
||||
} finally {
|
||||
postcode.loadPostcode = original
|
||||
}
|
||||
})
|
||||
|
||||
test('주소 검색 스크립트 단일 로드, 실패 후 재시도 및 기존 SDK 재사용', async () => {
|
||||
const { loadPostcode } = require('../src/utils/postcode')
|
||||
const scripts = []
|
||||
const previousWindow = global.window
|
||||
const previousDocument = global.document
|
||||
global.window = {}
|
||||
global.document = {
|
||||
createElement: () => ({ remove() { this.removed = true } }),
|
||||
head: { appendChild: script => scripts.push(script) }
|
||||
}
|
||||
try {
|
||||
const first = loadPostcode()
|
||||
assert.equal(loadPostcode(), first)
|
||||
assert.equal(scripts.length, 1)
|
||||
assert.equal(scripts[0].src, 'https://t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js')
|
||||
scripts[0].onerror()
|
||||
await assert.rejects(first, /주소 검색/)
|
||||
assert.equal(scripts[0].removed, true)
|
||||
const retry = loadPostcode()
|
||||
assert.equal(scripts.length, 2)
|
||||
global.window.daum = { Postcode: function() {} }
|
||||
scripts[1].onload()
|
||||
assert.equal(await retry, global.window.daum.Postcode)
|
||||
assert.equal(await loadPostcode(), global.window.daum.Postcode)
|
||||
assert.equal(scripts.length, 2)
|
||||
} finally {
|
||||
if (previousWindow === undefined) delete global.window
|
||||
else global.window = previousWindow
|
||||
if (previousDocument === undefined) delete global.document
|
||||
else global.document = previousDocument
|
||||
}
|
||||
})
|
||||
|
||||
test('관리자 선물함 메뉴 연결 및 중복 방지, 라우트 등록', async () => {
|
||||
for (const items of [[], [{ title: '선물함 관리', items: null }], [{ title: '선물함 관리', items: [{ title: '받을 주소', route: '/gift/mailbox' }] }]]) {
|
||||
Vue.axios = { get: async () => ({ status: 200, ...envelope(items) }) }
|
||||
const vm = new Vue({ ...SideMenu, created: undefined })
|
||||
vm.$store = { state: { accountStore: { role: 'ADMIN' } } }
|
||||
await vm.getMenus()
|
||||
const children = vm.items.find(item => item.title === '선물함 관리').items
|
||||
assert.equal(children.filter(item => item.route === '/gift/mailbox').length, 1)
|
||||
assert.equal(children.find(item => item.route === '/gift/mailbox').title, '받을 주소')
|
||||
}
|
||||
const router = fs.readFileSync(path.join(root, 'src/router/index.js'), 'utf8')
|
||||
assert.match(router, /path: '\/gift\/mailbox',\s*name: 'GiftMailbox',\s*component: \(\) => import\([^\n]*'\.\.\/views\/Gift\/GiftMailbox.vue'\)/)
|
||||
})
|
||||
|
||||
;(async () => {
|
||||
for (const { name, run } of tests) {
|
||||
try {
|
||||
await run()
|
||||
console.log(`PASS ${name}`)
|
||||
} catch (error) {
|
||||
process.exitCode = 1
|
||||
console.error(`FAIL ${name}`, error)
|
||||
}
|
||||
}
|
||||
})()
|
||||
Reference in New Issue
Block a user