|
@@ -0,0 +1,118 @@
|
|
|
|
|
+import test from 'node:test'
|
|
|
|
|
+import assert from 'node:assert/strict'
|
|
|
|
|
+import fs from 'node:fs'
|
|
|
|
|
+import path from 'node:path'
|
|
|
|
|
+import vm from 'node:vm'
|
|
|
|
|
+
|
|
|
|
|
+const areaFile = path.resolve('components/pages/activityArea/index.vue')
|
|
|
|
|
+const flushPromises = () => new Promise(resolve => setImmediate(resolve))
|
|
|
|
|
+
|
|
|
|
|
+const regionRows = [
|
|
|
|
|
+ { id: '320000', pid: '0', name: '江苏省' },
|
|
|
|
|
+ { id: '320100', pid: '320000', name: '南京市' },
|
|
|
|
|
+ { id: '320102', pid: '320100', name: '玄武区' },
|
|
|
|
|
+ { id: '320500', pid: '320000', name: '苏州市' },
|
|
|
|
|
+ { id: '320505', pid: '320500', name: '虎丘区' },
|
|
|
|
|
+ { id: '440000', pid: '0', name: '广东省' },
|
|
|
|
|
+ { id: '440100', pid: '440000', name: '广州市' },
|
|
|
|
|
+ { id: '440103', pid: '440100', name: '荔湾区' },
|
|
|
|
|
+ { id: '440300', pid: '440000', name: '深圳市' },
|
|
|
|
|
+ { id: '440303', pid: '440300', name: '罗湖区' }
|
|
|
|
|
+]
|
|
|
|
|
+
|
|
|
|
|
+async function mountActivityArea () {
|
|
|
|
|
+ const source = fs.readFileSync(areaFile, 'utf8')
|
|
|
|
|
+ const script = source.match(/<script setup[^>]*>([\s\S]*?)<\/script>/)[1]
|
|
|
|
|
+ .replace(/^\s*import\s+.*$/gm, '') +
|
|
|
|
|
+ '\nglobalThis.__area = { handleHotCityClick, handlePickerStart, handlePickerChange, handleReset, handleConfirm, pickerValue }'
|
|
|
|
|
+
|
|
|
|
|
+ const lifecycle = {}
|
|
|
|
|
+ const emitted = []
|
|
|
|
|
+ const nextTicks = []
|
|
|
|
|
+ const context = {
|
|
|
|
|
+ ref: value => ({ value }),
|
|
|
|
|
+ computed: getter => ({ get value () { return getter() } }),
|
|
|
|
|
+ watch: () => {},
|
|
|
|
|
+ nextTick: callback => nextTicks.push(callback),
|
|
|
|
|
+ getCurrentInstance: () => ({
|
|
|
|
|
+ proxy: {
|
|
|
|
|
+ $api: {
|
|
|
|
|
+ get: () => Promise.resolve({ data: { code: 0, data: regionRows } })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }),
|
|
|
|
|
+ defineEmits: () => (name, payload) => emitted.push({ name, payload }),
|
|
|
|
|
+ defineExpose: () => {},
|
|
|
|
|
+ onMounted: callback => { lifecycle.mounted = callback },
|
|
|
|
|
+ uni: { showToast: () => {} },
|
|
|
|
|
+ console
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ vm.runInNewContext(script, context)
|
|
|
|
|
+ lifecycle.mounted()
|
|
|
|
|
+ await flushPromises()
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ area: context.__area,
|
|
|
|
|
+ emitted,
|
|
|
|
|
+ flushNextTicks: () => {
|
|
|
|
|
+ while (nextTicks.length) nextTicks.shift()()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+test('点击非省会热门城市后保持目标城市而不是回退到省会', async () => {
|
|
|
|
|
+ const cases = [
|
|
|
|
|
+ { hotCity: '苏州', staleValue: [0, 0, 0], city: '苏州市', cityId: '320500', area: '虎丘区' },
|
|
|
|
|
+ { hotCity: '深圳', staleValue: [1, 0, 0], city: '深圳市', cityId: '440300', area: '罗湖区' }
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+ for (const expected of cases) {
|
|
|
|
|
+ const { area, emitted, flushNextTicks } = await mountActivityArea()
|
|
|
|
|
+
|
|
|
|
|
+ area.handleHotCityClick(expected.hotCity)
|
|
|
|
|
+ flushNextTicks()
|
|
|
|
|
+ // picker-view 的上一轮滚动动画可能在程序化定位后才派发 change。
|
|
|
|
|
+ area.handlePickerChange({ detail: { value: expected.staleValue } })
|
|
|
|
|
+ area.handleConfirm()
|
|
|
|
|
+
|
|
|
|
|
+ const result = emitted.at(-1).payload
|
|
|
|
|
+ assert.equal(result.city, expected.city)
|
|
|
|
|
+ assert.equal(result.cityId, expected.cityId)
|
|
|
|
|
+ assert.equal(result.area, expected.area)
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+test('连续点击热门城市时以最后一次选择为准', async () => {
|
|
|
|
|
+ const { area, emitted, flushNextTicks } = await mountActivityArea()
|
|
|
|
|
+
|
|
|
|
|
+ area.handleHotCityClick('苏州')
|
|
|
|
|
+ area.handleHotCityClick('深圳')
|
|
|
|
|
+ flushNextTicks()
|
|
|
|
|
+ area.handleConfirm()
|
|
|
|
|
+
|
|
|
|
|
+ const result = emitted.at(-1).payload
|
|
|
|
|
+ assert.equal(result.province, '广东省')
|
|
|
|
|
+ assert.equal(result.city, '深圳市')
|
|
|
|
|
+ assert.equal(result.cityId, '440300')
|
|
|
|
|
+ assert.equal(result.area, '罗湖区')
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+test('热门城市定位后仍允许手动滚动和重置', async () => {
|
|
|
|
|
+ const { area, emitted, flushNextTicks } = await mountActivityArea()
|
|
|
|
|
+
|
|
|
|
|
+ area.handleHotCityClick('苏州')
|
|
|
|
|
+ flushNextTicks()
|
|
|
|
|
+ area.handlePickerStart()
|
|
|
|
|
+ area.handlePickerChange({ detail: { value: [0, 0, 0] } })
|
|
|
|
|
+ area.handleConfirm()
|
|
|
|
|
+ assert.equal(emitted.at(-1).payload.city, '南京市')
|
|
|
|
|
+
|
|
|
|
|
+ area.handleHotCityClick('深圳')
|
|
|
|
|
+ flushNextTicks()
|
|
|
|
|
+ area.handleReset()
|
|
|
|
|
+ area.handleConfirm()
|
|
|
|
|
+ assert.equal(emitted.at(-1).payload.province, '江苏省')
|
|
|
|
|
+ assert.equal(emitted.at(-1).payload.city, '南京市')
|
|
|
|
|
+ assert.equal(emitted.at(-1).payload.area, '玄武区')
|
|
|
|
|
+})
|